aboutsummaryrefslogtreecommitdiffstats
path: root/config
diff options
context:
space:
mode:
Diffstat (limited to 'config')
-rw-r--r--config/arping/arping.inc54
-rw-r--r--config/arping/arping.xml85
-rw-r--r--config/arpwatch.xml116
-rwxr-xr-xconfig/arpwatch_reports.php127
-rw-r--r--config/assp.xml79
-rw-r--r--config/authng/bin/patchbin0 -> 41056 bytes
-rw-r--r--config/authng/diff/authng-fbegin.inc.diff15
-rw-r--r--config/authng/diff/authng-globals.inc.diff16
-rw-r--r--config/authng/diff/authng-guiconfig.inc.diff27
-rw-r--r--config/authng/diff/authng-pfSenseHead.diff2128
-rw-r--r--config/authng/doc/images/pfSense-AuthMethods.pngbin0 -> 11639 bytes
-rw-r--r--config/authng/doc/images/pfSense-Backends.pngbin0 -> 12499 bytes
-rw-r--r--config/authng/doc/images/pfSense-Peers.pngbin0 -> 12813 bytes
-rw-r--r--config/authng/pkg/authng.inc323
-rw-r--r--config/authng/pkg/authng.xml194
-rw-r--r--config/authng/pkg/authng_authgui.inc287
-rw-r--r--config/authng/pkg/authng_authmethods.inc222
-rw-r--r--config/authng/pkg/authng_backends.inc234
-rw-r--r--config/authng/pkg/authng_classdefs.inc479
-rw-r--r--config/authng/pkg/authng_peers.inc501
-rw-r--r--config/authng/pkg/authng_usermanager.inc247
-rw-r--r--config/authng/www/js/headjs.inc157
-rw-r--r--config/authng/www/php/head.inc669
-rw-r--r--config/authng/www/php/system_groupmanager.php797
-rw-r--r--config/authng/www/php/system_usermanager.php84
-rw-r--r--config/authng/www/php/system_usermanager_admin.inc92
-rw-r--r--config/authng/www/php/system_usermanager_admin_index.inc108
-rw-r--r--config/authng/www/php/system_usermanager_admin_newedit.inc167
-rw-r--r--config/authng/www/php/system_usermanager_edit.php294
-rwxr-xr-xconfig/authng/www/php/system_usermanager_settings.php110
-rw-r--r--config/authng/www/php/system_usermanager_user.inc66
-rw-r--r--config/authng/www/wizards/authng_wizard.xml496
-rw-r--r--config/autoconfigbackup/autoconfigbackup.inc219
-rw-r--r--config/autoconfigbackup/autoconfigbackup.php387
-rw-r--r--config/autoconfigbackup/autoconfigbackup.xml162
-rw-r--r--config/autoconfigbackup/autoconfigbackup_backup.php157
-rw-r--r--config/autoconfigbackup/autoconfigbackup_stats.php214
-rw-r--r--config/autoconfigbackup/certs/gd-class2-root.crt24
-rw-r--r--config/autoconfigbackup/certs/gd_intermediate.crt29
-rw-r--r--config/autoconfigbackup/crypt_acb.php129
-rw-r--r--config/autoconfigbackup/parse_config_upload.php8
-rw-r--r--config/autoconfigbackup/upload_config_filter.php8
-rw-r--r--config/avahi/avahi.inc167
-rw-r--r--config/avahi/avahi.xml90
-rw-r--r--config/bandwidthd/bandwidthd.inc201
-rw-r--r--config/bandwidthd/bandwidthd.xml153
-rwxr-xr-xconfig/bsdstats/bin/digbin0 -> 1083772 bytes
-rw-r--r--config/bsdstats/bsdstats.xml83
-rw-r--r--config/cg2/sample/i18n/messages_de.xml7
-rw-r--r--config/cg2/sample/i18n/messages_en.xml7
-rw-r--r--config/cg2/sample/sample.inc37
-rw-r--r--config/cg2/sample/sample.xml18
-rw-r--r--config/cg2/sample/sample_ui.xml156
-rw-r--r--config/cg2/sample/sample_ui2.xml29
-rw-r--r--config/clamav.inc263
-rw-r--r--config/clamav.xml130
-rw-r--r--config/clamsmtp.inc54
-rw-r--r--config/clamsmtp.xml69
-rw-r--r--config/darkstat/darkstat.sh22
-rw-r--r--config/darkstat/darkstat.xml109
-rw-r--r--config/dashboard/dashboard.inc38
-rw-r--r--config/dashboard/dashboard.xml71
-rw-r--r--config/developers/developers.xml63
-rw-r--r--config/diag_states_pt/diag_new_states.php381
-rw-r--r--config/diag_states_pt/diag_new_states.xml65
-rw-r--r--config/doorman.xml157
-rw-r--r--config/doormanusers.xml142
-rw-r--r--config/dspam/conf.default/config.xml1020
-rw-r--r--config/dspam/pear/Image/Canvas.php733
-rw-r--r--config/dspam/pear/Image/Canvas/Color.php182
-rw-r--r--config/dspam/pear/Image/Canvas/Fonts/README12
-rw-r--r--config/dspam/pear/Image/Canvas/Fonts/fontmap.txt25
-rw-r--r--config/dspam/pear/Image/Canvas/GD.php1693
-rw-r--r--config/dspam/pear/Image/Canvas/GD/JPG.php119
-rw-r--r--config/dspam/pear/Image/Canvas/GD/PNG.php125
-rw-r--r--config/dspam/pear/Image/Canvas/ImageMap.php354
-rw-r--r--config/dspam/pear/Image/Canvas/PDF.php1007
-rw-r--r--config/dspam/pear/Image/Canvas/SVG.php918
-rw-r--r--config/dspam/pear/Image/Canvas/Tool.php217
-rw-r--r--config/dspam/pear/Image/Canvas/WithMap.php278
-rw-r--r--config/dspam/pear/Image/Color.php719
-rw-r--r--config/dspam/pear/Image/Graph.php851
-rw-r--r--config/dspam/pear/Image/Graph/Axis.php1690
-rw-r--r--config/dspam/pear/Image/Graph/Axis/Category.php437
-rw-r--r--config/dspam/pear/Image/Graph/Axis/Logarithmic.php152
-rw-r--r--config/dspam/pear/Image/Graph/Axis/Marker/Area.php156
-rw-r--r--config/dspam/pear/Image/Graph/Axis/Marker/Line.php124
-rw-r--r--config/dspam/pear/Image/Graph/Axis/Radar.php204
-rw-r--r--config/dspam/pear/Image/Graph/Common.php313
-rw-r--r--config/dspam/pear/Image/Graph/Config.php30
-rw-r--r--config/dspam/pear/Image/Graph/Constants.php225
-rw-r--r--config/dspam/pear/Image/Graph/DataPreprocessor.php74
-rw-r--r--config/dspam/pear/Image/Graph/DataPreprocessor/Array.php103
-rw-r--r--config/dspam/pear/Image/Graph/DataPreprocessor/Currency.php66
-rw-r--r--config/dspam/pear/Image/Graph/DataPreprocessor/Date.php90
-rw-r--r--config/dspam/pear/Image/Graph/DataPreprocessor/Formatted.php90
-rw-r--r--config/dspam/pear/Image/Graph/DataPreprocessor/Function.php92
-rw-r--r--config/dspam/pear/Image/Graph/DataPreprocessor/NumberText.php89
-rw-r--r--config/dspam/pear/Image/Graph/DataPreprocessor/RomanNumerals.php79
-rw-r--r--config/dspam/pear/Image/Graph/DataPreprocessor/Sequential.php67
-rw-r--r--config/dspam/pear/Image/Graph/DataSelector.php67
-rw-r--r--config/dspam/pear/Image/Graph/DataSelector/EveryNthPoint.php97
-rw-r--r--config/dspam/pear/Image/Graph/DataSelector/NoZeros.php68
-rw-r--r--config/dspam/pear/Image/Graph/DataSelector/Values.php90
-rw-r--r--config/dspam/pear/Image/Graph/Dataset.php483
-rw-r--r--config/dspam/pear/Image/Graph/Dataset/Function.php147
-rw-r--r--config/dspam/pear/Image/Graph/Dataset/Random.php77
-rw-r--r--config/dspam/pear/Image/Graph/Dataset/Sequential.php114
-rw-r--r--config/dspam/pear/Image/Graph/Dataset/Trivial.php260
-rw-r--r--config/dspam/pear/Image/Graph/Dataset/VectorFunction.php185
-rw-r--r--config/dspam/pear/Image/Graph/Element.php763
-rw-r--r--config/dspam/pear/Image/Graph/Figure/Circle.php64
-rw-r--r--config/dspam/pear/Image/Graph/Figure/Ellipse.php97
-rw-r--r--config/dspam/pear/Image/Graph/Figure/Polygon.php94
-rw-r--r--config/dspam/pear/Image/Graph/Figure/Rectangle.php96
-rw-r--r--config/dspam/pear/Image/Graph/Fill.php63
-rw-r--r--config/dspam/pear/Image/Graph/Fill/Array.php137
-rw-r--r--config/dspam/pear/Image/Graph/Fill/Gradient.php149
-rw-r--r--config/dspam/pear/Image/Graph/Fill/Image.php97
-rw-r--r--config/dspam/pear/Image/Graph/Font.php158
-rw-r--r--config/dspam/pear/Image/Graph/Grid.php175
-rw-r--r--config/dspam/pear/Image/Graph/Grid/Bars.php117
-rw-r--r--config/dspam/pear/Image/Graph/Grid/Lines.php114
-rw-r--r--config/dspam/pear/Image/Graph/Grid/Polar.php111
-rw-r--r--config/dspam/pear/Image/Graph/Images/Icons/pinpoint.pngbin0 -> 452 bytes
-rw-r--r--config/dspam/pear/Image/Graph/Images/Icons/pinpointr.pngbin0 -> 437 bytes
-rw-r--r--config/dspam/pear/Image/Graph/Images/Maps/README17
-rw-r--r--config/dspam/pear/Image/Graph/Layout.php219
-rw-r--r--config/dspam/pear/Image/Graph/Layout/Horizontal.php186
-rw-r--r--config/dspam/pear/Image/Graph/Layout/Matrix.php201
-rw-r--r--config/dspam/pear/Image/Graph/Layout/Vertical.php108
-rw-r--r--config/dspam/pear/Image/Graph/Legend.php385
-rw-r--r--config/dspam/pear/Image/Graph/Line/Array.php129
-rw-r--r--config/dspam/pear/Image/Graph/Line/Dashed.php76
-rw-r--r--config/dspam/pear/Image/Graph/Line/Dotted.php67
-rw-r--r--config/dspam/pear/Image/Graph/Line/Formatted.php90
-rw-r--r--config/dspam/pear/Image/Graph/Line/Solid.php105
-rw-r--r--config/dspam/pear/Image/Graph/Logo.php153
-rw-r--r--config/dspam/pear/Image/Graph/Marker.php123
-rw-r--r--config/dspam/pear/Image/Graph/Marker/Array.php105
-rw-r--r--config/dspam/pear/Image/Graph/Marker/Asterisk.php109
-rw-r--r--config/dspam/pear/Image/Graph/Marker/Average.php91
-rw-r--r--config/dspam/pear/Image/Graph/Marker/Box.php76
-rw-r--r--config/dspam/pear/Image/Graph/Marker/Bubble.php91
-rw-r--r--config/dspam/pear/Image/Graph/Marker/Circle.php96
-rw-r--r--config/dspam/pear/Image/Graph/Marker/Cross.php114
-rw-r--r--config/dspam/pear/Image/Graph/Marker/Diamond.php73
-rw-r--r--config/dspam/pear/Image/Graph/Marker/Icon.php133
-rw-r--r--config/dspam/pear/Image/Graph/Marker/Pinpoint.php65
-rw-r--r--config/dspam/pear/Image/Graph/Marker/Plus.php98
-rw-r--r--config/dspam/pear/Image/Graph/Marker/Pointing.php140
-rw-r--r--config/dspam/pear/Image/Graph/Marker/Pointing/Angular.php105
-rw-r--r--config/dspam/pear/Image/Graph/Marker/Pointing/Radial.php91
-rw-r--r--config/dspam/pear/Image/Graph/Marker/ReversePinpoint.php65
-rw-r--r--config/dspam/pear/Image/Graph/Marker/Star.php88
-rw-r--r--config/dspam/pear/Image/Graph/Marker/Triangle.php75
-rw-r--r--config/dspam/pear/Image/Graph/Marker/Value.php214
-rw-r--r--config/dspam/pear/Image/Graph/Plot.php824
-rw-r--r--config/dspam/pear/Image/Graph/Plot/Area.php194
-rw-r--r--config/dspam/pear/Image/Graph/Plot/Band.php205
-rw-r--r--config/dspam/pear/Image/Graph/Plot/Bar.php307
-rw-r--r--config/dspam/pear/Image/Graph/Plot/BoxWhisker.php298
-rw-r--r--config/dspam/pear/Image/Graph/Plot/CandleStick.php251
-rw-r--r--config/dspam/pear/Image/Graph/Plot/Dot.php99
-rw-r--r--config/dspam/pear/Image/Graph/Plot/Fit/Line.php118
-rw-r--r--config/dspam/pear/Image/Graph/Plot/Impulse.php204
-rw-r--r--config/dspam/pear/Image/Graph/Plot/Line.php171
-rw-r--r--config/dspam/pear/Image/Graph/Plot/Odo.php719
-rw-r--r--config/dspam/pear/Image/Graph/Plot/Pie.php623
-rw-r--r--config/dspam/pear/Image/Graph/Plot/Radar.php118
-rw-r--r--config/dspam/pear/Image/Graph/Plot/Smoothed/Area.php145
-rw-r--r--config/dspam/pear/Image/Graph/Plot/Smoothed/Bezier.php173
-rw-r--r--config/dspam/pear/Image/Graph/Plot/Smoothed/Line.php172
-rw-r--r--config/dspam/pear/Image/Graph/Plot/Smoothed/Radar.php142
-rw-r--r--config/dspam/pear/Image/Graph/Plot/Step.php200
-rw-r--r--config/dspam/pear/Image/Graph/Plotarea.php1145
-rw-r--r--config/dspam/pear/Image/Graph/Plotarea/Element.php87
-rw-r--r--config/dspam/pear/Image/Graph/Plotarea/Map.php304
-rw-r--r--config/dspam/pear/Image/Graph/Plotarea/Radar.php243
-rw-r--r--config/dspam/pear/Image/Graph/Simple.php121
-rw-r--r--config/dspam/pear/Image/Graph/Title.php194
-rw-r--r--config/dspam/pear/Image/Graph/Tool.php291
-rw-r--r--config/dspam/pkg/000.mysql.sh68
-rw-r--r--config/dspam/pkg/010.clamav-clamd.sh56
-rw-r--r--config/dspam/pkg/020.clamav-freshclam.sh33
-rw-r--r--config/dspam/pkg/030.p3scan.sh60
-rw-r--r--config/dspam/pkg/clamd.conf299
-rw-r--r--config/dspam/pkg/default.prefs.sample43
-rw-r--r--config/dspam/pkg/dspam-config.inc42
-rw-r--r--config/dspam/pkg/dspam-guifunc.inc2606
-rw-r--r--config/dspam/pkg/dspam-pkgfunc.inc548
-rw-r--r--config/dspam/pkg/dspam-utilfunc.inc458
-rw-r--r--config/dspam/pkg/dspam.inc360
-rw-r--r--config/dspam/pkg/dspam.xml342
-rw-r--r--config/dspam/pkg/dspam_alerts.xml147
-rw-r--r--config/dspam/pkg/freshclam.conf110
-rw-r--r--config/dspam/pkg/p3scan-pf-emer.xml127
-rw-r--r--config/dspam/pkg/p3scan-pf-msg.xml198
-rw-r--r--config/dspam/pkg/p3scan-pf-spam.xml119
-rw-r--r--config/dspam/pkg/p3scan-pf-vir.xml162
-rw-r--r--config/dspam/pkg/p3scan-pf.xml211
-rw-r--r--config/dspam/pkg/p3scan.inc277
-rw-r--r--config/dspam/pkg/verdana.ttfbin0 -> 139640 bytes
-rw-r--r--config/dspam/www/dspam-admin-graph.php201
-rw-r--r--config/dspam/www/dspam-admin-prefs.php249
-rw-r--r--config/dspam/www/dspam-admin-stats.php123
-rw-r--r--config/dspam/www/dspam-admin.php207
-rw-r--r--config/dspam/www/dspam-analysis-graph.php137
-rw-r--r--config/dspam/www/dspam-analysis.php147
-rw-r--r--config/dspam/www/dspam-hfragment.php90
-rw-r--r--config/dspam/www/dspam-history.php172
-rw-r--r--config/dspam/www/dspam-perf.php222
-rw-r--r--config/dspam/www/dspam-prefs.php234
-rw-r--r--config/dspam/www/dspam-quarantine.php178
-rw-r--r--config/dspam/www/dspam-settings-algo.php204
-rw-r--r--config/dspam/www/dspam-settings-bmta.php202
-rw-r--r--config/dspam/www/dspam-settings-feat.php203
-rw-r--r--config/dspam/www/dspam-settings-header.php197
-rw-r--r--config/dspam/www/dspam-settings-overr.php197
-rw-r--r--config/dspam/www/dspam-settings-prefs.php197
-rw-r--r--config/dspam/www/dspam-settings-spwd.php197
-rw-r--r--config/dspam/www/dspam-settings-tuser.php195
-rw-r--r--config/dspam/www/dspam-settings.php2955
-rw-r--r--config/dspam/www/dspam-train.php284
-rw-r--r--config/dspam/www/dspam-viewmsg.php158
-rw-r--r--config/dspam/www/dspam.php264
-rw-r--r--config/dspam/www/themes/metallic/dspam.css115
-rw-r--r--config/dspam/www/wizards/dspam-lda-proxy.pngbin0 -> 20556 bytes
-rw-r--r--config/dspam/www/wizards/dspam-pop-proxy.pngbin0 -> 18247 bytes
-rw-r--r--config/dspam/www/wizards/dspam-smtp-relay.pngbin0 -> 30404 bytes
-rw-r--r--config/dspam/www/wizards/dspam_wizard.xml1848
-rw-r--r--config/dyntables/pkg/dyntables.inc117
-rw-r--r--config/dyntables/pkg/dyntables.xml139
-rw-r--r--config/dyntables/pkg/dyntables_classdefs.inc146
-rw-r--r--config/dyntables/www/js/dyntables.js287
-rw-r--r--config/dyntables/www/php/diag_dhcp_leases.php440
-rw-r--r--config/freenas/bin/ext2fs.kobin0 -> 61544 bytes
-rw-r--r--config/freenas/bin/geom_concat.kobin0 -> 20068 bytes
-rw-r--r--config/freenas/bin/geom_gpt.kobin0 -> 6277 bytes
-rw-r--r--config/freenas/bin/geom_mirror.kobin0 -> 78213 bytes
-rw-r--r--config/freenas/bin/geom_stripe.kobin0 -> 24734 bytes
-rw-r--r--config/freenas/bin/geom_vinum.kobin0 -> 70268 bytes
-rw-r--r--config/freenas/bin/iscontrolbin0 -> 86231 bytes
-rw-r--r--config/freenas/bin/iscsi_initiator.kobin0 -> 47530 bytes
-rw-r--r--config/freenas/bin/kernel.gzbin0 -> 3798453 bytes
-rw-r--r--config/freenas/bin/mountdbin0 -> 27112 bytes
-rw-r--r--config/freenas/bin/nfsdbin0 -> 14004 bytes
-rw-r--r--config/freenas/bin/ntfs.kobin0 -> 44199 bytes
-rw-r--r--config/freenas/bin/rpc.lockdbin0 -> 39404 bytes
-rw-r--r--config/freenas/bin/rpc.statdbin0 -> 11724 bytes
-rw-r--r--config/freenas/bin/rpcbindbin0 -> 39540 bytes
-rw-r--r--config/freenas/conf.default/config.xml179
-rw-r--r--config/freenas/conf.kernel/pfSense.6.freenas433
-rw-r--r--config/freenas/diffs/netatalk-2.0.3-afpd-zeroconf.patch1386
-rw-r--r--config/freenas/doc/README.txt52
-rw-r--r--config/freenas/pkg/freenas.inc297
-rw-r--r--config/freenas/pkg/freenas.xml570
-rw-r--r--config/freenas/pkg/freenas_config.inc45
-rw-r--r--config/freenas/pkg/freenas_disks.inc1256
-rw-r--r--config/freenas/pkg/freenas_functions.inc49
-rw-r--r--config/freenas/pkg/freenas_guiconfig.inc288
-rw-r--r--config/freenas/pkg/freenas_services.inc2025
-rw-r--r--config/freenas/pkg/freenas_system.inc838
-rw-r--r--config/freenas/pkg/freenas_utils.inc1049
-rw-r--r--config/freenas/pkg/rc.freenas102
-rw-r--r--config/freenas/www/diag_ad_infos.php159
-rw-r--r--config/freenas/www/diag_ataidle_infos.php149
-rw-r--r--config/freenas/www/diag_disk_infos.php143
-rw-r--r--config/freenas/www/diag_fn_logs_daemon.php119
-rw-r--r--config/freenas/www/diag_fn_logs_ftp.php118
-rw-r--r--config/freenas/www/diag_fn_logs_rsyncd.php117
-rw-r--r--config/freenas/www/diag_fn_logs_samba.php174
-rw-r--r--config/freenas/www/diag_fn_logs_settings.php310
-rw-r--r--config/freenas/www/diag_fn_logs_smartd.php118
-rw-r--r--config/freenas/www/diag_fn_logs_sshd.php117
-rw-r--r--config/freenas/www/diag_iscsi_infos.php142
-rw-r--r--config/freenas/www/diag_mounts_infos.php137
-rw-r--r--config/freenas/www/diag_part_infos.php141
-rw-r--r--config/freenas/www/diag_raid_infos.php163
-rw-r--r--config/freenas/www/diag_smart_infos.php141
-rw-r--r--config/freenas/www/diag_space_infos.php136
-rw-r--r--config/freenas/www/disks_manage.php208
-rw-r--r--config/freenas/www/disks_manage_edit.php275
-rw-r--r--config/freenas/www/disks_manage_init.php511
-rw-r--r--config/freenas/www/disks_manage_iscsi.php209
-rw-r--r--config/freenas/www/disks_manage_tools.php331
-rw-r--r--config/freenas/www/disks_mount.php235
-rw-r--r--config/freenas/www/disks_mount_edit.php307
-rw-r--r--config/freenas/www/disks_mount_tools.php233
-rw-r--r--config/freenas/www/disks_raid_gconcat.php236
-rw-r--r--config/freenas/www/disks_raid_gconcat_edit.php256
-rw-r--r--config/freenas/www/disks_raid_gconcat_infos.php143
-rw-r--r--config/freenas/www/disks_raid_gconcat_tools.php187
-rw-r--r--config/freenas/www/disks_raid_gmirror.php236
-rw-r--r--config/freenas/www/disks_raid_gmirror_edit.php277
-rw-r--r--config/freenas/www/disks_raid_gmirror_infos.php143
-rw-r--r--config/freenas/www/disks_raid_gmirror_init.php179
-rw-r--r--config/freenas/www/disks_raid_gmirror_tools.php191
-rw-r--r--config/freenas/www/disks_raid_graid5.php236
-rw-r--r--config/freenas/www/disks_raid_graid5_edit.php258
-rw-r--r--config/freenas/www/disks_raid_graid5_infos.php143
-rw-r--r--config/freenas/www/disks_raid_graid5_tools.php190
-rw-r--r--config/freenas/www/disks_raid_gstripe.php236
-rw-r--r--config/freenas/www/disks_raid_gstripe_edit.php258
-rw-r--r--config/freenas/www/disks_raid_gstripe_infos.php143
-rw-r--r--config/freenas/www/disks_raid_gstripe_tools.php187
-rw-r--r--config/freenas/www/disks_raid_gvinum.php235
-rw-r--r--config/freenas/www/disks_raid_gvinum_edit.php277
-rw-r--r--config/freenas/www/disks_raid_gvinum_infos.php144
-rw-r--r--config/freenas/www/disks_raid_gvinum_init.php181
-rw-r--r--config/freenas/www/disks_raid_gvinum_tools.php220
-rw-r--r--config/freenas/www/services_afp.php199
-rw-r--r--config/freenas/www/services_ftp.php392
-rw-r--r--config/freenas/www/services_nfs.php243
-rw-r--r--config/freenas/www/services_nfs_export.php165
-rw-r--r--config/freenas/www/services_nfs_export_edit.php783
-rw-r--r--config/freenas/www/services_rsyncd.php277
-rw-r--r--config/freenas/www/services_rsyncd_client.php585
-rw-r--r--config/freenas/www/services_rsyncd_local.php579
-rw-r--r--config/freenas/www/services_samba.php431
-rw-r--r--config/freenas/www/services_samba_share.php165
-rw-r--r--config/freenas/www/services_samba_share_edit.php157
-rw-r--r--config/freenas/www/services_unison.php249
-rw-r--r--config/freenas/www/status_disks.php127
-rw-r--r--config/freeradius.inc527
-rw-r--r--config/freeradius.xml249
-rw-r--r--config/freeradiusclients.xml116
-rw-r--r--config/freeradiussettings.xml141
-rw-r--r--config/freeswitch/begin_recording.wavbin0 -> 19480 bytes
-rw-r--r--config/freeswitch/class.phpmailer.tmp1896
-rw-r--r--config/freeswitch/class.smtp.tmp1062
-rw-r--r--config/freeswitch/freeswitch.inc2234
-rw-r--r--config/freeswitch/freeswitch.xml477
-rw-r--r--config/freeswitch/freeswitch_cmd.tmp49
-rw-r--r--config/freeswitch/freeswitch_dialplan.xml136
-rw-r--r--config/freeswitch/freeswitch_dialplan_includes.tmp271
-rw-r--r--config/freeswitch/freeswitch_dialplan_includes_details.tmp53
-rw-r--r--config/freeswitch/freeswitch_dialplan_includes_details_edit.tmp375
-rw-r--r--config/freeswitch/freeswitch_dialplan_includes_edit.tmp524
-rw-r--r--config/freeswitch/freeswitch_extensions.tmp209
-rw-r--r--config/freeswitch/freeswitch_extensions.xml225
-rw-r--r--config/freeswitch/freeswitch_extensions_edit.tmp351
-rw-r--r--config/freeswitch/freeswitch_external.xml136
-rw-r--r--config/freeswitch/freeswitch_gateways.tmp209
-rw-r--r--config/freeswitch/freeswitch_gateways_edit.tmp596
-rw-r--r--config/freeswitch/freeswitch_internal.xml136
-rw-r--r--config/freeswitch/freeswitch_ivr.tmp216
-rw-r--r--config/freeswitch/freeswitch_ivr_edit.tmp582
-rw-r--r--config/freeswitch/freeswitch_ivr_options.tmp52
-rw-r--r--config/freeswitch/freeswitch_ivr_options_edit.tmp216
-rw-r--r--config/freeswitch/freeswitch_mailto.tmp240
-rw-r--r--config/freeswitch/freeswitch_modules.xml1216
-rw-r--r--config/freeswitch/freeswitch_public.xml135
-rw-r--r--config/freeswitch/freeswitch_public_includes.tmp275
-rw-r--r--config/freeswitch/freeswitch_public_includes_details.tmp53
-rw-r--r--config/freeswitch/freeswitch_public_includes_details_edit.tmp410
-rw-r--r--config/freeswitch/freeswitch_public_includes_edit.tmp524
-rw-r--r--config/freeswitch/freeswitch_recordings.tmp499
-rw-r--r--config/freeswitch/freeswitch_recordings_edit.tmp186
-rw-r--r--config/freeswitch/freeswitch_recordings_play.tmp71
-rw-r--r--config/freeswitch/freeswitch_status.tmp337
-rw-r--r--config/freeswitch/freeswitch_time_conditions.tmp191
-rw-r--r--config/freeswitch/freeswitch_time_conditions_edit.tmp215
-rw-r--r--config/freeswitch/freeswitch_vars.xml136
-rw-r--r--config/freeswitch/libncurses.so.5.6bin0 -> 127748 bytes
-rw-r--r--config/freeswitch/libogg.so.5.3bin0 -> 43004 bytes
-rw-r--r--config/freeswitch/libspandsp.so.1bin0 -> 1398998 bytes
-rw-r--r--config/freeswitch/libtinfo.so.5.6bin0 -> 187069 bytes
-rw-r--r--config/freeswitch/libvorbis.so.4bin0 -> 179138 bytes
-rw-r--r--config/freeswitch/mod_fax.so.1bin0 -> 80741 bytes
-rw-r--r--config/freeswitch/mod_shout.so.1bin0 -> 2147544 bytes
-rw-r--r--config/freeswitch/please_enter_your_pin_number.wavbin0 -> 28212 bytes
-rw-r--r--config/freeswitch/your_pin_number_is_incorect_goodbye.wavbin0 -> 43420 bytes
-rw-r--r--config/frickin.xml75
-rwxr-xr-xconfig/frickin/bin/frickinbin0 -> 470088 bytes
-rw-r--r--config/frickin/frickin.inc137
-rw-r--r--config/frickin/frickin.xml89
-rw-r--r--config/havp.inc219
-rw-r--r--config/havp.sh85
-rw-r--r--config/havp.xml220
-rw-r--r--config/havp_blacklist.xml116
-rw-r--r--config/havp_startup.inc12
-rw-r--r--config/havp_trans_exclude.xml116
-rw-r--r--config/havp_whitelist.xml116
-rw-r--r--config/hula.xml109
-rw-r--r--config/ifdepd.xml118
-rw-r--r--config/ifstated.xml140
-rw-r--r--config/imspector/imspector.inc268
-rw-r--r--config/imspector/imspector.xml225
-rw-r--r--config/imspector/services_imspector_logs.php288
-rw-r--r--config/iperf.xml161
-rw-r--r--config/iperfserver.xml141
-rw-r--r--config/lcdproc/lcdproc.inc363
-rw-r--r--config/lcdproc/lcdproc.xml304
-rw-r--r--config/lcdproc/lcdproc_client.php525
-rw-r--r--config/lcdproc/lcdproc_screens.xml91
-rw-r--r--config/lightsquid/.project11
-rw-r--r--config/lightsquid/.settings/org.eclipse.ltk.core.refactoring.prefs3
-rw-r--r--config/lightsquid/lightsquid.inc432
-rw-r--r--config/lightsquid/lightsquid.xml254
-rw-r--r--config/miniupnpd/miniupnpd.inc290
-rw-r--r--config/miniupnpd/miniupnpd.xml182
-rwxr-xr-xconfig/miniupnpd/sbin/miniupnpdbin0 -> 56202 bytes
-rw-r--r--config/miniupnpd/status_upnp.php120
-rw-r--r--config/mtr-nox11.xml93
-rw-r--r--config/netio-newpkg.xml119
-rw-r--r--config/netio.xml94
-rw-r--r--config/netioserver-newpkg.xml83
-rw-r--r--config/netioserver.xml83
-rw-r--r--config/nmap/nmap.inc55
-rw-r--r--config/nmap/nmap.xml114
-rw-r--r--config/notes/notes.inc99
-rw-r--r--config/notes/notes.xml115
-rwxr-xr-xconfig/ntop/bin/librrd_th.so.2bin0 -> 308723 bytes
-rw-r--r--config/ntop/ntop.xml156
-rw-r--r--config/nut/nut.inc394
-rw-r--r--config/nut/nut.xml518
-rw-r--r--config/nut/status_nut.php242
-rw-r--r--config/open-vm-tools/open-vm-tools.xml64
-rw-r--r--config/openbgpd/openbgpd.inc219
-rw-r--r--config/openbgpd/openbgpd.xml155
-rw-r--r--config/openbgpd/openbgpd_groups.xml115
-rw-r--r--config/openbgpd/openbgpd_neighbors.xml179
-rw-r--r--config/openbgpd/openbgpd_status.php166
-rwxr-xr-xconfig/openvpn-client-export/client-export/template/7zS.sfxbin0 -> 132096 bytes
-rwxr-xr-xconfig/openvpn-client-export/client-export/template/config-import3
-rwxr-xr-xconfig/openvpn-client-export/client-export/template/config-standard3
-rwxr-xr-xconfig/openvpn-client-export/client-export/template/openvpn-postinstall.exebin0 -> 63001 bytes
-rwxr-xr-xconfig/openvpn-client-export/client-export/template/procchain-import2
-rwxr-xr-xconfig/openvpn-client-export/client-export/template/procchain-standard2
-rwxr-xr-xconfig/openvpn-client-export/client-export/template/procchain.exebin0 -> 65536 bytes
-rwxr-xr-xconfig/openvpn-client-export/client-export/vpn_openvpn_export.php362
-rwxr-xr-xconfig/openvpn-client-export/openvpn-client-export.inc256
-rwxr-xr-xconfig/openvpn-client-export/openvpn-client-export.xml48
-rwxr-xr-xconfig/openvpn-client-export/readme.txt44
-rwxr-xr-xconfig/openvpn-client-export/source/openvpn-postinstall.icobin0 -> 22486 bytes
-rwxr-xr-xconfig/openvpn-client-export/source/openvpn-postinstall.nsi112
-rwxr-xr-xconfig/openvpn-client-export/source/procchain.cpp80
-rw-r--r--config/p3scan-pf/p3scan-pf-emer.xml131
-rw-r--r--config/p3scan-pf/p3scan-pf-msg.xml202
-rw-r--r--config/p3scan-pf/p3scan-pf-spam.xml122
-rw-r--r--config/p3scan-pf/p3scan-pf-transex.xml124
-rw-r--r--config/p3scan-pf/p3scan-pf-vir.xml166
-rw-r--r--config/p3scan-pf/p3scan-pf.inc395
-rw-r--r--config/p3scan-pf/p3scan-pf.xml218
-rw-r--r--config/p3scan.inc61
-rw-r--r--config/p3scan.mail15
-rw-r--r--config/p3scan.xml73
-rw-r--r--config/package_installation_overview.txt29
-rw-r--r--config/per-user-bandwidth-distribution.xml145
-rw-r--r--config/pfflowd.xml115
-rw-r--r--config/pfstat.php70
-rw-r--r--config/pfstat.xml324
-rw-r--r--config/phpmrss.xml59
-rw-r--r--config/phpservice/phpservice.inc229
-rw-r--r--config/phpservice/phpservice.xml121
-rw-r--r--config/phpservice/phpservice_php.tmp192
-rw-r--r--config/phpservice/phpservice_php_edit.tmp213
-rw-r--r--config/phpsysinfo/phpsysinfo.inc159
-rw-r--r--config/phpsysinfo/phpsysinfo.xml121
-rw-r--r--config/postfix.xml117
-rw-r--r--config/powerdns.xml248
-rw-r--r--config/pubkey.xml52
-rw-r--r--config/pure-ftpd.xml149
-rw-r--r--config/pure-ftpdsettings.xml162
-rw-r--r--config/quagga/quagga.sh75
-rw-r--r--config/quagga/quagga.xml69
-rw-r--r--config/routed/routed.inc110
-rw-r--r--config/routed/routed.xml127
-rw-r--r--config/sassassin.inc63
-rw-r--r--config/sassassin.xml159
-rw-r--r--config/sassassin_bl.xml95
-rw-r--r--config/sassassin_wl.xml95
-rw-r--r--config/schema/packages.dtd224
-rw-r--r--config/siproxd.inc172
-rw-r--r--config/siproxd.xml166
-rw-r--r--config/siproxdusers.xml117
-rwxr-xr-xconfig/snort/bin/snort2cbin0 -> 13508 bytes
-rw-r--r--config/snort/snort.inc751
-rw-r--r--config/snort/snort.xml274
-rw-r--r--config/snort/snort_advanced.xml118
-rw-r--r--config/snort/snort_alerts.php117
-rw-r--r--config/snort/snort_blocked.php138
-rw-r--r--config/snort/snort_check_for_rule_updates.php111
-rw-r--r--config/snort/snort_download_rules.php240
-rw-r--r--config/snort/snort_dynamic_ip_reload.php46
-rw-r--r--config/snort/snort_rules.php506
-rw-r--r--config/snort/snort_rules_edit.php202
-rw-r--r--config/snort/snort_rulesets.php162
-rw-r--r--config/snort/snort_whitelist.xml121
-rw-r--r--config/snort/snort_xmlrpc_sync.php114
-rw-r--r--config/spamd.inc289
-rw-r--r--config/spamd.xml210
-rw-r--r--config/spamd_db.php457
-rw-r--r--config/spamd_db_ext.php239
-rw-r--r--config/spamd_exchexp.asp50
-rw-r--r--config/spamd_gather_stats.php82
-rw-r--r--config/spamd_outlook.xml90
-rw-r--r--config/spamd_rules.php34
-rw-r--r--config/spamd_settings.xml192
-rw-r--r--config/spamd_verify_to_address.php144
-rw-r--r--config/spamd_whitelist.xml132
-rw-r--r--config/squid-head/squid.inc862
-rw-r--r--config/squid-head/squid.xml215
-rw-r--r--config/squid-head/squid_auth.xml202
-rw-r--r--config/squid-head/squid_cache.xml180
-rw-r--r--config/squid-head/squid_monitor.sh69
-rw-r--r--config/squid-head/squid_nac.xml147
-rw-r--r--config/squid-head/squid_traffic.xml179
-rw-r--r--config/squid-head/squid_upstream.xml133
-rw-r--r--config/squid-head/squid_users.xml120
-rw-r--r--config/squid/proxy_monitor.sh72
-rw-r--r--config/squid/squid.inc1263
-rw-r--r--config/squid/squid.xml333
-rw-r--r--config/squid/squid_auth.inc446
-rw-r--r--config/squid/squid_auth.xml225
-rw-r--r--config/squid/squid_cache.xml223
-rw-r--r--config/squid/squid_extauth.xml106
-rw-r--r--config/squid/squid_nac.xml143
-rw-r--r--config/squid/squid_ng.inc1067
-rw-r--r--config/squid/squid_ng.xml267
-rw-r--r--config/squid/squid_traffic.xml177
-rw-r--r--config/squid/squid_upstream.xml133
-rw-r--r--config/squid/squid_users.xml120
-rw-r--r--config/squid3/proxy_monitor.sh72
-rw-r--r--config/squid3/squid.inc1264
-rw-r--r--config/squid3/squid.xml333
-rw-r--r--config/squid3/squid_auth.inc446
-rw-r--r--config/squid3/squid_auth.xml225
-rw-r--r--config/squid3/squid_cache.xml223
-rw-r--r--config/squid3/squid_extauth.xml106
-rw-r--r--config/squid3/squid_nac.xml143
-rw-r--r--config/squid3/squid_ng.inc1067
-rw-r--r--config/squid3/squid_ng.xml267
-rw-r--r--config/squid3/squid_traffic.xml177
-rw-r--r--config/squid3/squid_upstream.xml133
-rw-r--r--config/squid3/squid_users.xml120
-rw-r--r--config/squidGuard.xml125
-rw-r--r--config/squidGuard/.project11
-rw-r--r--config/squidGuard/sgerror.php284
-rw-r--r--config/squidGuard/squidguard.inc1394
-rw-r--r--config/squidGuard/squidguard.xml164
-rw-r--r--config/squidGuard/squidguard_acl.xml278
-rw-r--r--config/squidGuard/squidguard_configurator.inc2106
-rw-r--r--config/squidGuard/squidguard_default.xml142
-rw-r--r--config/squidGuard/squidguard_dest.xml190
-rw-r--r--config/squidGuard/squidguard_log.xml76
-rw-r--r--config/squidGuard/squidguard_rewr.xml142
-rw-r--r--config/squidGuard/squidguard_time.xml143
-rw-r--r--config/sshterm/diag_shell_head.php82
-rw-r--r--config/sshterm/diag_shell_releng.php75
-rw-r--r--config/sshterm/sshterm.xml101
-rw-r--r--config/stunnel.xml168
-rw-r--r--config/test_package/test_package.php14
-rw-r--r--config/test_package/test_package.xml213
-rw-r--r--config/tftp/tftp.inc279
-rw-r--r--config/tftp/tftp.xml91
-rw-r--r--config/tftp/tftp_files.tmp248
-rw-r--r--config/tinydns/new_zone_wizard.xml226
-rw-r--r--config/tinydns/tinydns.inc964
-rw-r--r--config/tinydns/tinydns.xml309
-rw-r--r--config/tinydns/tinydns_dhcp_filter.php129
-rw-r--r--config/tinydns/tinydns_domains.xml234
-rw-r--r--config/tinydns/tinydns_down.php42
-rw-r--r--config/tinydns/tinydns_filter.php38
-rw-r--r--config/tinydns/tinydns_parse_logs.php96
-rw-r--r--config/tinydns/tinydns_status.php188
-rw-r--r--config/tinydns/tinydns_sync.xml146
-rw-r--r--config/tinydns/tinydns_up.php42
-rw-r--r--config/tinydns/tinydns_view_logs.php122
-rw-r--r--config/tinydns/tinydns_xmlrpc_sync.php59
-rw-r--r--config/upclient.xml126
-rw-r--r--config/viralator.inc86
-rw-r--r--config/viralator.xml61
-rw-r--r--config/widentd.xml122
-rw-r--r--config/xsl/package.xsl316
-rw-r--r--config/zabbix-agent.xml164
577 files changed, 134025 insertions, 0 deletions
diff --git a/config/arping/arping.inc b/config/arping/arping.inc
new file mode 100644
index 00000000..193d031d
--- /dev/null
+++ b/config/arping/arping.inc
@@ -0,0 +1,54 @@
+<?php
+/* $Id$ */
+/*
+ arping.inc
+ Copyright (C) 2006 Scott Ullrich
+ part of pfSense
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+function arping_deinstall() {
+}
+
+function arping_package_reinstall() {
+}
+
+function arping_package_php_command() {
+ $pgtitle = "Services: Arping";
+ include("head.inc");
+
+ echo "<body link=\"#0000CC\" vlink=\"#0000CC\" alink=\"#0000CC\">";
+ include("fbegin.inc");
+ echo "<p class=\"pgtitle\">{$pgtitle}</p>";
+
+ echo "<pre>";
+ system("arping -c3 " . $_POST['hostip']);
+ echo "</pre>";
+ exit;
+}
+
+function arping_package_resync() {
+}
+
+?> \ No newline at end of file
diff --git a/config/arping/arping.xml b/config/arping/arping.xml
new file mode 100644
index 00000000..e8619496
--- /dev/null
+++ b/config/arping/arping.xml
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>arping</name>
+ <version>2.6.0.2</version>
+ <title>Services: arping</title>
+ <include_file>/usr/local/pkg/arping.inc</include_file>
+ <menu>
+ <name>Arping</name>
+ <tooltiptext>Host to arp ping</tooltiptext>
+ <section>Services</section>
+ <url>/pkg_edit.php?xml=arping.xml&amp;id=0</url>
+ </menu>
+ <service>
+ <name>arping</name>
+ <executable>arping</executable>
+ </service>
+ <tabs>
+ <tab>
+ <text>arping Settings</text>
+ <url>/pkg_edit.php?xml=arping.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ </tabs>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>077</chmod>
+ <item>http://www.pfsense.com/packages/config/arping/arping.inc</item>
+ </additional_files_needed>
+ <fields>
+ <field>
+ <fielddescr>Host IP or Mac</fielddescr>
+ <fieldname>hostip</fieldname>
+ <description>Select all WAN type interfaces</description>
+ <type>input</type>
+ </field>
+ </fields>
+ <custom_add_php_command>
+ arping_package_php_command();
+ </custom_add_php_command>
+</packagegui>
diff --git a/config/arpwatch.xml b/config/arpwatch.xml
new file mode 100644
index 00000000..66c8cc5a
--- /dev/null
+++ b/config/arpwatch.xml
@@ -0,0 +1,116 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>arpwatch</name>
+ <version>2.1.a13</version>
+ <title>arpwatch: Settings</title>
+ <aftersaveredirect>pkg_edit.php?xml=arpwatch.xml&amp;id=0</aftersaveredirect>
+ <menu>
+ <name>arpwatch</name>
+ <tooltiptext>Modify arpwatch settings.</tooltiptext>
+ <section>Services</section>
+ <configfile>arpwatch.xml</configfile>
+ <url>/pkg_edit.php?xml=arpwatch.xml&amp;id=0</url>
+ </menu>
+ <service>
+ <name>arpwatch</name>
+ <rcfile>arpwatch.sh</rcfile>
+ <executable>arpwatch</executable>
+ </service>
+ <tabs>
+ <tab>
+ <text>Settings</text>
+ <url>/pkg_edit.php?xml=arpwatch.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Reports</text>
+ <url>/arpwatch_reports.php</url>
+ </tab>
+ </tabs>
+ <configpath>installedpackages->package->$packagename->configuration->settings</configpath>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>a+rx</chmod>
+ <item>http://www.pfsense.com/packages/config/arpwatch_reports.php</item>
+ </additional_files_needed>
+ <fields>
+ <field>
+ <fielddescr>Listening Interface</fielddescr>
+ <fieldname>interface</fieldname>
+ <description>Enter the desired listening interface here.</description>
+ <type>interfaces_selection</type>
+ </field>
+ </fields>
+ <custom_php_global_functions>
+ function sync_package_arpwatch() {
+ global $config;
+ conf_mount_rw();
+ config_lock();
+ $int = $config['installedpackages']['arpwatch']['config'][0]['interface'];
+ $int = convert_friendly_interface_to_real_interface_name($int);
+ $start = "/usr/local/sbin/arpwatch -d -i {$int} > /var/log/arpwatch.reports 2>&amp;1 &amp;";
+ $stop = "/usr/bin/killall arpwatch";
+ write_rcfile(array(
+ "file" => "arpwatch.sh",
+ "start" => $start,
+ "stop" => $stop
+ )
+ );
+ restart_service("arpwatch");
+ conf_mount_ro();
+ config_unlock();
+ }
+ </custom_php_global_functions>
+ <custom_add_php_command>
+ sync_package_arpwatch();
+ </custom_add_php_command>
+ <custom_php_install_command>
+ unlink_if_exists("/usr/local/etc/rc.d/arpwatch.sh");
+ </custom_php_install_command>
+</packagegui>
+
diff --git a/config/arpwatch_reports.php b/config/arpwatch_reports.php
new file mode 100755
index 00000000..1bdb5233
--- /dev/null
+++ b/config/arpwatch_reports.php
@@ -0,0 +1,127 @@
+#!/usr/local/bin/php
+<?php
+/*
+ $Id$
+
+ diag_logs.php
+ Copyright (C) 2005 Colin Smith
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require("guiconfig.inc");
+
+$logfile = "/usr/local/arpwatch/arp.dat";
+
+if ($_POST['clear']) {
+ stop_service("arpwatch");
+ unlink_if_exists($logfile);
+ touch($logfile);
+ start_service("arpwatch");
+}
+
+if(file_exists($logfile)) {
+ $rawrep = file($logfile);
+ foreach($rawrep as $line) {
+ $todo = preg_split('/\s/', $line);
+ $rawmac = explode(":", trim($todo[0]));
+ foreach($rawmac as $set) $mac[] = str_pad($set, 2, "0", STR_PAD_LEFT);
+ $newmac = implode(":", $mac);
+ $report[$todo[1]][] = array(
+ "mac" => $newmac,
+ "timestamp" => trim($todo[2]),
+ "hostname" => trim($todo[3]) ? trim($todo[3]) : "Unknown"
+ );
+ unset($mac);
+ }
+}
+$pgtitle = "arpwatch: Reports";
+include("head.inc");
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<?php include("fbegin.inc"); ?>
+<p class="pgtitle"><?=$pgtitle?></p>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td>
+<?php
+ $tab_array = array();
+ $tab_array[] = array("Settings", false, "pkg_edit.php?xml=arpwatch.xml&id=0");
+ $tab_array[] = array("Reports", true, "arpwatch_reports.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <table class="tabcont" width="100%" border="0" cellspacing="0" cellpadding="0">
+ <tr>
+ <td colspan="4" class="listtopic">arp.dat entries</td>
+ </tr>
+ <tr>
+ <td width="15%" class="listhdrr">IP</td>
+ <td width="25%" class="listhdrr">Timestamp</td>
+ <td width="15%" class="listhdrr">MAC</td>
+ <td width="45%" class="listhdrr">Hostname</td>
+ </tr>
+ <?php
+ if($report)
+ foreach($report as $ip => $rawentries) {
+ $printip = true;
+ $entries = $rawentries;
+ sort($entries);
+ foreach($entries as $entry) {
+ echo '<tr>';
+ if($printip) {
+ echo '<td class="listlr">' . $ip . '</td>';
+ $stampclass = "listr";
+ $printip = false;
+ } else {
+ $stampclass = "listlr";
+ echo '<td></td>';
+ }
+ echo '<td class="' . $stampclass . '">' .
+ date("D M j G:i:s", $entry['timestamp']) .
+ '</td>';
+ echo '<td class="listr">' . $entry['mac'] . '</td>';
+ echo '<td class="listr">' . $entry['hostname'] . '</td>';
+ echo '</tr>';
+ }
+ }
+ ?>
+ <tr>
+ <td>
+ <br>
+ <form action="arpwatch_reports.php" method="post">
+ <input name="clear" type="submit" class="formbtn" value="Clear log">
+ </form>
+ </td>
+ </tr>
+ </table>
+ </div>
+ </td>
+ </tr>
+</table>
diff --git a/config/assp.xml b/config/assp.xml
new file mode 100644
index 00000000..94f35b2e
--- /dev/null
+++ b/config/assp.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>assp</name>
+ <version>0.1.0</version>
+ <title>Services: ASSP</title>
+ <!-- Menu is where this packages menu will appear -->
+ <menu>
+ <name>ASSP</name>
+ <tooltiptext>Access ASSP</tooltiptext>
+ <section>Services</section>
+ <url>http://$myurl:55555</url>
+ </menu>
+ <service>
+ <name>assp</name>
+ <rcfile>assp.sh</rcfile>
+ <executable>perl</executable>
+ </service>
+ <additional_files_needed>
+ <item>http://www.pfsense.com/packages/All/assp-1.0.tgz</item>
+ </additional_files_needed>
+ <custom_php_install_command>
+ $start = "/usr/bin/perl /usr/local/assp/assp.pl &amp;\necho $! > /var/run/assp.pid";
+ write_rcfile(array(
+ "file" => 'assp.sh',
+ "start" => $start,
+ "stop" => '/usr/bin/killall perl'
+ )
+ );
+ start_service("assp");
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ rmdir_recursive("/usr/local/assp");
+ </custom_php_deinstall_command>
+</packagegui>
diff --git a/config/authng/bin/patch b/config/authng/bin/patch
new file mode 100644
index 00000000..f807fa85
--- /dev/null
+++ b/config/authng/bin/patch
Binary files differ
diff --git a/config/authng/diff/authng-fbegin.inc.diff b/config/authng/diff/authng-fbegin.inc.diff
new file mode 100644
index 00000000..8a38c1b4
--- /dev/null
+++ b/config/authng/diff/authng-fbegin.inc.diff
@@ -0,0 +1,15 @@
+Index: usr/local/www/fbegin.inc
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/fbegin.inc,v
+retrieving revision 1.104.2.37.2.7
+diff -u -r1.104.2.37.2.7 fbegin.inc
+--- usr/local/www/fbegin.inc 31 May 2007 03:21:59 -0000 1.104.2.37.2.7
++++ usr/local/www/fbegin.inc 8 Sep 2007 21:16:29 -0000
+@@ -127,6 +127,7 @@
+ <?php endif; ?>
+ <li><a href="/wizard.php?xml=setup_wizard.xml" class="navlnk">Setup wizard</a></li>
+ <li><a href="/system_routes.php" class="navlnk">Static routes</a></li>
++ <?php echo return_ext_menu("System"); ?>
+ </ul>
+ </li>
+ <li class="drop">
diff --git a/config/authng/diff/authng-globals.inc.diff b/config/authng/diff/authng-globals.inc.diff
new file mode 100644
index 00000000..6dea7e6f
--- /dev/null
+++ b/config/authng/diff/authng-globals.inc.diff
@@ -0,0 +1,16 @@
+Index: globals.inc
+===================================================================
+RCS file: /cvsroot/pfSense/etc/inc/globals.inc,v
+retrieving revision 1.40.2.16
+diff -u -r1.40.2.16 globals.inc
+--- globals.inc 27 Feb 2007 20:45:31 -0000 1.40.2.16
++++ globals.inc 9 Sep 2007 20:54:52 -0000
+@@ -47,6 +47,8 @@
+ "cf_conf_path" => "/cf/conf",
+ "www_path" => "/usr/local/www",
+ "xml_rootobj" => "pfsense",
++ "admin_group" => "admins",
++ "product_name" => "pfSense",
+ "pppoe_interface" => "ng0",
+ "n_pptp_units" => 16, /* this value can be overriden in pptp->n_pptp_units */
+ "pptp_subnet" => 28, /* this value can be overriden in pptp->pptp_subnet */
diff --git a/config/authng/diff/authng-guiconfig.inc.diff b/config/authng/diff/authng-guiconfig.inc.diff
new file mode 100644
index 00000000..e65ae8b8
--- /dev/null
+++ b/config/authng/diff/authng-guiconfig.inc.diff
@@ -0,0 +1,27 @@
+Index: guiconfig.inc
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/guiconfig.inc,v
+retrieving revision 1.90.2.31.2.3
+diff -u -r1.90.2.31.2.3 guiconfig.inc
+--- guiconfig.inc 10 May 2007 20:49:41 -0000 1.90.2.31.2.3
++++ guiconfig.inc 9 Sep 2007 19:43:31 -0000
+@@ -41,7 +41,7 @@
+
+ /* Include authentication routines */
+ /* THIS MUST BE ABOVE ALL OTHER CODE */
+-require_once("auth.inc");
++require_once("authng_authgui.inc");
+
+ /* parse the configuration and include all configuration functions */
+ require_once("config.inc");
+@@ -574,10 +574,6 @@
+
+ usort($config['shaper']['rule'], "rqpcmp");
+ }
+-function gentitle($pgname) {
+- global $config;
+- return $config['system']['hostname'] . "." . $config['system']['domain'] . " - " . $pgname;
+-}
+
+ /* update the changedesc and changecount(er) variables */
+ function update_changedesc($update) {
diff --git a/config/authng/diff/authng-pfSenseHead.diff b/config/authng/diff/authng-pfSenseHead.diff
new file mode 100644
index 00000000..2a531271
--- /dev/null
+++ b/config/authng/diff/authng-pfSenseHead.diff
@@ -0,0 +1,2128 @@
+Index: usr/local/www/carp_status.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/carp_status.php,v
+retrieving revision 1.27.2.3
+diff -u -r1.27.2.3 carp_status.php
+--- usr/local/www/carp_status.php 3 Apr 2006 21:05:11 -0000 1.27.2.3
++++ usr/local/www/carp_status.php 8 Sep 2007 18:31:52 -0000
+@@ -56,6 +56,7 @@
+
+ $pgtitle = "CARP: Status";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/diag_arp.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/diag_arp.php,v
+retrieving revision 1.3.2.4
+diff -u -r1.3.2.4 diag_arp.php
+--- usr/local/www/diag_arp.php 19 Mar 2006 22:23:31 -0000 1.3.2.4
++++ usr/local/www/diag_arp.php 8 Sep 2007 18:32:10 -0000
+@@ -31,6 +31,7 @@
+ require("guiconfig.inc");
+ $pgtitle = "Diagnostics: ARP Table";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+ ?>
+ <body link="#000000" vlink="#000000" alink="#000000">
+ <script src="/javascript/sorttable.js"></script>
+Index: usr/local/www/diag_backup.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/diag_backup.php,v
+retrieving revision 1.70.2.18.2.2
+diff -u -r1.70.2.18.2.2 diag_backup.php
+--- usr/local/www/diag_backup.php 3 May 2007 22:16:01 -0000 1.70.2.18.2.2
++++ usr/local/www/diag_backup.php 8 Sep 2007 18:32:26 -0000
+@@ -225,6 +225,7 @@
+
+ $pgtitle = "Diagnostics: Backup/restore";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/diag_confbak.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/diag_confbak.php,v
+retrieving revision 1.20.2.2
+diff -u -r1.20.2.2 diag_confbak.php
+--- usr/local/www/diag_confbak.php 2 Jan 2006 23:46:23 -0000 1.20.2.2
++++ usr/local/www/diag_confbak.php 8 Sep 2007 18:32:54 -0000
+@@ -50,6 +50,7 @@
+
+ $pgtitle = "Diagnostics: Configuration History";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/diag_defaults.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/diag_defaults.php,v
+retrieving revision 1.6.4.3
+diff -u -r1.6.4.3 diag_defaults.php
+--- usr/local/www/diag_defaults.php 28 Apr 2006 02:27:19 -0000 1.6.4.3
++++ usr/local/www/diag_defaults.php 8 Sep 2007 18:32:58 -0000
+@@ -46,6 +46,7 @@
+
+ $pgtitle = "Diagnostics: Factory defaults";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/diag_dhcp_leases.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/diag_dhcp_leases.php,v
+retrieving revision 1.11.2.17
+diff -u -r1.11.2.17 diag_dhcp_leases.php
+--- usr/local/www/diag_dhcp_leases.php 2 Mar 2007 15:31:08 -0000 1.11.2.17
++++ usr/local/www/diag_dhcp_leases.php 8 Sep 2007 18:33:04 -0000
+@@ -35,6 +35,7 @@
+
+ $pgtitle = "Diagnostics: DHCP leases";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/diag_dump_states.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/diag_dump_states.php,v
+retrieving revision 1.10.2.14.2.1
+diff -u -r1.10.2.14.2.1 diag_dump_states.php
+--- usr/local/www/diag_dump_states.php 11 May 2007 17:21:06 -0000 1.10.2.14.2.1
++++ usr/local/www/diag_dump_states.php 8 Sep 2007 18:33:11 -0000
+@@ -30,6 +30,7 @@
+
+ $pgtitle = "Diagnostics: Show States";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ /* handle AJAX operations */
+ if($_GET['action']) {
+Index: usr/local/www/diag_ipsec_sad.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/diag_ipsec_sad.php,v
+retrieving revision 1.12.2.3
+diff -u -r1.12.2.3 diag_ipsec_sad.php
+--- usr/local/www/diag_ipsec_sad.php 3 Apr 2006 21:05:11 -0000 1.12.2.3
++++ usr/local/www/diag_ipsec_sad.php 8 Sep 2007 18:33:18 -0000
+@@ -35,6 +35,7 @@
+
+ $pgtitle = "Diagnostics: IPSec: SA";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/diag_ipsec_spd.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/diag_ipsec_spd.php,v
+retrieving revision 1.12.2.2
+diff -u -r1.12.2.2 diag_ipsec_spd.php
+--- usr/local/www/diag_ipsec_spd.php 2 Jan 2006 23:46:23 -0000 1.12.2.2
++++ usr/local/www/diag_ipsec_spd.php 8 Sep 2007 18:33:22 -0000
+@@ -35,6 +35,7 @@
+
+ $pgtitle = "Diagnostics: IPSec: SPD";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/diag_logs.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/diag_logs.php,v
+retrieving revision 1.32.2.11
+diff -u -r1.32.2.11 diag_logs.php
+--- usr/local/www/diag_logs.php 9 Oct 2006 00:19:17 -0000 1.32.2.11
++++ usr/local/www/diag_logs.php 8 Sep 2007 18:33:30 -0000
+@@ -56,6 +56,7 @@
+
+ $pgtitle = "Diagnostics: System logs: System";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/diag_logs_auth.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/diag_logs_auth.php,v
+retrieving revision 1.19.2.4
+diff -u -r1.19.2.4 diag_logs_auth.php
+--- usr/local/www/diag_logs_auth.php 5 Oct 2006 21:51:02 -0000 1.19.2.4
++++ usr/local/www/diag_logs_auth.php 8 Sep 2007 18:33:38 -0000
+@@ -43,6 +43,7 @@
+
+ $pgtitle = "Diagnostics: System logs: Portal Auth";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/diag_logs_dhcp.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/diag_logs_dhcp.php,v
+retrieving revision 1.19.2.4
+diff -u -r1.19.2.4 diag_logs_dhcp.php
+--- usr/local/www/diag_logs_dhcp.php 5 Oct 2006 21:51:02 -0000 1.19.2.4
++++ usr/local/www/diag_logs_dhcp.php 8 Sep 2007 18:33:43 -0000
+@@ -45,6 +45,7 @@
+
+ $pgtitle = "Diagnostics: System logs: DHCP";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/diag_logs_filter.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/diag_logs_filter.php,v
+retrieving revision 1.46.2.33.2.1
+diff -u -r1.46.2.33.2.1 diag_logs_filter.php
+--- usr/local/www/diag_logs_filter.php 5 Jul 2007 22:31:03 -0000 1.46.2.33.2.1
++++ usr/local/www/diag_logs_filter.php 8 Sep 2007 18:33:53 -0000
+@@ -173,6 +173,7 @@
+
+ $pgtitle = "Diagnostics: System logs: Firewall";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+ <body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+Index: usr/local/www/diag_logs_filter_dynamic.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/Attic/diag_logs_filter_dynamic.php,v
+retrieving revision 1.13.2.16.2.2
+diff -u -r1.13.2.16.2.2 diag_logs_filter_dynamic.php
+--- usr/local/www/diag_logs_filter_dynamic.php 4 Jul 2007 20:14:26 -0000 1.13.2.16.2.2
++++ usr/local/www/diag_logs_filter_dynamic.php 8 Sep 2007 18:34:01 -0000
+@@ -157,6 +157,7 @@
+
+ $pgtitle = "Diagnostics: System logs: Firewall";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+ <body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+Index: usr/local/www/diag_logs_ipsec.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/diag_logs_ipsec.php,v
+retrieving revision 1.30.2.5
+diff -u -r1.30.2.5 diag_logs_ipsec.php
+--- usr/local/www/diag_logs_ipsec.php 5 Oct 2006 21:51:02 -0000 1.30.2.5
++++ usr/local/www/diag_logs_ipsec.php 8 Sep 2007 18:35:14 -0000
+@@ -47,6 +47,7 @@
+
+ $pgtitle = "Diagnostics: System logs: IPSEC VPN";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+ <body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+Index: usr/local/www/diag_logs_ntpd.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/diag_logs_ntpd.php,v
+retrieving revision 1.1.2.4
+diff -u -r1.1.2.4 diag_logs_ntpd.php
+--- usr/local/www/diag_logs_ntpd.php 22 Oct 2006 05:30:56 -0000 1.1.2.4
++++ usr/local/www/diag_logs_ntpd.php 8 Sep 2007 18:35:19 -0000
+@@ -45,6 +45,7 @@
+
+ $pgtitle = "Diagnostics: System logs: OpenNTPD";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/diag_logs_openvpn.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/diag_logs_openvpn.php,v
+retrieving revision 1.2.2.8
+diff -u -r1.2.2.8 diag_logs_openvpn.php
+--- usr/local/www/diag_logs_openvpn.php 5 Oct 2006 21:51:02 -0000 1.2.2.8
++++ usr/local/www/diag_logs_openvpn.php 8 Sep 2007 18:35:24 -0000
+@@ -48,6 +48,7 @@
+ }
+
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+ <body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+Index: usr/local/www/diag_logs_settings.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/diag_logs_settings.php,v
+retrieving revision 1.18.2.8
+diff -u -r1.18.2.8 diag_logs_settings.php
+--- usr/local/www/diag_logs_settings.php 5 Oct 2006 21:51:02 -0000 1.18.2.8
++++ usr/local/www/diag_logs_settings.php 8 Sep 2007 18:35:31 -0000
+@@ -94,6 +94,7 @@
+
+ $pgtitle = "Diagnostics: System logs: Settings";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/diag_logs_slbd.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/diag_logs_slbd.php,v
+retrieving revision 1.3.2.5
+diff -u -r1.3.2.5 diag_logs_slbd.php
+--- usr/local/www/diag_logs_slbd.php 5 Oct 2006 21:51:02 -0000 1.3.2.5
++++ usr/local/www/diag_logs_slbd.php 8 Sep 2007 18:35:36 -0000
+@@ -46,6 +46,7 @@
+
+ $pgtitle = "Diagnostics: System logs: Load Balancer";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/diag_logs_vpn.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/diag_logs_vpn.php,v
+retrieving revision 1.26.2.8
+diff -u -r1.26.2.8 diag_logs_vpn.php
+--- usr/local/www/diag_logs_vpn.php 22 Oct 2006 05:30:56 -0000 1.26.2.8
++++ usr/local/www/diag_logs_vpn.php 8 Sep 2007 18:35:43 -0000
+@@ -70,6 +70,7 @@
+ }
+
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+ <body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+Index: usr/local/www/diag_packet_capture.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/diag_packet_capture.php,v
+retrieving revision 1.2.2.4.2.5
+diff -u -r1.2.2.4.2.5 diag_packet_capture.php
+--- usr/local/www/diag_packet_capture.php 1 Jul 2007 05:09:05 -0000 1.2.2.4.2.5
++++ usr/local/www/diag_packet_capture.php 8 Sep 2007 18:35:53 -0000
+@@ -106,7 +106,9 @@
+
+ }
+ $pgtitle = "Diagnostics: Packet Capture";
+-include("head.inc"); ?>
++include("head.inc");
++echo $pfSenseHead->getHTML();
++?>
+ <body link="#000000" vlink="#0000CC" alink="#0000CC">
+ <? include("fbegin.inc"); ?>
+
+Index: usr/local/www/diag_ping.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/Attic/diag_ping.php,v
+retrieving revision 1.8.2.6
+diff -u -r1.8.2.6 diag_ping.php
+--- usr/local/www/diag_ping.php 25 Apr 2006 22:06:42 -0000 1.8.2.6
++++ usr/local/www/diag_ping.php 8 Sep 2007 18:36:01 -0000
+@@ -86,7 +86,9 @@
+ }
+
+ $pgtitle = "Diagnostics: Ping";
+-include("head.inc"); ?>
++include("head.inc");
++echo $pfSenseHead->getHTML();
++?>
+ <body link="#000000" vlink="#000000" alink="#000000">
+ <? include("fbegin.inc"); ?>
+ <p class="pgtitle"><?=$pgtitle?></p>
+Index: usr/local/www/diag_pkglogs.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/diag_pkglogs.php,v
+retrieving revision 1.20.4.1
+diff -u -r1.20.4.1 diag_pkglogs.php
+--- usr/local/www/diag_pkglogs.php 2 Jan 2006 23:46:23 -0000 1.20.4.1
++++ usr/local/www/diag_pkglogs.php 8 Sep 2007 18:36:08 -0000
+@@ -68,6 +68,7 @@
+
+ $pgtitle = "Diagnostics: Package logs";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+ <body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+Index: usr/local/www/diag_resetstate.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/diag_resetstate.php,v
+retrieving revision 1.6.4.2
+diff -u -r1.6.4.2 diag_resetstate.php
+--- usr/local/www/diag_resetstate.php 2 Jan 2006 23:46:23 -0000 1.6.4.2
++++ usr/local/www/diag_resetstate.php 8 Sep 2007 18:36:12 -0000
+@@ -45,6 +45,7 @@
+
+ $pgtitle = "Diagnostics: Reset state";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+ <body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+Index: usr/local/www/diag_routes.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/diag_routes.php,v
+retrieving revision 1.2.2.4
+diff -u -r1.2.2.4 diag_routes.php
+--- usr/local/www/diag_routes.php 11 Mar 2006 08:25:22 -0000 1.2.2.4
++++ usr/local/www/diag_routes.php 8 Sep 2007 18:36:16 -0000
+@@ -34,6 +34,7 @@
+ $pgtitle = 'Diagnostics: Routing tables';
+
+ include('head.inc');
++echo $pfSenseHead->getHTML();
+
+ ?>
+ <body link="#000000" vlink="#000000" alink="#000000">
+Index: usr/local/www/diag_traceroute.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/Attic/diag_traceroute.php,v
+retrieving revision 1.4.2.7
+diff -u -r1.4.2.7 diag_traceroute.php
+--- usr/local/www/diag_traceroute.php 25 Apr 2006 22:06:42 -0000 1.4.2.7
++++ usr/local/www/diag_traceroute.php 8 Sep 2007 18:36:24 -0000
+@@ -32,6 +32,7 @@
+ require("guiconfig.inc");
+ $pgtitle = "Diagnostics: Traceroute";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+ ?>
+ <body link="#000000" vlink="#000000" alink="#000000">
+ <? include("fbegin.inc"); ?>
+Index: usr/local/www/edit.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/edit.php,v
+retrieving revision 1.35.2.5
+diff -u -r1.35.2.5 edit.php
+--- usr/local/www/edit.php 26 Sep 2006 22:49:53 -0000 1.35.2.5
++++ usr/local/www/edit.php 8 Sep 2007 19:09:08 -0000
+@@ -133,6 +133,7 @@
+ $pgtitle = "Diagnostics: Edit File";
+
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/exec.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/exec.php,v
+retrieving revision 1.10.4.9
+diff -u -r1.10.4.9 exec.php
+--- usr/local/www/exec.php 20 Mar 2007 18:38:33 -0000 1.10.4.9
++++ usr/local/www/exec.php 8 Sep 2007 19:09:08 -0000
+@@ -52,6 +52,7 @@
+
+ $pgtitle = "Diagnostics: Execute command";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+ ?>
+
+ <script language="javascript">
+Index: usr/local/www/firewall_aliases.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/firewall_aliases.php,v
+retrieving revision 1.21.2.10.2.1
+diff -u -r1.21.2.10.2.1 firewall_aliases.php
+--- usr/local/www/firewall_aliases.php 8 May 2007 22:06:49 -0000 1.21.2.10.2.1
++++ usr/local/www/firewall_aliases.php 8 Sep 2007 18:36:53 -0000
+@@ -144,7 +144,7 @@
+
+ $pgtitle = "Firewall: Aliases";
+ include("head.inc");
+-
++echo $pfSenseHead->getHTML();
+ ?>
+
+ <body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+Index: usr/local/www/firewall_aliases_edit.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/firewall_aliases_edit.php,v
+retrieving revision 1.25.2.12.2.1
+diff -u -r1.25.2.12.2.1 firewall_aliases_edit.php
+--- usr/local/www/firewall_aliases_edit.php 2 May 2007 12:43:56 -0000 1.25.2.12.2.1
++++ usr/local/www/firewall_aliases_edit.php 8 Sep 2007 18:40:54 -0000
+@@ -284,6 +284,7 @@
+ }
+
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ $jscriptstr = <<<EOD
+
+@@ -400,12 +401,13 @@
+
+ EOD;
+
++$pfSenseHead->addScript($jscriptstr);
++echo $pfSenseHead->getHTML();
+ ?>
+
+ <body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+ <?php
+ include("fbegin.inc");
+- echo $jscriptstr;
+ ?>
+
+ <script type="text/javascript" src="row_helper.js">
+Index: usr/local/www/firewall_nat.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/firewall_nat.php,v
+retrieving revision 1.31.2.15.2.1
+diff -u -r1.31.2.15.2.1 firewall_nat.php
+--- usr/local/www/firewall_nat.php 8 May 2007 22:06:49 -0000 1.31.2.15.2.1
++++ usr/local/www/firewall_nat.php 8 Sep 2007 18:41:11 -0000
+@@ -134,6 +134,7 @@
+
+ $pgtitle = "Firewall: NAT: Port Forward";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+ <body link="#000000" vlink="#000000" alink="#000000">
+Index: usr/local/www/firewall_nat_1to1.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/firewall_nat_1to1.php,v
+retrieving revision 1.20.2.2.2.1
+diff -u -r1.20.2.2.2.1 firewall_nat_1to1.php
+--- usr/local/www/firewall_nat_1to1.php 8 May 2007 22:06:49 -0000 1.20.2.2.2.1
++++ usr/local/www/firewall_nat_1to1.php 8 Sep 2007 18:41:22 -0000
+@@ -71,6 +71,7 @@
+
+ $pgtitle = "Firewall: NAT: 1:1";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+ <body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+Index: usr/local/www/firewall_nat_1to1_edit.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/firewall_nat_1to1_edit.php,v
+retrieving revision 1.9.2.2
+diff -u -r1.9.2.2 firewall_nat_1to1_edit.php
+--- usr/local/www/firewall_nat_1to1_edit.php 2 Jan 2006 23:46:23 -0000 1.9.2.2
++++ usr/local/www/firewall_nat_1to1_edit.php 8 Sep 2007 19:09:08 -0000
+@@ -130,6 +130,7 @@
+
+ $pgtitle = "Firewall: NAT: 1:1: Edit";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/firewall_nat_edit.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/firewall_nat_edit.php,v
+retrieving revision 1.30.2.19
+diff -u -r1.30.2.19 firewall_nat_edit.php
+--- usr/local/www/firewall_nat_edit.php 27 Dec 2006 07:49:18 -0000 1.30.2.19
++++ usr/local/www/firewall_nat_edit.php 8 Sep 2007 18:41:35 -0000
+@@ -257,6 +257,7 @@
+
+ $pgtitle = "Firewall: NAT: Port Forward: Edit";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/firewall_nat_out.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/firewall_nat_out.php,v
+retrieving revision 1.47.2.16.2.3
+diff -u -r1.47.2.16.2.3 firewall_nat_out.php
+--- usr/local/www/firewall_nat_out.php 9 May 2007 15:42:19 -0000 1.47.2.16.2.3
++++ usr/local/www/firewall_nat_out.php 8 Sep 2007 18:41:42 -0000
+@@ -177,6 +177,7 @@
+
+ $pgtitle = "Firewall: NAT: Outbound";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+ <body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+Index: usr/local/www/firewall_nat_out_edit.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/firewall_nat_out_edit.php,v
+retrieving revision 1.26.2.19
+diff -u -r1.26.2.19 firewall_nat_out_edit.php
+--- usr/local/www/firewall_nat_out_edit.php 6 Sep 2006 17:49:16 -0000 1.26.2.19
++++ usr/local/www/firewall_nat_out_edit.php 8 Sep 2007 18:44:06 -0000
+@@ -238,6 +238,8 @@
+ $pgtitle = "Firewall: NAT: Outbound: Edit";
+ $closehead = false;
+ include("head.inc");
++$pfSenseHead->setCloseHead(false);
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/firewall_nat_server.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/firewall_nat_server.php,v
+retrieving revision 1.17.4.2
+diff -u -r1.17.4.2 firewall_nat_server.php
+--- usr/local/www/firewall_nat_server.php 2 Jan 2006 23:46:24 -0000 1.17.4.2
++++ usr/local/www/firewall_nat_server.php 8 Sep 2007 18:44:22 -0000
+@@ -83,6 +83,7 @@
+
+ $pgtitle = "Firewall: NAT: NAT Addresses";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+ <body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+Index: usr/local/www/firewall_nat_server_edit.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/firewall_nat_server_edit.php,v
+retrieving revision 1.8.4.2
+diff -u -r1.8.4.2 firewall_nat_server_edit.php
+--- usr/local/www/firewall_nat_server_edit.php 2 Jan 2006 23:46:24 -0000 1.8.4.2
++++ usr/local/www/firewall_nat_server_edit.php 8 Sep 2007 18:44:27 -0000
+@@ -113,6 +113,7 @@
+
+ $pgtitle = "Firewall: NAT: NAT Addresses: Edit";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/firewall_rules.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/firewall_rules.php,v
+retrieving revision 1.42.2.17.2.6
+diff -u -r1.42.2.17.2.6 firewall_rules.php
+--- usr/local/www/firewall_rules.php 5 Jul 2007 22:35:33 -0000 1.42.2.17.2.6
++++ usr/local/www/firewall_rules.php 8 Sep 2007 18:45:02 -0000
+@@ -171,6 +171,8 @@
+
+ $pgtitle = "Firewall: Rules";
+ include("head.inc");
++$pfSenseHead->setCloseHead(false);
++echo $pfSenseHead->getHTML();
+
+ echo "<script type=\"text/javascript\" language=\"javascript\" src=\"/javascript/domTT/domLib.js\"></script>";
+ echo "<script type=\"text/javascript\" language=\"javascript\" src=\"/javascript/domTT/domTT.js\"></script>";
+Index: usr/local/www/firewall_rules_edit.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/firewall_rules_edit.php,v
+retrieving revision 1.86.2.34.2.3
+diff -u -r1.86.2.34.2.3 firewall_rules_edit.php
+--- usr/local/www/firewall_rules_edit.php 1 Jun 2007 17:12:12 -0000 1.86.2.34.2.3
++++ usr/local/www/firewall_rules_edit.php 8 Sep 2007 18:45:23 -0000
+@@ -349,10 +349,9 @@
+
+ $page_filename = "firewall_rules_edit.php";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+-
+-</head>
+
+ <body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+ <?php include("fbegin.inc"); ?>
+Index: usr/local/www/firewall_schedule.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/firewall_schedule.php,v
+retrieving revision 1.1.2.7.2.2
+diff -u -r1.1.2.7.2.2 firewall_schedule.php
+--- usr/local/www/firewall_schedule.php 9 May 2007 02:09:06 -0000 1.1.2.7.2.2
++++ usr/local/www/firewall_schedule.php 8 Sep 2007 18:45:43 -0000
+@@ -75,6 +75,7 @@
+ }
+
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+ ?>
+
+ <body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+Index: usr/local/www/firewall_schedule_edit.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/firewall_schedule_edit.php,v
+retrieving revision 1.1.2.15.2.2
+diff -u -r1.1.2.15.2.2 firewall_schedule_edit.php
+--- usr/local/www/firewall_schedule_edit.php 7 May 2007 11:46:55 -0000 1.1.2.15.2.2
++++ usr/local/www/firewall_schedule_edit.php 8 Sep 2007 18:46:49 -0000
+@@ -725,6 +725,9 @@
+
+ </script>
+ EOD;
++
++$pfSenseHead->addScript($jscriptstr);
++echo $pfSenseHead->getHTML();
+ ?>
+
+ <body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+Index: usr/local/www/firewall_shaper.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/firewall_shaper.php,v
+retrieving revision 1.41.2.10
+diff -u -r1.41.2.10 firewall_shaper.php
+--- usr/local/www/firewall_shaper.php 25 Mar 2006 00:14:06 -0000 1.41.2.10
++++ usr/local/www/firewall_shaper.php 8 Sep 2007 18:47:46 -0000
+@@ -189,6 +189,7 @@
+
+ $pgtitle = "Firewall: Shaper: Rules";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/firewall_shaper_edit.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/firewall_shaper_edit.php,v
+retrieving revision 1.28.2.6
+diff -u -r1.28.2.6 firewall_shaper_edit.php
+--- usr/local/www/firewall_shaper_edit.php 24 Apr 2006 18:41:52 -0000 1.28.2.6
++++ usr/local/www/firewall_shaper_edit.php 8 Sep 2007 18:48:15 -0000
+@@ -291,6 +291,8 @@
+ $pgtitle = "Firewall: Shaper: Rules: Edit";
+ $closehead = false;
+ include("head.inc");
++$pfSenseHead->setCloseHead();
++echo $pfSenseHead->getHTML();
+ ?>
+
+ <script language="JavaScript">
+Index: usr/local/www/firewall_shaper_queues.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/firewall_shaper_queues.php,v
+retrieving revision 1.51.2.4
+diff -u -r1.51.2.4 firewall_shaper_queues.php
+--- usr/local/www/firewall_shaper_queues.php 2 Jan 2006 23:46:24 -0000 1.51.2.4
++++ usr/local/www/firewall_shaper_queues.php 8 Sep 2007 18:48:26 -0000
+@@ -157,6 +157,7 @@
+
+ $pgtitle = "Firewall: Shaper: Queues";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/firewall_shaper_queues_edit.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/firewall_shaper_queues_edit.php,v
+retrieving revision 1.59.2.11
+diff -u -r1.59.2.11 firewall_shaper_queues_edit.php
+--- usr/local/www/firewall_shaper_queues_edit.php 21 Aug 2006 03:25:24 -0000 1.59.2.11
++++ usr/local/www/firewall_shaper_queues_edit.php 8 Sep 2007 18:48:32 -0000
+@@ -240,6 +240,7 @@
+
+ $pgtitle = "Firewall: Shaper: Queues: Edit";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/firewall_virtual_ip.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/firewall_virtual_ip.php,v
+retrieving revision 1.9.2.6.2.10
+diff -u -r1.9.2.6.2.10 firewall_virtual_ip.php
+--- usr/local/www/firewall_virtual_ip.php 21 May 2007 19:28:20 -0000 1.9.2.6.2.10
++++ usr/local/www/firewall_virtual_ip.php 8 Sep 2007 18:48:38 -0000
+@@ -80,6 +80,7 @@
+
+ $pgtitle = "Firewall: Virtual IP Addresses";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+ <body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+Index: usr/local/www/firewall_virtual_ip_edit.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/firewall_virtual_ip_edit.php,v
+retrieving revision 1.11.2.23
+diff -u -r1.11.2.23 firewall_virtual_ip_edit.php
+--- usr/local/www/firewall_virtual_ip_edit.php 27 Feb 2007 17:09:46 -0000 1.11.2.23
++++ usr/local/www/firewall_virtual_ip_edit.php 8 Sep 2007 18:48:44 -0000
+@@ -205,6 +205,7 @@
+
+ $pgtitle = "Firewall: Virtual IP Address: Edit";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/halt.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/Attic/halt.php,v
+retrieving revision 1.6.4.1
+diff -u -r1.6.4.1 halt.php
+--- usr/local/www/halt.php 2 Jan 2006 23:46:24 -0000 1.6.4.1
++++ usr/local/www/halt.php 8 Sep 2007 18:48:57 -0000
+@@ -46,6 +46,7 @@
+
+ $pgtitle = "Diagnostics: Halt system";
+ include('head.inc');
++echo $pfSenseHead->getHTML();
+ ?>
+
+ <body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+Index: usr/local/www/index.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/index.php,v
+retrieving revision 1.88.2.9
+diff -u -r1.88.2.9 index.php
+--- usr/local/www/index.php 21 May 2006 23:26:30 -0000 1.88.2.9
++++ usr/local/www/index.php 8 Sep 2007 18:51:09 -0000
+@@ -80,6 +80,7 @@
+
+ $pgtitle = 'pfSense first time setup';
+ include('head.inc');
++ echo $pfSenseHead->getHTML();
+
+ echo "<body link=\"#0000CC\" vlink=\"#0000CC\" alink=\"#0000CC\">\n";
+ echo "<form>\n";
+@@ -118,6 +119,7 @@
+ ## Set Page Title and Include Header
+ $pgtitle = "pfSense webGUI";
+ include("head.inc");
++ echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/interfaces_assign.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/interfaces_assign.php,v
+retrieving revision 1.13.2.11.2.2
+diff -u -r1.13.2.11.2.2 interfaces_assign.php
+--- usr/local/www/interfaces_assign.php 24 Apr 2007 01:00:36 -0000 1.13.2.11.2.2
++++ usr/local/www/interfaces_assign.php 8 Sep 2007 18:51:21 -0000
+@@ -193,6 +193,7 @@
+
+ $pgtitle = "Interfaces: Assign";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ if(file_exists("/var/run/interface_mismatch_reboot_needed"))
+ if ($_POST)
+Index: usr/local/www/interfaces_lan.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/interfaces_lan.php,v
+retrieving revision 1.49.2.23.2.1
+diff -u -r1.49.2.23.2.1 interfaces_lan.php
+--- usr/local/www/interfaces_lan.php 6 Jul 2007 18:10:05 -0000 1.49.2.23.2.1
++++ usr/local/www/interfaces_lan.php 8 Sep 2007 18:51:29 -0000
+@@ -138,6 +138,7 @@
+
+ $pgtitle = "Interfaces: LAN";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/interfaces_opt.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/interfaces_opt.php,v
+retrieving revision 1.56.2.25
+diff -u -r1.56.2.25 interfaces_opt.php
+--- usr/local/www/interfaces_opt.php 9 Jan 2007 17:40:16 -0000 1.56.2.25
++++ usr/local/www/interfaces_opt.php 8 Sep 2007 18:52:02 -0000
+@@ -228,6 +228,8 @@
+
+ $pgtitle = "Interfaces: Optional {$index} (" . htmlspecialchars($optcfg['descr']) . ")";
+ include("head.inc");
++$pfSenseHead->setCloseHead(false);
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/interfaces_vlan.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/interfaces_vlan.php,v
+retrieving revision 1.9.2.3
+diff -u -r1.9.2.3 interfaces_vlan.php
+--- usr/local/www/interfaces_vlan.php 25 Jan 2007 22:26:20 -0000 1.9.2.3
++++ usr/local/www/interfaces_vlan.php 8 Sep 2007 18:52:16 -0000
+@@ -88,6 +88,7 @@
+
+ $pgtitle = "Interfaces: VLAN";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/interfaces_vlan_edit.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/interfaces_vlan_edit.php,v
+retrieving revision 1.10.2.4
+diff -u -r1.10.2.4 interfaces_vlan_edit.php
+--- usr/local/www/interfaces_vlan_edit.php 14 Mar 2007 21:15:41 -0000 1.10.2.4
++++ usr/local/www/interfaces_vlan_edit.php 8 Sep 2007 18:52:28 -0000
+@@ -98,6 +98,7 @@
+
+ $pgtitle = "Firewall: VLAN: Edit";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/interfaces_wan.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/interfaces_wan.php,v
+retrieving revision 1.37.2.24.2.1
+diff -u -r1.37.2.24.2.1 interfaces_wan.php
+--- usr/local/www/interfaces_wan.php 17 May 2007 13:52:34 -0000 1.37.2.24.2.1
++++ usr/local/www/interfaces_wan.php 8 Sep 2007 19:09:08 -0000
+@@ -519,6 +519,8 @@
+ $pgtitle = "Interfaces: WAN";
+ $closehead = false;
+ include("head.inc");
++$pfSenseHead->setCloseHead(false);
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/interfaces_wlan_scan.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/interfaces_wlan_scan.php,v
+retrieving revision 1.3.2.1
+diff -u -r1.3.2.1 interfaces_wlan_scan.php
+--- usr/local/www/interfaces_wlan_scan.php 2 Jan 2006 23:46:24 -0000 1.3.2.1
++++ usr/local/www/interfaces_wlan_scan.php 8 Sep 2007 18:53:12 -0000
+@@ -36,6 +36,7 @@
+
+ $pgtitle = "Interfaces: Scan Wireless";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/license.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/license.php,v
+retrieving revision 1.6.4.5
+diff -u -r1.6.4.5 license.php
+--- usr/local/www/license.php 23 Feb 2007 00:40:28 -0000 1.6.4.5
++++ usr/local/www/license.php 8 Sep 2007 18:53:20 -0000
+@@ -3,6 +3,7 @@
+ require("guiconfig.inc");
+
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+ ?>
+
+
+Index: usr/local/www/load_balancer_pool.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/load_balancer_pool.php,v
+retrieving revision 1.5.2.6.2.1
+diff -u -r1.5.2.6.2.1 load_balancer_pool.php
+--- usr/local/www/load_balancer_pool.php 8 May 2007 22:06:49 -0000 1.5.2.6.2.1
++++ usr/local/www/load_balancer_pool.php 8 Sep 2007 18:53:27 -0000
+@@ -76,6 +76,7 @@
+
+ $pgtitle = "Load Balancer: Pool";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+ <body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+Index: usr/local/www/load_balancer_pool_edit.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/load_balancer_pool_edit.php,v
+retrieving revision 1.24.2.23.2.2
+diff -u -r1.24.2.23.2.2 load_balancer_pool_edit.php
+--- usr/local/www/load_balancer_pool_edit.php 20 Jun 2007 23:24:56 -0000 1.24.2.23.2.2
++++ usr/local/www/load_balancer_pool_edit.php 8 Sep 2007 18:53:32 -0000
+@@ -165,6 +165,7 @@
+
+ $pgtitle = "Load Balancer: Pool: Edit";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/load_balancer_virtual_server.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/load_balancer_virtual_server.php,v
+retrieving revision 1.6.2.1.2.1
+diff -u -r1.6.2.1.2.1 load_balancer_virtual_server.php
+--- usr/local/www/load_balancer_virtual_server.php 8 May 2007 22:06:49 -0000 1.6.2.1.2.1
++++ usr/local/www/load_balancer_virtual_server.php 8 Sep 2007 18:53:38 -0000
+@@ -66,6 +66,7 @@
+
+ $pgtitle = "Services: Load Balancer: Virtual Servers";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+ <body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+Index: usr/local/www/load_balancer_virtual_server_edit.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/load_balancer_virtual_server_edit.php,v
+retrieving revision 1.16.2.5
+diff -u -r1.16.2.5 load_balancer_virtual_server_edit.php
+--- usr/local/www/load_balancer_virtual_server_edit.php 28 May 2006 18:53:19 -0000 1.16.2.5
++++ usr/local/www/load_balancer_virtual_server_edit.php 8 Sep 2007 18:53:45 -0000
+@@ -113,6 +113,7 @@
+
+ $pgtitle = "Load Balancer: Virtual Server: Edit";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/pkg.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/pkg.php,v
+retrieving revision 1.41.4.4
+diff -u -r1.41.4.4 pkg.php
+--- usr/local/www/pkg.php 21 Feb 2007 03:56:09 -0000 1.41.4.4
++++ usr/local/www/pkg.php 8 Sep 2007 18:54:16 -0000
+@@ -99,6 +99,7 @@
+
+ $pgtitle = $title;
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/pkg_edit.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/pkg_edit.php,v
+retrieving revision 1.90.2.24
+diff -u -r1.90.2.24 pkg_edit.php
+--- usr/local/www/pkg_edit.php 20 Jan 2007 20:52:51 -0000 1.90.2.24
++++ usr/local/www/pkg_edit.php 8 Sep 2007 18:54:41 -0000
+@@ -102,9 +102,10 @@
+ } else {
+ if($pkg['custom_add_php_command']) {
+ if($pkg['donotsave'] <> "" or $pkg['preoutput'] <> "") {
+- ?>
+
+-<?php include("head.inc"); ?>
++include("head.inc");
++echo $pfSenseHead->getHTML();
++?>
+ <body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+ <?php include("fbegin.inc"); ?>
+ <?php
+Index: usr/local/www/pkg_mgr.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/pkg_mgr.php,v
+retrieving revision 1.64.2.12
+diff -u -r1.64.2.12 pkg_mgr.php
+--- usr/local/www/pkg_mgr.php 25 Aug 2006 23:04:56 -0000 1.64.2.12
++++ usr/local/www/pkg_mgr.php 8 Sep 2007 18:55:09 -0000
+@@ -54,6 +54,7 @@
+
+ $pgtitle = "System: Package Manager";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/pkg_mgr_install.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/pkg_mgr_install.php,v
+retrieving revision 1.147.2.10
+diff -u -r1.147.2.10 pkg_mgr_install.php
+--- usr/local/www/pkg_mgr_install.php 2 Feb 2007 17:47:53 -0000 1.147.2.10
++++ usr/local/www/pkg_mgr_install.php 8 Sep 2007 18:55:12 -0000
+@@ -39,6 +39,7 @@
+
+ $pgtitle = "System: Package Manager: Install Package";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/pkg_mgr_installed.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/pkg_mgr_installed.php,v
+retrieving revision 1.43.4.5
+diff -u -r1.43.4.5 pkg_mgr_installed.php
+--- usr/local/www/pkg_mgr_installed.php 25 Aug 2006 23:04:57 -0000 1.43.4.5
++++ usr/local/www/pkg_mgr_installed.php 8 Sep 2007 18:55:17 -0000
+@@ -39,6 +39,7 @@
+
+ $pgtitle = "System: Package Manager";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/reboot.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/Attic/reboot.php,v
+retrieving revision 1.7.2.5
+diff -u -r1.7.2.5 reboot.php
+--- usr/local/www/reboot.php 11 Feb 2006 03:04:21 -0000 1.7.2.5
++++ usr/local/www/reboot.php 8 Sep 2007 18:55:31 -0000
+@@ -42,6 +42,7 @@
+
+ $pgtitle = "Diagnostics: Reboot System";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+ <body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+Index: usr/local/www/restart_httpd.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/restart_httpd.php,v
+retrieving revision 1.3.2.1
+diff -u -r1.3.2.1 restart_httpd.php
+--- usr/local/www/restart_httpd.php 2 Jan 2006 23:46:24 -0000 1.3.2.1
++++ usr/local/www/restart_httpd.php 8 Sep 2007 18:55:37 -0000
+@@ -30,6 +30,7 @@
+ require_once("system.inc");
+ $pgtitle = "Restarting mini_httpd";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+ ?>
+
+ <body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+Index: usr/local/www/services_captiveportal.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/services_captiveportal.php,v
+retrieving revision 1.51.2.23.2.1
+diff -u -r1.51.2.23.2.1 services_captiveportal.php
+--- usr/local/www/services_captiveportal.php 9 May 2007 02:09:43 -0000 1.51.2.23.2.1
++++ usr/local/www/services_captiveportal.php 8 Sep 2007 18:56:01 -0000
+@@ -197,6 +197,8 @@
+ }
+ }
+ include("head.inc");
++$pfSenseHead->setCloseHead(false);
++echo $pfSenseHead->getHTML();
+ ?>
+ <?php include("fbegin.inc"); ?>
+ <script language="JavaScript">
+Index: usr/local/www/services_captiveportal_filemanager.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/services_captiveportal_filemanager.php,v
+retrieving revision 1.4.2.4.2.2
+diff -u -r1.4.2.4.2.2 services_captiveportal_filemanager.php
+--- usr/local/www/services_captiveportal_filemanager.php 9 May 2007 02:09:43 -0000 1.4.2.4.2.2
++++ usr/local/www/services_captiveportal_filemanager.php 8 Sep 2007 18:56:24 -0000
+@@ -98,6 +98,7 @@
+ }
+
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+ <?php include("fbegin.inc"); ?>
+Index: usr/local/www/services_captiveportal_ip.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/services_captiveportal_ip.php,v
+retrieving revision 1.30.2.6.2.2
+diff -u -r1.30.2.6.2.2 services_captiveportal_ip.php
+--- usr/local/www/services_captiveportal_ip.php 9 May 2007 02:09:43 -0000 1.30.2.6.2.2
++++ usr/local/www/services_captiveportal_ip.php 8 Sep 2007 18:56:32 -0000
+@@ -69,6 +69,7 @@
+
+
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+ ?>
+ <?php include("fbegin.inc"); ?>
+ <body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+Index: usr/local/www/services_captiveportal_ip_edit.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/services_captiveportal_ip_edit.php,v
+retrieving revision 1.17.2.2.2.1
+diff -u -r1.17.2.2.2.1 services_captiveportal_ip_edit.php
+--- usr/local/www/services_captiveportal_ip_edit.php 9 May 2007 02:09:43 -0000 1.17.2.2.2.1
++++ usr/local/www/services_captiveportal_ip_edit.php 8 Sep 2007 18:56:39 -0000
+@@ -93,6 +93,7 @@
+ }
+
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+ <?php include("fbegin.inc"); ?>
+Index: usr/local/www/services_captiveportal_mac.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/services_captiveportal_mac.php,v
+retrieving revision 1.35.2.6.2.1
+diff -u -r1.35.2.6.2.1 services_captiveportal_mac.php
+--- usr/local/www/services_captiveportal_mac.php 9 May 2007 02:09:43 -0000 1.35.2.6.2.1
++++ usr/local/www/services_captiveportal_mac.php 8 Sep 2007 18:56:45 -0000
+@@ -68,6 +68,7 @@
+ }
+
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+ <?php include("fbegin.inc"); ?>
+Index: usr/local/www/services_captiveportal_mac_edit.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/services_captiveportal_mac_edit.php,v
+retrieving revision 1.16.2.2.2.1
+diff -u -r1.16.2.2.2.1 services_captiveportal_mac_edit.php
+--- usr/local/www/services_captiveportal_mac_edit.php 9 May 2007 02:09:43 -0000 1.16.2.2.2.1
++++ usr/local/www/services_captiveportal_mac_edit.php 8 Sep 2007 18:57:06 -0000
+@@ -92,6 +92,7 @@
+ }
+ }
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+ ?>
+ <?php include("fbegin.inc"); ?>
+ <body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+Index: usr/local/www/services_captiveportal_users.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/services_captiveportal_users.php,v
+retrieving revision 1.24.2.3.2.2
+diff -u -r1.24.2.3.2.2 services_captiveportal_users.php
+--- usr/local/www/services_captiveportal_users.php 9 May 2007 02:09:43 -0000 1.24.2.3.2.2
++++ usr/local/www/services_captiveportal_users.php 8 Sep 2007 18:57:13 -0000
+@@ -63,6 +63,7 @@
+ }
+
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+ <?php include("fbegin.inc"); ?>
+Index: usr/local/www/services_captiveportal_users_edit.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/services_captiveportal_users_edit.php,v
+retrieving revision 1.7.2.3.2.1
+diff -u -r1.7.2.3.2.1 services_captiveportal_users_edit.php
+--- usr/local/www/services_captiveportal_users_edit.php 9 May 2007 02:09:43 -0000 1.7.2.3.2.1
++++ usr/local/www/services_captiveportal_users_edit.php 8 Sep 2007 18:57:20 -0000
+@@ -124,6 +124,7 @@
+ }
+
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+ <?php include("fbegin.inc"); ?>
+Index: usr/local/www/services_dhcp.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/services_dhcp.php,v
+retrieving revision 1.38.2.18.2.2
+diff -u -r1.38.2.18.2.2 services_dhcp.php
+--- usr/local/www/services_dhcp.php 8 May 2007 22:06:49 -0000 1.38.2.18.2.2
++++ usr/local/www/services_dhcp.php 8 Sep 2007 18:57:42 -0000
+@@ -255,6 +255,8 @@
+
+ $pgtitle = "Services: DHCP server";
+ include("head.inc");
++$pfSenseHead->setCloseHead(false):
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/services_dhcp_edit.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/services_dhcp_edit.php,v
+retrieving revision 1.18.2.5.2.1
+diff -u -r1.18.2.5.2.1 services_dhcp_edit.php
+--- usr/local/www/services_dhcp_edit.php 8 May 2007 18:58:26 -0000 1.18.2.5.2.1
++++ usr/local/www/services_dhcp_edit.php 8 Sep 2007 18:57:48 -0000
+@@ -147,6 +147,7 @@
+
+ $pgtitle = "Services: DHCP: Edit static mapping";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/services_dhcp_relay.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/services_dhcp_relay.php,v
+retrieving revision 1.8.2.3.2.2
+diff -u -r1.8.2.3.2.2 services_dhcp_relay.php
+--- usr/local/www/services_dhcp_relay.php 23 May 2007 21:08:15 -0000 1.8.2.3.2.2
++++ usr/local/www/services_dhcp_relay.php 8 Sep 2007 18:58:08 -0000
+@@ -141,6 +141,8 @@
+
+ $pgtitle = "Services: DHCP Relay";
+ include("head.inc");
++$pfSenseHead->setCloseHead(false);
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/services_dnsmasq.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/services_dnsmasq.php,v
+retrieving revision 1.17.4.4.2.1
+diff -u -r1.17.4.4.2.1 services_dnsmasq.php
+--- usr/local/www/services_dnsmasq.php 8 May 2007 22:06:49 -0000 1.17.4.4.2.1
++++ usr/local/www/services_dnsmasq.php 8 Sep 2007 18:58:55 -0000
+@@ -93,6 +93,8 @@
+
+ $pgtitle = "Services: DNS forwarder";
+ include("head.inc");
++$pfSenseHead->setCloseHead(false);
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/services_dnsmasq_domainoverride_edit.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/services_dnsmasq_domainoverride_edit.php,v
+retrieving revision 1.7.4.2
+diff -u -r1.7.4.2 services_dnsmasq_domainoverride_edit.php
+--- usr/local/www/services_dnsmasq_domainoverride_edit.php 2 Jan 2006 23:46:24 -0000 1.7.4.2
++++ usr/local/www/services_dnsmasq_domainoverride_edit.php 8 Sep 2007 18:59:01 -0000
+@@ -96,6 +96,7 @@
+
+ $pgtitle = "Services: DNS forwarder: Edit Domain Override";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/services_dnsmasq_edit.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/services_dnsmasq_edit.php,v
+retrieving revision 1.11.4.2
+diff -u -r1.11.4.2 services_dnsmasq_edit.php
+--- usr/local/www/services_dnsmasq_edit.php 2 Jan 2006 23:46:24 -0000 1.11.4.2
++++ usr/local/www/services_dnsmasq_edit.php 8 Sep 2007 18:59:09 -0000
+@@ -102,6 +102,7 @@
+
+ $pgtitle = "Services: DNS forwarder: Edit host";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/services_dyndns.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/services_dyndns.php,v
+retrieving revision 1.12.2.9
+diff -u -r1.12.2.9 services_dyndns.php
+--- usr/local/www/services_dyndns.php 7 Feb 2007 03:42:33 -0000 1.12.2.9
++++ usr/local/www/services_dyndns.php 8 Sep 2007 18:59:40 -0000
+@@ -128,6 +128,8 @@
+
+ $pgtitle = "Services: Dynamic DNS client";
+ include("head.inc");
++$pfSenseHead->setCloseHead(false);
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/services_proxyarp.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/services_proxyarp.php,v
+retrieving revision 1.16.2.1
+diff -u -r1.16.2.1 services_proxyarp.php
+--- usr/local/www/services_proxyarp.php 2 Jan 2006 23:46:24 -0000 1.16.2.1
++++ usr/local/www/services_proxyarp.php 8 Sep 2007 18:59:47 -0000
+@@ -66,6 +66,7 @@
+
+ $pgtitle = "Services: Proxy ARP";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/services_proxyarp_edit.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/services_proxyarp_edit.php,v
+retrieving revision 1.13.4.2
+diff -u -r1.13.4.2 services_proxyarp_edit.php
+--- usr/local/www/services_proxyarp_edit.php 2 Jan 2006 23:46:24 -0000 1.13.4.2
++++ usr/local/www/services_proxyarp_edit.php 8 Sep 2007 19:00:15 -0000
+@@ -133,6 +133,8 @@
+
+ $pgtitle = "Services: Proxy ARP: Edit";
+ include("head.inc");
++$pfSenseHead->setCloseHead(false);
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/services_snmp.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/services_snmp.php,v
+retrieving revision 1.9.4.12
+diff -u -r1.9.4.12 services_snmp.php
+--- usr/local/www/services_snmp.php 4 Mar 2007 21:18:17 -0000 1.9.4.12
++++ usr/local/www/services_snmp.php 8 Sep 2007 19:00:58 -0000
+@@ -145,6 +145,8 @@
+
+ $pgtitle = "Services: SNMP";
+ include("head.inc");
++$pfSenseHead->setCloseHead(false);
++echo $pfSenseHead->getHTML();
+
+ ?>
+ <script language="JavaScript">
+Index: usr/local/www/services_usermanager.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/services_usermanager.php,v
+retrieving revision 1.10.4.1
+diff -u -r1.10.4.1 services_usermanager.php
+--- usr/local/www/services_usermanager.php 2 Jan 2006 23:46:24 -0000 1.10.4.1
++++ usr/local/www/services_usermanager.php 8 Sep 2007 19:01:11 -0000
+@@ -77,6 +77,7 @@
+
+ $pgtitle = "Services: User Manager";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/services_wol.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/services_wol.php,v
+retrieving revision 1.12.2.2.2.1
+diff -u -r1.12.2.2.2.1 services_wol.php
+--- usr/local/www/services_wol.php 8 May 2007 22:06:49 -0000 1.12.2.2.2.1
++++ usr/local/www/services_wol.php 8 Sep 2007 19:01:15 -0000
+@@ -92,6 +92,7 @@
+
+ $pgtitle = "Services: Wake on LAN";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/services_wol_edit.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/services_wol_edit.php,v
+retrieving revision 1.11.2.2
+diff -u -r1.11.2.2 services_wol_edit.php
+--- usr/local/www/services_wol_edit.php 2 Jan 2006 23:46:24 -0000 1.11.2.2
++++ usr/local/www/services_wol_edit.php 8 Sep 2007 19:01:21 -0000
+@@ -91,6 +91,7 @@
+
+ $pgtitle = "Services: Wake on LAN: Edit";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/status.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/status.php,v
+retrieving revision 1.24.2.9
+diff -u -r1.24.2.9 status.php
+--- usr/local/www/status.php 27 Mar 2007 20:34:35 -0000 1.24.2.9
++++ usr/local/www/status.php 8 Sep 2007 19:02:02 -0000
+@@ -160,6 +160,8 @@
+
+ $pgtitle = "pfSense: status";
+ include("head.inc");
++$pfSenseHead->setCloseHead(false);
++echo $pfSenseHead->getHTML();
+
+ ?>
+ <style type="text/css">
+@@ -172,6 +174,7 @@
+ }
+ -->
+ </style>
++</head>
+
+ <body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+ <?php include("fbegin.inc"); ?>
+Index: usr/local/www/status_captiveportal.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/status_captiveportal.php,v
+retrieving revision 1.7.2.4
+diff -u -r1.7.2.4 status_captiveportal.php
+--- usr/local/www/status_captiveportal.php 3 Apr 2006 21:05:12 -0000 1.7.2.4
++++ usr/local/www/status_captiveportal.php 8 Sep 2007 19:02:17 -0000
+@@ -36,6 +36,7 @@
+ $pgtitle = "Status: Captive portal ({$concurrent})";
+
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/status_filter_reload.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/status_filter_reload.php,v
+retrieving revision 1.1.2.8
+diff -u -r1.1.2.8 status_filter_reload.php
+--- usr/local/www/status_filter_reload.php 5 Apr 2006 02:01:18 -0000 1.1.2.8
++++ usr/local/www/status_filter_reload.php 8 Sep 2007 19:02:22 -0000
+@@ -33,6 +33,7 @@
+ $pgtitle = "Diagnostics: Filter Reload Status";
+
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ if(file_exists("{$g['varrun_path']}/filter_reload_status"))
+ $status = file_get_contents("{$g['varrun_path']}/filter_reload_status");
+Index: usr/local/www/status_graph.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/status_graph.php,v
+retrieving revision 1.14.2.5.2.2
+diff -u -r1.14.2.5.2.2 status_graph.php
+--- usr/local/www/status_graph.php 24 Apr 2007 21:25:11 -0000 1.14.2.5.2.2
++++ usr/local/www/status_graph.php 8 Sep 2007 19:02:27 -0000
+@@ -54,6 +54,7 @@
+
+ $pgtitle = "Status: Traffic Graph";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/status_interfaces.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/status_interfaces.php,v
+retrieving revision 1.29.2.13.2.3
+diff -u -r1.29.2.13.2.3 status_interfaces.php
+--- usr/local/www/status_interfaces.php 30 May 2007 16:11:26 -0000 1.29.2.13.2.3
++++ usr/local/www/status_interfaces.php 8 Sep 2007 19:02:33 -0000
+@@ -61,6 +61,7 @@
+
+ $pgtitle = "Status: Interfaces";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/status_queues.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/status_queues.php,v
+retrieving revision 1.25.2.10
+diff -u -r1.25.2.10 status_queues.php
+--- usr/local/www/status_queues.php 24 Apr 2006 22:02:15 -0000 1.25.2.10
++++ usr/local/www/status_queues.php 8 Sep 2007 19:02:40 -0000
+@@ -53,6 +53,7 @@
+
+ $pgtitle = "Status: Traffic shaper: Queues";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/status_rrd_graph.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/status_rrd_graph.php,v
+retrieving revision 1.7.2.31.2.1
+diff -u -r1.7.2.31.2.1 status_rrd_graph.php
+--- usr/local/www/status_rrd_graph.php 6 Jul 2007 21:43:43 -0000 1.7.2.31.2.1
++++ usr/local/www/status_rrd_graph.php 8 Sep 2007 19:03:22 -0000
+@@ -78,10 +78,13 @@
+
+ $pgtitle = gettext("Status: RRD Graphs");
+ include("head.inc");
++$pfSenseHead->setCloseHead(false);
++echo $pfSenseHead->getHTML();
+
+ ?>
+ <script src="/javascript/scriptaculous/prototype.js" type="text/javascript"></script>
+ <script src="/javascript/scriptaculous/scriptaculous.js" type="text/javascript"></script>
++</head>
+ <body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+ <?php include("fbegin.inc"); ?>
+ <p class="pgtitle"><?=$pgtitle?></p>
+Index: usr/local/www/status_services.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/status_services.php,v
+retrieving revision 1.40.2.19.2.4
+diff -u -r1.40.2.19.2.4 status_services.php
+--- usr/local/www/status_services.php 2 Jun 2007 20:47:41 -0000 1.40.2.19.2.4
++++ usr/local/www/status_services.php 8 Sep 2007 19:03:38 -0000
+@@ -142,6 +142,7 @@
+
+ $pgtitle = "Status: Services";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/status_slbd_pool.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/status_slbd_pool.php,v
+retrieving revision 1.3.2.4.2.1
+diff -u -r1.3.2.4.2.1 status_slbd_pool.php
+--- usr/local/www/status_slbd_pool.php 28 Apr 2007 16:46:56 -0000 1.3.2.4.2.1
++++ usr/local/www/status_slbd_pool.php 8 Sep 2007 19:03:44 -0000
+@@ -47,6 +47,7 @@
+
+ $pgtitle = "Status: Load Balancer: Pool";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+ <body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+Index: usr/local/www/status_slbd_vs.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/status_slbd_vs.php,v
+retrieving revision 1.2.2.2
+diff -u -r1.2.2.2 status_slbd_vs.php
+--- usr/local/www/status_slbd_vs.php 8 May 2007 16:29:17 -0000 1.2.2.2
++++ usr/local/www/status_slbd_vs.php 8 Sep 2007 19:03:50 -0000
+@@ -51,6 +51,7 @@
+
+ $pgtitle = "Status: Load Balancer: Virtual Server";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+ <body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+Index: usr/local/www/status_upnp.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/status_upnp.php,v
+retrieving revision 1.1.2.3.2.1
+diff -u -r1.1.2.3.2.1 status_upnp.php
+--- usr/local/www/status_upnp.php 23 May 2007 20:26:19 -0000 1.1.2.3.2.1
++++ usr/local/www/status_upnp.php 8 Sep 2007 19:04:09 -0000
+@@ -49,7 +49,7 @@
+ /* put your custom HTML head content here */
+ /* using some of the $pfSenseHead function calls */
+ //$pfSenseHead->addMeta("<meta http-equiv=\"refresh\" content=\"120;url={$_SERVER['SCRIPT_NAME']}\" />");
+-//echo $pfSenseHead->getHTML();
++echo $pfSenseHead->getHTML();
+
+ ?>
+ <body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+Index: usr/local/www/status_wireless.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/status_wireless.php,v
+retrieving revision 1.9.2.9
+diff -u -r1.9.2.9 status_wireless.php
+--- usr/local/www/status_wireless.php 5 May 2006 21:31:47 -0000 1.9.2.9
++++ usr/local/www/status_wireless.php 8 Sep 2007 19:04:16 -0000
+@@ -36,6 +36,7 @@
+
+ $pgtitle = "Diagnostics: Wireless Status";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ $if = $_POST['if'];
+ if($_GET['if'] <> "")
+Index: usr/local/www/system.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/system.php,v
+retrieving revision 1.41.2.7.2.1
+diff -u -r1.41.2.7.2.1 system.php
+--- usr/local/www/system.php 6 Jul 2007 18:30:31 -0000 1.41.2.7.2.1
++++ usr/local/www/system.php 8 Sep 2007 19:04:21 -0000
+@@ -190,6 +190,7 @@
+
+ $pgtitle = "System: General Setup";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/system_advanced.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/system_advanced.php,v
+retrieving revision 1.114.2.46.2.4
+diff -u -r1.114.2.46.2.4 system_advanced.php
+--- usr/local/www/system_advanced.php 21 Jul 2007 21:22:18 -0000 1.114.2.46.2.4
++++ usr/local/www/system_advanced.php 8 Sep 2007 19:04:26 -0000
+@@ -266,6 +266,7 @@
+
+ $pgtitle = "System: Advanced functions";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/system_advanced_create_certs.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/system_advanced_create_certs.php,v
+retrieving revision 1.14.4.4
+diff -u -r1.14.4.4 system_advanced_create_certs.php
+--- usr/local/www/system_advanced_create_certs.php 19 Jan 2006 05:58:23 -0000 1.14.4.4
++++ usr/local/www/system_advanced_create_certs.php 8 Sep 2007 19:04:32 -0000
+@@ -140,6 +140,7 @@
+
+ $pgtitle = "System: Advanced functions: Create Certificates";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/system_firmware.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/system_firmware.php,v
+retrieving revision 1.73.2.12
+diff -u -r1.73.2.12 system_firmware.php
+--- usr/local/www/system_firmware.php 14 Mar 2007 19:22:10 -0000 1.73.2.12
++++ usr/local/www/system_firmware.php 8 Sep 2007 19:04:47 -0000
+@@ -37,6 +37,7 @@
+ if(file_exists($d_firmwarelock_path)) {
+ $pgtitle = "System: Firmware: Manual Update";
+ include("head.inc");
++ echo $pfSenseHead->getHTML();
+ echo "<body link=\"#0000CC\" vlink=\"#0000CC\" alink=\"#0000CC\">\n";
+ include("fbegin.inc");
+ echo "<p class=\"pgtitle\"><?=$pgtitle?></p>\n";
+@@ -124,6 +125,7 @@
+
+ $pgtitle = "System: Firmware: Manual Update";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+ <body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+Index: usr/local/www/system_firmware_auto.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/system_firmware_auto.php,v
+retrieving revision 1.52.4.2
+diff -u -r1.52.4.2 system_firmware_auto.php
+--- usr/local/www/system_firmware_auto.php 15 Apr 2006 16:50:47 -0000 1.52.4.2
++++ usr/local/www/system_firmware_auto.php 8 Sep 2007 19:05:05 -0000
+@@ -41,6 +41,7 @@
+
+ $pgtitle = "System: Firmware: Auto Update";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/system_firmware_check.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/system_firmware_check.php,v
+retrieving revision 1.38.4.3
+diff -u -r1.38.4.3 system_firmware_check.php
+--- usr/local/www/system_firmware_check.php 15 Apr 2006 16:50:47 -0000 1.38.4.3
++++ usr/local/www/system_firmware_check.php 8 Sep 2007 19:05:21 -0000
+@@ -39,6 +39,7 @@
+ $versions = check_firmware_version();
+ $pgtitle = "System: Firmware: Auto Update";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+ <body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+Index: usr/local/www/system_firmware_settings.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/system_firmware_settings.php,v
+retrieving revision 1.15.2.4
+diff -u -r1.15.2.4 system_firmware_settings.php
+--- usr/local/www/system_firmware_settings.php 15 Apr 2006 16:50:47 -0000 1.15.2.4
++++ usr/local/www/system_firmware_settings.php 8 Sep 2007 19:06:04 -0000
+@@ -57,6 +57,8 @@
+
+ $pgtitle = "System: Firmware: Settings";
+ include("head.inc");
++$pfSenseHead->setCloseHead(false);
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+@@ -88,7 +90,7 @@
+
+ // -->
+ </script>
+-
++</head>
+ <body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+ <?php include("fbegin.inc");?>
+ <p class="pgtitle"><?=$pgtitle?></p>
+Index: usr/local/www/system_routes.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/system_routes.php,v
+retrieving revision 1.16.2.4.2.2
+diff -u -r1.16.2.4.2.2 system_routes.php
+--- usr/local/www/system_routes.php 10 May 2007 16:06:32 -0000 1.16.2.4.2.2
++++ usr/local/www/system_routes.php 8 Sep 2007 19:06:11 -0000
+@@ -89,6 +89,7 @@
+
+ $pgtitle = "System: Static Routes";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/system_routes_edit.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/system_routes_edit.php,v
+retrieving revision 1.9.4.4.2.1
+diff -u -r1.9.4.4.2.1 system_routes_edit.php
+--- usr/local/www/system_routes_edit.php 10 May 2007 16:06:32 -0000 1.9.4.4.2.1
++++ usr/local/www/system_routes_edit.php 8 Sep 2007 19:06:16 -0000
+@@ -112,6 +112,7 @@
+
+ $pgtitle = "System: Static Routes: Edit route";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/vpn_ipsec.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/vpn_ipsec.php,v
+retrieving revision 1.28.2.10.2.5
+diff -u -r1.28.2.10.2.5 vpn_ipsec.php
+--- usr/local/www/vpn_ipsec.php 5 Jun 2007 00:23:07 -0000 1.28.2.10.2.5
++++ usr/local/www/vpn_ipsec.php 8 Sep 2007 19:06:38 -0000
+@@ -84,6 +84,7 @@
+
+ $pgtitle = "VPN: IPsec";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/vpn_ipsec_ca.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/vpn_ipsec_ca.php,v
+retrieving revision 1.12.4.2
+diff -u -r1.12.4.2 vpn_ipsec_ca.php
+--- usr/local/www/vpn_ipsec_ca.php 18 Mar 2007 03:37:06 -0000 1.12.4.2
++++ usr/local/www/vpn_ipsec_ca.php 8 Sep 2007 19:06:42 -0000
+@@ -48,6 +48,7 @@
+
+ $pgtitle = "VPN: IPsec: Certificate Authority";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/vpn_ipsec_ca_edit.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/vpn_ipsec_ca_edit.php,v
+retrieving revision 1.12.4.2
+diff -u -r1.12.4.2 vpn_ipsec_ca_edit.php
+--- usr/local/www/vpn_ipsec_ca_edit.php 2 Jan 2006 23:46:25 -0000 1.12.4.2
++++ usr/local/www/vpn_ipsec_ca_edit.php 8 Sep 2007 19:06:47 -0000
+@@ -94,6 +94,7 @@
+
+ $pgtitle = "VPN: IPsec: Certificate Authority: Edit";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/vpn_ipsec_ca_edit_create_cert.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/vpn_ipsec_ca_edit_create_cert.php,v
+retrieving revision 1.13.4.1
+diff -u -r1.13.4.1 vpn_ipsec_ca_edit_create_cert.php
+--- usr/local/www/vpn_ipsec_ca_edit_create_cert.php 2 Jan 2006 23:46:25 -0000 1.13.4.1
++++ usr/local/www/vpn_ipsec_ca_edit_create_cert.php 8 Sep 2007 19:06:53 -0000
+@@ -143,6 +143,7 @@
+
+ $pgtitle = "VPN: IPSec: Certificate Authority: Create Certificate";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+ <body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+Index: usr/local/www/vpn_ipsec_edit.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/vpn_ipsec_edit.php,v
+retrieving revision 1.29.2.13.2.1
+diff -u -r1.29.2.13.2.1 vpn_ipsec_edit.php
+--- usr/local/www/vpn_ipsec_edit.php 8 May 2007 22:06:49 -0000 1.29.2.13.2.1
++++ usr/local/www/vpn_ipsec_edit.php 8 Sep 2007 19:06:58 -0000
+@@ -263,6 +263,7 @@
+
+ $pgtitle = "VPN: IPsec: Edit tunnel";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/vpn_ipsec_keys.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/vpn_ipsec_keys.php,v
+retrieving revision 1.15.4.2.2.1
+diff -u -r1.15.4.2.2.1 vpn_ipsec_keys.php
+--- usr/local/www/vpn_ipsec_keys.php 8 May 2007 22:06:49 -0000 1.15.4.2.2.1
++++ usr/local/www/vpn_ipsec_keys.php 8 Sep 2007 19:07:03 -0000
+@@ -48,6 +48,7 @@
+
+ $pgtitle = "VPN: IPsec: Keys";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/vpn_ipsec_keys_edit.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/vpn_ipsec_keys_edit.php,v
+retrieving revision 1.11.4.2
+diff -u -r1.11.4.2 vpn_ipsec_keys_edit.php
+--- usr/local/www/vpn_ipsec_keys_edit.php 2 Jan 2006 23:46:25 -0000 1.11.4.2
++++ usr/local/www/vpn_ipsec_keys_edit.php 8 Sep 2007 19:07:07 -0000
+@@ -92,6 +92,7 @@
+
+ $pgtitle = "VPN: IPsec: Edit pre-shared key";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/vpn_ipsec_mobile.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/vpn_ipsec_mobile.php,v
+retrieving revision 1.12.4.2
+diff -u -r1.12.4.2 vpn_ipsec_mobile.php
+--- usr/local/www/vpn_ipsec_mobile.php 18 Mar 2007 03:37:06 -0000 1.12.4.2
++++ usr/local/www/vpn_ipsec_mobile.php 8 Sep 2007 19:07:11 -0000
+@@ -162,6 +162,7 @@
+
+ $pgtitle = "VPN: IPsec: Mobile";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+ <body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+Index: usr/local/www/vpn_openvpn.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/Attic/vpn_openvpn.php,v
+retrieving revision 1.13.2.2
+diff -u -r1.13.2.2 vpn_openvpn.php
+--- usr/local/www/vpn_openvpn.php 30 Jan 2006 02:25:12 -0000 1.13.2.2
++++ usr/local/www/vpn_openvpn.php 8 Sep 2007 19:07:16 -0000
+@@ -144,6 +144,7 @@
+
+ $pgtitle = "VPN: OpenVPN";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/vpn_openvpn_ccd.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/Attic/vpn_openvpn_ccd.php,v
+retrieving revision 1.1.2.2
+diff -u -r1.1.2.2 vpn_openvpn_ccd.php
+--- usr/local/www/vpn_openvpn_ccd.php 30 Jan 2006 02:25:12 -0000 1.1.2.2
++++ usr/local/www/vpn_openvpn_ccd.php 8 Sep 2007 19:07:20 -0000
+@@ -95,6 +95,7 @@
+
+ $pgtitle = "VPN: OpenVPN";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+ <?php include("fbegin.inc"); ?>
+Index: usr/local/www/vpn_openvpn_ccd_edit.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/Attic/vpn_openvpn_ccd_edit.php,v
+retrieving revision 1.1.2.2
+diff -u -r1.1.2.2 vpn_openvpn_ccd_edit.php
+--- usr/local/www/vpn_openvpn_ccd_edit.php 30 Jan 2006 02:25:12 -0000 1.1.2.2
++++ usr/local/www/vpn_openvpn_ccd_edit.php 8 Sep 2007 19:07:26 -0000
+@@ -209,6 +209,7 @@
+
+ $pgtitle = "VPN: OpenVPN: Edit client-specific configuration";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+ <body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+Index: usr/local/www/vpn_openvpn_cli.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/Attic/vpn_openvpn_cli.php,v
+retrieving revision 1.16.2.3
+diff -u -r1.16.2.3 vpn_openvpn_cli.php
+--- usr/local/www/vpn_openvpn_cli.php 30 Jan 2006 02:25:12 -0000 1.16.2.3
++++ usr/local/www/vpn_openvpn_cli.php 8 Sep 2007 19:07:31 -0000
+@@ -83,6 +83,7 @@
+
+ $pgtitle = "VPN: OpenVPN";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+ <?php include("fbegin.inc"); ?>
+Index: usr/local/www/vpn_openvpn_cli_edit.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/Attic/vpn_openvpn_cli_edit.php,v
+retrieving revision 1.15.2.3
+diff -u -r1.15.2.3 vpn_openvpn_cli_edit.php
+--- usr/local/www/vpn_openvpn_cli_edit.php 30 Jan 2006 02:25:12 -0000 1.15.2.3
++++ usr/local/www/vpn_openvpn_cli_edit.php 8 Sep 2007 19:07:36 -0000
+@@ -285,6 +285,7 @@
+
+ $pgtitle = "VPN: OpenVPN: Edit client";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+ <body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+Index: usr/local/www/vpn_openvpn_create_certs.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/vpn_openvpn_create_certs.php,v
+retrieving revision 1.14.4.2
+diff -u -r1.14.4.2 vpn_openvpn_create_certs.php
+--- usr/local/www/vpn_openvpn_create_certs.php 7 Apr 2006 21:36:51 -0000 1.14.4.2
++++ usr/local/www/vpn_openvpn_create_certs.php 8 Sep 2007 19:07:57 -0000
+@@ -151,6 +151,8 @@
+
+ $pgtitle = "VPN: OpenVPN: Create Certs";
+ include("head.inc");
++$pfSenseHead->setCloseHead(false);
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/vpn_openvpn_crl.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/Attic/vpn_openvpn_crl.php,v
+retrieving revision 1.1.2.2
+diff -u -r1.1.2.2 vpn_openvpn_crl.php
+--- usr/local/www/vpn_openvpn_crl.php 30 Jan 2006 02:25:12 -0000 1.1.2.2
++++ usr/local/www/vpn_openvpn_crl.php 8 Sep 2007 19:08:02 -0000
+@@ -76,6 +76,7 @@
+
+ $pgtitle = "VPN: OpenVPN";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+ <?php include("fbegin.inc"); ?>
+Index: usr/local/www/vpn_openvpn_crl_edit.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/Attic/vpn_openvpn_crl_edit.php,v
+retrieving revision 1.1.2.2
+diff -u -r1.1.2.2 vpn_openvpn_crl_edit.php
+--- usr/local/www/vpn_openvpn_crl_edit.php 30 Jan 2006 02:25:12 -0000 1.1.2.2
++++ usr/local/www/vpn_openvpn_crl_edit.php 8 Sep 2007 19:08:07 -0000
+@@ -152,6 +152,7 @@
+
+ $pgtitle = "VPN: OpenVPN: Edit CRL";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+ <body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+Index: usr/local/www/vpn_openvpn_srv.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/Attic/vpn_openvpn_srv.php,v
+retrieving revision 1.1.2.3
+diff -u -r1.1.2.3 vpn_openvpn_srv.php
+--- usr/local/www/vpn_openvpn_srv.php 30 Jan 2006 02:25:12 -0000 1.1.2.3
++++ usr/local/www/vpn_openvpn_srv.php 8 Sep 2007 19:08:11 -0000
+@@ -84,6 +84,7 @@
+
+ $pgtitle = "VPN: OpenVPN";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+ <?php include("fbegin.inc"); ?>
+Index: usr/local/www/vpn_openvpn_srv_edit.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/Attic/vpn_openvpn_srv_edit.php,v
+retrieving revision 1.1.2.3
+diff -u -r1.1.2.3 vpn_openvpn_srv_edit.php
+--- usr/local/www/vpn_openvpn_srv_edit.php 30 Jan 2006 02:25:12 -0000 1.1.2.3
++++ usr/local/www/vpn_openvpn_srv_edit.php 8 Sep 2007 19:08:16 -0000
+@@ -513,6 +513,7 @@
+
+ $pgtitle = "VPN: OpenVPN: Edit server";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+ <body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+Index: usr/local/www/vpn_pppoe.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/vpn_pppoe.php,v
+retrieving revision 1.14.2.8.2.1
+diff -u -r1.14.2.8.2.1 vpn_pppoe.php
+--- usr/local/www/vpn_pppoe.php 27 Apr 2007 20:19:26 -0000 1.14.2.8.2.1
++++ usr/local/www/vpn_pppoe.php 8 Sep 2007 19:08:22 -0000
+@@ -139,6 +139,7 @@
+
+ $pgtitle = "VPN: PPPoE";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/vpn_pppoe_users.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/vpn_pppoe_users.php,v
+retrieving revision 1.5.2.4.2.1
+diff -u -r1.5.2.4.2.1 vpn_pppoe_users.php
+--- usr/local/www/vpn_pppoe_users.php 8 May 2007 22:06:49 -0000 1.5.2.4.2.1
++++ usr/local/www/vpn_pppoe_users.php 8 Sep 2007 19:08:26 -0000
+@@ -67,6 +67,7 @@
+
+ $pgtitle = "VPN: PPPoE: Users";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/vpn_pppoe_users_edit.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/vpn_pppoe_users_edit.php,v
+retrieving revision 1.3.2.3
+diff -u -r1.3.2.3 vpn_pppoe_users_edit.php
+--- usr/local/www/vpn_pppoe_users_edit.php 11 Mar 2006 20:35:47 -0000 1.3.2.3
++++ usr/local/www/vpn_pppoe_users_edit.php 8 Sep 2007 19:08:32 -0000
+@@ -113,6 +113,7 @@
+
+ $pgtitle = "VPN: PPPoE: User: Edit";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+ <body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+Index: usr/local/www/vpn_pptp.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/vpn_pptp.php,v
+retrieving revision 1.21.2.5
+diff -u -r1.21.2.5 vpn_pptp.php
+--- usr/local/www/vpn_pptp.php 5 May 2006 02:15:20 -0000 1.21.2.5
++++ usr/local/www/vpn_pptp.php 8 Sep 2007 19:08:36 -0000
+@@ -148,6 +148,7 @@
+
+ $pgtitle = "VPN PPTP";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/vpn_pptp_users.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/vpn_pptp_users.php,v
+retrieving revision 1.16.2.3.2.1
+diff -u -r1.16.2.3.2.1 vpn_pptp_users.php
+--- usr/local/www/vpn_pptp_users.php 8 May 2007 22:06:49 -0000 1.16.2.3.2.1
++++ usr/local/www/vpn_pptp_users.php 8 Sep 2007 19:08:42 -0000
+@@ -65,6 +65,7 @@
+
+ $pgtitle = "VPN: PPTP: Users";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+
+Index: usr/local/www/vpn_pptp_users_edit.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/vpn_pptp_users_edit.php,v
+retrieving revision 1.12.4.3
+diff -u -r1.12.4.3 vpn_pptp_users_edit.php
+--- usr/local/www/vpn_pptp_users_edit.php 19 Jan 2007 16:39:07 -0000 1.12.4.3
++++ usr/local/www/vpn_pptp_users_edit.php 8 Sep 2007 19:08:47 -0000
+@@ -110,6 +110,7 @@
+
+ $pgtitle = "VPN: PPTP: User: Edit";
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+ <body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+Index: usr/local/www/wizard.php
+===================================================================
+RCS file: /cvsroot/pfSense/usr/local/www/wizard.php,v
+retrieving revision 1.46.2.15
+diff -u -r1.46.2.15 wizard.php
+--- usr/local/www/wizard.php 6 Feb 2007 19:33:01 -0000 1.46.2.15
++++ usr/local/www/wizard.php 8 Sep 2007 19:08:58 -0000
+@@ -148,6 +148,7 @@
+
+ $pgtitle = $title;
+ include("head.inc");
++echo $pfSenseHead->getHTML();
+
+ ?>
+ <body link="#0000CC" vlink="#0000CC" alink="#0000CC" onLoad="enablechange();">
diff --git a/config/authng/doc/images/pfSense-AuthMethods.png b/config/authng/doc/images/pfSense-AuthMethods.png
new file mode 100644
index 00000000..afd62083
--- /dev/null
+++ b/config/authng/doc/images/pfSense-AuthMethods.png
Binary files differ
diff --git a/config/authng/doc/images/pfSense-Backends.png b/config/authng/doc/images/pfSense-Backends.png
new file mode 100644
index 00000000..9086f5d4
--- /dev/null
+++ b/config/authng/doc/images/pfSense-Backends.png
Binary files differ
diff --git a/config/authng/doc/images/pfSense-Peers.png b/config/authng/doc/images/pfSense-Peers.png
new file mode 100644
index 00000000..b1ca8ea7
--- /dev/null
+++ b/config/authng/doc/images/pfSense-Peers.png
Binary files differ
diff --git a/config/authng/pkg/authng.inc b/config/authng/pkg/authng.inc
new file mode 100644
index 00000000..06774acd
--- /dev/null
+++ b/config/authng/pkg/authng.inc
@@ -0,0 +1,323 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.inc
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+/* PHP classes like factories users, and groups */
+require_once("authng_classdefs.inc");
+/* PHP classes representing specific auth methods */
+require_once("authng_authmethods.inc");
+/* PHP classes representing specific backends */
+require_once("authng_backends.inc");
+/* PHP peer classes that are providing a persistence layer */
+require_once("authng_peers.inc");
+
+// TODO: Define user- and groupindex array
+
+// get principal store type from config.xml
+// TODO: needs to be defined in config.xml
+//$principalStore = $config['system']['webgui']['principal_store'];
+$principalStore = "xml";
+// get PeerFactory instance
+$peerFactory =& PeerFactory::getInstance();
+// get the actual UserPeer that holds the user index
+$userPeer =& $peerFactory->getUserPeerByPrincipalStore($principalStore);
+// get the actual GroupPeer that holds the user index
+$groupPeer =& $peerFactory->getGroupPeerByPrincipalStore($principalStore);
+// get AuthMethodFactory instance
+$authMethodFactory =& AuthMethodFactory::getInstance();
+// get BackendFactory instance
+$backendFactory =& BackendFactory::getInstance();
+// get the actual auth method
+$authMethod =& $authMethodFactory->getAuthMethodByName($config['system']['webgui']['auth_method']);
+// get the actual backend
+$backend =& $backendFactory->getBackendByName($config['system']['webgui']['backing_method']);
+
+function getUsermanagerPagetitle() {
+ global $userPeer;
+
+ $result = "";
+
+ if ($userPeer->isSystemAdmin($HTTP_SERVER_VARS['AUTH_USER'])) {
+ // Page title for admins
+ $result = array(gettext("System"), gettext("User manager"));
+ } else {
+ // Page title for non-admins
+ $result = array(gettext("System"), gettext("User password"));
+ }
+
+ return $result;
+}
+
+function processUserManagerPostVars() {
+ global $input_errors, $savemsg, $config;
+
+ if (isset($_POST['save'])) {
+ unset($input_errors);
+
+ /* input validation */
+ $reqdfields = explode(" ", "passwordfld1");
+ $reqdfieldsn = explode(",", "Password");
+
+ do_input_validation($_POST, $reqdfields, $reqdfieldsn, &$input_errors);
+
+ if ($_POST['passwordfld1'] != $_POST['passwordfld2'])
+ $input_errors[] = "The passwords do not match.";
+
+ if (!$input_errors) {
+ // all values are okay --> saving changes
+ $config['system']['user'][$userindex[$HTTP_SERVER_VARS['AUTH_USER']]]['password'] = crypt(trim($_POST['passwordfld1']));
+
+ write_config();
+
+ sync_webgui_passwords();
+
+ $retval = system_password_configure();
+ $savemsg = get_std_save_message($retval);
+ $savemsg = "Password successfully changed<br />";
+ }
+ }
+}
+
+function processUserManagerAdminPostVars() {
+ global $config;
+
+ $id = $_GET['id'];
+ if (isset($_POST['id']))
+ $id = $_POST['id'];
+
+ if (!is_array($config['system']['user'])) {
+ $config['system']['user'] = array();
+ }
+
+ admin_users_sort();
+ $a_user = &$config['system']['user'];
+ $t_privs = $a_user[$id]['priv'];
+
+ if ($_GET['act'] == "del" && $_GET['what'] == "user") {
+ if ($a_user[$_GET['id']]) {
+ $userdeleted = $a_user[$_GET['id']]['name'];
+ unset($a_user[$_GET['id']]);
+ write_config();
+ $retval = system_password_configure();
+ $savemsg = get_std_save_message($retval);
+ $savemsg = gettext("User") . " " . $userdeleted . " " . gettext("successfully deleted") . "<br />";
+ }
+ } else if ($_GET['act'] == "del" && $_GET['what'] == "priv") {
+ if ($t_privs[$_GET['privid']]) {
+ $privdeleted = $t_privs[$_GET['privid']]['id'];
+ unset($t_privs[$_GET['privid']]);
+ write_config();
+ $_GET['act'] = "edit";
+ $retval = 0;
+ $savemsg = get_std_save_message($retval);
+ $savemsg = gettext("Privilege") . " " . $privdeleted . " " . gettext("of user") . " " . $a_user[$_GET['id']]['name'] . " " . gettext("successfully deleted") . "<br />";
+ }
+ }
+
+ if ($_POST) {
+ unset($input_errors);
+ $pconfig = $_POST;
+
+ /* input validation */
+ if (isset($id) && ($a_user[$id])) {
+ $reqdfields = explode(" ", "usernamefld");
+ $reqdfieldsn = explode(",", "Username");
+ } else {
+ $reqdfields = explode(" ", "usernamefld passwordfld1");
+ $reqdfieldsn = explode(",", "Username,Password");
+ }
+
+ do_input_validation($_POST, $reqdfields, $reqdfieldsn, &$input_errors);
+
+ if (hasShellAccess($_POST['usernamefld'])) {
+ if (preg_match("/[^a-zA-Z0-9\.\-_]/", $_POST['usernamefld']))
+ $input_errors[] = gettext("The username contains invalid characters.");
+ } else {
+ if (preg_match("/[^a-zA-Z0-9\@\.\-_]/", $_POST['usernamefld']))
+ $input_errors[] = gettext("The username contains invalid characters.");
+ }
+
+ if (($_POST['passwordfld1']) && ($_POST['passwordfld1'] != $_POST['passwordfld2']))
+ $input_errors[] = gettext("The passwords do not match.");
+
+ if (!$input_errors && !(isset($id) && $a_user[$id])) {
+ /* make sure there are no dupes */
+ foreach ($a_user as $userent) {
+ if ($userent['name'] == $_POST['usernamefld']) {
+ $input_errors[] = gettext("Another entry with the same username already exists.");
+ break;
+ }
+ }
+ }
+
+ if ($pconfig['utype'] <> "system" && !isset($groupindex[$_POST['groupname']])) {
+ $input_errors[] = gettext("group does not exist, please define the group before assigning users.");
+ }
+
+ if (isset($config['system']['ssh']['sshdkeyonly']) &&
+ empty($_POST['authorizedkeys'])) {
+ $input_errors[] = gettext("You must provide an authorized key otherwise you won't be able to login into this system.");
+ }
+
+ /* if this is an AJAX caller then handle via JSON */
+ if (isAjax() && is_array($input_errors)) {
+ input_errors2Ajax($input_errors);
+ exit;
+ }
+
+ if (!$input_errors) {
+ if (isset($id) && $a_user[$id])
+ $userent = $a_user[$id];
+
+ /* the user did change his username */
+ if ($_POST['usernamefld'] <> $_POST['oldusername']) {
+ $_SERVER['REMOTE_USER'] = $_POST['usernamefld'];
+ }
+
+ $userent['name'] = $_POST['usernamefld'];
+ $userent['fullname'] = $_POST['fullname'];
+ if ($pconfig['utype'] <> "system") {
+ $userent['groupname'] = $_POST['groupname'];
+ }
+ isset($_POST['utype']) ? $userent['scope'] = $_POST['utype'] : $userent['scope'] = "system";
+
+ if ($_POST['passwordfld1'])
+ $userent['password'] = crypt($_POST['passwordfld1']);
+
+ if(isset($config['system']['ssh']['sshdkeyonly'])) {
+ $userent['authorizedkeys'] = base64_encode($_POST['authorizedkeys']);
+ }
+
+ if (isset($id) && $a_user[$id])
+ $a_user[$id] = $userent;
+ else
+ $a_user[] = $userent;
+
+ write_config();
+ $retval = system_password_configure();
+ sync_webgui_passwords();
+
+ pfSenseHeader("system_usermanager.php");
+ }
+ }
+}
+
+/**
+ * getWindowJSScriptRefs()
+ *
+ * @return
+ */
+function getWindowJSScriptRefs(){
+ $result = array('<script type="text/javascript" src="/javascript/windows-js/javascript/window.js"></script>',
+ '<script type="text/javascript" src="/javascript/windows-js/javascript/window_effects.js"></script>',
+ '<script type="text/javascript" src="/javascript/windows-js/javascript/debug.js"></script>');
+
+ return $result;
+}
+
+function gotNoUsers() {
+ global $config;
+ return empty($config['installedpackages']['authng']['config']);
+}
+
+/**
+ * openNoUserDefsDialog()
+ *
+ * @param mixed $effectClass
+ * @return
+ */
+function openNoUserDefsDialog($effectClass) {
+ if (gotNoUsers()) {
+ $alertMessage = gettext("No users or groups found. You will be forwarded to the AuthNG wizard to be able to define users and groups.");
+ $dialogScript = "
+ <script type='text/javascript'>
+ var anchor = document.getElementById('popupanchor');
+
+ function forwardToWizard() {
+ window.location.href = '/wizard.php?xml=authng_wizard.xml';
+ }
+
+ function openNoUserDefsDialog(html) {
+ var effect = new PopupEffect(html, {className: '${effectClass}'});
+ Dialog.alert('${alertMessage}',{className:'alphacube', top:150, width:400, height:null, showEffect:effect.show.bind(effect), hideEffect:effect.hide.bind(effect), onOk:forwardToWizard});
+ }
+
+ openNoUserDefsDialog(anchor);
+ </script>
+ ";
+
+ return $dialogScript;
+ }
+}
+
+/**
+ * getWindowJSStyleRefs()
+ *
+ * @return
+ */
+function getWindowJSStyleRefs(){
+ $result = array('<link href="/javascript/windows-js/themes/default.css" rel="stylesheet" type="text/css" />',
+ '<link href="/javascript/windows-js/themes/alert.css" rel="stylesheet" type="text/css" />',
+ '<link href="/javascript/windows-js/themes/alphacube.css" rel="stylesheet" type="text/css" />');
+
+ return $result;
+}
+
+/**
+ * installPackageAuthNG()
+ *
+ * @return
+ */
+function installPackageAuthNG() {
+ mwexec("cd / && /usr/bin/patch < /usr/local/pkg/authng-pfSenseHead.diff");
+ mwexec("cd / && /usr/bin/patch < /usr/local/pkg/authng-fbegin.inc.diff");
+ mwexec("cd / && /usr/bin/patch < /usr/local/pkg/authng-guiconfig.inc.diff");
+ mwexec("cd / && /usr/bin/patch < /usr/local/pkg/authng-globals.inc.diff");
+}
+
+/**
+ * deinstallPackageAuthNG()
+ *
+ * @return
+ */
+function deinstallPackageAuthNG() {
+ mwexec("cd / && /usr/bin/patch -R < /usr/local/pkg/authng-pfSenseHead.diff");
+ mwexec("cd / && /usr/bin/patch -R < /usr/local/pkg/authng-fbegin.inc.diff");
+ mwexec("cd / && /usr/bin/patch -R < /usr/local/pkg/authng-guiconfig.inc.diff");
+ mwexec("cd / && /usr/bin/patch -R < /usr/local/pkg/authng-globals.inc.diff");
+}
+?> \ No newline at end of file
diff --git a/config/authng/pkg/authng.xml b/config/authng/pkg/authng.xml
new file mode 100644
index 00000000..cebcea93
--- /dev/null
+++ b/config/authng/pkg/authng.xml
@@ -0,0 +1,194 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>
+ This package provides a user- and groupmanager which
+ allows to add arbitrary groups to the system and assign
+ them to a particular group.
+
+ Permission control is provided on a per group basis.
+ </description>
+ <requirements>
+ This package is supposed to be run on RELENG based pfSense systems.
+ </requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>authng</name>
+ <version>1.0</version>
+ <title>System: User Manager</title>
+ <include_file>/usr/local/pkg/authng.inc</include_file>
+ <!-- Menu is where this packages menu will appear -->
+ <menu>
+ <name>Auth Manager</name>
+ <section>System</section>
+ <url>/system_usermanager.php</url>
+ </menu>
+ <!--
+ <service>
+ <name>yourservice</name>
+ <rcfile>/usr/local/etc/rc.d/yourservice.sh</rcfile>
+ </service>
+ -->
+ <tabs />
+ <!--
+ configpath gets expanded out automatically and config items
+ will be stored in that location
+ -->
+ <configpath>['installedpackages']['authng']['config']</configpath>
+ <!--
+ |
+ | PHP files (user management)
+ |
+ -->
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/authng/www/php/system_usermanager.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/authng/www/php/system_usermanager_edit.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/authng/www/php/system_usermanager_settings.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/authng/www/php/system_groupmanager.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/authng/www/php/head.inc</item>
+ </additional_files_needed>
+ <!--
+ |
+ | Include files (class defs etc.)
+ |
+ -->
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/authng/pkg/authng_classdefs.inc</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/authng/pkg/authng_peers.inc</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/authng/pkg/authng.inc</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/authng/pkg/authng_backends.inc</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/authng/pkg/authng_authmethods.inc</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/authng/pkg/authng_authgui.inc</item>
+ </additional_files_needed>
+ <!--
+ |
+ | Patch files
+ |
+ -->
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/authng/diff/authng-pfSenseHead.diff</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/authng/diff/authng-fbegin.inc.diff</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/authng/diff/authng-globals.inc.diff</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/authng/diff/authng-guiconfig.inc.diff</item>
+ </additional_files_needed>
+ <!--
+ |
+ | Binary files
+ |
+ -->
+ <additional_files_needed>
+ <prefix>/usr/bin/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/authng/bin/patch</item>
+ </additional_files_needed>
+ <!--
+ fields gets invoked when the user adds or edits a item. The following items
+ will be parsed and rendered for the user as a gui with input, and selectboxes.
+ -->
+ <!--
+ Arbitrary PHP Code, that gets executed if a certain event gets triggered.
+ -->
+ <custom_php_resync_config_command>
+ syncPackageAuthNG();
+ </custom_php_resync_config_command>
+ <custom_php_install_command>
+ installPackageAuthNG();
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ deinstallPackageAuthNG();
+ </custom_php_deinstall_command>
+</packagegui>
diff --git a/config/authng/pkg/authng_authgui.inc b/config/authng/pkg/authng_authgui.inc
new file mode 100644
index 00000000..944c9b89
--- /dev/null
+++ b/config/authng/pkg/authng_authgui.inc
@@ -0,0 +1,287 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng_authgui.inc
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+require_once("authng.inc");
+
+/* Authenticate user - exit if failed (we should have a callback for this maybe) */
+if (empty($authMethod)) { print "auth_method missing!\n"; }
+if (empty($backend)) { print "backing_method missing!\n"; }
+if (!$authMethod->authenticate($backend)) { exit; }
+
+/* scriptname is set in headjs.php if the user did try to access a page other
+ * than index.php without beeing logged in.
+ */
+if (isset($_POST['scriptname']) && $userPeer->isSystemAdmin($HTTP_SERVER_VARS['AUTH_USER'])) {
+ pfSenseHeader("{$_POST['scriptname']}");
+ exit;
+}
+
+$allowed = array();
+
+// Once here, the user has authenticated with the web server.
+// Now, we give them access only to the appropriate pages for their group.
+if (!($userPeer->isSystemAdmin($HTTP_SERVER_VARS['AUTH_USER']))) {
+ $allowed[] = '';
+ if (isset($config['system']['group'][$groupindex[$config['system']['user'][$userindex[$HTTP_SERVER_VARS['AUTH_USER']]]['groupname']]]['pages'][0]['page'])) {
+ $useridx = $userindex[$HTTP_SERVER_VARS['AUTH_USER']];
+ $grouidx = $groupindex[$config['system']['user'][$useridx]];
+ $allowed = &$config['system']['group'][$groupidx]['pages'][0]['page'];
+ }
+
+ $group = $config['system']['user'][$userindex[$HTTP_SERVER_VARS['AUTH_USER']]]['groupname'];
+ /* get the group homepage, to be able to forward
+ * the user to this particular PHP page.
+ */
+ $groupPeer->getGroupHomePage($group) == "" ? $home = "/index.php" : $home = "/" . $groupPeer->getGroupHomePage($group);
+
+ /* okay but if the user realy tries to explicitely access a particular
+ * page, set $home to that page instead.
+ */
+ if (isset($_POST['scriptname']) && $_POST['scriptname'] <> "/" && $_POST['scriptname'] <> "/index.php")
+ $home = basename($_POST['scriptname']);
+
+ // If the user is attempting to hit the default page, set it to specifically look for /index.php.
+ // Without this, any user would have access to the index page.
+ //if ($_SERVER['SCRIPT_NAME'] == '/')
+ // $_SERVER['SCRIPT_NAME'] = $home;
+
+ // Strip the leading / from the currently requested PHP page
+ if (!in_array(basename($_SERVER['SCRIPT_NAME']),$allowed)) {
+ // The currently logged in user is not allowed to access the page
+ // they are attempting to go to. Redirect them to an allowed page.
+
+ if(stristr($_SERVER['SCRIPT_NAME'],"sajax")) {
+ echo "||Access to AJAX has been disallowed for this user.";
+ exit;
+ }
+
+ if ($home <> "" && in_array($home, $allowed)) {
+ pfSenseHeader("{$home}");
+ exit;
+ } else {
+ header("HTTP/1.0 401 Unauthorized");
+ header("Status: 401 Unauthorized");
+
+ echo display_error_form("401", "401 Unauthorized. Authorization required.");
+ exit;
+ }
+ }
+
+ if (isset($_SESSION['Logged_In'])) {
+ /*
+ * only forward if the user has just logged in
+ * TODO: session auth based - may be an issue.
+ */
+ if ($_SERVER['SCRIPT_NAME'] <> $home && empty($_SESSION['First_Visit'])) {
+ $_SESSION['First_Visit'] = "False";
+ pfSenseHeader("{$home}");
+ exit;
+ }
+ }
+}
+
+function display_error_form($http_code, $desc) {
+ global $g;
+
+ $htmlstr = <<<EOD
+<html>
+ <head>
+ <script type="text/javascript" src="/javascript/scriptaculous/prototype.js"></script>
+ <script type="text/javascript" src="/javascript/scriptaculous/scriptaculous.js"></script>
+ <title>An error occurred: {$http_code}</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+ <link rel="shortcut icon" href="/themes/{$g['theme']}/images/icons/favicon.ico" />
+ <link rel="stylesheet" type="text/css" href="/themes/{$g['theme']}/all.css" media="all" />
+ <style type="text/css">
+ #errordesc {
+ background: #cccccc;
+ border: 0px solid #666666;
+ margin: 5em auto;
+ padding: 0em;
+ width: 340px;
+ }
+ #errordesc h1 {
+ background: url(/themes/{$g['theme']}/images/misc/logon.png) no-repeat top left;
+ margin-top: 0;
+ display: block;
+ text-indent: -1000px;
+ height: 50px;
+ border-bottom: none;
+ }
+
+ #login p {
+ font-size: 1em;
+ font-weight: bold;
+ padding: 3px;
+ margin: 0em;
+ text-indent: 10px;
+ }
+
+ #login span {
+ font-size: 1em;
+ font-weight: bold;
+ width: 20%;
+ padding: 3px;
+ margin: 0em;
+ text-indent: 10px;
+ }
+
+ #login p#text {
+ font-size: 1em;
+ font-weight: normal;
+ padding: 3px;
+ margin: 0em;
+ text-indent: 10px;
+ }
+ </style>
+
+ <script type="text/javascript">
+ <!--
+ function page_load() {
+ NiftyCheck();
+ Rounded("div#errordesc","bl br","#333","#cccccc","smooth");
+ Effect.Pulsate('errortext', { duration: 10 });
+ }
+ <?php
+ require("headjs.php");
+ echo getHeadJS();
+ ?>
+ //-->
+ </script>
+ <script type="text/javascript" src="/themes/{$g['theme']}/javascript/niftyjsCode.js"></script>
+ </head>
+ <body onload="page_load();">
+ <div id="errordesc">
+ <h1>&nbsp</h1>
+ <p id="errortext" style="vertical-align: middle; text-align: center;"><span style="color: #000000; font-weight: bold;">{$desc}</span></p>
+ </div>
+ </body>
+</html>
+
+EOD;
+
+ return $htmlstr;
+}
+
+function display_login_form() {
+ require_once("globals.inc");
+ global $g;
+
+ if(isAjax()) {
+ if (isset($_POST['login'])) {
+ if($_SESSION['Logged_In'] <> "True") {
+ isset($_SESSION['Login_Error']) ? $login_error = $_SESSION['Login_Error'] : $login_error = "unknown reason";
+ echo "showajaxmessage('Invalid login ({$login_error}).');";
+ }
+ if (file_exists("{$g['tmp_path']}/webconfigurator.lock")) {
+ $whom = file_get_contents("{$g['tmp_path']}/webconfigurator.lock");
+ echo "showajaxmessage('This device is currently beeing maintained by: {$whom}.');";
+ }
+ }
+ exit;
+ }
+
+?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html>
+ <head>
+ <script type="text/javascript" src="/javascript/scriptaculous/prototype.js"></script>
+ <script type="text/javascript" src="/javascript/scriptaculous/scriptaculous.js"></script>
+ <title><?=gettext("Login"); ?></title>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+ <link rel="shortcut icon" href="/themes/<?= $g['theme'] ?>/images/icons/favicon.ico" />
+ <?php if (file_exists("{$g['www_path']}/themes/{$g['theme']}/login.css")): ?>
+ <link rel="stylesheet" type="text/css" href="/themes/<?= $g['theme'] ?>/login.css" media="all" />
+ <?php else: ?>
+ <link rel="stylesheet" type="text/css" href="/themes/<?= $g['theme'] ?>/all.css" media="all" />
+ <?php endif; ?>
+ <script type="text/javascript">
+ <!--
+ <?php if (file_exists("{$g['www_path']}/themes/{$g['theme']}/login.css")): ?>
+ var dontUseCustomBGColor = false;
+ <?php else: ?>
+ var dontUseCustomBGColor = true;
+ <?php endif; ?>
+ function page_load() {
+ NiftyCheck();
+ Rounded("div#login","bl br","#333","#cccccc","smooth");
+ document.login_iform.usernamefld.focus();
+ }
+ function clearError() {
+ if($('inputerrors'))
+ $('inputerrors').innerHTML='';
+ }
+ <?php
+// require("headjs.php");
+// echo getHeadJS();
+ ?>
+ //-->
+ </script>
+ <script type="text/javascript" src="/themes/<?= $g['theme'] ?>/javascript/niftyjsCode.js"></script>
+ </head>
+ <body onload="page_load()">
+ <div id="login">
+ <h1>&nbsp;</h1>
+ <form id="iform" name="login_iform" method="post" autocomplete="off" action="<?= $_SERVER['SCRIPT_NAME'] ?>">
+ <div id="inputerrors"></div>
+ <p>
+ <span style="text-align: left;">
+ <?=gettext("Username"); ?>:&nbsp;&nbsp;
+ </span>
+ <input onclick="clearError();" onchange="clearError();" id="usernamefld" type="text" name="usernamefld" class="formfld user" tabindex="1" />
+ </p>
+ <p>
+ <span style="text-align: left;">
+ <?=gettext("Password"); ?>:&nbsp;&nbsp;
+ </span>
+ <input onclick="clearError();" onchange="clearError();" id="passwordfld" type="password" name="passwordfld" class="formfld pwd" tabindex="2" />
+ </p>
+ <table width="90%" style="margin-right: auto; margin-left: auto;">
+ <tr>
+ <td valign="middle" align="right" style="font-style: italic;"><br /><?=gettext("Enter username and password to login."); ?></td>
+ <td valign="middle" align="left"><input type="submit" id="submit" name="login" class="formbtn" value="<?=gettext("Login"); ?>" tabindex="3" /></td>
+ </tr>
+ </table>
+ </form>
+ </div>
+ </body>
+</html>
+<?php
+} // end function
+?> \ No newline at end of file
diff --git a/config/authng/pkg/authng_authmethods.inc b/config/authng/pkg/authng_authmethods.inc
new file mode 100644
index 00000000..15e15566
--- /dev/null
+++ b/config/authng/pkg/authng_authmethods.inc
@@ -0,0 +1,222 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng_authmethods.inc
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+class AbstractAuthMethod {
+ function authenticate($backend) {
+ trigger_error('AbstractAuthMethod::authenticate() needs to be overridden in a subclass.', E_USER_ERROR);
+ }
+}
+
+class BasicAuthMethod extends AbstractAuthMethod {
+ function authenticate($backend) {
+ global $HTTP_SERVER_VARS;
+
+ /* Check for AUTH_USER */
+ if ($HTTP_SERVER_VARS['PHP_AUTH_USER'] <> "") {
+ $HTTP_SERVER_VARS['AUTH_USER'] = $HTTP_SERVER_VARS['PHP_AUTH_USER'];
+ $HTTP_SERVER_VARS['AUTH_PW'] = $HTTP_SERVER_VARS['PHP_AUTH_PW'];
+ }
+ if (!isset($HTTP_SERVER_VARS['AUTH_USER'])) {
+ require_once("authng_authgui.inc");
+ header("WWW-Authenticate: Basic realm=\".\"");
+ header("HTTP/1.0 401 Unauthorized");
+ display_error_form("401", gettext("You must enter valid credentials to access this resource."));
+ exit;
+ } else {
+ return $backend($HTTP_SERVER_VARS['AUTH_USER'],$HTTP_SERVER_VARS['AUTH_PW']);
+ }
+ }
+}
+
+class SessionAuthMethod extends AbstractAuthMethod {
+ function authenticate($backend) {
+ global $g, $HTTP_SERVER_VARS, $userindex, $config;
+
+ session_start();
+
+ /* Validate incoming login request */
+ if (isset($_POST['login'])) {
+ if ($backend($_POST['usernamefld'], $_POST['passwordfld'])) {
+ $_SESSION['Logged_In'] = "True";
+ $_SESSION['Username'] = $_POST['usernamefld'];
+ $_SESSION['last_access'] = time();
+ } else {
+ $_SESSION['Login_Error'] = "Username or password incorrect.";
+ }
+ }
+
+ /* Show login page if they aren't logged in */
+ if (empty($_SESSION['Logged_In'])) {
+
+ /* Don't display login forms to AJAX */
+ if (isAjax())
+ return false;
+
+ require_once("authng_authgui.inc");
+ display_login_form();
+ return false;
+ } else {
+ /* If session timeout isn't set, we don't mark sessions stale */
+ if (!isset($config['system']['webgui']['session_timeout']) or
+ $config['system']['webgui']['session_timeout'] == 0 or
+ $config['system']['webgui']['session_timeout'] == "")
+ $_SESSION['last_access'] = time();
+ else
+ /* Check for stale session */
+ if ($_SESSION['last_access'] < (time() - ($config['system']['webgui']['session_timeout'] * 60)))
+ $_GET['logout'] = true;
+ else
+ /* only update if it wasn't ajax */
+ if (!isAjax())
+ $_SESSION['last_access'] = time();
+
+ /* user hit the logout button */
+ if (isset($_GET['logout'])) {
+ if (hasLockAbility($_SESSION['Username'])) {
+ unlink_if_exists("{$g['tmp_path']}/webconfigurator.lock");
+ }
+
+ /* wipe out $_SESSION */
+ $_SESSION = array();
+
+ if (isset($_COOKIE[session_name()])) {
+ setcookie(session_name(), '', time()-42000, '/');
+ }
+
+ /* and destroy it */
+ session_destroy();
+
+ $scriptName = split("/", $_SERVER["SCRIPT_FILENAME"]);
+ $scriptElms = count($scriptName);
+ $scriptName = $scriptName[$scriptElms-1];
+
+ if (isAjax())
+ return false;
+
+ /* redirect to page the user is on, it'll prompt them to login again */
+ pfSenseHeader($scriptName);
+
+ return false;
+
+ /* user wants to explicitely delete the log file.
+ * Requires a particular privilege.
+ */
+ } else if ($_GET['deletelock'] && hasLockAbility($_SESSION['Username'])) {
+ unlink_if_exists("{$g['tmp_path']}/webconfigurator.lock");
+ $HTTP_SERVER_VARS['AUTH_USER'] = $_SESSION['Username'];
+ return true;
+
+ /* this is for debugging purpose if you do not want to use Ajax
+ * to submit a HTML form. It basically disables the observation
+ * of the submit event and hence does not trigger Ajax.
+ */
+ } else if ($_GET['disable_ajax']) {
+ $_SESSION['NO_AJAX'] = "True";
+ $HTTP_SERVER_VARS['AUTH_USER'] = $_SESSION['Username'];
+ return true;
+
+ /* Same to re-enable Ajax.
+ */
+ } else if ($_GET['enable_ajax']) {
+ unset($_SESSION['NO_AJAX']);
+ $HTTP_SERVER_VARS['AUTH_USER'] = $_SESSION['Username'];
+ return true;
+
+ /* user wants to explicitely create a lock.
+ * Requires a particular privilege.
+ */
+ } else if ($_GET['createlock'] && hasLockAbility($_SESSION['Username'])) {
+ $fd = fopen("{$g['tmp_path']}/webconfigurator.lock", "w");
+ fputs($fd, "{$_SERVER['REMOTE_ADDR']} (" .
+ getRealName($_SESSION['Username']) . ")");
+ fclose($fd);
+ /* if the user did delete the lock manually, do not
+ * re-create it while the session is valide.
+ */
+ $_SESSION['Lock_Created'] = "True";
+ $HTTP_SERVER_VARS['AUTH_USER'] = $_SESSION['Username'];
+ return true;
+
+ /* proceed with the login process */
+ } else {
+ /* if the user is allowed to create a lock,
+ * create it once per session.
+ */
+ if (hasLockAbility($_SESSION['Username']) &&
+ ! isset($_SESSION['Lock_Created'])) {
+
+ $fd = fopen("{$g['tmp_path']}/webconfigurator.lock", "w");
+ fputs($fd, "{$_SERVER['REMOTE_ADDR']} (" .
+ getRealName($_SESSION['Username']) . ")");
+ fclose($fd);
+ /* if the user did delete the lock manually, do not
+ * re-create it while the session is valide.
+ */
+ $_SESSION['Lock_Created'] = "True";
+
+ /* give regular users a chance to automatically invalidate
+ * a lock if its older than a particular time.
+ */
+ } else if (! hasLockAbility($_SESSION['Username']) &&
+ file_exists("{$g['tmp_path']}/webconfigurator.lock")) {
+
+ $offset = 12; //hours
+ $mtime = filemtime("{$g['tmp_path']}/webconfigurator.lock");
+ $now_minus_offset = mktime(date("H") - $offset, 0, 0, date("m"), date("d"), date("Y"));
+
+ if (($mtime - $now_minus_offset) < $mtime) {
+ require_once("auth/authgui.inc");
+ display_login_form();
+ return false;
+ } else {
+ /* file is older than mtime + offset which may
+ * indicate a stale lockfile, hence we are going
+ * to remove it.
+ */
+ unlink_if_exists("{$g['tmp_path']}/webconfigurator.lock");
+ }
+ }
+
+ $HTTP_SERVER_VARS['AUTH_USER'] = $_SESSION['Username'];
+ return true;
+ } // end if
+ } // end if
+ } // end function
+}
+
+?> \ No newline at end of file
diff --git a/config/authng/pkg/authng_backends.inc b/config/authng/pkg/authng_backends.inc
new file mode 100644
index 00000000..1b58e6c1
--- /dev/null
+++ b/config/authng/pkg/authng_backends.inc
@@ -0,0 +1,234 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng_backends.inc
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+class AbstractBackend {
+ function authenticate($username, $passwd) {
+ trigger_error('AbstractBackend::authenticate() needs to be overridden in a subclass.', E_USER_ERROR);
+ }
+}
+
+class HtpasswdBackend extends AbstractBackend {
+ function HtpasswdBackend() {
+ }
+
+ function authenticate($username, $passd) {
+ $authfile = file("/var/run/htpasswd");
+
+ /* sanity check to ensure that /usr/local/www/.htpasswd doesn't exist */
+ unlink_if_exists("/usr/local/www/.htpasswd");
+
+ $matches="";
+ if(!($line = array_shift(preg_grep("/^$username:.*$/", $authfile))))
+ return false;
+
+ /* Get crypted password */
+ preg_match("/^$username:((\\$1\\$[.\d\w_\/]{8}\\$)[.\d\w_\/]{22})$/", $line, $matches);
+ $pass = $matches[1];
+ $salt = $matches[2];
+
+ /* Encrypt entered password with salt
+ * And finally validate password
+ */
+ if ($pass == crypt($passwd, $salt))
+ return true;
+ else
+ return false;
+ }
+}
+
+class PasswdBackend extends AbstractBackend {
+ function PasswdBackend() {
+ }
+
+ function authenticate($username, $passd) {
+ $authfile = file("/etc/master.passwd");
+
+ $matches="";
+
+ /* Check to see if user even exists */
+ if(!($line = array_shift(preg_grep("/^$username:.*$/", $authfile))))
+ return false;
+
+ /* Get crypted password */
+ preg_match("/^$username:((\\$1\\$[.\d\w_\/]{8}\\$)[.\d\w_\/]{22})$/", $line, $matches);
+ $pass = $matches[1];
+ $salt = $matches[2];
+
+ /* Encrypt entered password with salt
+ * And finally validate password
+ */
+ if ($pass == crypt($passwd, $salt))
+ return true;
+ else
+ return false;
+ }
+}
+
+class PamBackend extends AbstractBackend {
+ function PamBackend() {
+ }
+
+ function authenticate($username, $passd) {
+ /* we do not support blank pwds, don't we? */
+ if ($username == "" || passwd == "") { return false; }
+
+ if(! extension_loaded( 'pam_auth' )) {
+ if(! @dl( 'pam_auth.so' )) {
+ return false;
+ } else {
+ /* no php file no auth, sorry */
+ if (! file_exists("/etc/pam.d/php")) {
+ if (! file_exists("/etc/pam.d")) { mkdir("/etc/pam.d"); }
+
+ $pam_php = <<<EOD
+# /etc/pam.d/php
+#
+# note: both an auth and account entry are required
+
+# auth
+auth required pam_nologin.so no_warn
+auth sufficient pam_opie.so no_warn no_fake_prompts
+auth requisite pam_opieaccess.so no_warn allow_local
+auth required pam_unix.so no_warn try_first_pass
+
+# account
+account required pam_unix.so
+
+# session
+session required pam_permit.so
+
+# password
+password required pam_unix.so no_warn try_first_pass
+
+EOD;
+
+ file_put_contents("/etc/pam.d/php", $pam_php);
+ } // end if
+
+ if (pam_auth($username, $passwd, &$error)) {
+ return true;
+ } else {
+ return false;
+ }
+ } // end if
+ } // end if
+ } // end function
+}
+
+class RadiusBackend extends AbstractBackend {
+ function RadiusBackend() {
+ }
+
+ function authenticate($username, $passwd) {
+ global $config, $debug;
+ $ret = false;
+ $radiusservers = $config['system']['radius']['servers'];
+
+ $rauth = new Auth_RADIUS_PAP($username, $passwd);
+ foreach ($radiusservers as $radsrv) {
+ // Add a new server to our instance
+ $rauth->addServer($radsrv['ipaddr'], $radsrv['port'], $radsrv['sharedsecret']);
+ }
+
+ if (!$rauth->start()) {
+ $retvalue['auth_val'] = 1;
+ $retvalue['error'] = $rauth->getError();
+ if ($debug)
+ printf("Radius start: %s", $retvalue['error']);
+ }
+
+ // XXX - billm - somewhere in here we need to handle securid challenge/response
+
+ // Send request
+ $result = $rauth->send();
+
+ if (PEAR::isError($result)) {
+ $retvalue['auth_val'] = 1;
+ $retvalue['error'] = $result->getMessage();
+ if ($debug)
+ printf("Radius send failed: %s", $retvalue['error']);
+ } else if ($result === true) {
+ $retvalue['auth_val'] = 2;
+ if ($debug)
+ printf (gettext("Radius Auth succeeded"));
+ $ret = true;
+ } else {
+ $retvalue['auth_val'] = 3;
+ if ($debug)
+ printf (gettext("Radius Auth rejected"));
+ }
+ // close OO RADIUS_AUTHENTICATION
+ $rauth->close();
+
+ return $ret;
+ } // end function
+}
+
+class LdapBackend extends AbstractBackend {
+ function LdapBackend() {
+ }
+
+ function authenticate($username, $passwd) {
+ $ldapserver = $config['system']['ldap']['server'];
+ $ldapport = isset($config['system']['ldap']['port']) ? $config['system']['ldap']['server'] : 389;
+ $retval = false;
+
+ $connection = ldap_connect($ldapserver, $ldapport)
+ or die("Could not connect to $ldaphost");
+
+ if ($connection) {
+ $bind = ldap_bind($connection);
+
+ if ($bind) {
+ $basedn = $config['system']['ldap']['basedn'];
+ $result = ldap_search($connection, $basedn, "uid={$username}");
+ $info = ldap_get_entries($connection, $result);
+ $userPassword = $info[0]['userPassword'];
+
+ if ($userPassword == $passwd) {
+ $retval = true;
+ } else {
+ $retval = false;
+ }
+ } // end if
+ } // end if
+
+ return $retval;
+ }
+}
+?> \ No newline at end of file
diff --git a/config/authng/pkg/authng_classdefs.inc b/config/authng/pkg/authng_classdefs.inc
new file mode 100644
index 00000000..64f0ff14
--- /dev/null
+++ b/config/authng/pkg/authng_classdefs.inc
@@ -0,0 +1,479 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng_classdefs.inc
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+class Object {
+ function Object() {
+ $args = func_get_args();
+ if (method_exists($this, '__destruct')) {
+ register_shutdown_function(array(&$this, '__destruct'));
+ }
+ call_user_func_array(array(&$this, '__construct'), $args);
+ }
+
+ function __construct() {
+ }
+}
+
+class SingletonInterface extends Object {
+ function __construct() {
+ // Perform object initialization here.
+ }
+
+ function &__getInstanceImp($name) {
+ static $instances = array();
+ if (!isset($instances[$name])) {
+ $instances[$name] = new $name(); // No changes necessary here.
+ }
+ return $instances[$name];
+ }
+
+ function &getInstance() {
+ trigger_error('SingletonInterface::getInstance() needs to be overridden in a subclass.', E_USER_ERROR);
+ }
+}
+
+class BackendFactory extends SingletonInterface {
+ function __construct() {
+ // Perform object initialization here.
+ parent::__construct();
+ }
+
+ function &getInstance() {
+ return parent::__getInstanceImp('BackendFactory');
+ }
+
+ function &getBackendByName($name) {
+ $result = null;
+
+ /* Each name links to an entry in config.xml
+ * Example: <auth_method>session</auth_method>
+ */
+ switch ($name) {
+ case "htpasswd":
+ $result = new HtpasswdBackend();
+ break;
+ case "pam":
+ $result = new PamBackend();
+ break;
+ case "radius":
+ $result = new RadiusBackend();
+ break;
+ case "passwd":
+ $result = new PasswdBackend();
+ break;
+ case "ldap":
+ $result = new LdapBackend();
+ break;
+ default:
+ }
+
+ return $result;
+ }
+}
+
+class AuthMethodFactory extends SingletonInterface {
+ function __construct() {
+ // Perform object initialization here.
+ parent::__construct();
+ }
+
+ function &getInstance() {
+ return parent::__getInstanceImp('AuthMethodFactory');
+ }
+
+ function &getAuthMethodByName($name) {
+ $result = null;
+
+ /* Each name links to an entry in config.xml
+ * Example: <backing_method>htpasswd</backing_method>
+ */
+ switch ($name) {
+ case "session":
+ $result = new SessionAuthMethod();
+ break;
+ case "basic":
+ $result = new BasicAuthMethod();
+ break;
+ default:
+ }
+
+ return $result;
+ }
+}
+
+class AuthngAuxiliary {
+ /* ========================================================================== */
+ /* == Auxiliary Functions == */
+ /* ========================================================================== */
+ function &getSystemAdminNames() {
+ global $config, $g, $userindex;
+ $adminUsers = array();
+
+ if (is_array($config['system']['user'])) {
+ foreach($config['system']['user'] as $user){
+ if (isSystemAdmin($user['name'])) {
+ $adminUsers[] = $user['name'];
+ }
+ } // end foreach
+ } // end if
+
+ return $adminUsers;
+ } // end function
+
+ function assignUID($username = "") {
+ global $userindex, $config, $g;
+
+ if ($username == "") { return; }
+
+ $nextuid = $config['system']['nextuid'];
+ $user =& $config['system']['user'][$userindex[$username]];
+
+ if (empty($user['uid'])) {
+ $user['uid'] = $nextuid;
+ $nextuid++;
+ $config['system']['nextuid'] = $nextuid;
+
+ write_config();
+
+ return $user;
+ } // end if
+ } // end function
+}
+
+class AuthngPrivilege {
+ /* ========================================================================== */
+ /* == Class Members == */
+ /* ========================================================================== */
+
+ var $id;
+ var $name;
+ var $description;
+
+ /* ========================================================================== */
+ /* == Constructor == */
+ /* ========================================================================== */
+
+ function AuthngPrivilege() {
+ }
+
+ /* ========================================================================== */
+ /* == Accessors == */
+ /* ========================================================================== */
+
+ function getId() {
+ return $this->id;
+ }
+
+ function setId($id) {
+ $this->id = $id;
+ }
+
+ function getName() {
+ return $this->name;
+ }
+
+ function setName($name) {
+ $this->name = $name;
+ }
+
+ function getDescription() {
+ return $this->description;
+ }
+
+ function setDescription($desc) {
+ $this->description = $desc;
+ }
+}
+
+class SystemPrivileges {
+ /* ========================================================================== */
+ /* == Class Members == */
+ /* ========================================================================== */
+
+ var $privileges = array();
+
+ /* ========================================================================== */
+ /* == Constructor == */
+ /* ========================================================================== */
+
+ function SystemPrivileges() {
+ $newPriv = new Privilege();
+ $newPriv->setId("lockwc");
+ $newPriv->setName("Lock webConfigurator");
+ $newPriv->setDescription("Indicates whether this user will lock access to the webConfigurator for other users.");
+
+ $this->privileges[$newPriv->getId()] = $newPriv;
+
+ $newPriv = new Privilege();
+ $newPriv->setId("lock-ipages");
+ $newPriv->setName("Lock individual pages");
+ $newPriv->setDescription("Indicates whether this user will lock individual " .
+ "HTML pages after having accessed a particular page" .
+ "(the lock will be freed if the user leaves or " .
+ "saves the page form).");
+
+ $this->privileges[$newPriv->getId()] = $newPriv;
+
+ $newPriv = new Privilege();
+ $newPriv->setId("hasshell");
+ $newPriv->setName("Has shell access");
+ $newPriv->setDescription("Indicates whether this user is able to login for " .
+ "example via SSH.");
+
+ $this->privileges[$newPriv->getId()] = $newPriv;
+
+ $newPriv = new Privilege();
+ $newPriv->setId("copyfiles");
+ $newPriv->setName("Is allowed to copy files");
+ $newPriv->setDescription("Indicates whether this user is allowed to copy files " .
+ "onto the {$g['product_name']} appliance via SCP/SFTP. " .
+ "If you are going to use this privilege, you must install " .
+ "scponly on the appliance (Hint: pkg_add -r scponly).");
+
+ $this->privileges[$newPriv->getId()] = $newPriv;
+
+ $newPriv = new Privilege();
+ $newPriv->setId("isroot");
+ $newPriv->setName("Is root user");
+ $newPriv->setDescription("This user is associated with the UNIX root user " .
+ "(you should associate this privilege only with one " .
+ "single user).");
+
+ $this->privileges[$newPriv->getId()] = $newPriv;
+ }
+
+ /* ========================================================================== */
+ /* == Accessors == */
+ /* ========================================================================== */
+
+ function getPrivileges() {
+ return $this->privileges;
+ }
+
+ function setPrivileges($privs) {
+ $this->privileges = $privs;
+ }
+
+ function getPrivilegeById($id) {
+ return $this->privileges[$id];
+ }
+
+ function setPrivilegeById($privilege, $id) {
+ return $this->privileges[$id] = $privilege;
+ }
+}
+
+class AuthngUser {
+ /* ========================================================================== */
+ /* == Class Members == */
+ /* ========================================================================== */
+
+ var $name;
+ var $fullname;
+ var $scope;
+ var $groupname;
+ var $password;
+ var $uid;
+ var $systemAdmin = false;
+ var $unixRoot = false;
+ var $privileges = array();
+
+ /* ========================================================================== */
+ /* == Constructor == */
+ /* ========================================================================== */
+
+ function AuthngUser() {
+ }
+
+ /* ========================================================================== */
+ /* == Accessors == */
+ /* ========================================================================== */
+
+ function isSystemAdmin() {
+ return $this->systemAdmin;
+ }
+
+ function setIsSystemAdmin($flag = false) {
+ $this->systemAdmin = $flag;
+ }
+
+ function isUNIXRoot() {
+ return $this->unixRoot;
+ }
+
+ function setIsUNIXRoot($flag = false) {
+ $this->unixRoot = $flag;
+ }
+
+ function getName() {
+ return $this->name;
+ }
+
+ function setName($name) {
+ $this->name = $name;
+ }
+
+ function getFullname() {
+ return $this->fullname;
+ }
+
+ function setFullname($name) {
+ $this->fullname = $name;
+ }
+
+ function getScope() {
+ return $this->scope;
+ }
+
+ function setScope($scope) {
+ $this->scope = $scope;
+ }
+
+ function getGroupname() {
+ return $this->groupname;
+ }
+
+ function setGroupname($name) {
+ $this->groupname = $name;
+ }
+
+ function getPassword() {
+ return $this->password;
+ }
+
+ function setPassword($pwd) {
+ $this->password = $pwd;
+ }
+
+ function getUid() {
+ return $this->uid;
+ }
+
+ function setUid($uid) {
+ $this->uid = $uid;
+ }
+
+ function getPrivileges() {
+ return $this->privileges;
+ }
+
+ function setPrivileges($privs) {
+ $this->privileges = $privs;
+ }
+
+ function addPrivilege($priv) {
+ $this->privileges[] = $priv;
+ }
+}
+
+class AuthngGroup {
+ /* ========================================================================== */
+ /* == Class Members == */
+ /* ========================================================================== */
+
+ var $name;
+ var $description;
+ var $scope;
+ var $pages = array();
+ var $home;
+ var $gid;
+
+ /* ========================================================================== */
+ /* == Constructor == */
+ /* ========================================================================== */
+
+ function AuthngGroup() {
+ }
+
+ /* ========================================================================== */
+ /* == Accessors == */
+ /* ========================================================================== */
+
+ function getName() {
+ return $this->name;
+ }
+
+ function setName($name) {
+ $this->name = $name;
+ }
+
+ function getDescription() {
+ return $this->description;
+ }
+
+ function setDescription($desc) {
+ $this->description = $desc;
+ }
+
+ function getScope() {
+ return $this->scope;
+ }
+
+ function setScope($scope) {
+ $this->scope = $scope;
+ }
+
+ function getPages() {
+ return $this->pages;
+ }
+
+ function setPages($pages) {
+ $this->pages = $pages;
+ }
+ function getHome() {
+ return $this->home;
+ }
+
+ function setHome($home) {
+ $this->home = $home;
+ }
+
+ function getGid() {
+ return $this->gid;
+ }
+
+ function setGid($gid) {
+ $this->gid = $gid;
+ }
+
+ function addPage($page) {
+ $this->pages[] = $page;
+ }
+}
+
+?> \ No newline at end of file
diff --git a/config/authng/pkg/authng_peers.inc b/config/authng/pkg/authng_peers.inc
new file mode 100644
index 00000000..bce3c494
--- /dev/null
+++ b/config/authng/pkg/authng_peers.inc
@@ -0,0 +1,501 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng_peers.inc
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+class PeerFactory extends SingletonInterface {
+ function __construct() {
+ // Perform object initialization here.
+ parent::__construct();
+ }
+
+ function &getInstance() {
+ return parent::__getInstanceImp('PeerFactory');
+ }
+
+ function &getGroupPeerByPrincipalStore($store) {
+ $result = null;
+
+ /* Each name links to an entry in config.xml
+ * Example: <principal_store>xml</principal_store>
+ */
+ switch ($store) {
+ case "xml":
+ $result = new XMLGroupPeer();
+ break;
+ case "ldap":
+ trigger_error('PeerFactory::getGroupPeerByPrincipal() LDAP peer type is not supported.', E_USER_ERROR);
+ break;
+ case "db":
+ trigger_error('PeerFactory::getGroupPeerByPrincipal() DB peer type is not supported.', E_USER_ERROR);
+ break;
+ default:
+ }
+
+ return $result;
+ }
+
+ function &getUserPeerByPrincipalStore($store) {
+ $result = null;
+
+ /* Each name links to an entry in config.xml
+ * Example: <principal_store>xml</principal_store>
+ */
+ switch ($store) {
+ case "xml":
+ $result = new XMLUserPeer();
+ break;
+ case "ldap":
+ trigger_error('PeerFactory::getGroupPeerByPrincipal() LDAP peer type is not supported.', E_USER_ERROR);
+ break;
+ case "db":
+ trigger_error('PeerFactory::getGroupPeerByPrincipal() DB peer type is not supported.', E_USER_ERROR);
+ break;
+ default:
+ }
+
+ return $result;
+ }
+}
+
+/**
+ * @author Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ * @abstract
+ */
+class AbstractPrivilegePeer {
+ /* ========================================================================== */
+ /* == Class Members == */
+ /* ========================================================================== */
+
+ var $privilege_index;
+ var $privileges;
+ var $userPeer;
+
+ /* ========================================================================== */
+ /* == Constructor == */
+ /* ========================================================================== */
+
+ function AbstractPrivilegePeer() {
+ }
+
+ /* ========================================================================== */
+ /* == Accessors == */
+ /* ========================================================================== */
+
+ function setUserPeer($peer) {
+ $this->userPeer = $peer;
+ }
+
+ function getUserPeer() {
+ return $this->userPeer;
+ }
+
+ /**
+ * @return mixed int array of priv indexes
+ */
+ function getPrivilegeIndex() {
+ return $this->privilege_index;
+ }
+
+ /**
+ * @param string a priv name
+ * @return int the index that corresponds to a username
+ */
+ function getPrivilegeIndexByID($id) {
+ return $this->privilege_index[$id];
+ }
+
+ /**
+ * @param int an index
+ * @return mixed an instance of AuthngPrivilege
+ */
+ function getPrivilegeByIndex($index) {
+ return $this->privileges[$index];
+ }
+}
+
+/**
+ * @author Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ * @abstract
+ */
+class AbstractUserPeer {
+ /* ========================================================================== */
+ /* == Class Members == */
+ /* ========================================================================== */
+
+ var $user_index;
+ var $users;
+
+ /* ========================================================================== */
+ /* == Constructor == */
+ /* ========================================================================== */
+
+ function AbstractUserPeer() {
+ }
+
+ /* ========================================================================== */
+ /* == Accessors == */
+ /* ========================================================================== */
+
+ /**
+ * @return mixed int array of user indexes
+ */
+ function getUserIndex() {
+ return $this->user_index;
+ }
+
+ /**
+ * @param string a username
+ * @return int the index that corresponds to a username
+ */
+ function getUserIndexByName($username) {
+ return $this->user_index[$username];
+ }
+
+ /**
+ * @param int an index
+ * @return mixed an instance of AuthngUser
+ */
+ function getUserByIndex($index) {
+ return $this->users[$index];
+ }
+
+ function getUserByName($username) {
+ return $this->users[$username];
+ }
+
+ function isSystemAdmin($username) {
+ $result = false;
+ $user = $this->getUserByName($username);
+
+ if ($user) {
+ $result = $user->isSystemAdmin();
+ }
+
+ return $result;
+ }
+}
+
+/**
+ * @author Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ * @abstract
+ */
+class AbstractGroupPeer {
+ /* ========================================================================== */
+ /* == Class Members == */
+ /* ========================================================================== */
+
+ var $group_index;
+ var $groups;
+
+ /* ========================================================================== */
+ /* == Constructor == */
+ /* ========================================================================== */
+
+ function AbstractGroupPeer() {
+ }
+
+ /* ========================================================================== */
+ /* == Accessors == */
+ /* ========================================================================== */
+
+ function getGroupIndex() {
+ return $this->group_index;
+ }
+
+ function getGroupIndexByName($groupname) {
+ return $this->group_index[$groupname];
+ }
+
+ function getGroupByIndex($index) {
+ return $this->groups[$index];
+ }
+
+ function getGroupByName($groupname) {
+ return $this->groups[$groupname];
+ }
+
+ function getGroupHomePage($groupname) {
+ $result = false;
+ $group = $this->getGroupByName($groupname);
+
+ if ($group) {
+ $result = $group->getHome();
+ }
+
+ return $result;
+ }
+}
+
+/**
+ * @author Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ */
+class XMLPrivilegePeer extends AbstractPrivilegePeer {
+ /* ========================================================================== */
+ /* == Class Members == */
+ /* ========================================================================== */
+
+ /* ========================================================================== */
+ /* == Constructor == */
+ /* ========================================================================== */
+
+ function XMLPrivilegePeer($userPeer) {
+ global $g, $config;
+
+ parent::AbstractPrivilegePeer();
+
+ $this->setUserPeer($peer);
+
+ foreach ($peer->users as $userent) {
+ foreach ($userent->getPrivileges() as $privent) {
+ $this->privileges[$userent->getName()] = $privent;
+ }
+ }
+ }
+
+ /* ========================================================================== */
+ /* == Accessors == */
+ /* ========================================================================== */
+
+ /* ========================================================================== */
+ /* == Helper Methods == */
+ /* ========================================================================== */
+
+ function addPrivilegeFromEnt(&$ent) {
+ $newPrivilege = new AuthngUser();
+ $newPrivilege->setId($ent['id']);
+ $newPrivilege->setName($ent['name']);
+ $newPrivilege->setDescription($ent['description']);
+ $newPrivilege->setPassword($ent['password']);
+ $newPrivilege->setUid($ent['uid']);
+
+ $this->privileges[] = $newPrivilege;
+ }
+
+ function setPrivilegeID($id, $name, $username) {
+ $userid = getPrivilegeIndexByName($username);
+ $user = $config['system']['user'][$userid];
+ }
+
+ function setFullName($id, $name) {
+ $userid = getUserIndexByName($id);
+ $config['system']['user'][$userid]['fullname'] = $name;
+ }
+
+ function setGroupName($id, $name) {
+ $userid = getUserIndexByName($id);
+ $config['system']['user'][$userid]['groupname'] = $name;
+ }
+
+ function setPassword($id, $pwd) {
+ $userid = getUserIndexByName($id);
+ $config['system']['user'][$userid]['password'] = $pwd;
+ }
+
+ function setUid($id, $uid) {
+ $userid = getUserIndexByName($id);
+ $config['system']['user'][$userid]['uid'] = $uid;
+ }
+}
+
+/**
+ * @author Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ */
+class XMLUserPeer extends AbstractUserPeer {
+ /* ========================================================================== */
+ /* == Class Members == */
+ /* ========================================================================== */
+
+ /* ========================================================================== */
+ /* == Constructor == */
+ /* ========================================================================== */
+
+ function XMLUserPeer() {
+ global $g, $config;
+
+ parent::AbstractUserPeer();
+
+ if (isset($config['system']['user'])) {
+ $i = 0;
+
+ foreach($config['system']['user'] as $userent) {
+ $this->user_index[$userent['name']] = $i;
+ $this->addUserFromEnt($userent);
+ $i++;
+ }
+ }
+ }
+
+ /* ========================================================================== */
+ /* == Accessors == */
+ /* ========================================================================== */
+
+ /* ========================================================================== */
+ /* == Helper Methods == */
+ /* ========================================================================== */
+
+ function addUserFromEnt(&$ent) {
+ print "HURTZ";
+ $newUser = new AuthngUser();
+ $newUser->setName($ent['name']);
+ $newUser->setFullname($ent['fullname']);
+ $newUser->setGroupname($ent['groupname']);
+ $newUser->setPassword($ent['password']);
+ $newUser->setUid($ent['uid']);
+
+ if ($ent['priv'] && is_array($ent['priv'])) {
+ foreach ($ent['priv'] as $privent) {
+ $newPrivilege = new Privilege();
+ $newPrivilege->setId($privent['id']);
+ $newPrivilege->setName($privent['name']);
+ $newPrivilege->setDescription($privent['description']);
+
+ $newUser->addPrivilege($newPrivilege);
+ }
+ }
+
+ $this->users["${ent['name']}"] = $newUser;
+ }
+
+ function setUserName($id, $name) {
+ $userid = getUserIndexByName($id);
+ $config['system']['user'][$userid]['name'] = $name;
+ }
+
+ function setFullName($id, $name) {
+ $userid = getUserIndexByName($id);
+ $config['system']['user'][$userid]['fullname'] = $name;
+ }
+
+ function setGroupName($id, $name) {
+ $userid = getUserIndexByName($id);
+ $config['system']['user'][$userid]['groupname'] = $name;
+ }
+
+ function setPassword($id, $pwd) {
+ $userid = getUserIndexByName($id);
+ $config['system']['user'][$userid]['password'] = $pwd;
+ }
+
+ function setUid($id, $uid) {
+ $userid = getUserIndexByName($id);
+ $config['system']['user'][$userid]['uid'] = $uid;
+ }
+}
+
+/**
+ * @author Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ */
+class XMLGroupPeer extends AbstractGroupPeer {
+ /* ========================================================================== */
+ /* == Class Members == */
+ /* ========================================================================== */
+
+ /* ========================================================================== */
+ /* == Constructor == */
+ /* ========================================================================== */
+
+ function XMLGroupPeer() {
+ global $g, $config;
+
+ parent::AbstractGroupPeer();
+
+ if (isset($config['system']['group'])) {
+ $i = 0;
+
+ foreach($config['system']['group'] as $groupent) {
+ $this->group_index[$groupent['name']] = $i;
+ $i++;
+ }
+ }
+ }
+
+ /* ========================================================================== */
+ /* == Accessors == */
+ /* ========================================================================== */
+
+ /* ========================================================================== */
+ /* == Helper Methods == */
+ /* ========================================================================== */
+
+ function addGroupFromEnt(&$ent) {
+ $newGoup = new AuthngGroup();
+ $newGoup->setName($ent['name']);
+ $newGoup->setDescription($ent['description']);
+ $newGoup->setScope($ent['scope']);
+ $newGoup->setHome($ent['home']);
+ $newGoup->setGid($ent['gid']);
+
+ if ($ent['pages'] && is_array($ent['gid'])) {
+ foreach ($ent['pages'] as $pageent) {
+ $newGoup->addPage($pageent);
+ }
+ }
+
+ $this->groups["${ent['name']}"] = $newGoup;
+ }
+
+ function setGroupName($id, $name) {
+ $groupid = getGroupIndexByName($id);
+ $config['system']['group'][$groupid]['name'] = $name;
+ }
+
+ function setGroupDescription($id, $desc) {
+ $groupid = getGroupIndexByName($id);
+ $config['system']['group'][$groupid]['description'] = $desc;
+ }
+
+ function setGroupScope($id, $scope) {
+ $groupid = getGroupIndexByName($id);
+ $config['system']['group'][$groupid]['scope'] = $scope;
+ }
+
+ function setGroupHome($id, $home) {
+ $groupid = getGroupIndexByName($id);
+ $config['system']['group'][$groupid]['home'] = $home;
+ }
+
+ function setGroupGid($id, $gid) {
+ $groupid = getGroupIndexByName($id);
+ $config['system']['group'][$groupid]['gid'] = $gid;
+ }
+
+ function addPageToGroup($id, $page) {
+ $groupid = getGroupIndexByName($id);
+ $config['system']['group'][$groupid]['pages'][] = $page;
+ }
+}
+?>
diff --git a/config/authng/pkg/authng_usermanager.inc b/config/authng/pkg/authng_usermanager.inc
new file mode 100644
index 00000000..f96759fb
--- /dev/null
+++ b/config/authng/pkg/authng_usermanager.inc
@@ -0,0 +1,247 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng_usermanager.inc
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+function initUserFromGetVars() {
+ if ($_GET['act'] == "edit") {
+ if (isset($id) && $a_user[$id]) {
+ $pconfig['usernamefld'] = $a_user[$id]['name'];
+ $pconfig['fullname'] = $a_user[$id]['fullname'];
+ $pconfig['groupname'] = $a_user[$id]['groupname'];
+ $pconfig['utype'] = $a_user[$id]['scope'];
+ $pconfig['authorizedkeys'] = base64_decode($a_user[$id]['authorizedkeys']);
+ }
+ } else if ($_GET['act'] == "new") {
+ /* set this value cause the text field is read only
+ * and the user should not be able to mess with this
+ * setting.
+ */
+ $pconfig['utype'] = "user";
+ }
+}
+function processUserManagerPostVarsUser() {
+ if (isset($_POST['save'])) {
+ unset($input_errors);
+
+ /* input validation */
+ $reqdfields = explode(" ", "passwordfld1");
+ $reqdfieldsn = explode(",", "Password");
+
+ do_input_validation($_POST, $reqdfields, $reqdfieldsn, &$input_errors);
+
+ if ($_POST['passwordfld1'] != $_POST['passwordfld2'])
+ $input_errors[] = "The passwords do not match.";
+
+ if (!$input_errors) {
+ // all values are okay --> saving changes
+ $config['system']['user'][$userindex[$HTTP_SERVER_VARS['AUTH_USER']]]['password'] = crypt(trim($_POST['passwordfld1']));
+
+ write_config();
+
+ sync_webgui_passwords();
+
+ $retval = system_password_configure();
+ $savemsg = get_std_save_message($retval);
+ $savemsg = "Password successfully changed<br />";
+ }
+ }
+}
+
+function processUserManagerPostVarsAdmin() {
+ $id = $_GET['id'];
+ if (isset($_POST['id']))
+ $id = $_POST['id'];
+
+ if (!is_array($config['system']['user'])) {
+ $config['system']['user'] = array();
+ }
+
+ admin_users_sort();
+ $a_user = &$config['system']['user'];
+ $t_privs = $a_user[$id]['priv'];
+
+ if ($_GET['act'] == "del" && $_GET['what'] == "user") {
+ if ($a_user[$_GET['id']]) {
+ $userdeleted = $a_user[$_GET['id']]['name'];
+ unset($a_user[$_GET['id']]);
+ write_config();
+ $retval = system_password_configure();
+ $savemsg = get_std_save_message($retval);
+ $savemsg = gettext("User") . " " . $userdeleted . " " . gettext("successfully deleted") . "<br />";
+ }
+ } else if ($_GET['act'] == "del" && $_GET['what'] == "priv") {
+ if ($t_privs[$_GET['privid']]) {
+ $privdeleted = $t_privs[$_GET['privid']]['id'];
+ unset($t_privs[$_GET['privid']]);
+ write_config();
+ $_GET['act'] = "edit";
+ $retval = 0;
+ $savemsg = get_std_save_message($retval);
+ $savemsg = gettext("Privilege") . " " . $privdeleted . " " . gettext("of user") . " " . $a_user[$_GET['id']]['name'] . " " . gettext("successfully deleted") . "<br />";
+ }
+ }
+
+ if ($_POST) {
+ unset($input_errors);
+ $pconfig = $_POST;
+
+ /* input validation */
+ if (isset($id) && ($a_user[$id])) {
+ $reqdfields = explode(" ", "usernamefld");
+ $reqdfieldsn = explode(",", "Username");
+ } else {
+ $reqdfields = explode(" ", "usernamefld passwordfld1");
+ $reqdfieldsn = explode(",", "Username,Password");
+ }
+
+ do_input_validation($_POST, $reqdfields, $reqdfieldsn, &$input_errors);
+
+ if (hasShellAccess($_POST['usernamefld'])) {
+ if (preg_match("/[^a-zA-Z0-9\.\-_]/", $_POST['usernamefld']))
+ $input_errors[] = gettext("The username contains invalid characters.");
+ } else {
+ if (preg_match("/[^a-zA-Z0-9\@\.\-_]/", $_POST['usernamefld']))
+ $input_errors[] = gettext("The username contains invalid characters.");
+ }
+
+ if (($_POST['passwordfld1']) && ($_POST['passwordfld1'] != $_POST['passwordfld2']))
+ $input_errors[] = gettext("The passwords do not match.");
+
+ if (!$input_errors && !(isset($id) && $a_user[$id])) {
+ /* make sure there are no dupes */
+ foreach ($a_user as $userent) {
+ if ($userent['name'] == $_POST['usernamefld']) {
+ $input_errors[] = gettext("Another entry with the same username already exists.");
+ break;
+ }
+ }
+ }
+
+ if ($pconfig['utype'] <> "system" && !isset($groupindex[$_POST['groupname']])) {
+ $input_errors[] = gettext("group does not exist, please define the group before assigning users.");
+ }
+
+ if (isset($config['system']['ssh']['sshdkeyonly']) &&
+ empty($_POST['authorizedkeys'])) {
+ $input_errors[] = gettext("You must provide an authorized key otherwise you won't be able to login into this system.");
+ }
+
+ /* if this is an AJAX caller then handle via JSON */
+ if (isAjax() && is_array($input_errors)) {
+ input_errors2Ajax($input_errors);
+ exit;
+ }
+
+ if (!$input_errors) {
+ if (isset($id) && $a_user[$id])
+ $userent = $a_user[$id];
+
+ /* the user did change his username */
+ if ($_POST['usernamefld'] <> $_POST['oldusername']) {
+ $_SERVER['REMOTE_USER'] = $_POST['usernamefld'];
+ }
+
+ $userent['name'] = $_POST['usernamefld'];
+ $userent['fullname'] = $_POST['fullname'];
+ if ($pconfig['utype'] <> "system") {
+ $userent['groupname'] = $_POST['groupname'];
+ }
+ isset($_POST['utype']) ? $userent['scope'] = $_POST['utype'] : $userent['scope'] = "system";
+
+ if ($_POST['passwordfld1'])
+ $userent['password'] = crypt($_POST['passwordfld1']);
+
+ if(isset($config['system']['ssh']['sshdkeyonly'])) {
+ $userent['authorizedkeys'] = base64_encode($_POST['authorizedkeys']);
+ }
+
+ if (isset($id) && $a_user[$id])
+ $a_user[$id] = $userent;
+ else
+ $a_user[] = $userent;
+
+ write_config();
+ $retval = system_password_configure();
+ sync_webgui_passwords();
+
+ pfSenseHeader("system_usermanager.php");
+ }
+ }
+}
+
+/**
+ * getWindowJSScriptRefs()
+ *
+ * @return
+ */
+function getWindowJSScriptRefs(){
+ $result = array('<script type="text/javascript" src="/javascripts/windows-js/javascript/effects.js"></script>',
+ '<script type="text/javascript" src="/javascripts/windows-js/javascript/window.js"></script>',
+ '<script type="text/javascript" src="/javascripts/windows-js/javascript/window_effects.js"></script>',
+ '<script type="text/javascript" src="/javascripts/windows-js/javascript/window_effects.js"></script>',
+ '<script type="text/javascript" src="/javascripts/windows-js/javascript/debug.js"></script>');
+
+ return $result;
+}
+
+/**
+ * openNoUserDefsDialog()
+ *
+ * @param mixed $effectClass
+ * @return
+ */
+function openNoUserDefsDialog($effectClass) {
+ if (empty($config['installedpackages']['authng']['config'])) {
+ $alertMessage = gettext("No users or group found. You will be forwarded to the AuthNG wizard to be able to define users and groups.");
+ $dialogScript = "
+ <script type='text/javascript'>
+ function forwardToWizard() {
+ window.location.href = '/wizard.php?xml=authng_wizard.xml';
+ }
+
+ function openNoUserDefsDialog(html) {
+ var effect = new PopupEffect(html, {className: '${effectClass}'});
+ Dialog.alert('${alertMessage},{className:'alphacube', width: 400, height:null, showEffect:effect.show.bind(effect), hideEffect:effect.hide.bind(effect), onOk:forwardToWizard});
+ }
+ </script>
+ ";
+
+ return $dialogScript;
+ }
+}
+
+?> \ No newline at end of file
diff --git a/config/authng/www/js/headjs.inc b/config/authng/www/js/headjs.inc
new file mode 100644
index 00000000..73c0a4db
--- /dev/null
+++ b/config/authng/www/js/headjs.inc
@@ -0,0 +1,157 @@
+<?php
+
+function getHeadJS() {
+ global $_SERVER, $HTTP_SERVER_VARS, $g, $use_loader_tab_gif;
+
+ if(!$use_loader_tab_gif)
+ $loader_gif = "/themes/{$g['theme']}/images/misc/loader.gif";
+ else
+ $loader_gif = "/themes/{$g['theme']}/images/misc/loader_tab.gif";
+
+ $headjs = "
+ var input_errors = '';
+ Event.observe(window, 'load', init, false);
+ ";
+
+ $_SESSION['NO_AJAX'] == "True" ? $noajax = "var noAjaxOnSubmit = true;" : $noajax = "var noAjaxOnSubmit = false;";
+
+ $headjs .= "
+ {$noajax}
+
+ function init() {
+ if($('submit') && ! noAjaxOnSubmit) {
+ // debugging helper
+ //alert('adding observe event for submit button');
+
+ Event.observe(\"submit\", \"click\", submit_form, false);
+ $('submit').onclick = function() {return false;};
+ var to_insert = \"<div style='visibility:hidden' id='loading' name='loading'><img src='{$loader_gif}' \/><\/div>\";
+ new Insertion.Before('submit', to_insert);
+ }
+ }
+
+ function submit_form(e){
+ // debugging helper
+ //alert(Form.serialize($('iform')));
+
+ if($('inputerrors'))
+ $('inputerrors').innerHTML = '';
+
+ /* dsh: Introduced because pkg_edit tries to set some hidden fields
+ * if executing submit's onclick event. Tho click gets deleted
+ * by Ajax. Hence using onkeydown instead.
+ */
+ if($('submit') && $('submit').onkeydown)
+ $('submit').onkeydown();
+ if($('submit'))
+ $('submit').style.visibility = 'hidden';
+ if($('cancelbutton'))
+ $('cancelbutton').style.visibility = 'hidden';
+ $('loading').style.visibility = 'visible';
+ // submit the form using Ajax
+ ";
+
+
+ isset($HTTP_SERVER_VARS['AUTH_USER']) ? $scriptName = split("/", $_SERVER["SCRIPT_FILENAME"]) : $scriptName = split("/", "/index.php");
+ isset($HTTP_SERVER_VARS['AUTH_USER']) ? $loggedin = "var isLoggedIn = true;" : $loggedin = "var isLoggedIn = false;";
+ $scriptElms = count($scriptName);
+ $scriptName = $scriptName[$scriptElms-1];
+ $realScriptName = $_SERVER["SCRIPT_NAME"];
+
+ $headjs .= "
+ {$loggedin}
+
+ if (! isLoggedIn) {
+ var newInput = document.createElement('input');
+ newInput.setAttribute('id', 'scriptname');
+ newInput.setAttribute('name', 'scriptname');
+ newInput.setAttribute('value', '$realScriptName');
+ newInput.setAttribute('type', 'hidden');
+
+ $('iform').appendChild(newInput);
+ }
+
+ new Ajax.Request('{$scriptName}', {
+ method : 'post',
+ parameters : Form.serialize($('iform')),
+ onSuccess : formSubmitted,
+ onFailure : formFailure
+ });
+ }
+
+ function formSubmitted(resp) {
+ var responseText = resp.responseText;
+
+ // debugging helper
+ //alert(responseText);
+
+ if(responseText.indexOf('html') > 0) {
+ /* somehow we have been fed an html page! */
+ //alert('Somehow we have been fed an html page! Forwarding to /.');
+ document.location.href = '/';
+ }
+
+ eval(responseText);
+ }
+
+ /* this function will be called if an HTTP error will be triggered */
+ function formFailure(resp) {
+ alert('An error occured while saving the data ' + resp.responseText);
+ }
+
+ function showajaxmessage(message) {
+ var message_html;
+
+ if (message == '') {
+ NiftyCheck();
+ Rounded(\"div#redbox\",\"all\",\"#FFF\",\"#990000\",\"smooth\");
+ Rounded(\"td#blackbox\",\"all\",\"#FFF\",\"#000000\",\"smooth\");
+
+ if($('submit'))
+ $('submit').style.visibility = 'visible';
+ if($('cancelbutton'))
+ $('cancelbutton').style.visibility = 'visible';
+ if($('loading'))
+ $('loading').style.visibility = 'hidden';
+
+ return;
+ }
+
+ message_html = '<table height=\"32\" width=\"100%\"><tr><td>';
+ message_html += '<div style=\"background-color:#990000\" id=\"redbox\">';
+ message_html += '<table width=\"100%\"><tr><td width=\"8%\">';
+ message_html += '&nbsp;&nbsp;&nbsp;';
+ message_html += '<img style=\"vertical-align:middle\" src=\"/themes/{$g['theme']}/images/icons/icon_exclam.gif\" width=\"28\" height=\"32\" \/>';
+ message_html += '<\/td><td width=\"70%\"><font color=\"white\">';
+ message_html += '<b>' + message + '<\/b><\/font><\/td>';
+
+ if(message.indexOf('apply') > 0) {
+ message_html += '<td>';
+ message_html += '<input name=\"apply\" type=\"submit\" class=\"formbtn\" id=\"apply\" value=\"" . gettext("Apply changes") . "\" \/>';
+ message_html += '<\/td>';
+ }
+
+ message_html += '<\/tr><\/table><\/div><\/td><\/table><br \/>';
+ $('inputerrors').innerHTML = message_html;
+
+ NiftyCheck();
+ Rounded(\"div#redbox\",\"all\",\"#FFF\",\"#990000\",\"smooth\");
+ Rounded(\"td#blackbox\",\"all\",\"#FFF\",\"#000000\",\"smooth\");
+
+ if($('submit'))
+ $('submit').style.visibility = 'visible';
+ if($('cancelbutton'))
+ $('cancelbutton').style.visibility = 'visible';
+ if($('loading'))
+ $('loading').style.visibility = 'hidden';
+ if($('inputerrors'))
+ window.scrollTo(0, 0);
+ if($('inputerrors'))
+ new Effect.Shake($('inputerrors'));
+ }
+ ";
+
+ return $headjs;
+}
+
+?>
diff --git a/config/authng/www/php/head.inc b/config/authng/www/php/head.inc
new file mode 100644
index 00000000..5365c715
--- /dev/null
+++ b/config/authng/www/php/head.inc
@@ -0,0 +1,669 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng_classdefs.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+require("headjs.inc");
+
+/* if user has selected a custom template, use it.
+ * otherwise default to pfsense tempalte
+ */
+if($config['theme'] <> "") {
+ $g['theme'] = $config['theme'];
+} else {
+ $g['theme'] = "pfsense";
+}
+
+// navigation level separator string
+$navlevelsep = ": ";
+
+function gentitle($title) {
+ global $navlevelsep;
+
+ if(!is_array($title)) {
+ return $title;
+ }
+
+ return join($navlevelsep, $title);
+}
+
+function genhtmltitle($title) {
+ global $config;
+ //return $config['system']['hostname'] . "." . $config['system']['domain'] . " - " . gentitle($title);
+ return gentitle($title);
+}
+
+$scriptName = split("/", $_SERVER["SCRIPT_FILENAME"]);
+$scriptElms = count($scriptName);
+$scriptName = $scriptName[$scriptElms-1];
+
+$pfSenseHead = new pfSenseHTMLHead();
+$pfSenseHead->setCloseHead(true);
+$pfSenseHead->setTitle(genhtmltitle($pgtitle));
+
+/* all.css has to be treated a bit different, compared to generic stylesheets */
+$allID = $pfSenseHead->addLink("<link rel=\"stylesheet\" type=\"text/css\" href=\"/themes/" . $g['theme'] . "/all.css\" media=\"all\" />\n");
+$pfSenseHead->setAllCssID($allID);
+
+$pfSenseHead->addLink("<link rel='shortcut icon' href='/themes/{$g['theme']}/images/icons/favicon.ico' />\n");
+$pfSenseHead->addScript("<script type='text/javascript'>\nvar theme = '" . $g['theme'] . "';\nvar dontUseCustomBGColor = true;\n</script>\n", 1);
+$pfSenseHead->addScript("<script type='text/javascript' src=\"/themes/" . $g['theme'] . "/loader.js\"></script>\n", 2);
+//TODO: if ((($_POST || $_GET || isAjax()) &&
+if ((($_POST || $_GET) &&
+ is_array($error_bucket)) ||
+ strpos($_SERVER['SCRIPT_NAME'], "wizard.php") !== false) {
+ $pfSenseHead->addScript("<script type='text/javascript' src='/javascript/domTT/domLib.js'></script>", 500);
+ $pfSenseHead->addScript("<script type='text/javascript' src='/javascript/domTT/domTT.js'></script>", 510);
+ $pfSenseHead->addScript("<script type='text/javascript' src='/javascript/domTT/behaviour.js'></script>", 520);
+ $pfSenseHead->addScript("<script type='text/javascript' src='/javascript/domTT/fadomatic.js'></script>", 530);
+}
+
+/*
+ * Find all javascript files that need to be included
+ * for this page ... from the arrays ... :)
+ * Coded by: Erik Kristensen
+ */
+$scriptWeight = 100;
+
+$dir = trim(basename($_SERVER["SCRIPT_FILENAME"]), '.php');
+$path = "/usr/local/www/javascript/" . $dir . "/";
+if (is_dir($path)) {
+ if ($dh = opendir($path)) {
+ while (($file = readdir($dh)) !== false) {
+ if (is_dir($file)) { continue; }
+ if (strpos($file, ".js") === false) { continue; }
+
+ $pfSenseHead->addScript("<script type='text/javascript' src='/javascript/{$dir}/{$file}'></script>\n", $scriptWeight);
+ $scriptWeight++;
+ }
+ closedir($dh);
+ }
+}
+
+/*
+ * Find all JavaScript files that may be provided by the current theme
+ * TODO: Commented because this pulls in PHP5 specific stuff from the theme.
+ *
+ */
+//$path = "/usr/local/www/themes/{$g['theme']}/javascript/";
+
+//if (is_dir($path)) {
+// if ($dh = opendir($path)) {
+// while (($file = readdir($dh)) !== false) {
+// if (is_dir($file)) { continue; }
+// if (strpos($file, ".js") !== false) {
+// $pfSenseHead->addScript("<script type='text/javascript' src='/themes/{$g['theme']}/javascript/{$file}'></script>\n", $scriptWeight);
+// } else if (strpos($file, ".php") !== false &&
+// strpos($file, "-head") !== false &&
+// strpos($file, ".disabled") === false) {
+// $filename = ucfirst(trim(trim($file, '.php'), '-head'));
+// require_once("themes/{$g['theme']}/javascript/{$file}");
+
+// if (function_exists("{$g['theme']}{$filename}GetHeadJS")) {
+// $jsfunction = "{$g['theme']}{$filename}GetHeadJS";
+// $jscript = $jsfunction();
+// $pfSenseHead->addScript("<script type='text/javascript'>\n<!--\n{$jscript}\n-->\n</script>\n", $scriptWeight);
+// }
+// } else {
+// continue;
+// }
+
+// $scriptWeight++;
+// }
+// closedir($dh);
+// }
+//}
+
+/*
+ * Find all JavaScript events that may be provided by the current theme
+ *
+ */
+$path = "/usr/local/www/themes/{$g['theme']}/jsevents/";
+if (is_dir($path)) {
+ if ($dh = opendir($path)) {
+ while (($file = readdir($dh)) !== false) {
+ if (is_dir($file)) { continue; }
+ if (strpos($file, ".def") !== false) {
+ if (empty($jsevents)) { $jsevents = array(); }
+
+ switch ($file) {
+ case "body.def":
+ $contents = file_get_contents("/usr/local/www/themes/{$g['theme']}/jsevents/{$file}");
+ $contents_a = split("\n", $contents);
+ foreach ($contents_a as $line) {
+ if (strpos($line, "#") === 0) { continue; }
+ if (strpos($line, "!") !== false) {
+ $events_forbidden_pages = split("!", $line);
+ $keyval = split("=", $events_forbidden_pages[0]);
+
+ if (strpos($events_forbidden_pages[1], basename($_SERVER['SCRIPT_NAME'])) !== false) { continue; }
+ } else {
+ $keyval = split("=", $line);
+ }
+ $jsevents["body"][$keyval[0]] = $keyval[1];
+ }
+ break;
+ }
+ } else {
+ continue;
+ }
+ }
+ closedir($dh);
+ }
+}
+
+/*
+ * Find all CSS files that may be provided by the current theme
+ * TODO: Not needed right now.
+ */
+//$path = "/usr/local/www/themes/{$g['theme']}/styles/";
+//if (is_dir($path)) {
+// if ($dh = opendir($path)) {
+// while (($file = readdir($dh)) !== false) {
+// if (is_dir($file)) { continue; }
+// if (strpos($file, ".css") === false) { continue; }
+
+// $pfSenseHead->addLink("<link rel='stylesheet' type='text/css' href='/themes/{$g['theme']}/styles/{$file}' media='all' />\n");
+// }
+// closedir($dh);
+// }
+//}
+
+if ($oSajax) {
+$pfSenseHead->addScript("<script type='text/javascript'>\n" .
+ $oSajax->sajax_get_javascript() . "\n</script>\n", ++$scriptWeight);
+}
+
+// TODO: This line needs to be commented if any PHP calls
+// $pfSenseHead->getHTML(); on its own.
+//echo $pfSenseHead->getHTML();
+
+/**
+ * pfSenseHTMLHead
+ *
+ * @package www
+ * @author Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ * @copyright Copyright (c) 2006
+ * @version $Id$
+ * @access public
+ **/
+class pfSenseHTMLHead
+{
+ var $xmlHead = "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n";
+ var $docType = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n";
+ var $title = "UNSET";
+ var $meta = array();
+ var $link = array();
+ var $script = array();
+ var $style = array();
+ var $html = "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n<head>\n<title>%TITLE%</title>\n%META%\n%STYLE%\n%LINK%\n%SCRIPT%";
+ var $closehead = true;
+ var $returnedHTML = false;
+ var $allCSSID = "NOT-SET";
+
+ /**
+ * pfSenseHTMLHead::pfSenseHTMLHead()
+ *
+ * Class Konstructor
+ **/
+ function pfSenseHTMLHead() {
+ $this->meta[] = array("meta" => " <meta http-equiv=\"Content-Type\" " .
+ "content=\"text/html; charset=iso-8859-1\" />",
+ "ID" => "meta-" . strval(microtime()));
+ $this->link[] = array("link" => " <link rel=\"stylesheet\" type=\"text/css\" " .
+ "href=\"/niftycssprintCode.css\" media=\"print\" />",
+ "ID" => "link-" . strval(microtime()));
+ $this->script[] = array("script" => " <script type=\"text/javascript\" " .
+ "src=\"/javascript/scriptaculous/prototype.js\"></script>",
+ "weight" => 3,
+ "ID" => "script-" . strval(microtime()));
+ $this->script[] = array("script" => " <script type=\"text/javascript\" " .
+ "src=\"/javascript/scriptaculous/scriptaculous.js\"></script>",
+ "weight" => 4,
+ "ID" => "script-" . strval(microtime()));
+// $this->script[] = array("script" => " <script type=\"text/javascript\">\n<!--\n" . getHeadJS() . "\n//-->\n</script>",
+// "weight" => 5,
+// "ID" => "script-" . strval(microtime()));
+ }
+
+ /**
+ * pfSenseHTMLHead::getAllCssID()
+ *
+ * Allows to store the ID associated with the all CSS file.
+ * @return an ID
+ **/
+ function getAllCssID() {
+ return $this->allCSSID;
+ }
+
+ /**
+ * pfSenseHTMLHead::setAllCssID()
+ *
+ * Allows to set the ID associated with the all CSS file.
+ * @param mixed $myID a string representing an ID that was already generated.
+ **/
+ function setAllCssID($myID = "") {
+ if ($myID == "") { return; }
+
+ $this->allCSSID = $myID;
+ }
+
+ /**
+ * pfSenseHTMLHead::setCloseHead()
+ *
+ * Should the HTML &lt;head /&gt; element be closed by the class or
+ * do you want to close it manually?
+ * @param mixed $myCloseHead Boolean value which indicates whether &lt;head /&gt; should be closed by the class
+ * @return
+ **/
+ function setCloseHead($myCloseHead = true) {
+ $this->closehead = $myCloseHead;
+ }
+
+ /**
+ * pfSenseHTMLHead::setTitle()
+ *
+ * Set the HTML &lt;title /&gt; element.
+ * @param string $myTitle The title (without any markup)
+ * @return NULL
+ **/
+ function setTitle($myTitle = "") {
+ $this->title = $myTitle;
+ }
+
+ /**
+ * pfSenseHTMLHead::addStyle()
+ *
+ * Allows to add a complete HTML &lt;style /&gt; element to the current
+ * meta element array. You can provide an ID if you want to access your
+ * particular element at a later time, for example to delete it from the
+ * array etc.. If you don't provide an ID, a random ID will be generated
+ * and returned.
+ * @param string $myStyleElement an HTML string that represents a &lt;style /&gt; tag.
+ * @param string $myID an ID that identifies this element.
+ * @return the ID that identifies the particular element that you've just added.
+ **/
+ function addStyle($myStyleElement = "", $myID = "") {
+ if ($myID == "") { $myID = "style-" . strval(microtime()); }
+
+ $this->style[] = array("style" => $myStyleElement,
+ "ID" => $myID);
+
+ return $myID;
+ }
+
+ /**
+ * pfSenseHTMLHead::getStyleArray()
+ *
+ * @return a reference to the meta element array.
+ **/
+ function &getStyleArray() {
+ return $this->style;
+ }
+
+ /**
+ * pfSenseHTMLHead::getStyleByID()
+ *
+ * Returns a reference to an array element that is identified by an ID.
+ * Can be used for example to manipulate an array element after it was
+ * already stored in the array.
+ * @param string $myID an ID that identifies the element that should be retrieved.
+ * @return a reference to an array element or NULL if the element does not exist.
+ **/
+ function &getStyleByID($myID = "") {
+ foreach($this->style as $styleel){
+ if ($styleel["ID"] == $myID) {
+ return $styleel;
+ }
+ }
+ return NULL;
+ }
+
+ /**
+ * pfSenseHTMLHead::removeStyleByID()
+ *
+ * Provides a way to delete an element from an HTML element array.
+ * You must provide an ID which identifies the element to be deleted.
+ * @param string $myID an ID the identifies the element.
+ * @return 1 if the element was found or 0 if it does not exist.
+ **/
+ function removeStyleByID($myID = "") {
+ foreach($this->style as $styleel){
+ if ($styleel["ID"] == $myID) {
+ unset($styleel);
+ return 1;
+ }
+ }
+ return 0;
+ }
+
+ /**
+ * pfSenseHTMLHead::addMeta()
+ *
+ * Allows to add a complete HTML &lt;meta /&gt; element to the current
+ * meta element array. You can provide an ID if you want to access your
+ * particular element at a later time, for example to delete it from the
+ * array etc.. If you don't provide an ID, a random ID will be generated
+ * and returned.
+ * @param string $myMetaElement an HTML string that represents a &lt;meta /&gt; tag.
+ * @param string $myID an ID that identifies this element.
+ * @return the ID that identifies the particular element that you've just added.
+ **/
+ function addMeta($myMetaElement = "", $myID = "") {
+ if ($myID == "") { $myID = "meta-" . strval(microtime()); }
+
+ $this->meta[] = array("meta" => $myMetaElement,
+ "ID" => $myID);
+
+ return $myID;
+ }
+
+ /**
+ * pfSenseHTMLHead::getMetaArray()
+ *
+ * @return a reference to the meta element array.
+ **/
+ function &getMetaArray() {
+ return $this->meta;
+ }
+
+ /**
+ * pfSenseHTMLHead::getMetaByID()
+ *
+ * Returns a reference to an array element that is identified by an ID.
+ * Can be used for example to manipulate an array element after it was
+ * already stored in the array.
+ * @param string $myID an ID that identifies the element that should be retrieved.
+ * @return a reference to an array element or NULL if the element does not exist.
+ **/
+ function &getMetaByID($myID = "") {
+ foreach($this->meta as $metael){
+ if ($metael["ID"] == $myID) {
+ return $metael;
+ }
+ }
+ return NULL;
+ }
+
+ /**
+ * pfSenseHTMLHead::removeMetaByID()
+ *
+ * Provides a way to delete an element from an HTML element array.
+ * You must provide an ID which identifies the element to be deleted.
+ * @param string $myID an ID the identifies the element.
+ * @return 1 if the element was found or 0 if it does not exist.
+ **/
+ function removeMetaByID($myID = "") {
+ foreach($this->meta as $metael){
+ if ($metael["ID"] == $myID) {
+ unset($metael);
+ return 1;
+ }
+ }
+ return 0;
+ }
+
+ /**
+ * pfSenseHTMLHead::addLink()
+ *
+ * Allows to add a complete HTML &lt;link /&gt; element to the current
+ * link element array. You can provide an ID if you want to access your
+ * particular element at a later time, for example to delete it from the
+ * array etc.. If you don't provide an ID, a random ID will be generated
+ * and returned.
+ * @param string $myLinkElement an HTML string that represents a &lt;link /&gt; tag.
+ * @param string $myID an ID that identifies this element.
+ * @return the ID that identifies the particular element that you've just added.
+ **/
+ function addLink ($myLinkElement = "", $myID = "") {
+ if ($myID == "") { $myID = "link-" . strval(microtime()); }
+
+ $this->link[] = array("link" => $myLinkElement,
+ "ID" => $myID);
+
+ return $myID;
+ }
+
+ /**
+ * pfSenseHTMLHead::getLinkArray()
+ *
+ * @return a reference to the link element array.
+ **/
+ function &getLinkArray() {
+ return $this->link;
+ }
+
+ /**
+ * pfSenseHTMLHead::getLinkByID()
+ *
+ * Returns a reference to an array element that is identified by an ID.
+ * Can be used for example to manipulate an array element after it was
+ * already stored in the array.
+ * @param string $myID an ID that identifies the element that should be retrieved.
+ * @return a reference to an array element or NULL if the element does not exist.
+ **/
+ function &getLinkByID($myID = "") {
+ foreach($this->link as $linkel){
+ if ($linkel["ID"] == $myID) {
+ return $linkel;
+ }
+ }
+ return NULL;
+ }
+
+ /**
+ * pfSenseHTMLHead::removeLinkByID()
+ *
+ * Provides a way to delete an element from an HTML element array.
+ * You must provide an ID which identifies the element to be deleted.
+ * @param string $myID an ID the identifies the element.
+ * @return 1 if the element was found or 0 if it does not exist.
+ **/
+ function removeLinkByID($myID = "") {
+ foreach($this->link as $linkel){
+ if ($linkel["ID"] == $myID) {
+ unset($linkel);
+ return 1;
+ }
+ }
+ return 0;
+ }
+
+ /**
+ * pfSenseHTMLHead::replaceLinkByID()
+ *
+ * Provides a way to replace an element from an HTML element array.
+ * You must provide an ID which identifies the element to be replace.
+ * @param string $myID an ID the identifies the element.
+ * @return 1 if the element was found or 0 if it does not exist.
+ **/
+ function replaceLinkByID($myID = "", $byWhat = "") {
+ for ($i = 0; $i < count($this->link); $i++) {
+ $linkel =& $this->link[$i];
+ if ($linkel["ID"] == $myID) {
+ $linkel["link"] = $byWhat;
+ return 1;
+ }
+ }
+
+ return 0;
+ }
+
+ /**
+ * pfSenseHTMLHead::addScript()
+ *
+ * Allows to add a complete HTML &lt;link /&gt; element to the current
+ * link element array. You can provide an ID if you want to access your
+ * particular element at a later time, for example to delete it from the
+ * array etc.. If you don't provide an ID, a random ID will be generated
+ * and returned.
+ *
+ * The <code>weight</code> parameter can be used to force the &lt;script /&gt;
+ * element to appear at the beginning of the HTML &lt;head /&gt; element or at
+ * its end. The greater the value for weight, the later the &lt;script /&gt;
+ * element will appear within the HTML &lt;head /&gt; element.
+ * @param string $myScriptElement an HTML string that represents a &lt;script /&gt; tag.
+ * @param integer $weight allows to position this element within the HTML &lt;head /&gt;
+ * @param string $myID an ID that identifies this element.
+ * @return the ID that identifies the particular element that you've just added.
+ **/
+ function addScript($myScriptElement = "", $weight = 1000000, $myID = "") {
+ if ($myID == "") { $myID = "script-" . strval(microtime()); }
+
+ $this->script[] = array("script" => $myScriptElement,
+ "weight" => $weight,
+ "ID" => $myID);
+ }
+
+ /**
+ * pfSenseHTMLHead::getScriptArray()
+ *
+ * @return a reference to the script element array.
+ **/
+ function &getScriptArray() {
+ return $this->script;
+ }
+
+ /**
+ * pfSenseHTMLHead::getScriptByID()
+ *
+ * Returns a reference to an array element that is identified by an ID.
+ * Can be used for example to manipulate an array element after it was
+ * already stored in the array.
+ * @param string $myID an ID that identifies the element that should be retrieved.
+ * @return a reference to an array element or NULL if the element does not exist.
+ **/
+ function &getScriptByID($myID = "") {
+ foreach($this->script as $scriptel){
+ if ($scriptel["ID"] == $myID) {
+ return $scriptel;
+ }
+ }
+ return NULL;
+ }
+
+ /**
+ * pfSenseHTMLHead::removeScriptByID()
+ *
+ * Provides a way to delete an element from an HTML element array.
+ * You must provide an ID which identifies the element to be deleted.
+ * @param string $myID an ID the identifies the element.
+ * @return 1 if the element was found or 0 if it does not exist.
+ **/
+ function removeScriptByID($myID = "") {
+ foreach($this->script as $scriptel){
+ if ($scriptel["ID"] == $myID) {
+ unset($scriptel);
+ return 1;
+ }
+ }
+ return 0;
+ }
+
+ /**
+ * pfSenseHTMLHead::getHTML()
+ *
+ * This function finally renders the HTML string representation of the
+ * HTML document header that is represented by this class. If you did
+ * specify to not close the HTML &lt;head /&gt; element via <code>closehead</code>
+ * you need to close it manually.
+ *
+ * @return a string that contains a HTML &lt;head /&gt; element.
+ **/
+ function getHTML () {
+ $language = $GLOBALS['config']['system']['language'];
+
+ if ($this->returnedHTML) {
+ return;
+ } else {
+ $metastr = "";
+ if (is_array($this->meta) && count($this->meta) > 0)
+ foreach($this->meta as $metael) {
+ $metastr .= $metael["meta"] . "\n";
+ }
+
+ $linkstr = "";
+ if (is_array($this->link) && count($this->link) > 0)
+ foreach($this->link as $linkel) {
+ $linkstr .= $linkel["link"] . "\n";
+ }
+
+ $stylestr = "";
+ if (is_array($this->style) && count($this->style) > 0)
+ foreach($this->style as $styleel) {
+ $stylestr .= $styleel["style"] . "\n";
+ }
+
+ $scriptstr = "";
+ usort($this->script, "sortScriptArray");
+ if (is_array($this->script) && count($this->script) > 0)
+ foreach($this->script as $scriptel) {
+
+ $scriptstr .= $scriptel["script"] . "\n";
+ }
+
+ $this->html = str_replace("%TITLE%", $this->title, $this->html);
+ $this->html = str_replace("%META%", $metastr, $this->html);
+ $this->html = str_replace("%STYLE%", $stylestr, $this->html);
+ $this->html = str_replace("%LINK%", $linkstr, $this->html);
+ $this->html = str_replace("%SCRIPT%", $scriptstr, $this->html);
+ //$this->html = str_replace("%LANG%", $language, $this->html);
+ $this->html = $this->xmlHead . $this->docType . $this->html;
+
+ $this->returnedHTML = true;
+
+ return $this->closehead ? ($this->html . "</head>") : ($this->html);
+ }
+ }
+}
+
+/**
+ * sortScriptArray()
+ *
+ * Sorts the script array according of the weight of a particular
+ * script element.
+ * @param mixed $a
+ * @param mixed $b
+ * @return
+ **/
+function sortScriptArray($a, $b) {
+ if ($a["weigth"] == $b["weight"]) {
+ return 0;
+ }
+
+ return (intval($a["weight"]) > intval($b["weight"])) ? 1 : -1;
+}
+
+?>
diff --git a/config/authng/www/php/system_groupmanager.php b/config/authng/www/php/system_groupmanager.php
new file mode 100644
index 00000000..13259e63
--- /dev/null
+++ b/config/authng/www/php/system_groupmanager.php
@@ -0,0 +1,797 @@
+<?php
+/*
+ $Id$
+ part of pfSense (http://www.pfSense.com)
+ originally part of part of m0n0wall (http://m0n0.ch/wall)
+
+ Copyright (C) 2006 Scott Ullrich <sullrich@gmail.com>.
+ All rights reserved.
+
+ Copyright (C) 2005 Paul Taylor <paultaylor@winn-dixie.com>.
+ All rights reserved.
+
+ Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require("guiconfig.inc");
+
+$_SESSION['NO_AJAX'] = true;
+
+$pgtitle = array(gettext("System"), gettext("Group manager"));
+$treeItemID = 0;
+
+function walkArea($title,
+ $t,
+ $area,
+ $id,
+ &$counter,
+ &$script_tag,
+ $tmpfname,
+ &$group) {
+ global $treeItemID;
+
+ foreach($area as $a => $aa) {
+ if (is_array($aa) && count($aa) > 0) {
+ $title .= "_{$a}";
+ echo "<li class=\"closed\"><a id=\"treeitem_{$treeItemID}\" href=\"#\">$a</a><ul>";
+ $treeItemID++;
+ walkArea($title,
+ $a,
+ $aa,
+ $id,
+ $counter,
+ $script_tag,
+ $tmpfname,
+ $group);
+ echo "</ul>\n";
+ } else {
+ $tmp_string = "{$t}";
+ $tmp_string .= ": ";
+ $tmp_string .= $a;
+ $trimmed_title = trim($title);
+ $trimmed_a = trim($a);
+ $this_id = "{$trimmed_title}_{$trimmed_a}_{$counter}";
+ $this_id = str_replace(" ", "", $this_id);
+ $this_id = str_replace("/", "", $this_id);
+ $stripped_session = str_replace("/tmp/", "", $tmpfname);
+ $allowed = false;
+ if (is_array($group['pages'][0]['page'])) {
+ foreach($group['pages'][0]['page'] as $page) {
+ if (stristr($aa, $page))
+ $allowed = true;
+ // echo "$page || $aa";
+ }
+ }
+ $allowed ? $checked = " checked=\"checked\"" : $checked = "";
+ echo " <li id=\"treeitem_{$treeItemID}\" class=\"closed\" title=\"{$aa}\"><a name=\"anchor_{$treeItemID}\" style=\"display: none;\">&nbsp;</a>";
+ $idForOnClick = $treeItemID;
+ $treeItemID++;
+ echo "<input type=\"checkbox\" class=\"formfld\" id=\"treeitem_{$treeItemID}\" ";
+ $treeItemID++;
+ echo "name=\"treeitem_{$treeItemID}\" title=\"{$area}\" onClick=\"getURL('system_groupmanager.php?id={$id}&amp;toggle={$aa}&amp;item={$idForOnClick}&amp;session={$stripped_session}', after_request_callback); rotate();\" {$checked} />&nbsp;";
+ $treeItemID++;
+ echo "<a id=\"treeitem_{$treeItemID}\" href=\"#anchor_{$idForOnClick}\" onclick=\"getURL('system_groupmanager.php?id={$id}&amp;toggle={$aa}&amp;item={$idForOnClick}&amp;session={$stripped_session}', after_request_callback); rotate();\">{$a}</a></li>\n";
+ $idForScript = $treeItemID;
+ $treeItemID++;
+
+//echo "$script_tag <hr />";
+ $script_tag .= "var item = document.getElementById('treeitem_{$idForScript}');\n";
+ if ($allowed) {
+ $script_tag .= "item.style.backgroundImage = \"url('/tree/page-file_play.gif')\";\n";
+ } else {
+ $script_tag .= "item.style.backgroundImage = \"url('/tree/page-file_x.gif')\";\n";
+ }
+ $counter++;
+ } // end if
+ } // end foreach
+}
+
+function init_ajax_helper_file($tmpfname)
+{
+ global $config, $id, $global;
+ $a_group = &$config['system']['group'];
+ $id = $_GET['id'];
+ if (isset($id) && $a_group[$id])
+ $group = $a_group[$id];
+ else
+ $group = array();
+ $fd = fopen("/tmp/{$tmpfname}", "w");
+ if ($group['pages'][0]['page'])
+ foreach($group['pages'][0]['page'] as $page) {
+ fwrite($fd, $page . "\n");
+ }
+ fclose($fd);
+ return;
+}
+
+if ($_GET['toggle'] <> "") {
+ /* AJAX is calling, lets take care of it */
+ if (!file_exists("/tmp/" . $_GET['session'])) {
+ init_ajax_helper_file($_GET['session']);
+ }
+ $fc = file_get_contents("/tmp/" . $_GET['session']);
+ $file_split = split("\n", $fc);
+ $found = -1;
+ for($x = 0; $x < count($file_split); $x++) {
+ if ($file_split[$x] == $_GET['toggle']) {
+ $found = $x;
+ }
+ }
+ if ($found == -1) {
+ $file_split[] = $_GET['toggle'];
+ $image = "/tree/page-file_play.gif";
+ } else {
+ unset($file_split[$found]);
+ $image = "/tree/page-file_x.gif";
+ }
+ $fd = fopen("/tmp/{$_GET['session']}", "w");
+ if ($file_split)
+ foreach($file_split as $fs) {
+ if ($fs)
+ fwrite($fd, $fs . "\n");
+ }
+ fclose($fd);
+ echo $_GET['item'] . "_a||" . "{$image}";
+ exit;
+}
+
+function convert_array_to_pgtitle($orig)
+{
+ $newstring = "";
+ foreach($orig as $o) {
+ if ($newstring <> "")
+ $newstring .= ": ";
+ $newstring .= $o;
+ }
+ return $newstring;
+}
+// Returns an array of pages with their descriptions
+function getAdminPageList()
+{
+ global $g;
+
+ $tmp = Array();
+
+ if ($dir = opendir($g['www_path'])) {
+ while ($file = readdir($dir)) {
+ // Make sure the file exists and is not a directory
+ if ($file == "." or $file == ".." or $file[0] == '.')
+ continue;
+ // Is this a .inc.php file? pfSense!
+ if (fnmatch('guiconfig.inc', $file))
+ continue;
+ if (fnmatch('*.inc', $file))
+ continue;
+ if (fnmatch('*.inc.php', $file))
+ continue;
+ if (fnmatch('*.php', $file)) {
+ // Read the description out of the file
+ $contents = file_get_contents($file);
+ $contents_split = split("\n", $contents);
+ $mlinestr = "";
+ foreach($contents_split as $contents) {
+ $pgtitle = "";
+ // Looking for a line like:
+ // $pgtitle = array(gettext("System"), gettext("Group manager")); // - DO NOT REMOVE.
+ if ($mlinestr == "" && stristr($contents, "\$pgtitle") == false)
+ continue;
+ if ($mlinestr == "" && stristr($contents, "=") == false)
+ continue;
+ if (stristr($contents, "<"))
+ continue;
+ if (stristr($contents, ">"))
+ continue;
+ /* at this point its evalable */
+ $contents = trim ($contents);
+ $lastchar = substr($contents, strlen($contents) - 1, strlen($contents));
+ $firstchar = substr($contents, 0, 1);
+
+ /* check whether pgtitle is on one or multible lines */
+ if ($firstchar <> "/" && $firstchar <> "#" && $lastchar <> ";") {
+ /* remember the partitial pgtitle string for the next loop iteration */
+ $mlinestr .= $contents;
+ continue;
+ } else if ($mlinestr <> "" && $lastchar == ";") {
+ /* this is the final pgtitle part including the semicolon */
+ $mlinestr .= $contents;
+ } else if ($mlinestr == "" && $lastchar == ";") {
+ /* this is a single line pgtitle, hence just
+ * copy its contents into mlinestr
+ */
+ $mlinestr = $contents;
+ } else if ($firstchar == "/" || $firstchar == "#") {
+ /* same applies for comment lines */
+ $mlinestr = $contents;
+ }
+
+ eval($mlinestr);
+
+ /* after eval, if not an array, continue */
+ if (!is_array($pgtitle)) {
+ /* reset mlinestr for the next loop iteration */
+ $mlinestr = "";
+ continue;
+ }
+
+ $tmp[$file] = convert_array_to_pgtitle($pgtitle);
+
+ /* break out of the for loop, on to next file */
+ break;
+ }
+ }
+ }
+
+ /* loop through and read in wizard information */
+ if ($dir = opendir("{$g['www_path']}/wizards")) {
+ while ($file = readdir($dir)) {
+ // Make sure the file exists and is not directory
+ if ($file == "." or $file == ".." or $file[0] == '.')
+ continue;
+ // Is this a .xml file? pfSense!
+ if (fnmatch('*.xml', $file)) {
+ /* parse package and retrieve the package title */
+ $pkg = parse_xml_config_pkg("{$g['www_path']}/wizards/{$file}", "pfsensewizard");
+ $title = $pkg['title'];
+ if ($title)
+ $tmp[$file] = trim($title);
+ }
+ }
+ }
+
+ /* loop through and read in package information */
+ if ($dir = opendir("{$g['pkg_path']}")) {
+ while ($file = readdir($dir)) {
+ // Make sure the file exists and is not directory
+ if ($file == "." or $file == ".." or $file[0] == '.')
+ continue;
+ // Is this a .xml file? pfSense!
+ if (fnmatch('*.xml', $file)) {
+ /* parse package and retrieve the package title */
+ $pkg = parse_xml_config_pkg("{$g['pkg_path']}/{$file}", "packagegui");
+ $title = $pkg['title'];
+ if ($title)
+ $tmp[$file] = trim($title);
+ }
+ }
+ }
+
+ closedir($dir);
+ // Sets Interfaces:Optional page that didn't read in properly with the above method,
+ // and pages that don't have descriptions.
+ $tmp['interfaces_opt.php'] = ("Interfaces: Optional");
+ $tmp['graph.php'] = ("Status: Traffic Graph");
+ $tmp['graph_cpu.php'] = ("Diagnostics: CPU Utilization");
+ $tmp['exec_raw.php'] = ("Hidden: Exec Raw");
+ $tmp['uploadconfig.php'] = ("Hidden: Upload Configuration");
+ $tmp['index.php'] = ("Status: System");
+ $tmp['system_usermanager.php'] = ("System: User Password");
+ $tmp['diag_logs_settings.php'] = ("Diagnostics: Logs: Settings");
+ $tmp['diag_logs_vpn.php'] = ("Diagnostics: Logs: PPTP VPN");
+ $tmp['diag_logs_filter.php'] = ("Diagnostics: Logs: Firewall");
+ $tmp['diag_logs_portal.php'] = ("Diagnostics: Logs: Captive Portal");
+ $tmp['diag_logs_dhcp.php'] = ("Diagnostics: Logs: DHCP");
+ $tmp['diag_logs.php'] = ("Diagnostics: Logs: System");
+
+ $tmp['ifstats.php'] = ("Hidden: *XMLRPC Interface Stats");
+ $tmp['license.php'] = ("System: License");
+ $tmp['progress.php'] = ("Hidden: *No longer included");
+ $tmp['diag_logs_filter_dynamic.php'] = ("Hidden: *No longer included");
+ $tmp['preload.php'] = ("Hidden: *XMLRPC Preloader");
+ $tmp['xmlrpc.php'] = ("Hidden: *XMLRPC Library");
+ $tmp['pkg.php'] = ("System: *Renderer for XML based package GUIs (Part I)");
+ $tmp['pkg_edit.php'] = ("System: *Renderer for XML based package GUIs (Part II)");
+
+ $tmp['functions.inc.php'] = ("Hidden: Ajax Helper 1");
+ $tmp['javascript.inc.php'] = ("Hidden: Ajax Helper 2 ");
+ $tmp['sajax.class.php'] = ("Hidden: Ajax Helper 3");
+
+ asort($tmp);
+
+ return $tmp;
+ }
+}
+// Get a list of all admin pages & Descriptions
+$pages = getAdminPageList();
+
+if (!is_array($config['system']['group'])) {
+ $config['system']['group'] = array();
+}
+admin_groups_sort();
+$a_group = &$config['system']['group'];
+
+$id = $_GET['id'];
+if (isset($_POST['id']))
+ $id = $_POST['id'];
+
+if ($_GET['act'] == "del") {
+ if ($a_group[$_GET['id']]) {
+ $ok_to_delete = true;
+ if (isset($config['system']['user'])) {
+ foreach ($config['system']['user'] as $userent) {
+ if ($userent['groupname'] == $a_group[$_GET['id']]['name']) {
+ $ok_to_delete = false;
+ $input_errors[] = gettext("users still exist who are members of this group!");
+ break;
+ }
+ }
+ }
+ if ($ok_to_delete) {
+ unset($a_group[$_GET['id']]);
+ write_config();
+ pfSenseHeader("system_groupmanager.php");
+ exit;
+ }
+ }
+}
+
+if ($_POST) {
+ unset($input_errors);
+ $pconfig = $_POST;
+ /* input validation */
+ $reqdfields = explode(" ", "groupname");
+ $reqdfieldsn = explode(",", "Group Name");
+
+ do_input_validation($_POST, $reqdfields, $reqdfieldsn, &$input_errors);
+
+ if (preg_match("/[^a-zA-Z0-9\.\-_ ]/", $_POST['groupname']))
+ $input_errors[] = gettext("The group name contains invalid characters.");
+
+ if (!$input_errors && !(isset($id) && $a_group[$id])) {
+ /* make sure there are no dupes */
+ foreach ($a_group as $group) {
+ if ($group['name'] == $_POST['groupname']) {
+ $input_errors[] = gettext("Another entry with the same group name already exists.");
+ break;
+ }
+ }
+ }
+
+ if (!$input_errors) {
+ if (isset($id) && $a_group[$id])
+ $group = $a_group[$id];
+
+ $group['name'] = $_POST['groupname'];
+ isset($_POST['homepage']) ? $group['home'] = $_POST['homepage'] : $group['home'] = "index.php";
+ isset($_POST['gtype']) ? $group['scope'] = $_POST['gtype'] : $group['scope'] = "system";
+ $group['description'] = $_POST['description'];
+ unset($group['pages'][0]['page']);
+
+ $file_split = split("\n", file_get_contents("/tmp/" . $_POST['session']));
+ for($x = 0; $x < count($file_split); $x++) {
+ if ($file_split[$x])
+ $group['pages'][0]['page'][] = $file_split[$x];
+ }
+
+ if (isset($id) && $a_group[$id])
+ $a_group[$id] = $group;
+ else
+ $a_group[] = $group;
+
+ write_config();
+
+ unlink_if_exists("/tmp/" . $_GET['session']);
+
+ pfSenseHeader("system_groupmanager.php");
+ exit;
+ }
+}
+
+include("head.inc");
+
+$checkallstr = <<<EOD
+ function checkallareas(enable) {
+ var elem = document.iform.elements.length;
+ var endis = (document.iform.checkall.checked || enable);
+
+ for (i = 0; i < elem; i++) {
+ if (document.iform.elements[i].name.indexOf("chk-") >= 0) {
+ document.iform.elements[i].checked = true;
+ document.iform.elements[i].click();
+ }
+ }
+ }
+
+EOD;
+
+$pfSenseHead->addScript("<script type=\"text/javascript\">\n" . $checkallstr . "</script>\n");
+$pfSenseHead->addLink("<link href=\"/tree/tree.css\" rel=\"stylesheet\" type=\"text/css\" />");
+echo $pfSenseHead->getHTML();
+
+?>
+<body link="#000000" vlink="#000000" alink="#000000" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc");?>
+<?php if ($input_errors) print_input_errors($input_errors);?>
+<?php if ($savemsg) print_info_box($savemsg);?>
+ <table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[] = array(gettext("Users"), false, "system_usermanager.php");
+ $tab_array[] = array(gettext("Group"), true, "system_groupmanager.php");
+ $tab_array[] = array(gettext("Settings"), false, "system_usermanager_settings.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td class="tabcont">
+<?php
+if ($_GET['act'] == "new" || $_GET['act'] == "edit") {
+ $tmpfname = tempnam("/tmp", "edit_add_groupmanager");
+ $tmpfname = str_replace("/tmp/", "", $tmpfname);
+ unlink("/tmp/$tmpfname");
+ init_ajax_helper_file($tmpfname);
+ if ($_GET['act'] == "edit") {
+ if (isset($id) && $a_group[$id]) {
+ $pconfig['name'] = $a_group[$id]['name'];
+ $pconfig['description'] = $a_group[$id]['description'];
+ $pconfig['home'] = $a_group[$id]['home'];
+ $pconfig['gtype'] = $a_group[$id]['scope'];
+ $pconfig['pages'] = $a_group[$id]['pages'][0]['page'];
+ }
+ } else if ($_GET['act'] == "new") {
+ /* set this value cause the text field is read only
+ * and the user should not be able to mess with this
+ * setting.
+ */
+ $pconfig['gtype'] = "user";
+ }
+
+?>
+ <form action="system_groupmanager.php" method="post" name="iform" id="iform">
+ <div id="inputerrors"></div>
+<script type="text/javascript">
+if (typeof getURL == 'undefined') {
+ getURL = function(url, callback) {
+ if (!url)
+ throw 'No URL for getURL';
+ try {
+ if (typeof callback.operationComplete == 'function')
+ callback = callback.operationComplete;
+ } catch (e) {}
+ if (typeof callback != 'function')
+ throw 'No callback function for getURL';
+ var http_request = null;
+ if (typeof XMLHttpRequest != 'undefined') {
+ http_request = new XMLHttpRequest();
+ }
+ else if (typeof ActiveXObject != 'undefined') {
+ try {
+ http_request = new ActiveXObject('Msxml2.XMLHTTP');
+ } catch (e) {
+ try {
+ http_request = new ActiveXObject('Microsoft.XMLHTTP');
+ } catch (e) {}
+ }
+ }
+ if (!http_request)
+ throw 'Both getURL and XMLHttpRequest are undefined';
+ http_request.onreadystatechange = function() {
+ if (http_request.readyState == 4) {
+ callback( { success : true,
+ content : http_request.responseText,
+ contentType : http_request.getResponseHeader("Content-Type") } );
+ }
+ }
+ http_request.open('GET', url, true);
+ http_request.send(null);
+ }
+}
+function after_request_callback(callback_data) {
+ var data = callback_data.content;
+ data_split = data.split("||");
+ var item = document.getElementById(data_split[0]);
+ var check = document.getElementById("chk-" + data_split[0]);
+ item.style.backgroundImage = 'url(' + data_split[1] + ')';
+ if (data_split[1] == "/tree/page-file_play.gif") {
+ check.checked = true;
+ } else {
+ check.checked = false;
+ }
+ $('troot_text').innerHTML = '<?= gettext("webConfigurator"); ?>';
+}
+
+function rotate() {
+ $('troot_text').innerHTML = '<img src="/themes/<?= $g['theme'] ?>/images/misc/loader.gif" alt="" />';
+}
+</script>
+
+ <input type="hidden" name="session" value="<?=$tmpfname?>" />
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="22%" valign="top" class="vncellreq">
+ <?=gettext("Group name");?>
+ </td>
+ <td width="78%" class="vtable">
+ <input name="groupname" type="text" class="formfld group" id="groupname" size="20" value="<?=htmlspecialchars($pconfig['name']);?>" />
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">
+ <?=gettext("Home Page");?>
+ </td>
+ <td width="78%" class="vtable">
+ <input name="homepage" type="text" class="formfld url" id="homepage" size="20" value="<?=htmlspecialchars($pconfig['home']);?>" />
+ <br />
+ <?=gettext("A webpage that should be shown to the user after having logged in.");?>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq">
+ <?=gettext("Group Type");?>
+ </td>
+ <td width="78%" class="vtable">
+ <input name="gtype" type="text" class="formfld unknown" id="gtype" size="20" value="<?=htmlspecialchars($pconfig['gtype']);?>" readonly="readonly" />
+ <br />
+ <?=gettext("Indicates whether this is a system (aka non-deletable) group or a group created by the user.");?>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("Description");?></td>
+ <td width="78%" class="vtable">
+ <textarea name="description" class="formpre" id="description" rows="2" cols="20"><?=htmlspecialchars($pconfig['description']);?></textarea>
+ <br />
+ <?=gettext("Group description, for your own information only");?>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="5">
+ <script type="text/javascript" src="/tree/tree.js"></script>
+<?php
+ if (isset($id) && $a_group[$id])
+ $group = $a_group[$id];
+ else
+ $group = array();
+ $menu_array = array();
+ /* build up an array similar to fbegin.inc's $menu */
+ foreach ($pages as $fname => $title) {
+ $identifier = str_replace('.php', '', $fname);
+ $identifier = $fname;
+ $title_split = split(": ", $title);
+ $tmp = "\$menu_array";
+ foreach($title_split as $ts)
+ $tmp .= "['{$ts}']";
+ $tmp .= " = \"{$identifier}\";";
+ echo "<!-- $tmp -->\n";
+ eval($tmp);
+ }
+
+ echo "<span id=\"troot_text\" style=\"position: relative; top: 12px;\">" . gettext("webConfigurator") . "</span><ul class=\"tree\" id=\"troot\">\n";
+ $counter = 0;
+ /* XXX: we may wanna pull from or add to each row a +e item (+edit) */
+ $script_tag = "";
+
+ if (is_array($menu_array) && count($menu_array) > 0) {
+ foreach($menu_array as $title => $m) {
+ echo "<li class=\"closed\"><a id=\"treeitem_{$treeItemID}\" href=\"#\">$title</a><ul>";
+ $treeItemID++;
+ if (is_array($m) && count($m) > 0) {
+ foreach($m as $t => $area) {
+ if (is_array($area) && count($area) > 0) {
+ echo "<li class=\"closed\"><a id=\"treeitem_{$treeItemID}\" href=\"#\">$t</a><ul>";
+ $treeItemID++;
+ walkArea("{$title}_{$t}",
+ $t,
+ $area,
+ $id,
+ $counter,
+ $script_tag,
+ $tmpfname,
+ $group);
+ echo "</ul>\n";
+ } else {
+ $trimmed_title = trim($title);
+ $trimmed_t = trim($t);
+ $this_id = "{$trimmed_title}_{$trimmed_t}_{$counter}";
+ $this_id = str_replace(" ", "", $this_id);
+ $this_id = str_replace("/", "", $this_id);
+ $allowed = false;
+ if (is_array($group['pages'][0]['page'])) {
+ foreach($group['pages'][0]['page'] as $page) {
+ if (stristr($area, $page))
+ $allowed = true;
+ // echo "$page || $area || $t";
+ }
+ }
+ $allowed ? $checked = " checked=\"checked\"" : $checked = "";
+ $stripped_session = str_replace("/tmp/", "", $tmpfname);
+ echo"<li id=\"treeitem_{$treeItemID}\" class=\"closed\" title=\"{$area}\"><a name=\"anchor_{$treeItemID}\" style=\"display: none;\">&nbsp;</a>";
+ $idForOnClick = $treeItemID;
+ $treeItemID++;
+ echo " <input type=\"checkbox\" class=\"formfld\" id=\"treeitem_{$treeItemID}\" ";
+ $treeItemID++;
+ echo "name=\"treeitem_{$treeItemID}\" title=\"{$area}\" onclick=\"getURL('system_groupmanager.php?id={$id}&amp;toggle={$area}&amp;item={$idForOnClick}&amp;session={$stripped_session}', after_request_callback); rotate();\" {$checked}/>&nbsp;";
+ echo " <a id=\"treeitem_{$treeItemID}\" ";
+ $idForScript = $treeItemID;
+ $treeItemID++;
+ echo "href=\"#anchor_{$idForOnClick}\" onclick=\"getURL('system_groupmanager.php?id={$id}&amp;toggle={$area}&amp;item={$idForOnClick}&amp;session={$stripped_session}', after_request_callback); rotate();\">{$t}</a></li>\n";
+ $treeItemID++;
+ $script_tag .= "var item = document.getElementById('treeitem_{$idForScript}');\n";
+ if ($allowed) {
+ $script_tag .= "item.style.backgroundImage = \"url('/tree/page-file_play.gif')\";\n";
+ } else {
+ $script_tag .= "item.style.backgroundImage = \"url('/tree/page-file_x.gif')\";\n";
+ }
+ $counter++;
+ }
+ }
+ }
+ echo "</ul>\n";
+ }
+ }
+ echo "</ul>\n";
+
+?>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="5">
+ <table>
+ <tr>
+ <td><input type="checkbox" name="checkall" id="checkall" title="Check/Uncheck all areas" onclick="checkallareas();"/></td>
+ <td><?=gettext("Check/Uncheck all areas");?></td>
+ </tr>
+ <tr>
+ <td><img src="/tree/page-file_play.gif" alt="" /></td>
+ <td><?=gettext("Allowed access to area");?></td>
+ </tr>
+ <tr>
+ <td><img src="/tree/page-file_x.gif" alt="" /></td>
+ <td><?=gettext("Disallowed access to area");?></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="5">
+ <?=gettext("Select that pages that this group may access. Members of this group will be able to perform all actions that are possible from each individual web page. Ensure you set access levels appropriately.");?>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="5">
+ <input id="submit" name="save" type="submit" class="formbtn" value="<?=gettext("Save");?>" />
+ <?php if (isset($id) && $a_group[$id]): ?>
+ <input name="id" type="hidden" value="<?=$id;?>" />
+ <?php endif;?>
+ <p>
+ <span class="vexpl">
+ <span class="red">
+ <strong><?=gettext("Note");?>: </strong>
+ </span>
+ <?=gettext("Pages marked with an * are strongly recommended for every group.");?>
+ </span>
+ </p>
+ </td>
+ </tr>
+ </table>
+ </form>
+ </td> <!-- end <td class="tabcont"/> -->
+ </tr>
+ </table>
+<?php
+} else {
+
+?>
+ <table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td width="35%" class="listhdrr"><?=gettext("Group name");?></td>
+ <td width="20%" class="listhdrr"><?=gettext("Description");?></td>
+ <td width="20%" class="listhdrr"><?=gettext("Pages Accessible");?></td>
+ <td width="10%" class="list"></td>
+ </tr>
+<?php
+ $i = 0;
+ foreach($a_group as $group):
+?>
+ <tr>
+ <td class="listlr" valign="middle" nowrap="nowrap">
+ <table border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td align="left" valign="middle">
+ <?php if($group['scope'] == "user"): ?>
+ <img src="/themes/<?=$g['theme'];?>/images/icons/icon_system-group.png" alt="Group" title="Group" border="0" height="20" width="20" />
+ <?php else: ?>
+ <img src="/themes/<?=$g['theme'];?>/images/icons/icon_system-group-grey.png" alt="Group" title="Group" border="0" height="20" width="20" />
+ <?php endif; ?>
+ &nbsp;
+ </td>
+ <td align="left" valign="middle">
+ <?
+ if($group['name'] != "")
+ echo htmlspecialchars($group['name']);
+ else
+ echo "&nbsp";
+ ?>
+ </td>
+ </tr>
+ </table>
+ </td>
+ <td class="listr">
+ <?
+ if($group['description'] != "")
+ echo htmlspecialchars($group['description']);
+ else
+ echo "&nbsp;";
+ ?>
+ </td>
+ <td class="listbg">
+ <?php if(is_array($group['pages'][0])): ?>
+ <font color="white"><?=count($group['pages'][0]['page']);?></font>
+ <?php elseif (isset($group['pages'][0])): ?>
+ <font color="white"><?=$group['pages'][0];?></font>
+ <?php else: ?>
+ <font color="white"><?=gettext("NOT SET");?></font>
+ <?php endif; ?>
+ </td>
+ <?php if($group['scope'] == "user"): ?>
+ <td valign="middle" nowrap class="list">
+ <a href="system_groupmanager.php?act=edit&amp;id=<?=$i;?>">
+ <img src="/themes/<?= $g['theme'];?>/images/icons/icon_e.gif" title="<?=gettext("edit group");?>" width="17" height="17" border="0" alt="" />
+ </a>
+ <a href="system_groupmanager.php?act=del&amp;id=<?=$i;?>" onclick="return confirm('<?=gettext("Do you really want to delete this group?");?>')">
+ <img src="./themes/<?= $g['theme'];?>/images/icons/icon_x.gif" title="<?=gettext("delete group");?>" width="17" height="17" border="0" alt="" />
+ </a>
+ </td>
+ <?php endif; ?>
+ </tr>
+<?php
+ $i++;
+ endforeach;
+?>
+ <tr>
+ <td class="list" colspan="3"></td>
+ <td class="list">
+ <a href="system_groupmanager.php?act=new">
+ <img src="/themes/<?= $g['theme'];?>/images/icons/icon_plus.gif" title="<?=gettext("add group");?>" width="17" height="17" border="0" alt="" />
+ </a>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="3">
+ <p>
+ <?=gettext("Additional webConfigurator admin groups can be added here. Each group can be restricted to specific portions of the webConfigurator. Individually select the desired web pages each group may access. For example, a troubleshooting group could be created which has access only to selected Status and Diagnostics pages.");?>
+ </p>
+ <p>
+ <?=gettext("A group icon that appears grey indicates that it is a system group and thus can't be modified or deleted.");?>
+ </p>
+ </td>
+ </tr>
+ </table>
+</td></tr>
+</table>
+<?php
+}
+?>
+
+<script type="text/javascript">
+ window.setTimeout('afterload()', '10');
+ function afterload() {
+ <?php echo $script_tag ?>
+ }
+</script>
+<?php include("fend.inc");?>
+</body>
+</html>
diff --git a/config/authng/www/php/system_usermanager.php b/config/authng/www/php/system_usermanager.php
new file mode 100644
index 00000000..0a13be95
--- /dev/null
+++ b/config/authng/www/php/system_usermanager.php
@@ -0,0 +1,84 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ system_usermanager.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+require("guiconfig.inc");
+// The page title for non-admins
+$pgtitle = getUsermanagerPagetitle();
+
+include("head.inc");
+
+$effectStyle = '
+ <style type="text/css">
+ .popup_nousers {
+ background: #000000;
+ opacity: 0.2;
+ }
+ </style>
+';
+foreach(getWindowJSScriptRefs() as $jscript){
+ $pfSenseHead->addScript($jscript);
+}
+foreach(getWindowJSStyleRefs() as $style){
+ $pfSenseHead->addStyle($style);
+}
+$pfSenseHead->addStyle($effectStyle);
+echo $pfSenseHead->getHTML();
+?>
+<body link="#000000" vlink="#000000" alink="#000000">
+<?php include("fbegin.inc");?>
+<p class="pgtitle"><?= gentitle($pgtitle); ?></p>
+<form action="system_usermanager.php" method="post" name="iform" id="iform">
+<?php if ($input_errors) print_input_errors($input_errors);?>
+<?php if ($savemsg) print_info_box($savemsg);?>
+<?php
+ if (! gotNoUsers()) {
+ if ($userPeer->isSystemAdmin($HTTP_SERVER_VARS['AUTH_USER'])) {
+ processUserManagerAdminPostVars();
+ require_once("system_usermanager_admin.inc");
+ } else {
+ processUserManagerPostVars();
+ require_once("system_usermanager_user.inc");
+ }
+ }
+?>
+</form>
+<div id="popupanchor">&#160;</div>
+<?= openNoUserDefsDialog("popup_nousers"); ?>
+<?php include("fend.inc");?>
+</body>
+</html>
diff --git a/config/authng/www/php/system_usermanager_admin.inc b/config/authng/www/php/system_usermanager_admin.inc
new file mode 100644
index 00000000..73cda74f
--- /dev/null
+++ b/config/authng/www/php/system_usermanager_admin.inc
@@ -0,0 +1,92 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ system_usermanager_admin.inc
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+/* ======================= P A G E F R A G M E N T ======================== */
+/* ========================================================================== */
+?>
+ <table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td>
+<?php
+ $tab_array = array();
+ $tab_array[] = array(gettext("Users"), true, "system_usermanager.php");
+ $tab_array[] = array(gettext("Group"), false, "system_groupmanager.php");
+ $tab_array[] = array(gettext("Settings"), false, "system_usermanager_settings.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <table class="tabcont" width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td>
+ <?php
+ if ($_GET['act'] == "new" || $_GET['act'] == "edit" || $input_errors) {
+ if ($_GET['act'] == "edit") {
+ if (isset($id) && $a_user[$id]) {
+ $pconfig['usernamefld'] = $a_user[$id]['name'];
+ $pconfig['fullname'] = $a_user[$id]['fullname'];
+ $pconfig['groupname'] = $a_user[$id]['groupname'];
+ $pconfig['utype'] = $a_user[$id]['scope'];
+ $pconfig['authorizedkeys'] = base64_decode($a_user[$id]['authorizedkeys']);
+ }
+ } else if ($_GET['act'] == "new") {
+ /* set this value cause the text field is read only
+ * and the user should not be able to mess with this
+ * setting.
+ */
+ $pconfig['utype'] = "user";
+ }
+
+ // finally pull in the php file containing the appropriate markup
+ require_once("system_usermanager_admin_newedit.inc");
+ ?>
+ <?php
+ } else {
+ // finally pull in the php file containing the appropriate markup
+ require_once("system_usermanager_admin_index.inc");
+ ?>
+ <?php } ?>
+ </td>
+ </tr>
+ </table>
+ </div> <!-- MAINAREA DIV -->
+ </td>
+ </tr>
+ </table>
diff --git a/config/authng/www/php/system_usermanager_admin_index.inc b/config/authng/www/php/system_usermanager_admin_index.inc
new file mode 100644
index 00000000..807c7e53
--- /dev/null
+++ b/config/authng/www/php/system_usermanager_admin_index.inc
@@ -0,0 +1,108 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ system_usermanager_admin_edituser.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+/* ======================= P A G E F R A G M E N T ======================== */
+/* ========================================================================== */
+?>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+<tr>
+ <td width="35%" class="listhdrr">Username</td>
+ <td width="20%" class="listhdrr">Full name</td>
+ <td width="20%" class="listhdrr">Group</td>
+ <td width="10%" class="list"></td>
+</tr>
+<?php
+ $i = 0;
+ foreach($a_user as $userent):
+?>
+<tr ondblclick="document.location.herf = 'system_usermanager.php?act=edit&id=<?=$i;?>';">
+ <td class="listlr">
+ <table border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td align="left" valign="middle">
+ <?php if($userent['scope'] == "user"): ?>
+ <img src="/themes/<?=$g['theme'];?>/images/icons/icon_system-user.png" alt="User" title="User" border="0" height="20" width="20" />
+ <?php else: ?>
+ <img src="/themes/<?=$g['theme'];?>/images/icons/icon_system-user-grey.png" alt="User" title="User" border="0" height="20" width="20" />
+ <?php endif; ?>
+ &nbsp;
+ </td>
+ <td align="left" valign="middle">
+ <?=htmlspecialchars($userent['name']);?>
+ </td>
+ </tr>
+ </table>
+ </td>
+ <td class="listr"><?=htmlspecialchars($userent['fullname']);?>&nbsp;</td>
+ <td class="listbg">
+ <font color="white"><?=htmlspecialchars($userent['groupname']);?></font>&nbsp;
+ </td>
+ <td valign="middle" nowrap class="list">
+ <a href="system_usermanager.php?act=edit&id=<?=$i;?>">
+ <img src="/themes/<?= $g['theme'];?>/images/icons/icon_e.gif" title="edit user" alt="edit user" width="17" height="17" border="0" />
+ </a>
+ <?php if($userent['scope'] == "user"): ?>
+ &nbsp;
+ <a href="system_usermanager.php?act=del&what=user&id=<?=$i;?>" onclick="return confirm('<?=gettext("Do you really want to delete this User?");?>')">
+ <img src="/themes/<?= $g['theme'];?>/images/icons/icon_x.gif" title="delete user" alt="delete user" width="17" height="17" border="0" />
+ </a>
+ <?php endif; ?>
+ </td>
+</tr>
+<?php
+ $i++;
+ endforeach;
+?>
+<tr>
+ <td class="list" colspan="3"></td>
+ <td class="list">
+ <a href="system_usermanager.php?act=new">
+ <img src="/themes/<?= $g['theme'];?>/images/icons/icon_plus.gif" title="add user" alt="add user" width="17" height="17" border="0" />
+ </a>
+ </td>
+</tr>
+<tr>
+ <td colspan="3">
+ <p>
+ <?=gettext("Additional webConfigurator users can be added here. User permissions are determined by the admin group they are a member of.");?>
+ </p>
+ <p>
+ <?=gettext("An user icon that appears grey indicates that it is a system user and thus it's only possible to modified a subset of the regular user data. Additionally such an user can't be deleted.");?>
+ </p>
+ </td>
+</tr>
+</table> \ No newline at end of file
diff --git a/config/authng/www/php/system_usermanager_admin_newedit.inc b/config/authng/www/php/system_usermanager_admin_newedit.inc
new file mode 100644
index 00000000..d5b7126d
--- /dev/null
+++ b/config/authng/www/php/system_usermanager_admin_newedit.inc
@@ -0,0 +1,167 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ system_usermanager_admin_newuser.inc
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+/* ======================= P A G E F R A G M E N T ======================== */
+/* ========================================================================== */
+?>
+
+<div id="inputerrors"></div>
+<table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?=gettext("Username");?></td>
+ <td width="78%" class="vtable">
+ <input name="usernamefld" type="text" class="formfld user" id="usernamefld" size="20" value="<?=htmlspecialchars($pconfig['usernamefld']);?>" <?php if ($pconfig['utype'] == "system") { echo "readonly=\"readonly\" "; }?>/>
+ <input name="oldusername" type="hidden" id="oldusername" value="<?=htmlspecialchars($pconfig['usernamefld']);?>" />
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq" rowspan="2"><?=gettext("Password");?></td>
+ <td width="78%" class="vtable">
+ <input name="passwordfld1" type="password" class="formfld pwd" id="passwordfld1" size="20" value="" />
+ </td>
+ </tr>
+ <tr>
+ <td width="78%" class="vtable">
+ <input name="passwordfld2" type="password" class="formfld pwd" id="passwordfld2" size="20" value="" />&nbsp;<?= gettext("(confirmation)"); ?>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("Full name");?></td>
+ <td width="78%" class="vtable">
+ <input name="fullname" type="text" class="formfld unknown" id="fullname" size="20" value="<?=htmlspecialchars($pconfig['fullname']);?>" <?php if ($pconfig['utype'] == "system") { echo "readonly=\"readonly\" "; }?>/>
+ <br />
+ <?=gettext("User's full name, for your own information only");?>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("User type");?></td>
+ <td width="78%" class="vtable">
+ <input name="utype" type="text" class="formfld unknown" id="utype" size="20" value="<?=htmlspecialchars($pconfig['utype']);?>" readonly="readonly" />
+ <br />
+ <?=gettext("Indicates whether this is a system (aka non-deletable) user or a user created by a particular user.");?>
+ </td>
+ </tr>
+ <?php if (isSystemAdmin($HTTP_SERVER_VARS['AUTH_USER'])): ?>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("User Privileges");?></td>
+ <td width="78%" class="vtable">
+ <table class="tabcont" width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td width="5%" class="listhdrr"><?=gettext("ID");?></td>
+ <td width="30%" class="listhdrr"><?=gettext("Name");?></td>
+ <td width="40%" class="listhdrr"><?=gettext("Description");?></td>
+ <td width="5%" class="list"></td>
+ </tr>
+
+ <?php if(is_array($t_privs)): ?>
+ <?php $i = 0; foreach ($t_privs as $priv): ?>
+ <?php if($priv['id'] <> ""): ?>
+ <tr>
+ <td class="listlr" <?php if($a_user[$id]['scope'] == "user") echo "ondblclick=\"document.location='system_usermanager_edit.php?id={$i}&userid={$id}&useract={$_GET['act']}';\""; ?>>
+ <?=htmlspecialchars($priv['id']);?>
+ </td>
+ <td class="listlr" <?php if($a_user[$id]['scope'] == "user") echo "ondblclick=\"document.location='system_usermanager_edit.php?id={$i}&userid={$id}&useract={$_GET['act']}';\""; ?>>
+ <?=htmlspecialchars($priv['name']);?>
+ </td>
+ <td class="listbg" <?php if($a_user[$id]['scope'] == "user") echo "ondblclick=\"document.location='system_usermanager_edit?id={$i}&userid={$id}&useract={$_GET['act']}';\""; ?>>
+ <font color="#FFFFFF"><?=htmlspecialchars($priv['descr']);?>&nbsp;</font>
+ </td>
+ <td valign="middle" nowrap class="list">
+ <?php if($a_user[$id]['scope'] == "user"): ?>
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td valign="middle"><a href="system_usermanager_edit.php?id=<?=$i;?>&userid=<?= $id ?>&useract=<?= $_GET['act'] ?>"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_e.gif" width="17" height="17" border="0" alt="" /></a></td>
+ <td valign="middle"><a href="system_usermanager.php?act=del&privid=<?=$i;?>&what=priv&id=<?= $id ?>" onclick="return confirm('<?=gettext("Do you really want to delete this mapping?");?>')"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_x.gif" width="17" height="17" border="0" alt="" /></a></td>
+ </tr>
+ </table>
+ <?php endif; ?>
+ </td>
+ </tr>
+ <?php endif; ?>
+ <?php $i++; endforeach; ?>
+ <?php endif; ?>
+
+ <?php if($a_user[$id]['scope'] == "user"): ?>
+ <tr>
+ <td class="list" colspan="3"></td>
+ <td class="list">
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td valign="middle"><a href="system_usermanager_edit.php?userid=<?= $id ?>&useract=<?= $_GET['act'] ?>"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" width="17" height="17" border="0" alt="" /></a></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <?php endif; ?>
+ </table>
+ </td>
+ </tr>
+ <?php endif; ?>
+ <?php if (isset($config['system']['ssh']['sshdkeyonly'])): ?>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("Authorized keys");?></td>
+ <td width="78%" class="vtable">
+ <textarea name="authorizedkeys" cols="65" rows="7" id="authorizedkeys" class="formfld_cert" wrap="off"><?=htmlspecialchars($pconfig['authorizedkeys']);?></textarea>
+ <br />
+ <?=gettext("Paste an authorized keys file here.");?>
+ </td>
+ </tr>
+ <?php endif; ?>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("Group Name");?></td>
+ <td width="78%" class="vtable">
+ <select name="groupname" class="formselect" id="groupname" <?php if ($pconfig['utype'] == "system") { echo "disabled=\"disabled\" "; } ?>>
+ <?php foreach ($config['system']['group'] as $group): ?>
+ <option value="<?=$group['name'];?>" <?php if ($group['name'] == $pconfig['groupname']) { echo "selected"; } ?>>
+ <?=htmlspecialchars($group['name']);?>
+ </option>
+ <?php endforeach;?>
+ </select>
+ <br />
+ <?=gettext("The admin group to which this user is assigned.");?>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <input id="submit" name="save" type="submit" class="formbtn" value="Save" />
+ <?php if (isset($id) && $a_user[$id]): ?>
+ <input name="id" type="hidden" value="<?=$id;?>" />
+ <?php endif;?>
+ </td>
+ </tr>
+</table>
diff --git a/config/authng/www/php/system_usermanager_edit.php b/config/authng/www/php/system_usermanager_edit.php
new file mode 100644
index 00000000..25dc2ac3
--- /dev/null
+++ b/config/authng/www/php/system_usermanager_edit.php
@@ -0,0 +1,294 @@
+<?php
+/* $Id$ */
+/*
+ system_usermanager_edit.php
+
+ Copyright (C) 2006 Daniel S. Haischt.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+$pgtitle = array(gettext("System"),
+ gettext("User manager"),
+ gettext("Edit Privilege"));
+
+require("guiconfig.inc");
+
+/*
+ The following code presumes, that the following XML structure exists or
+ if it does not exist, it will be created.
+
+ <priv>
+ <id>fooid</id>
+ <name>foo</name>
+ <descr>foo desc</descr>
+ </priv>
+ <priv>
+ <id>barid</id>
+ <name>bar</name>
+ <descr>bar desc</descr>
+ </priv>
+*/
+
+$useract = $_GET['useract'];
+if (isset($_POST['useract']))
+ $useract = $_POST['useract'];
+
+/* USERID must be set no matter whether this is a new entry or an existing entry */
+$userid = $_GET['userid'];
+if (isset($_POST['userid']))
+ $userid = $_POST['userid'];
+
+/* ID is only set if the user wants to edit an existing entry */
+$id = $_GET['id'];
+if (isset($_POST['id']))
+ $id = $_POST['id'];
+
+if (empty($config['system']['user'][$userid])) {
+ pfSenseHeader("system_usermanager.php?id={$userid}&act={$_GET['useract']}");
+ exit;
+}
+
+if (!is_array($config['system']['user'][$userid]['priv'])) {
+ $config['system']['user'][$userid]['priv'] = array();
+}
+
+$t_privs = &$config['system']['user'][$userid]['priv'];
+
+if (isset($id) && $t_privs[$id]) {
+ $pconfig['pid'] = $t_privs[$id]['id'];
+ $pconfig['pname'] = $t_privs[$id]['name'];
+ $pconfig['descr'] = $t_privs[$id]['descr'];
+} else {
+ $pconfig['pid'] = $_GET['pid'];
+ $pconfig['pname'] = $_GET['pname'];
+ $pconfig['descr'] = $_GET['descr'];
+}
+
+if ($_POST) {
+
+ unset($input_errors);
+ $pconfig = $_POST;
+
+ /* input validation */
+ $reqdfields = explode(" ", "pid pname");
+ $reqdfieldsn = explode(",", "ID, Privilege Name");
+
+ do_input_validation($_POST, $reqdfields, $reqdfieldsn, &$input_errors);
+
+ /* check for overlaps */
+ foreach ($t_privs as $priv) {
+ if (isset($id) && ($t_privs[$id]) && ($t_privs[$id] === $priv)) {
+ continue;
+ }
+ if ($priv['id'] == $pconfig['pid']) {
+ $input_errors[] = gettext("This privilege ID already exists.");
+ break;
+ }
+ }
+
+ if (hasShellAccess($userindex[$userid]['name']) ||
+ isAllowedToCopyFiles($userindex[$userid]['name'])) {
+ if (preg_match("/[^a-zA-Z0-9\.\-_]/", $userindex[$userid]['name']))
+ $input_errors[] = gettext("The username contains invalid characters " .
+ "((this means this user can't be used to create" .
+ " a shell account).");
+ }
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($input_errors)) {
+ input_errors2Ajax($input_errors);
+ exit;
+ }
+
+ if (!$input_errors) {
+ $priv = array();
+ $priv['id'] = $pconfig['pid'];
+ $priv['name'] = $pconfig['pname'];
+ $priv['descr'] = $pconfig['descr'];
+
+ if (isset($id) && $t_privs[$id])
+ $t_privs[$id] = $priv;
+ else
+ $t_privs[] = $priv;
+
+ if ($priv['id'] == "hasshell") {
+ assignUID($user['name']);
+ assignGID($user['groupname']);
+ }
+
+ write_config();
+
+ $retval = 0;
+ config_lock();
+ config_unlock();
+
+ $savemsg = get_std_save_message($retval);
+
+ pfSenseHeader("system_usermanager.php?id={$userid}&act={$useract}");
+ exit;
+ }
+}
+
+/* if ajax is calling, give them an update message */
+if(isAjax())
+ print_info_box_np($savemsg);
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+
+$jscriptstr = <<<EOD
+<script type="text/javascript">
+<!--
+
+ var privs = new Array();
+
+
+EOD;
+
+$privs =& getSystemPrivs();
+
+if (is_array($privs)) {
+ $id = 0;
+
+ $jscriptstr .= "privs[{$id}] = new Object();\n";
+ $jscriptstr .= "privs[{$id}]['id'] = 'custom';\n";
+ $jscriptstr .= "privs[{$id}]['name'] = '*** Custom privilege ***';\n";
+ $jscriptstr .= "privs[{$id}]['desc'] = 'This is your own, user defined privilege that you may change according to your requirements.';\n";
+ $id++;
+
+ foreach($privs as $priv){
+ $jscriptstr .= "privs[{$id}] = new Object();\n";
+ $jscriptstr .= "privs[{$id}]['id'] = '{$priv['id']}';\n";
+ $jscriptstr .= "privs[{$id}]['name'] = '{$priv['name']}';\n";
+ $jscriptstr .= "privs[{$id}]['desc'] = '{$priv['desc']}';\n";
+ $id++;
+ }
+}
+
+$jscriptstr .= <<<EOD
+ function setTextFields() {
+ var idx = document.iform.sysprivs.selectedIndex;
+ var value = document.iform.sysprivs.options[idx].value;
+
+ for (var i = 0; i < privs.length; i++) {
+ if (privs[i]['id'] == value && privs[i]['id'] != 'custom') {
+ document.iform.pid.value = privs[i]['id'];
+ document.iform.pid.readOnly = true;
+ document.iform.pname.value = privs[i]['name'];
+ document.iform.pname.readOnly = true;
+ document.iform.descr.value = privs[i]['desc'];
+ document.iform.descr.readOnly = true;
+ break;
+ } else if (privs[i]['id'] == value) {
+ document.iform.pid.value = privs[i]['id'];
+ document.iform.pid.readOnly = false;
+ document.iform.pname.value = privs[i]['name'];
+ document.iform.pname.readOnly = false;
+ document.iform.descr.value = privs[i]['desc'];
+ document.iform.descr.readOnly = false;
+ break;
+ }
+ }
+ }
+
+//-->
+</script>
+
+EOD;
+
+$pfSenseHead->addScript($jscriptstr);
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc"); ?>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+ <form action="system_usermanager_edit.php" method="post" name="iform" id="iform">
+ <div id="inputerrors"></div>
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?=gettext("System Privileges");?></td>
+ <td width="78%" class="vtable">
+ <select name="sysprivs" id="sysprivs" class="formselect" onchange="setTextFields();">
+ <option value="custom">*** Custom privilege ***</option>
+ <?php
+ $privs =& getSystemPrivs();
+
+ if (is_array($privs)) {
+ foreach($privs as $priv){
+ if (isset($config['system']['ssh']['sshdkeyonly']) && $priv['name'] <> "copyfiles")
+ echo "<option value=\"{$priv['id']}\">${priv['name']}</option>";
+ else if (empty($config['system']['ssh']['sshdkeyonly']))
+ echo "<option value=\"{$priv['id']}\">${priv['name']}</option>";
+ }
+ }
+ ?>
+ </select><br />
+ (If you do not want to define your own privilege, you may
+ select one from this list)
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?=gettext("Privilege Identifier");?></td>
+ <td width="78%" class="vtable">
+ <input name="pid" type="text" class="formfld unknown" id="pid" size="30" value="<?=htmlspecialchars($pconfig['pid']);?>" />
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?=gettext("Privilege Name");?></td>
+ <td width="78%" class="vtable">
+ <input name="pname" type="text" class="formfld unknown" id="pname" size="30" value="<?=htmlspecialchars($pconfig['pname']);?>" />
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("Description");?></td>
+ <td width="78%" class="vtable">
+ <input name="descr" type="text" class="formfld unknown" id="descr" size="60" value="<?=htmlspecialchars($pconfig['descr']);?>" />
+ <br /> <span class="vexpl"><?=gettext("You may enter a description here
+ for your reference (not parsed).");?></span></td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <input id="submitt" name="Submit" type="submit" class="formbtn" value="<?=gettext("Save");?>" />
+ <input id="cancelbutton" class="formbtn" type="button" value="<?=gettext("Cancel");?>" onclick="history.back()" />
+ <?php if (isset($id) && $t_privs[$id]): ?>
+ <input name="id" type="hidden" value="<?=$id;?>" />
+ <?php endif; ?>
+ <?php if (isset($userid)): ?>
+ <input name="userid" type="hidden" value="<?=$userid;?>" />
+ <?php endif; ?>
+ <?php if (isset($useract)): ?>
+ <input name="useract" type="hidden" value="<?=$useract;?>" />
+ <?php endif; ?>
+ </td>
+ </tr>
+ </table>
+ </form>
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/authng/www/php/system_usermanager_settings.php b/config/authng/www/php/system_usermanager_settings.php
new file mode 100755
index 00000000..5853fab4
--- /dev/null
+++ b/config/authng/www/php/system_usermanager_settings.php
@@ -0,0 +1,110 @@
+<?php
+/* $Id$ */
+/*
+ part of pfSense (http://www.pfsense.org/)
+
+ Copyright (C) 2007 Bill Marquette <bill.marquette@gmail.com>
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+require("guiconfig.inc");
+
+$pconfig['session_timeout'] = &$config['system']['webgui']['session_timeout'];
+
+// Page title for main admin
+$pgtitle = array(gettext("System"), gettext("User manager settings"));
+
+if ($_POST) {
+ unset($input_errors);
+
+ /* input validation */
+ $reqdfields = explode(" ", "session_timeout");
+ $reqdfieldsn = explode(",", "Session Timeout");
+
+ do_input_validation($_POST, $reqdfields, $reqdfieldsn, &$input_errors);
+
+ if ($_POST['session_timeout'] != "" && !is_numeric($_POST['session_timeout']))
+ $input_errors[] = gettext("Session timeout must be an integer with value 0 or greater.");
+
+ /* if this is an AJAX caller then handle via JSON */
+ if (isAjax() && is_array($input_errors)) {
+ input_errors2Ajax($input_errors);
+ exit;
+ }
+
+
+ if (!$input_errors) {
+ $pconfig['session_timeout'] = $_POST['session_timeout'];
+
+ write_config();
+ pfSenseHeader("system_usermanager_settings.php");
+ }
+}
+
+include("head.inc");
+echo $pfSenseHead->getHTML();
+?>
+
+<body link="#000000" vlink="#000000" alink="#000000" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc");?>
+<?php if ($input_errors) print_input_errors($input_errors);?>
+<?php if ($savemsg) print_info_box($savemsg);?>
+ <table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[] = array(gettext("Users"), false, "system_usermanager.php");
+ $tab_array[] = array(gettext("Group"), false, "system_groupmanager.php");
+ $tab_array[] = array(gettext("Settings"), true, "system_usermanager_settings.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <form id="iform" name="iform" action="system_usermanager_settings.php" method="post">
+ <table class="tabcont" width="100%" border="0" cellspacing="0" cellpadding="0">
+ <tr>
+ <td width="22%" valign="top" class="vncell">Session Timeout</td>
+ <td width="78%" class="vtable"> <input name="session_timeout" id="session_timeout" type="text"size="20" class="formfld unknown" value="<?=htmlspecialchars($pconfig['session_timeout']);?>" />
+ <br />
+ <?=gettext("Time in minutes to expire idle management sessions.");?><br />
+ </td>
+ </tr>
+
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%"> <input id="submit" name="Submit" type="submit" class="formbtn" value="<?=gettext("Save");?>" />
+ </td>
+ </tr>
+ </table>
+ </form>
+ </div>
+ </td>
+ </tr>
+ </table>
+
+<?php include("fend.inc");?>
+</body>
+</html>
diff --git a/config/authng/www/php/system_usermanager_user.inc b/config/authng/www/php/system_usermanager_user.inc
new file mode 100644
index 00000000..25d2e210
--- /dev/null
+++ b/config/authng/www/php/system_usermanager_user.inc
@@ -0,0 +1,66 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ system_usermanager_user.inc
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+/* ======================= P A G E F R A G M E N T ======================== */
+/* ========================================================================== */
+?>
+ <div id="inputerrors"></div>
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td colspan="2" valign="top" class="listtopic"><?=$HTTP_SERVER_VARS['AUTH_USER']?>'s Password</td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell" rowspan="2">Password</td>
+ <td width="78%" class="vtable">
+ <input name="passwordfld1" type="password" class="formfld pwd" id="passwordfld1" size="20" />
+ </td>
+ </tr>
+ <tr>
+ <td width="78%" class="vtable">
+ <input name="passwordfld2" type="password" class="formfld pwd" id="passwordfld2" size="20" />
+ &nbsp;<?=gettext("(confirmation)");?>
+ <br />
+ <span class="vexpl"><?=gettext("Select a new password");?></span>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <input name="save" type="submit" class="formbtn" value="<?=gettext("Save");?>" />
+ </td>
+ </tr>
+ </table>
diff --git a/config/authng/www/wizards/authng_wizard.xml b/config/authng/www/wizards/authng_wizard.xml
new file mode 100644
index 00000000..94796e2f
--- /dev/null
+++ b/config/authng/www/wizards/authng_wizard.xml
@@ -0,0 +1,496 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<pfsensewizard>
+<copyright>
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng_wizard.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+</copyright>
+<totalsteps>8</totalsteps>
+<step>
+ <id>1</id>
+ <title>pfSense AuthNG Wizard</title>
+ <disableheader>true</disableheader>
+ <description>
+ This wizard will guide you through the initial configuration of
+ the pfSense authentication system.
+ </description>
+ <fields>
+ <field>
+ <name>Next</name>
+ <type>submit</type>
+ </field>
+ </fields>
+</step>
+<step>
+ <id>2</id>
+ <title>pfSense Backend settings</title>
+ <description>
+ On this screen you will define where to define pfSense users and groups
+ </description>
+ <fields>
+ <field>
+ <name>PrincipalStore</name>
+ <type>select</type>
+ <donotdisable>true</donotdisable>
+ <bindstofield>installedpackages->authng->config->principal_store</bindstofield>
+ <options>
+ <option>
+ <name>XML</name>
+ <value>xml</value>
+ </option>
+ <option>
+ <name>LDAP</name>
+ <value>ldap</value>
+ </option>
+ <option>
+ <name>DB</name>
+ <value>db</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <name>Backend</name>
+ <type>select</type>
+ <donotdisable>true</donotdisable>
+ <bindstofield>installedpackages->authng->config->backend</bindstofield>
+ <options>
+ <option>
+ <name>htpasswd</name>
+ <value>htpasswd</value>
+ </option>
+ <option>
+ <name>PAM</name>
+ <value>pam</value>
+ </option>
+ <option>
+ <name>Radius</name>
+ <value>radius</value>
+ </option>
+ <option>
+ <name>passwd</name>
+ <value>passwd</value>
+ </option>
+ <option>
+ <name>LDAP</name>
+ <value>ldap</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <name>AuthenticationMethod</name>
+ <type>select</type>
+ <donotdisable>true</donotdisable>
+ <bindstofield>installedpackages->authng->config->auth_method</bindstofield>
+ <options>
+ <option>
+ <name>Session</name>
+ <value>session</value>
+ </option>
+ <option>
+ <name>Basic</name>
+ <value>basic</value>
+ </option>
+ </options>
+ </field>
+ </fields
+</step>
+<step>
+ <id>3</id>
+ <title>Time Server Information</title>
+ <description>Please enter the time, date and time zone.</description>
+ <fields>
+ <field>
+ <name>Time server dns name</name>
+ <description>Enter the name of the time server.</description>
+ <type>input</type>
+ <bindstofield>system->timeservers</bindstofield>
+ </field>
+ <field>
+ <name>Timezone</name>
+ <type>timezone_select</type>
+ <bindstofield>system->timezone</bindstofield>
+ </field>
+ <field>
+ <name>Next</name>
+ <type>submit</type>
+ </field>
+ </fields>
+</step>
+<step>
+ <id>4</id>
+ <disableallfieldsbydefault>true</disableallfieldsbydefault>
+ <title>Configure WAN Interface</title>
+ <description>On this screen we will configure the Wide Area Network information.</description>
+ <javascriptafterformdisplay>
+ var selectedItem = 0;
+ if(document.forms[0].ipaddress.value == 'dhcp') {
+ selectedItem = 1;
+ document.forms[0].ipaddress.value = '';
+ } else if(document.forms[0].ipaddress.value == 'PPPoE') {
+ selectedItem = 2;
+ document.forms[0].ipaddress.value = '';
+ } else if(document.forms[0].ipaddress.value == 'PPTP') {
+ selectedItem = 3;
+ document.forms[0].ipaddress.value = '';
+ } else if(document.forms[0].ipaddress.value == 'BigPond') {
+ selectedItem = 4;
+ document.forms[0].ipaddress.value = '';
+ } else {
+ selectedItem = 0;
+ }
+ document.forms[0].selectedtype.selectedIndex = selectedItem;
+ enableitems(selectedItem);
+ </javascriptafterformdisplay>
+ <fields>
+ <field>
+ <name>SelectedType</name>
+ <type>select</type>
+ <donotdisable>true</donotdisable>
+ <options>
+ <option>
+ <name>Static</name>
+ <value>Static</value>
+ <enablefields>ipaddress,subnetmask,gateway</enablefields>
+ </option>
+ <option>
+ <name>DHCP</name>
+ <value>dhcp</value>
+ <enablefields>dhcphostname</enablefields>
+ </option>
+ <option>
+ <name>PPPoE</name>
+ <value>pppoe</value>
+ <enablefields>pppoeusername,pppoepassword,pppoeservicename,pppoedialondemand,pppoeidletimeout</enablefields>
+ </option>
+ <option>
+ <name>PPTP</name>
+ <value>pptp</value>
+ <enablefields>pptpusername,pptppassword,pptplocalipaddress,pptplocalsubnet,pptpremoteipaddress,pptpdialondemand,pptpidletimeout
+ </enablefields>
+ </option>
+ <option>
+ <name>BigPond</name>
+ <value>bigpond</value>
+ <enablefields>bigpondusername,bigpondpassword,bigpondauthenticationserver,bigpondauthenticationdomain,bigpondminheartbeatinterval</enablefields>
+ </option>
+ </options>
+ </field>
+ <field>
+ <name>General configuration</name>
+ <type>listtopic</type>
+ </field>
+ <field>
+ <donotdisable>true</donotdisable>
+ <name>MAC Address</name>
+ <bindstofield>interfaces->wan->spoofmac</bindstofield>
+ <type>input</type>
+ <description> This field can be used to modify ("spoof") the MAC address of the WAN interface (may be required with some cable connections) Enter a MAC address in the following format: xx:xx:xx:xx:xx:xx or leave blank</description>
+ </field>
+ <field>
+ <donotdisable>true</donotdisable>
+ <name>MTU</name>
+ <type>input</type>
+ <bindstofield>interfaces->wan->mtu</bindstofield>
+ <description> If you enter a value in this field, then MSS clamping for TCP connections to the value entered above minus 40 (TCP/IP header size) will be in effect. If you leave this field blank, an MTU of 1492 bytes for PPPoE and 1500 bytes for all other connection types will be assumed.</description>
+ </field>
+ <field>
+ <name>Static IP Configuration</name>
+ <type>listtopic</type>
+ </field>
+ <field>
+ <name>IP Address</name>
+ <bindstofield>interfaces->wan->ipaddr</bindstofield>
+ <type>input</type>
+ <typehint> / </typehint>
+ <combinefieldsbegin>true</combinefieldsbegin>
+ </field>
+ <field>
+ <combinefieldsend>true</combinefieldsend>
+ <dontdisplayname>true</dontdisplayname>
+ <dontcombinecells>true</dontcombinecells>
+ <name>Subnet Mask</name>
+ <bindstofield>interfaces->wan->subnet</bindstofield>
+ <type>subnet_select</type>
+ </field>
+ <field>
+ <name>Gateway</name>
+ <bindstofield>interfaces->wan->gateway</bindstofield>
+ <type>input</type>
+ </field>
+ <field>
+ <name>DHCP client configuration</name>
+ <type>listtopic</type>
+ </field>
+ <field>
+ <name>DHCP Hostname</name>
+ <type>input</type>
+ <bindstofield>interfaces->wan->dhcphostname</bindstofield>
+ <description> The value in this field is sent as the DHCP client identifier and hostname when requesting a DHCP lease. Some ISPs may require this (for client identification).</description>
+ </field>
+ <field>
+ <name>PPPoE configuration</name>
+ <type>listtopic</type>
+ </field>
+ <field>
+ <name>PPPoE Username</name>
+ <type>input</type>
+ <bindstofield>pppoe->username</bindstofield>
+ </field>
+ <field>
+ <name>PPPoE Password</name>
+ <type>input</type>
+ <bindstofield>pppoe->password</bindstofield>
+ </field>
+ <field>
+ <name>PPPoE Service name</name>
+ <type>input</type>
+ <description>Hint: this field can usually be left empty</description>
+ </field>
+ <field>
+ <name>PPPoE Dial on demand</name>
+ <typehint>Enable Dial-On-Demand mode</typehint>
+ <type>checkbox</type>
+ <description>This option causes the interface to operate in dial-on-demand mode, allowing you to have a virtual full time connection. The interface is configured, but the actual connection of the link is delayed until qualifying outgoing traffic is detected.</description>
+ </field>
+ <field>
+ <name>PPPoE Idle timeout</name>
+ <type>input</type>
+ <description>If no qualifying outgoing packets are transmitted for the specified number of seconds, the connection is brought down. An idle timeout of zero disables this feature.</description>
+ </field>
+ <field>
+ <name>PPTP configuration</name>
+ <type>listtopic</type>
+ </field>
+ <field>
+ <name>PPTP Username</name>
+ <type>input</type>
+ <bindstofield>pptp->username</bindstofield>
+ </field>
+ <field>
+ <name>PPTP Password</name>
+ <type>input</type>
+ <bindstofield>pptp->password</bindstofield>
+ </field>
+ <field>
+ <combinefieldsbegin>true</combinefieldsbegin>
+ <name>PPTP Local IP Address</name>
+ <type>input</type>
+ <typehint> / </typehint>
+ <bindstofield>pptp->local</bindstofield>
+ </field>
+ <field>
+ <combinefieldsend>true</combinefieldsend>
+ <dontdisplayname>true</dontdisplayname>
+ <dontcombinecells>true</dontcombinecells>
+ <name>pptplocalsubnet</name>
+ <bindstofield>pptp->subnet</bindstofield>
+ <type>subnet_select</type>
+ </field>
+ <field>
+ <name>PPTP Remote IP Address</name>
+ <bindstofield>pptp->remote</bindstofield>
+ <type>input</type>
+ </field>
+ <field>
+ <name>PPTP Dial on demand</name>
+ <typehint>Enable Dial-On-Demand mode</typehint>
+ <type>checkbox</type>
+ <description>This option causes the interface to operate in dial-on-demand mode, allowing you to have a virtual full time connection. The interface is configured, but the actual connection of the link is delayed until qualifying outgoing traffic is detected.</description>
+ </field>
+ <field>
+ <name>PPTP Idle timeout</name>
+ <type>input</type>
+ <description>If no qualifying outgoing packets are transmitted for the specified number of seconds, the connection is brought down. An idle timeout of zero disables this feature.</description>
+ </field>
+ <field>
+ <name>BigPond configuration</name>
+ <type>listtopic</type>
+ </field>
+ <field>
+ <name>BigPond Username</name>
+ <type>input</type>
+ <bindstofield>bigpond->username</bindstofield>
+ </field>
+ <field>
+ <name>BigPond Password</name>
+ <type>input</type>
+ <bindstofield>bigpond->password</bindstofield>
+ </field>
+ <field>
+ <name>BigPond Authentication server</name>
+ <type>input</type>
+ <bindstofield>bigpond->authserver</bindstofield>
+ <description>If this field is left empty, the default ("dce-server") is used.</description>
+ </field>
+ <field>
+ <name>BigPond Authentication domain</name>
+ <type>input</type>
+ <bindstofield>bigpond->authdomain</bindstofield>
+ <description>If this field is left empty, the domain name assigned via DHCP will be used. Note: the BigPond client implicitly sets the "Allow DNS server list to be overridden by DHCP/PPP on WAN" on the System: General setup page.</description>
+ </field>
+ <field>
+ <name>BigPond min heartbeat interval</name>
+ <type>input</type>
+ <typehint>seconds</typehint>
+ <bindstofield>bigpond->minheartbeatinterval</bindstofield>
+ <description> Setting this to a sensible value (e.g. 60 seconds) can protect against DoS attacks.</description>
+ </field>
+ <field>
+ <name>RFC1918 Networks</name>
+ <type>listtopic</type>
+ </field>
+ <field>
+ <donotdisable>true</donotdisable>
+ <name>Block RFC1918 Private Networks</name>
+ <description> When set, this option blocks traffic from IP addresses that are reserved for private networks as per RFC 1918 (10/8, 172.16/12, 192.168/16) as well as loopback addresses (127/8). You should generally leave this option turned on, unless your WAN network lies in such a private address space, too.</description>
+ <type>checkbox</type>
+ <bindstofield>interfaces->wan->blockpriv</bindstofield>
+ <typehint>Block private networks from entering via WAN</typehint>
+ </field>
+ <field>
+ <name>Block bogon networks</name>
+ <type>listtopic</type>
+ </field>
+ <field>
+ <donotdisable>true</donotdisable>
+ <name>Block bogon networks</name>
+ <description>Block bogon networks when set, this option blocks traffic from IP addresses that are reserved (but not RFC 1918) or not yet assigned by IANA. Bogons are prefixes that should never appear in the Internet routing table, and obviously should not appear as the source address in any packets you receive.</description>
+ <type>checkbox</type>
+ <bindstofield>interfaces->wan->blockbogons</bindstofield>
+ <typehint>Block non-Internet routed networks from entering via WAN</typehint>
+ </field>
+ <field>
+ <name>Next</name>
+ <type>submit</type>
+ </field>
+ </fields>
+ <stepsubmitbeforesave>
+ if($_POST['selectedtype'] == "Static") { } else {
+ $_POST['ipaddress'] = $_POST['selectedtype'];
+ $config['interfaces']['wan']['ipaddr'] = $_POST['selectedtype'];
+ write_config();
+ }
+ </stepsubmitbeforesave>
+</step>
+<step>
+ <id>5</id>
+ <title>Configure LAN Interface</title>
+ <description>On this screen we will configure the Local Area Network information.</description>
+ <fields>
+ <field>
+ <name>LAN IP Address</name>
+ <type>input</type>
+ <bindstofield>interfaces->lan->ipaddr</bindstofield>
+ <description>Type dhcp if this interface uses dhcp to obtain its ip address.</description>
+ </field>
+ <field>
+ <name>Subnet Mask</name>
+ <type>subnet_select</type>
+ <bindstofield>interfaces->lan->subnet</bindstofield>
+ </field>
+ <field>
+ <name>Next</name>
+ <type>submit</type>
+ </field>
+ </fields>
+ <stepsubmitphpaction>
+ $ft = split("\.", $_POST['lanipaddress']);
+ $ft_ip = $ft[0] . "." . $ft[1] . "." . $ft[2] . ".";
+ $config['dhcpd']['lan']['range']['from'] = $ft_ip . "10";
+ $highestip = gen_subnet_max($_POST['lanipaddress'], $config['interfaces']['lan']['subnet']);
+ $hi = split("\.", $highestip);
+ $highestip = $hi[3]-10;
+ $config['dhcpd']['lan']['range']['to'] = $ft_ip . $highestip;
+ </stepsubmitphpaction>
+</step>
+<step>
+ <id>6</id>
+ <title>Set Admin WebGUI Password</title>
+ <description>On this screen we will set the Admin password which is used to access the WebGUI and also SSH services if you wish to enable.</description>
+ <fields>
+ <field>
+ <name>Admin Password</name>
+ <type>password</type>
+ </field>
+ <field>
+ <name>Admin Password AGAIN</name>
+ <type>password</type>
+ </field>
+ <field>
+ <name>Next</name>
+ <type>submit</type>
+ </field>
+ </fields>
+ <stepsubmitphpaction>
+ if($_POST['adminpassword'] != "") {
+ if($_POST['adminpassword'] == $_POST['adminpasswordagain']) {
+ $fd = popen("/usr/sbin/pw usermod -n root -H 0", "w");
+ $salt = md5(time());
+ $crypted_pw = crypt($_POST['adminpassword'],$salt);
+ fwrite($fd, $crypted_pw);
+ pclose($fd);
+ $config['system']['password'] = crypt($_POST['adminpassword']);
+ write_config();
+ system_password_configure();
+ } else {
+ print_info_box_np("Passwords do not match! Please press back in your browser window and correct.");
+ die;
+ }
+ }
+ </stepsubmitphpaction>
+</step>
+<step>
+ <id>7</id>
+ <title>Reload configuration</title>
+ <disableheader>true</disableheader>
+ <description>Click 'Reload' to reload pfSense with new changes. If you changed the password, pfSense will ask you to log in again.</description>
+ <fields>
+ <field>
+ <name>Reload</name>
+ <type>submit</type>
+ </field>
+ </fields>
+</step>
+<step>
+ <id>8</id>
+ <title>Reload in progress</title>
+ <description>A reload is now in progress. Please wait. &lt;p&gt; The system will automatically try to access $myurl in 120 seconds. &lt;p&gt; You can click on the icon above to access the site more quickly.
+ &lt;meta http-equiv="refresh" content="60; url=$myurl" &gt;</description>
+ <stepafterformdisplay>
+ reload_all();
+ </stepafterformdisplay>
+</step>
+</pfsensewizard>
diff --git a/config/autoconfigbackup/autoconfigbackup.inc b/config/autoconfigbackup/autoconfigbackup.inc
new file mode 100644
index 00000000..fd0d3169
--- /dev/null
+++ b/config/autoconfigbackup/autoconfigbackup.inc
@@ -0,0 +1,219 @@
+<?php
+/* $Id$ */
+/*
+ autoconfigbackup.inc
+ Copyright (C) 2008 Scott Ullrich
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+$pfSversion = str_replace("\n", "", file_get_contents("/etc/version"));
+if(strstr($pfSversion, "1.2"))
+ require_once("crypt_acb.php");
+
+/* ensures patches match */
+function custom_php_validation_command($post, $input_errors) {
+ global $_POST, $savemsg, $config;
+
+ if($post['password'] <> $post['passwordagain'])
+ $input_errors[] = "Sorry, the entered passwords do not match.";
+
+ if($post['crypto_password'] <> $post['crypto_password2'])
+ $input_errors[] = "Sorry, the entered encryption passwords do not match.";
+
+ if($post['testconnection']) {
+ $status = test_connection($post);
+ if($status)
+ $savemsg = "Connection to portal.pfsense.org was tested with no errors.";
+ }
+
+ // We do not need to store this value.
+ unset($_POST['testconnection']);
+}
+
+function test_connection($post) {
+ global $savemsg, $config;
+
+ // Seperator used during client / server communications
+ $oper_sep = "\|\|";
+
+ // Encryption password
+ $decrypt_password = $post['crypto_password'];
+
+ // Defined username
+ $username = $post['username'];
+
+ // Defined password
+ $password = $post['password'];
+
+ // Set hostname
+ $hostname = $config['system']['hostname'] . "." . $config['system']['domain'];
+
+ // URL to restore.php
+ $get_url = "https://{$username}:{$password}@portal.pfsense.org/pfSconfigbackups/restore.php";
+
+ // Populate available backups
+ $curl_session = curl_init();
+ curl_setopt($curl_session, CURLOPT_URL, $get_url);
+ curl_setopt($curl_session, CURLOPT_SSL_VERIFYPEER, 0);
+ curl_setopt($curl_session, CURLOPT_POST, 1);
+ curl_setopt($curl_session, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($curl_session, CURLOPT_POSTFIELDS, "action=showbackups&hostname={$hostname}");
+ $data = curl_exec($curl_session);
+
+ if (curl_errno($curl_session))
+ return("An error occurred " . curl_error($curl_session));
+ else
+ curl_close($curl_session);
+
+ return;
+}
+
+function upload_config($reasonm = "") {
+ global $config, $g, $input_errors;
+
+ /*
+ * pfSense upload config to pfSense.org script
+ * This file plugs into filter.inc (/usr/local/pkg/pf)
+ * and runs every time the running firewall filter changes.
+ *
+ * Written by Scott Ullrich
+ * (C) 2008 BSD Perimeter LLC
+ *
+ */
+
+ if(file_exists("/tmp/acb_nooverwrite")) {
+ unlink("/tmp/acb_nooverwrite");
+ $nooverwrite = "true";
+ } else {
+ $nooverwrite = "false";
+ }
+
+ // Define some needed variables
+ if(!file_exists("/cf/conf/lastpfSbackup.txt")) {
+ conf_mount_rw();
+ touch("/cf/conf/lastpfSbackup.txt");
+ conf_mount_ro();
+ }
+
+ $last_backup_date = str_replace("\n", "", file_get_contents("/cf/conf/lastpfSbackup.txt"));
+ $last_config_change = $config['revision']['time'];
+ $hostname = $config['system']['hostname'] . "." . $config['system']['domain'];
+ if($reasonm)
+ $reason = $reasonm;
+ else
+ $reason = $config['revision']['description'];
+ $username = $config['installedpackages']['autoconfigbackup']['config'][0]['username'];
+ $password = $config['installedpackages']['autoconfigbackup']['config'][0]['password'];
+ $encryptpw = $config['installedpackages']['autoconfigbackup']['config'][0]['crypto_password'];
+
+ // Define upload_url, must be present after other variable definitions due to username, password
+ $upload_url = "https://{$username}:{$password}@portal.pfsense.org/pfSconfigbackups/backup.php";
+
+ if(!$username or !$password or !$encryptpw) {
+ if(!file_exists("/cf/conf/autoconfigback.notice")) {
+ $notice_text = "Either the username, password or encryption password is not set for Automatic Configuration Backup. ";
+ $notice_text .= "Please correct this in Diagnostics -> AutoConfigBackup -> Settings.";
+ log_error($notice_text);
+ file_notice("AutoConfigBackup", $notice_text, $notice_text, "");
+ conf_mount_rw();
+ touch("/cf/conf/autoconfigback.notice");
+ conf_mount_ro();
+ }
+ } else {
+ /* If configuration has changed, upload to pfS */
+ if($last_backup_date <> $last_config_change) {
+
+ // Mount RW (if needed)
+ conf_mount_rw();
+ // Lock config
+ config_lock();
+
+ $notice_text = "Beginning https://portal.pfsense.org configuration backup.";
+ log_error($notice_text);
+ update_filter_reload_status($notice_text);
+
+ // Encrypt config.xml
+ $raw_config_sha256_hash = trim(`/sbin/sha256 /cf/conf/config.xml | awk '{ print $4 }'`);
+ $data = file_get_contents("/cf/conf/config.xml");
+ $data = encrypt_data($data, $encryptpw);
+ tagfile_reformat($data, $data, "config.xml");
+
+ $post_fields = array(
+ 'reason' => urlencode($reason),
+ 'hostname' => urlencode($hostname),
+ 'configxml' => urlencode($data),
+ 'nooverwrite' => urlencode($nooverwrite),
+ 'raw_config_sha256_hash' => urlencode($raw_config_sha256_hash)
+ );
+
+ //url-ify the data for the POST
+ foreach($post_fields as $key=>$value)
+ $fields_string .= $key.'='.$value.'&';
+ rtrim($fields_string,'&');
+
+ // Check configuration into the BSDP repo
+ $curl_session = curl_init();
+ curl_setopt($curl_session, CURLOPT_URL, $upload_url);
+ curl_setopt($curl_session, CURLOPT_POST, count($post_fields));
+ curl_setopt($curl_session, CURLOPT_POSTFIELDS, $fields_string);
+ curl_setopt($curl_session, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($curl_session, CURLOPT_SSL_VERIFYPEER, 0);
+ $data = curl_exec($curl_session);
+ if (curl_errno($curl_session)) {
+ $fd = fopen("/tmp/backupdebug.txt", "w");
+ fwrite($fd, $upload_url . "" . $fields_string . "\n\n");
+ fwrite($fd, $data);
+ fwrite($fd, curl_error($curl_session));
+ fclose($fd);
+ } else {
+ curl_close($curl_session);
+ }
+
+ if(!strstr($data, "500")) {
+ $notice_text = "An error occured while uploading your pfSense configuration to portal.pfsense.org";
+ log_error($notice_text . " - " . $data);
+ file_notice("autoconfigurationbackup", $notice_text, $data, "");
+ update_filter_reload_status($notice_text . " - " . $data);
+ } else {
+ // Update last pfS backup time
+ $fd = fopen("/cf/conf/lastpfSbackup.txt", "w");
+ fwrite($fd, $config['revision']['time']);
+ fclose($fd);
+ $notice_text = "End of portal.pfsense.org configuration backup (success).";
+ log_error($notice_text);
+ update_filter_reload_status($notice_text);
+ }
+
+ // Unlock config
+ config_unlock();
+ // Mount image RO (if needed)
+ conf_mount_ro();
+
+ } else {
+ log_error("No https://portal.pfsense.org backup required.");
+ }
+
+ }
+}
+
+?> \ No newline at end of file
diff --git a/config/autoconfigbackup/autoconfigbackup.php b/config/autoconfigbackup/autoconfigbackup.php
new file mode 100644
index 00000000..80db5543
--- /dev/null
+++ b/config/autoconfigbackup/autoconfigbackup.php
@@ -0,0 +1,387 @@
+<?php
+/* $Id$ */
+/*
+ autoconfigbackup.php
+ Copyright (C) 2008 Scott Ullrich
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require("guiconfig.inc");
+
+$pfSversion = str_replace("\n", "", file_get_contents("/etc/version"));
+if(strstr($pfSversion, "1.2"))
+ require("crypt_acb.php");
+
+// Seperator used during client / server communications
+$oper_sep = "\|\|";
+
+// Encryption password
+$decrypt_password = $config['installedpackages']['autoconfigbackup']['config'][0]['crypto_password'];
+
+// Defined username
+$username = $config['installedpackages']['autoconfigbackup']['config'][0]['username'];
+
+// Defined password
+$password = $config['installedpackages']['autoconfigbackup']['config'][0]['password'];
+
+// URL to restore.php
+$get_url = "https://{$username}:{$password}@portal.pfsense.org/pfSconfigbackups/restore.php";
+
+// URL to stats
+$stats_url = "https://{$username}:{$password}@portal.pfsense.org/pfSconfigbackups/showstats.php";
+
+// URL to delete.php
+$del_url = "https://{$username}:{$password}@portal.pfsense.org/pfSconfigbackups/delete.php";
+
+// Set hostname
+if($_REQUEST['hostname'])
+ $hostname = $_REQUEST['hostname'];
+else
+ $hostname = $config['system']['hostname'] . "." . $config['system']['domain'];
+
+// Hostname of local machine
+$myhostname = $config['system']['hostname'] . "." . $config['system']['domain'];
+
+if(!$username) {
+ Header("Location: /pkg_edit.php?xml=autoconfigbackup.xml&id=0");
+ exit;
+}
+
+if($_REQUEST['savemsg'])
+ $savemsg = htmlentities($_REQUEST['savemsg']);
+
+if($_REQUEST['download'])
+ $pgtitle = "Diagnostics: Auto Configuration Backup revision information";
+else
+ $pgtitle = "Diagnostics: Auto Configuration Backup";
+
+include("head.inc");
+
+function get_hostnames() {
+ global $stats_url, $username, $oper_sep;
+ // Populate available backups
+ $curl_session = curl_init();
+ curl_setopt($curl_session, CURLOPT_URL, $stats_url);
+ curl_setopt($curl_session, CURLOPT_SSL_VERIFYPEER, 0);
+ curl_setopt($curl_session, CURLOPT_POST, 1);
+ curl_setopt($curl_session, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($curl_session, CURLOPT_POSTFIELDS, "action=showstats");
+ $data = curl_exec($curl_session);
+ if (curl_errno($curl_session)) {
+ $fd = fopen("/tmp/acb_statsdebug.txt", "w");
+ fwrite($fd, $stats_url . "" . "action=showstats" . "\n\n");
+ fwrite($fd, $data);
+ fwrite($fd, curl_error($curl_session));
+ fclose($fd);
+ } else {
+ curl_close($curl_session);
+ }
+ // Loop through and create new confvers
+ $data_split = split("\n", $data);
+ $statvers = array();
+ foreach($data_split as $ds) {
+ $ds_split = split($oper_sep, $ds);
+ if($ds_split[0])
+ $statvers[] = $ds_split[0];;
+ }
+ return $statvers;
+}
+
+?>
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<div id='maincontent'>
+<script src="/javascript/scriptaculous/prototype.js" type="text/javascript"></script>
+<?php
+ include("fbegin.inc");
+ if(strstr($pfSversion, "1.2"))
+ echo "<p class=\"pgtitle\">{$pgtitle}</p>";
+ if($savemsg) {
+ echo "<div id='savemsg'>";
+ print_info_box($savemsg);
+ echo "</div>";
+ }
+ if ($input_errors)
+ print_input_errors($input_errors);
+ if($hostname <> $myhostname)
+ print_info_box("Warning! You are currently viewing an alternate hosts backup history ($hostname)");
+?>
+<table width="100%" border="0" cellpadding="0" cellspacing="0"> <tr><td>
+<div id='feedbackdiv'></div>
+ <?php
+ $tab_array = array();
+ $tab_array[0] = array("Settings", false, "/pkg_edit.php?xml=autoconfigbackup.xml&amp;id=0");
+ if($_REQUEST['download'])
+ $active = false;
+ else
+ $active = true;
+ $tab_array[1] = array("Restore", $active, "/autoconfigbackup.php");
+ if($_REQUEST['download'])
+ $tab_array[] = array("Revision", true, "/autoconfigbackup.php?download={$_REQUEST['download']}");
+ $tab_array[] = array("Backup now", false, "/autoconfigbackup_backup.php");
+ $tab_array[] = array("Stats", false, "/autoconfigbackup_stats.php");
+ display_top_tabs($tab_array);
+ $hostnames = get_hostnames();
+ ?>
+ </td></tr>
+ <tr>
+ <td>
+ <table id="backuptable" class="tabcont" align="center" width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td colspan="2" align="left">
+ <div id="loading">
+ <img src="themes/metallic/images/misc/loader.gif"> Loading, please wait...
+ </div>
+ <?php
+ if($_REQUEST['rmver'] != "") {
+ $curl_session = curl_init();
+ curl_setopt($curl_session, CURLOPT_URL, $del_url);
+ curl_setopt($curl_session, CURLOPT_POST, 3);
+ curl_setopt($curl_session, CURLOPT_SSL_VERIFYPEER, 0);
+ curl_setopt($curl_session, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($curl_session, CURLOPT_POSTFIELDS, "action=delete" .
+ "&hostname=" . urlencode($hostname) .
+ "&revision=" . urlencode($_REQUEST['rmver']));
+ $data = curl_exec($curl_session);
+ if (curl_errno($curl_session)) {
+ $fd = fopen("/tmp/acb_deletedebug.txt", "w");
+ fwrite($fd, $get_url . "" . "action=delete&hostname=" .
+ urlencode($hostname) . "&revision=" .
+ urlencode($_REQUEST['rmver']) . "\n\n");
+ fwrite($fd, $data);
+ fwrite($fd, curl_error($curl_session));
+ fclose($fd);
+ $savemsg = "An error occurred while trying to remove the item from portal.pfsense.org.";
+ } else {
+ curl_close($curl_session);
+ $savemsg = "Backup revision {$_REQUEST['rmver']} has been removed.";
+ }
+ print_info_box($savemsg);
+ }
+ if($_REQUEST['newver'] != "") {
+ // Phone home and obtain backups
+ $curl_session = curl_init();
+ curl_setopt($curl_session, CURLOPT_URL, $get_url);
+ curl_setopt($curl_session, CURLOPT_POST, 3);
+ curl_setopt($curl_session, CURLOPT_SSL_VERIFYPEER, 0);
+ curl_setopt($curl_session, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($curl_session, CURLOPT_POSTFIELDS, "action=restore" .
+ "&hostname=" . urlencode($hostname) .
+ "&revision=" . urlencode($_REQUEST['newver']));
+ $data = curl_exec($curl_session);
+ $data_split = split("\+\+\+\+", $data);
+ $sha256 = $data_split[0]; // sha256
+ $data = $data_split[1];
+ if (!tagfile_deformat($data, $data, "config.xml"))
+ $input_errors[] = "The downloaded file does not appear to contain an encrypted pfSense configuration.";
+ $data = decrypt_data($data, $decrypt_password);
+ $fd = fopen("/tmp/config_restore.xml", "w");
+ fwrite($fd, $data);
+ fclose($fd);
+ if(strlen($data) < 50)
+ $input_errors[] = "The decrypted config.xml is under 50 characters, something went wrong. Aborting.";
+ $ondisksha256 = trim(`/sbin/sha256 /tmp/config_restore.xml | awk '{ print $4 }'`);
+ if($sha256 != "0" && $sha256 != "") // we might not have a sha256 on file for older backups
+ if($ondisksha256 <> $sha256)
+ $input_errors[] = "SHA256 values does not match, cannot restore.";
+ if (curl_errno($curl_session)) {
+ /* If an error occured, log the error in /tmp/ */
+ $fd = fopen("/tmp/acb_restoredebug.txt", "w");
+ fwrite($fd, $get_url . "" . "action=restore&hostname={$hostname}&revision=" . urlencode($_REQUEST['newver']) . "\n\n");
+ fwrite($fd, $data);
+ fwrite($fd, curl_error($curl_session));
+ fclose($fd);
+ } else {
+ curl_close($curl_session);
+ }
+ if(!$input_errors && $data) {
+ if(config_restore("/tmp/config_restore.xml") == 0) {
+ $savemsg = "Successfully reverted the pfSense configuration to revision " . urldecode($_REQUEST['newver']) . ".";
+ $savemsg .= <<<EOF
+ <p/>
+ <form action="reboot.php" method="post">
+ Would you like to reboot?
+ <input name="Submit" type="submit" class="formbtn" value=" Yes ">
+ <input name="Submit" type="submit" class="formbtn" value=" No ">
+ </form>
+EOF;
+ } else {
+ $savemsg = "Unable to revert to the selected configuration.";
+ }
+ print_info_box($savemsg);
+ }
+ unlink("/tmp/config_restore.xml");
+ }
+ if($_REQUEST['download']) {
+ // Phone home and obtain backups
+ $curl_session = curl_init();
+ curl_setopt($curl_session, CURLOPT_URL, $get_url);
+ curl_setopt($curl_session, CURLOPT_POST, 3);
+ curl_setopt($curl_session, CURLOPT_SSL_VERIFYPEER, 0);
+ curl_setopt($curl_session, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($curl_session, CURLOPT_POSTFIELDS, "action=restore" .
+ "&hostname=" . urlencode($hostname) .
+ "&revision=" . urlencode($_REQUEST['download']));
+ $data = curl_exec($curl_session);
+ if (!tagfile_deformat($data, $data1, "config.xml"))
+ $input_errors[] = "The downloaded file does not appear to contain an encrypted pfSense configuration.";
+ if ($input_errors) {
+ print_input_errors($input_errors);
+ } else {
+ $ds = split("\+\+\+\+", $data);
+ $revision = $_REQUEST['download'];
+ $sha256sum = $ds[0];
+ if($sha256sum == "0")
+ $sha256sum = "None on file.";
+ $data = $ds[1];
+ $configtype = "Encrypted";
+ if (!tagfile_deformat($data, $data, "config.xml"))
+ $input_errors[] = "The downloaded file does not appear to contain an encrypted pfSense configuration.";
+ $data = decrypt_data($data, $decrypt_password);
+ if(!strstr($data, "pfsense")) {
+ $data = "Could not decrypt. Different encryption key?";
+ $input_errors[] = "Could not decrypt config.xml";
+ }
+ echo "<h2>Hostname</h2>";
+ echo "<textarea rows='1' cols='70'>{$hostname}</textarea>";
+ echo "<h2>Revision date/time</h2>";
+ echo "<textarea name='download' rows='1' cols='70'>{$_REQUEST['download']}</textarea>";
+ echo "<h2>Revision reason</h2>";
+ echo "<textarea name='download' rows='1' cols='70'>{$_REQUEST['reason']}</textarea>";
+ echo "<h2>SHA256 summary</h2>";
+ echo "<textarea name='shasum' rows='1' cols='70'>{$sha256sum}</textarea>";
+ echo "<h2>Encrypted config.xml</h2>";
+ echo "<textarea name='config_xml' rows='40' cols='70'>{$ds[1]}</textarea>";
+ echo "<h2>Decrypted config.xml</h2>";
+ echo "<textarea name='dec_config_xml' rows='40' cols='70'>{$data}</textarea>";
+ }
+ if(!$input_errors)
+ echo "<p/><input type=\"button\" value=\"Install this revision\" onClick=\"document.location='autoconfigbackup.php?newver=" . urlencode($_REQUEST['download']) . "';\">";
+ echo "<script type=\"text/javascript\">";
+ echo "$('loading').innerHTML = '';";
+ echo "</script>";
+ echo "</td></tr></table></div></td></td></tr></tr></table></form>";
+ require("fend.inc");
+ exit;
+ }
+ // Populate available backups
+ $curl_session = curl_init();
+ curl_setopt($curl_session, CURLOPT_URL, $get_url);
+ curl_setopt($curl_session, CURLOPT_SSL_VERIFYPEER, 0);
+ curl_setopt($curl_session, CURLOPT_POST, 1);
+ curl_setopt($curl_session, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($curl_session, CURLOPT_POSTFIELDS, "action=showbackups&hostname={$hostname}");
+ $data = curl_exec($curl_session);
+ if (curl_errno($curl_session)) {
+ $fd = fopen("/tmp/acb_backupdebug.txt", "w");
+ fwrite($fd, $get_url . "" . "action=showbackups" . "\n\n");
+ fwrite($fd, $data);
+ fwrite($fd, curl_error($curl_session));
+ fclose($fd);
+ } else {
+ curl_close($curl_session);
+ }
+ // Loop through and create new confvers
+ $data_split = split("\n", $data);
+ $confvers = array();
+ foreach($data_split as $ds) {
+ $ds_split = split($oper_sep, $ds);
+ $tmp_array = array();
+ $tmp_array['username'] = $ds_split[0];
+ $tmp_array['reason'] = $ds_split[1];
+ $tmp_array['time'] = $ds_split[2];
+ if($ds_split[2] && $ds_split[0])
+ $confvers[] = $tmp_array;
+ }
+ ?>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2">
+ <center>
+ <b>Hostname:</b>
+ <select id="hostname" name="hostname" onChange="document.location='autoconfigbackup.php?hostname=' + this.value;">
+ <?foreach($hostnames as $hn):?>
+ <option value='<?=$hn?>'><?=$hn?></option>
+ <?endforeach?>
+ <option value='<?=$hostname?>' SELECTED><?=$hostname?></option>
+ </select>
+ </td>
+ </tr>
+
+ <tr>
+ <td width="30%" class="listhdrr">Date</td>
+ <td width="70%" class="listhdrr">Configuration Change</td>
+ </tr>
+<?php
+ $counter = 0;
+ echo "<script type=\"text/javascript\">";
+ echo "$('loading').innerHTML = '';";
+ echo "</script>";
+ foreach($confvers as $cv):
+?>
+ <tr valign="top">
+ <td class="listlr"> <?= $cv['time']; ?></td>
+ <td class="listbg"> <?= $cv['reason']; ?></td>
+ <td colspan="2" valign="middle" class="list" nowrap>
+ <a title="Restore this revision" onClick="return confirm('Are you sure you want to restore <?= $cv['time']; ?>?')" href="autoconfigbackup.php?hostname=<?=urlencode($hostname)?>&newver=<?=urlencode($cv['time']);?>">
+ <img src="/themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" width="17" height="17" border="0">
+ </a>
+ <a title="Show info" href="autoconfigbackup.php?download=<?=urlencode($cv['time']);?>&hostname=<?=urlencode($hostname)?>&reason=<?php echo urlencode($cv['reason']);?>">
+ <img src="/themes/<?= $g['theme']; ?>/images/icons/icon_down.gif" width="17" height="17" border="0">
+ </a>
+ <a title="Delete" onClick="return confirm('Are you sure you want to delete <?= $cv['time']; ?>?')"href="autoconfigbackup.php?hostname=<?=urlencode($hostname)?>&rmver=<?=urlencode($cv['time']);?>">
+ <img src="/themes/<?= $g['theme']; ?>/images/icons/icon_x.gif" width="17" height="17" border="0">
+ </a>
+ </td>
+ </tr>
+<?php
+ $counter++;
+ endforeach;
+ if($counter == 0)
+ echo "<tr><td colspan='3'><center>Sorry, we could not locate any backups at portal.pfsense.org for this hostname ({$hostname}).</td></tr>";
+ else
+ echo "<tr><td colspan='3'><center><br/>Backups hosted currently for this hostname on portalpfsense.org: {$counter}.</td></tr>";
+?>
+ </table>
+ </div>
+ </td>
+ <tr>
+ <td>
+ <p>
+ <strong>
+ &nbsp;&nbsp;
+ <span class="red">
+ Hint:&nbsp;
+ </span>
+ </strong>
+ Click the + sign next to the revision you would like to restore.
+ </p>
+ </td>
+ </tr>
+ </tr>
+</table>
+</form>
+<?php include("fend.inc"); ?>
+</body>
+</html> \ No newline at end of file
diff --git a/config/autoconfigbackup/autoconfigbackup.xml b/config/autoconfigbackup/autoconfigbackup.xml
new file mode 100644
index 00000000..5e5eaf73
--- /dev/null
+++ b/config/autoconfigbackup/autoconfigbackup.xml
@@ -0,0 +1,162 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+ /* $Id$ */
+ /*
+ autoconfigbackup.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2008 BSD Perimeter
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+ ]]>
+ </copyright>
+ <description>Automatically backs up your pfSense configuration. All contents are encrypted on the server. Requires pfSense Premium Support Portal Subscription from https://portal.pfsense.org</description>
+ <requirements>pfSense Premium Support Portal</requirements>
+ <name>AutoConfigBackup</name>
+ <version>1.0</version>
+ <title>Diagnostics: Auto Configuration Backup</title>
+ <savetext>Change</savetext>
+ <include_file>/usr/local/pkg/autoconfigbackup.inc</include_file>
+ <aftersaveredirect>pkg_edit.php?xml=autoconfigbackup.xml&amp;id=0</aftersaveredirect>
+ <menu>
+ <name>AutoConfigBackup</name>
+ <tooltiptext>Set autoconfigbackup settings such as password and port.</tooltiptext>
+ <section>Diagnostics</section>
+ <url>/autoconfigbackup.php</url>
+ </menu>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/pf/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/autoconfigbackup/upload_config_filter.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/parse_config/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/autoconfigbackup/parse_config_upload.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/autoconfigbackup/autoconfigbackup.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/autoconfigbackup/autoconfigbackup.inc</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/etc/inc/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/autoconfigbackup/crypt_acb.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/autoconfigbackup/autoconfigbackup_backup.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/autoconfigbackup/autoconfigbackup_stats.php</item>
+ </additional_files_needed>
+ <tabs>
+ <tab>
+ <text>Settings</text>
+ <url>/pkg_edit.php?xml=autoconfigbackup.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Restore</text>
+ <url>/autoconfigbackup.php</url>
+ </tab>
+ <tab>
+ <text>Backup now</text>
+ <url>/autoconfigbackup_backup.php</url>
+ </tab>
+ <tab>
+ <text>Stats</text>
+ <url>/autoconfigbackup_stats.php</url>
+ </tab>
+ </tabs>
+ <fields>
+ <field>
+ <fielddescr>Subscription Username</fielddescr>
+ <fieldname>username</fieldname>
+ <description>Enter the subscription username for portal.pfsense.org</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Subscription Password</fielddescr>
+ <fieldname>password</fieldname>
+ <description>Enter the password for portal.pfsense.org</description>
+ <type>password</type>
+ </field>
+ <field>
+ <fielddescr>Enter Password again</fielddescr>
+ <fieldname>passwordagain</fieldname>
+ <type>password</type>
+ </field>
+ <field>
+ <fielddescr>Encryption Password</fielddescr>
+ <description>This password will be used to encrypt config.xml before sending to portal.pfsense.org. Do not share the password and keep it safe!</description>
+ <fieldname>crypto_password</fieldname>
+ <type>password</type>
+ </field>
+ <field>
+ <fielddescr>Encryption Password again</fielddescr>
+ <description>Enter the encryption password again.</description>
+ <fieldname>crypto_password2</fieldname>
+ <type>password</type>
+ </field>
+ <field>
+ <fielddescr>Test connection</fielddescr>
+ <description>Check this box to test the connection to portal.pfsense.org.</description>
+ <fieldname>testconnection</fieldname>
+ <type>checkbox</type>
+ </field>
+ </fields>
+ <custom_php_validation_command>
+ custom_php_validation_command($_POST, &amp;$input_errors);
+ </custom_php_validation_command>
+ <custom_php_global_functions>
+ </custom_php_global_functions>
+ <custom_add_php_command>
+ </custom_add_php_command>
+ <custom_php_resync_config_command>
+ <![CDATA[
+ exec("echo > /cf/conf/lastpfSbackup.txt");
+ filter_configure();
+ if($savemsg)
+ $savemsg .= "<br/>";
+ $savemsg .= "A configuration backup has been queued.";
+ ]]>
+ </custom_php_resync_config_command>
+ <custom_php_install_command>
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ </custom_php_deinstall_command>
+</packagegui>
diff --git a/config/autoconfigbackup/autoconfigbackup_backup.php b/config/autoconfigbackup/autoconfigbackup_backup.php
new file mode 100644
index 00000000..cebd7a56
--- /dev/null
+++ b/config/autoconfigbackup/autoconfigbackup_backup.php
@@ -0,0 +1,157 @@
+<?php
+/* $Id$ */
+/*
+ autoconfigbackup_backup.php
+ Copyright (C) 2008 Scott Ullrich
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require("globals.inc");
+require("guiconfig.inc");
+require("/usr/local/pkg/autoconfigbackup.inc");
+
+$pfSversion = str_replace("\n", "", file_get_contents("/etc/version"));
+if(strstr($pfSversion, "1.2"))
+ require("crypt_acb.php");
+
+// Seperator used during client / server communications
+$oper_sep = "\|\|";
+
+// Encryption password
+$decrypt_password = $config['installedpackages']['autoconfigbackup']['config'][0]['crypto_password'];
+
+// Defined username
+$username = $config['installedpackages']['autoconfigbackup']['config'][0]['username'];
+
+// Defined password
+$password = $config['installedpackages']['autoconfigbackup']['config'][0]['password'];
+
+// URL to restore.php
+$get_url = "https://{$username}:{$password}@portal.pfsense.org/pfSconfigbackups/restore.php";
+
+// URL to delete.php
+$del_url = "https://{$username}:{$password}@portal.pfsense.org/pfSconfigbackups/delete.php";
+
+// Set hostname
+$hostname = $config['system']['hostname'] . "." . $config['system']['domain'];
+
+if(!$username) {
+ Header("Location: /pkg_edit.php?xml=autoconfigbackup.xml&id=0");
+ exit;
+}
+
+if($_POST) {
+ if($_REQUEST['nooverwrite'])
+ touch("/tmp/acb_nooverwrite");
+ if($_REQUEST['reason'])
+ write_config($_REQUEST['reason']);
+ else
+ write_config("Backup invoked via Auto Config Backup.");
+ $config = parse_config(true);
+ exec("echo > /cf/conf/lastpfSbackup.txt");
+ upload_config($_REQUEST['reason']);
+ $savemsg = "Backup completed successfully.";
+ $donotshowheader=true;
+}
+
+$pgtitle = "Diagnostics: Auto Configuration Backup Now";
+
+include("head.inc");
+
+?>
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<div id='maincontent'>
+<?php
+ include("fbegin.inc");
+ if(strstr($pfSversion, "1.2"))
+ echo "<p class=\"pgtitle\">{$pgtitle}</p>";
+ if($savemsg) {
+ print_info_box($savemsg);
+ }
+ if ($input_errors)
+ print_input_errors($input_errors);
+
+?>
+<form method="post" action="autoconfigbackup_backup.php">
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td>
+ <div id='feedbackdiv'>
+ </div>
+ <?php
+ $tab_array = array();
+ $tab_array[] = array("Settings", false, "/pkg_edit.php?xml=autoconfigbackup.xml&amp;id=0");
+ $tab_array[] = array("Restore", false, "/autoconfigbackup.php");
+ $tab_array[] = array("Backup now", true, "/autoconfigbackup_backup.php");
+ $tab_array[] = array("Stats", false, "/autoconfigbackup_stats.php");
+ display_top_tabs($tab_array);
+ ?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <table id="backuptable" class="tabcont" align="center" width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td colspan="2" align="left">
+ <table>
+ <tr>
+ <td align="right">
+ Enter the backup reason:
+ </td>
+ <td>
+ <input name="reason" id="reason" size="80">
+ </td>
+ </tr>
+ <tr>
+ <td align="right">
+ Do not overwrite previous backups for this hostname:
+ </td>
+ <td>
+ <input type="checkbox" name="nooverwrite">
+ </td>
+ </tr>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ </tr>
+ <tr>
+ <td align="right">
+ <input type="submit" name="Backup" value="Backup">
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </div>
+ </td>
+ </tr>
+</table>
+</form>
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/autoconfigbackup/autoconfigbackup_stats.php b/config/autoconfigbackup/autoconfigbackup_stats.php
new file mode 100644
index 00000000..65f02b2d
--- /dev/null
+++ b/config/autoconfigbackup/autoconfigbackup_stats.php
@@ -0,0 +1,214 @@
+<?php
+/* $Id$ */
+/*
+ autoconfigbackup_stats.php
+ Copyright (C) 2008 Scott Ullrich
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require("globals.inc");
+require("guiconfig.inc");
+require("/usr/local/pkg/autoconfigbackup.inc");
+
+$pfSversion = str_replace("\n", "", file_get_contents("/etc/version"));
+if(strstr($pfSversion, "1.2"))
+ require("crypt_acb.php");
+
+// Seperator used during client / server communications
+$oper_sep = "\|\|";
+
+// Encryption password
+$decrypt_password = $config['installedpackages']['autoconfigbackup']['config'][0]['crypto_password'];
+
+// Defined username
+$username = $config['installedpackages']['autoconfigbackup']['config'][0]['username'];
+
+// Defined password
+$password = $config['installedpackages']['autoconfigbackup']['config'][0]['password'];
+
+// URL to restore.php
+$get_url = "https://{$username}:{$password}@portal.pfsense.org/pfSconfigbackups/restore.php";
+
+// URL to delete.php
+$del_url = "https://{$username}:{$password}@portal.pfsense.org/pfSconfigbackups/delete.php";
+
+// URL to stats.php
+$stats_url = "https://{$username}:{$password}@portal.pfsense.org/pfSconfigbackups/showstats.php";
+
+// Set hostname
+$hostname = $config['system']['hostname'] . "." . $config['system']['domain'];
+
+if(!$username) {
+ Header("Location: /pkg_edit.php?xml=autoconfigbackup.xml&id=0");
+ exit;
+}
+
+if($_REQUEST['delhostname']) {
+ $curl_session = curl_init();
+ curl_setopt($curl_session, CURLOPT_URL, $del_url);
+ curl_setopt($curl_session, CURLOPT_POST, 2);
+ curl_setopt($curl_session, CURLOPT_SSL_VERIFYPEER, 0);
+ curl_setopt($curl_session, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($curl_session, CURLOPT_POSTFIELDS, "action=deletehostname&delhostname=" . urlencode($_REQUEST['delhostname']));
+ $data = curl_exec($curl_session);
+ if (curl_errno($curl_session)) {
+ $fd = fopen("/tmp/acb_deletedebug.txt", "w");
+ fwrite($fd, $get_url . "" . "action=deletehostname&hostname=" .
+ urlencode($_REQUEST['delhostname']) . "\n\n");
+ fwrite($fd, $data);
+ fwrite($fd, curl_error($curl_session));
+ fclose($fd);
+ $savemsg = "An error occurred while trying to remove the item from portal.pfsense.org.";
+ } else {
+ curl_close($curl_session);
+ $savemsg = "ALL backup revisions for {$_REQUEST['delhostname']} have been removed.";
+ }
+}
+
+$pgtitle = "Diagnostics: Auto Configuration Stats";
+
+include("head.inc");
+
+?>
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<script src="/javascript/scriptaculous/prototype.js" type="text/javascript"></script>
+<div id='maincontent'>
+<?php
+ include("fbegin.inc");
+ if(strstr($pfSversion, "1.2"))
+ echo "<p class=\"pgtitle\">{$pgtitle}</p>";
+ if($savemsg) {
+ print_info_box($savemsg);
+ }
+ if ($input_errors)
+ print_input_errors($input_errors);
+
+?>
+<form method="post" action="autoconfigbackup_stats.php">
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td>
+ <div id='feedbackdiv'>
+ </div>
+ <?php
+ $tab_array = array();
+ $tab_array[] = array("Settings", false, "/pkg_edit.php?xml=autoconfigbackup.xml&amp;id=0");
+ $tab_array[] = array("Restore", false, "/autoconfigbackup.php");
+ $tab_array[] = array("Backup now", false, "/autoconfigbackup_backup.php");
+ $tab_array[] = array("Stats", true, "/autoconfigbackup_stats.php");
+ display_top_tabs($tab_array);
+ ?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <table id="backuptable" class="tabcont" align="center" width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td colspan="2" align="left">
+ <div id="loading">
+ <img src="themes/metallic/images/misc/loader.gif"> Loading, please wait...
+ </div>
+ </tr>
+ <tr>
+ <td width="30%" class="listhdrr">Hostname</td>
+ <td width="70%" class="listhdrr">Backup count</td>
+ </tr>
+<?php
+ // Populate available backups
+ $curl_session = curl_init();
+ curl_setopt($curl_session, CURLOPT_URL, $stats_url);
+ curl_setopt($curl_session, CURLOPT_SSL_VERIFYPEER, 0);
+ curl_setopt($curl_session, CURLOPT_POST, 1);
+ curl_setopt($curl_session, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($curl_session, CURLOPT_POSTFIELDS, "action=showstats");
+ $data = curl_exec($curl_session);
+ if (curl_errno($curl_session)) {
+ $fd = fopen("/tmp/acb_statsdebug.txt", "w");
+ fwrite($fd, $get_url . "" . "action=showstats" . "\n\n");
+ fwrite($fd, $data);
+ fwrite($fd, curl_error($curl_session));
+ fclose($fd);
+ } else {
+ curl_close($curl_session);
+ }
+ // Loop through and create new confvers
+ $data_split = split("\n", $data);
+ $statvers = array();
+ foreach($data_split as $ds) {
+ $ds_split = split($oper_sep, $ds);
+ $tmp_array = array();
+ $tmp_array['hostname'] = $ds_split[0];
+ $tmp_array['hostnamecount'] = $ds_split[1];
+ if($ds_split[0] && $ds_split[1])
+ $statvers[] = $tmp_array;
+ }
+ $counter = 0;
+ echo "<script type=\"text/javascript\">";
+ echo "$('loading').innerHTML = '';";
+ echo "</script>";
+ $total_backups = 0;
+ foreach($statvers as $cv):
+?>
+ <tr valign="top">
+ <td class="listlr">
+ <?= $cv['hostname']; ?>
+ </td>
+ <td class="listbg">
+ <?= $cv['hostnamecount']; ?>
+ </td>
+ <td>
+ <nobr>
+ <a title="View all backups for this host" href="autoconfigbackup.php?hostname=<?=urlencode($cv['hostname'])?>">
+ <img src="/themes/<?= $g['theme']; ?>/images/icons/icon_e.gif" width="17" height="17" border="0">
+ </a>
+ <a title="Delete all backups for this host" onClick="return confirm('Are you sure you want to delete *ALL BACKUPS FOR THIS HOSTNAME* <?= $cv['hostname']; ?>?')" href="autoconfigbackup_stats.php?delhostname=<?=urlencode($cv['hostname'])?>">
+ <img src="/themes/<?= $g['theme']; ?>/images/icons/icon_x.gif" width="17" height="17" border="0">
+ </a>
+ </nobr>
+ </td>
+ </tr>
+<?php
+ $total_backups = $total_backups + $cv['hostnamecount'];
+ $counter++;
+ endforeach;
+ if($counter == 0)
+ echo "<tr><td colspan='3'><center>Sorry, we could not load the status information for the account ($username).</td></tr>";
+?>
+ <tr>
+ <td align="right">
+ Total
+ </td>
+ <td>
+ <?=$total_backups?>
+ </td>
+ </tr>
+ </td>
+ </tr>
+</table>
+</td></tr>
+</table>
+</form>
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/autoconfigbackup/certs/gd-class2-root.crt b/config/autoconfigbackup/certs/gd-class2-root.crt
new file mode 100644
index 00000000..42e8d1ee
--- /dev/null
+++ b/config/autoconfigbackup/certs/gd-class2-root.crt
@@ -0,0 +1,24 @@
+-----BEGIN CERTIFICATE-----
+MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh
+MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE
+YWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3
+MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRo
+ZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3Mg
+MiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggEN
+ADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCA
+PVYYYwhv2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6w
+wdhFJ2+qN1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXi
+EqITLdiOr18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMY
+avx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+
+YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0OBBYEFNLE
+sNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h
+/t2oatTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5
+IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmlj
+YXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD
+ggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wimPQoZ+YeAEW5p5JYXMP80kWNy
+OO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKtI3lpjbi2Tc7P
+TMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ
+HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mER
+dEr/VxqHD3VILs9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5Cuf
+ReYNnyicsbkqWletNw+vHX/bvZ8=
+-----END CERTIFICATE-----
diff --git a/config/autoconfigbackup/certs/gd_intermediate.crt b/config/autoconfigbackup/certs/gd_intermediate.crt
new file mode 100644
index 00000000..33d97396
--- /dev/null
+++ b/config/autoconfigbackup/certs/gd_intermediate.crt
@@ -0,0 +1,29 @@
+-----BEGIN CERTIFICATE-----
+MIIE3jCCA8agAwIBAgICAwEwDQYJKoZIhvcNAQEFBQAwYzELMAkGA1UEBhMCVVMx
+ITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28g
+RGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjExMTYw
+MTU0MzdaFw0yNjExMTYwMTU0MzdaMIHKMQswCQYDVQQGEwJVUzEQMA4GA1UECBMH
+QXJpem9uYTETMBEGA1UEBxMKU2NvdHRzZGFsZTEaMBgGA1UEChMRR29EYWRkeS5j
+b20sIEluYy4xMzAxBgNVBAsTKmh0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5j
+b20vcmVwb3NpdG9yeTEwMC4GA1UEAxMnR28gRGFkZHkgU2VjdXJlIENlcnRpZmlj
+YXRpb24gQXV0aG9yaXR5MREwDwYDVQQFEwgwNzk2OTI4NzCCASIwDQYJKoZIhvcN
+AQEBBQADggEPADCCAQoCggEBAMQt1RWMnCZM7DI161+4WQFapmGBWTtwY6vj3D3H
+KrjJM9N55DrtPDAjhI6zMBS2sofDPZVUBJ7fmd0LJR4h3mUpfjWoqVTr9vcyOdQm
+VZWt7/v+WIbXnvQAjYwqDL1CBM6nPwT27oDyqu9SoWlm2r4arV3aLGbqGmu75RpR
+SgAvSMeYddi5Kcju+GZtCpyz8/x4fKL4o/K1w/O5epHBp+YlLpyo7RJlbmr2EkRT
+cDCVw5wrWCs9CHRK8r5RsL+H0EwnWGu1NcWdrxcx+AuP7q2BNgWJCJjPOq8lh8BJ
+6qf9Z/dFjpfMFDniNoW1fho3/Rb2cRGadDAW/hOUoz+EDU8CAwEAAaOCATIwggEu
+MB0GA1UdDgQWBBT9rGEyk2xF1uLuhV+auud2mWjM5zAfBgNVHSMEGDAWgBTSxLDS
+kdRMEXGzYcs9of7dqGrU4zASBgNVHRMBAf8ECDAGAQH/AgEAMDMGCCsGAQUFBwEB
+BCcwJTAjBggrBgEFBQcwAYYXaHR0cDovL29jc3AuZ29kYWRkeS5jb20wRgYDVR0f
+BD8wPTA7oDmgN4Y1aHR0cDovL2NlcnRpZmljYXRlcy5nb2RhZGR5LmNvbS9yZXBv
+c2l0b3J5L2dkcm9vdC5jcmwwSwYDVR0gBEQwQjBABgRVHSAAMDgwNgYIKwYBBQUH
+AgEWKmh0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5jb20vcmVwb3NpdG9yeTAO
+BgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQADggEBANKGwOy9+aG2Z+5mC6IG
+OgRQjhVyrEp0lVPLN8tESe8HkGsz2ZbwlFalEzAFPIUyIXvJxwqoJKSQ3kbTJSMU
+A2fCENZvD117esyfxVgqwcSeIaha86ykRvOe5GPLL5CkKSkB2XIsKd83ASe8T+5o
+0yGPwLPk9Qnt0hCqU7S+8MxZC9Y7lhyVJEnfzuz9p0iRFEUOOjZv2kWzRaJBydTX
+RE4+uXR21aITVSzGh6O1mawGhId/dQb8vxRMDsxuxN89txJx9OjxUUAiKEngHUuH
+qDTMBqLdElrRhjZkAzVvb3du6/KFUJheqwNTrZEjYx8WnM25sgVjOuH0aBsXBTWV
+U+4=
+-----END CERTIFICATE----- \ No newline at end of file
diff --git a/config/autoconfigbackup/crypt_acb.php b/config/autoconfigbackup/crypt_acb.php
new file mode 100644
index 00000000..804b6a41
--- /dev/null
+++ b/config/autoconfigbackup/crypt_acb.php
@@ -0,0 +1,129 @@
+<?php
+
+/* $Id$ */
+/*
+ Copyright (C) 2008 Shrew Soft Inc
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ DISABLE_PHP_LINT_CHECKING
+*/
+
+ function crypt_data($val, $pass, $opt) {
+ $file = tempnam("/tmp", "php-encrypt");
+ $fd = fopen("$file.dec", "w");
+ fwrite($fd, $val);
+ fclose($fd);
+ exec("/usr/bin/openssl enc {$opt} -aes-256-cbc -in $file.dec -out $file.enc -k {$pass}");
+ $result = file_get_contents("$file.enc");
+ exec("rm $file");
+ exec("rm $file.dec");
+ exec("rm $file.enc");
+ return $result;
+ }
+
+ function crypt_dataA(& $data, $pass, $opt) {
+ log_error("entering crypt_data()");
+ $pspec = "/usr/bin/openssl enc {$opt} -aes-256-cbc -k {$pass}";
+ $dspec = array( 0 => array("pipe", "r"),
+ 1 => array("pipe", "w"),
+ 2 => array("pipe", "e"));
+ log_error("proc_open");
+ $fp = proc_open($pspec, $dspec, $pipes);
+ if (!$fp)
+ return false;
+ log_error("writing to pipe[0]");
+ fwrite($pipes[0], $data);
+ log_error("closing pipe[0]");
+ fclose($pipes[0]);
+
+ log_error("enter while()");
+
+ while (!feof($pipes[1])) {
+ $rslt .= fread($pipes[1], 8192);
+ }
+
+ log_error("exit while()");
+
+ fclose($pipes[1]);
+
+ proc_close($fp);
+
+ return $rslt;
+ }
+
+ function encrypt_data(& $data, $pass) {
+ return base64_encode(crypt_data($data, $pass, "-e"));
+ }
+
+ function decrypt_data(& $data, $pass) {
+ return crypt_data(base64_decode($data), $pass, "-d");
+ }
+
+ function tagfile_reformat($in, & $out, $tag) {
+
+ $out = "---- BEGIN {$tag} ----\n";
+
+ $size = 80;
+ $oset = 0;
+ while ($size >= 64) {
+ $line = substr($in, $oset, 64);
+ $out .= $line."\n";
+ $size = strlen($line);
+ $oset += $size;
+ }
+
+ $out .= "---- END {$tag} ----\n";
+
+ return true;
+ }
+
+ function tagfile_deformat($in, & $out, $tag) {
+
+ $btag_val = "---- BEGIN {$tag} ----";
+ $etag_val = "---- END {$tag} ----";
+
+ $btag_len = strlen($btag_val);
+ $etag_len = strlen($etag_val);
+
+ $btag_pos = stripos($in, $btag_val);
+ $etag_pos = stripos($in, $etag_val);
+
+ if (($btag_pos === false) || ($etag_pos === false))
+ return false;
+
+ $body_pos = $btag_pos + $btag_len;
+ $body_len = strlen($in);
+ $body_len -= strlen($btag_len);
+ $body_len -= strlen($etag_len);
+
+ $out = substr($in, $body_pos, $body_len);
+
+ return true;
+ }
+
+ function stripos($str,$needle) {
+ return strpos(strtolower($str), strtolower($needle));
+ }
+
+?> \ No newline at end of file
diff --git a/config/autoconfigbackup/parse_config_upload.php b/config/autoconfigbackup/parse_config_upload.php
new file mode 100644
index 00000000..ce592966
--- /dev/null
+++ b/config/autoconfigbackup/parse_config_upload.php
@@ -0,0 +1,8 @@
+<?php
+
+if(file_exists("/usr/local/pkg/autoconfigbackup.inc")) {
+ require_once("/usr/local/pkg/autoconfigbackup.inc");
+ upload_config();
+}
+
+?>
diff --git a/config/autoconfigbackup/upload_config_filter.php b/config/autoconfigbackup/upload_config_filter.php
new file mode 100644
index 00000000..ce592966
--- /dev/null
+++ b/config/autoconfigbackup/upload_config_filter.php
@@ -0,0 +1,8 @@
+<?php
+
+if(file_exists("/usr/local/pkg/autoconfigbackup.inc")) {
+ require_once("/usr/local/pkg/autoconfigbackup.inc");
+ upload_config();
+}
+
+?>
diff --git a/config/avahi/avahi.inc b/config/avahi/avahi.inc
new file mode 100644
index 00000000..a95eaaf0
--- /dev/null
+++ b/config/avahi/avahi.inc
@@ -0,0 +1,167 @@
+<?php
+
+/*
+ $Id$
+ avahi.inc
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2009 Scott Ullrich
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+function start_avahi() {
+ mwexec_bg("sh /usr/local/etc/rc.d/avahi-daemon.sh start");
+}
+
+function stop_avahi() {
+ mwexec_bg("sh /usr/local/etc/rc.d/avahi-daemon.sh stop");
+}
+
+function setup_avahi() {
+ global $g, $config;
+
+ // Extract out libraries and avahi-daemon
+ if(file_exists("/tmp/avahi.tgz")) {
+ exec("/usr/bin/tar xzPf /tmp/avahi.tgz -C /");
+ unlink("/tmp/avahi.tgz");
+ }
+
+ // Make sure everthing was extracted
+ if(!file_exists("/usr/local/sbin/avahi-daemon")) {
+ log_error("Sorry, something went wrong while extract avahi binaries. Please try the operation again");
+ return;
+ }
+
+ // Pull some various values out of config.xml
+ $hostname = $config['system']['hostname'];
+ $domain = $config['system']['domain'];
+ $enable = $config['installedpackages']['avahi']['config'][0]['enable'];
+ $browsedomains = $config['installedpackages']['avahi']['config'][0]['browsedomains'];
+ $denyif = $config['installedpackages']['avahi']['config'][0]['denyinterfaces'];
+
+ // Is package disabled?
+ if(!$enable) {
+ delete_avahi();
+ return;
+ }
+
+ // Add needed users and groups
+ exec("/usr/sbin/pw useradd avahi");
+ exec("/usr/sbin/pw groupadd avahi");
+
+ // No supplied domains? Use the defaults.
+ if(!$browsedomains)
+ $browsedomains = "local, 0pointer.de, zeroconf.org";
+
+ // Never pass along WAN. Bad.
+ $denyinterfaces = $config['interfaces']['wan']['if'];
+
+ // Process interfaces defined by user to deny.
+ if($denyif) {
+ $if = split(",", $denyif);
+ foreach($if as $i) {
+ $ifreal = convert_friendly_interface_to_real_interface_name($i);
+ if($ifreal)
+ $denyinterfaces .= ", " . $ifreal;
+ }
+ }
+
+ // Construct the avahi configuration
+ $avahiconfig = <<<EOF
+
+# avahi.conf - This file was automatically generated by the pfSense pacakge
+# manager. Do not edit this file, it will be overwritten automatically.
+# See /usr/local/pkg/avahi.inc to make changes to this file!
+
+[server]
+host-name={$hostname}
+domain-name={$domain}
+browse-domains={$browsedomains}
+deny-interfaces={$denyinterfaces}
+use-ipv4=yes
+use-ipv6=no
+enable-dbus=no
+#check-response-ttl=no
+#use-iff-running=no
+#disallow-other-stacks=no
+#allow-point-to-point=no
+
+[wide-area]
+enable-wide-area=yes
+
+[publish]
+#disable-publishing=no
+#disable-user-service-publishing=no
+#add-service-cookie=no
+#publish-addresses=yes
+#publish-hinfo=yes
+#publish-workstation=yes
+#publish-domain=yes
+#publish-dns-servers=192.168.50.1, 192.168.50.2
+#publish-resolv-conf-dns-servers=yes
+#publish-aaaa-on-ipv4=yes
+#publish-a-on-ipv6=no
+
+[reflector]
+enable-reflector=yes
+#reflect-ipv=no
+
+[rlimits]
+rlimit-core=0
+rlimit-data=4194304
+rlimit-fsize=0
+rlimit-nofile=300
+rlimit-stack=4194304
+rlimit-nproc=3
+#rlimit-as=
+
+EOF;
+
+ // Make image RW
+ conf_mount_rw();
+ /* Write out .conf file */
+ safe_mkdir("/usr/local/etc/avahi");
+ $fd = fopen("/usr/local/etc/avahi/avahi-daemon.conf", "w");
+ fwrite($fd, $avahiconfig);
+ fclose($fd);
+ /* Write out rc.d startup file */
+ $start = "/etc/rc.conf_mount_rw\n";
+ $start .= "if [ ! -d /proc/0 ]; then\n";
+ $start .= " mkdir -p /proc\n";
+ $start .= " mount -t procfs procfs /proc\n";
+ $start .= "fi\n";
+ $start .= "/usr/local/sbin/avahi-daemon -D\n";
+ $start .= "/etc/rc.conf_mount_ro\n";
+ $stop = "/usr/bin/killall avahi-daemon";
+ write_rcfile(array(
+ "file" => "avahi-daemon.sh",
+ "start" => $start,
+ "stop" => $stop
+ )
+ );
+ // Make image RO
+ conf_mount_ro();
+ start_avahi();
+}
+
+?>
diff --git a/config/avahi/avahi.xml b/config/avahi/avahi.xml
new file mode 100644
index 00000000..6baef60b
--- /dev/null
+++ b/config/avahi/avahi.xml
@@ -0,0 +1,90 @@
+<packagegui>
+ <copyright>
+ <![CDATA[
+ /*
+ $Id$
+ avahi.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2009 Scott Ullrich
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+ ]]>
+ </copyright>
+ <name>avahi</name>
+ <version>1.0</version>
+ <title>Services: Avahi</title>
+ <menu>
+ <name>Avahi</name>
+ <tooltiptext>Modify avahi settings.</tooltiptext>
+ <section>Services</section>
+ <url>pkg_edit.php?xml=avahi.xml&amp;id=0</url>
+ </menu>
+ <service>
+ <name>avahi</name>
+ <rcfile>avahi.sh</rcfile>
+ <executable>avahi</executable>
+ </service>
+ <additional_files_needed>
+ <prefix>/tmp/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.org/packages/config/avahi/binaries/avahi.tgz</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.org/packages/config/avahi/avahi.inc</item>
+ </additional_files_needed>
+ <fields>
+ <field>
+ <fielddescr>Enable</fielddescr>
+ <fieldname>enable</fieldname>
+ <description>Enable Avahi Bonjour/Zeroconf proxy.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Browse domains (comma separated)</fielddescr>
+ <fieldname>browsedomains</fieldname>
+ <description>Enter the domains that you would like proxied. (example: local, pfsense.org, mydomain.com)</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Deny interfaces</fielddescr>
+ <fieldname>denyinterfaces</fieldname>
+ <description>Interfaces that you do NOT want Avahi to listen on. NOTE: WAN is disabled by default.</description>
+ <type>interfaces_selection</type>
+ <multiple>true</multiple>
+ </field>
+ </fields>
+ <custom_add_php_command>
+ setup_avahi();
+ </custom_add_php_command>
+ <custom_php_install_command>
+ setup_avahi();
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ unlink_if_exists("/usr/local/etc/rc.d/avahi-daemon.sh");
+ exec("killall avahi-daemon");
+ </custom_php_deinstall_command>
+ <include_file>/usr/local/pkg/avahi.inc</include_file>
+</packagegui>
diff --git a/config/bandwidthd/bandwidthd.inc b/config/bandwidthd/bandwidthd.inc
new file mode 100644
index 00000000..262530ce
--- /dev/null
+++ b/config/bandwidthd/bandwidthd.inc
@@ -0,0 +1,201 @@
+<?php
+/* $Id$ */
+/*
+ bandwidthd.inc
+ Copyright (C) 2006 Scott Ullrich
+ part of pfSense
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+function bandwidthd_install_deinstall() {
+ conf_mount_rw();
+ config_lock();
+ exec("cd /var/db/pkg/ && pkg_delete `ls | grep bandwidthd`");
+ exec("rm /usr/local/etc/rc.d/bandwidthd*");
+ exec("rm -rf /usr/local/bandwidthd*");
+ exec("rm /usr/local/www/bandwidthd");
+ conf_mount_ro();
+ config_unlock();
+}
+
+function bandwidthd_install_config() {
+ global $config, $g;
+
+ conf_mount_rw();
+ config_lock();
+
+ /* user defined values */
+ $meta_refresh = $config['installedpackages']['bandwidthd']['config'][0]['metarefresh'];
+ if($meta_refresh)
+ $meta_refresh = "meta_refresh $meta_refresh\n";
+ $graph = $config['installedpackages']['bandwidthd']['config'][0]['graph'];
+ if($graph)
+ $graph = "graph true\n";
+ $filter_text = $config['installedpackages']['bandwidthd']['config'][0]['filter'];
+ if($filter_text)
+ $filter_text = "filter $filter_text\n";
+ $recover_cdf = $config['installedpackages']['bandwidthd']['config'][0]['recovercdf'];
+ if($recover_cdf)
+ $recover_cdf = "recover_cdf true\n";
+ $output_cdf = $config['installedpackages']['bandwidthd']['config'][0]['outputcdf'];
+ if($output_cdf)
+ $output_cdf = "output_cdf true\n";
+ $promiscuous = $config['installedpackages']['bandwidthd']['config'][0]['promiscuous'];
+ if($promiscuous)
+ $promiscuous = "promiscuous true\n";
+ $graph_cutoff = $config['installedpackages']['bandwidthd']['config'][0]['graphcutoff'];
+ if($graph_cutoff)
+ $graph_cutoff = "graph_cutoff $graph_cutoff\n";
+ $skip_intervals = $config['installedpackages']['bandwidthd']['config'][0]['skipintervals'];
+ if($skip_intervals)
+ $skip_intervals = "skip_intervals $skip_intervals\n";
+
+ if($config['installedpackages']['bandwidthd']['config'][0]['active_interface']){
+ $ifdescrs = array($config['installedpackages']['bandwidthd']['config'][0]['active_interface']);
+ } else {
+ log_error("You should specify a interface for bandwidthd to listen on. exiting.");
+ }
+
+ /* initialize to "" */
+ $subnets = "";
+ //$ifdescrs = array("lan", "wan");
+ //for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++) {
+ //$ifdescrs['opt' . $j] = "opt" . $j;
+ //}
+ if(is_array($ifdescrs)) {
+ foreach($ifdescrs as $int) {
+ /* calculate interface subnet information */
+ $ifcfg = &$config['interfaces'][$int];
+ $subnet = gen_subnet($ifcfg['ipaddr'], $ifcfg['subnet']);
+ $subnetmask = gen_subnet_mask($ifcfg['subnet']);
+ if($subnet == "pppoe") {
+ $subnet = find_interface_ip("ng0");
+ if($subnet)
+ $subnets .= "subnet {$subnet}/32\n";
+ } else {
+ if($subnet)
+ $subnets .= "subnet {$subnet}/{$ifcfg['subnet']}\n";
+ }
+ }
+ }
+
+ /* initialize to "" */
+ $dev = "";
+ if(is_array($ifdescrs)) {
+ foreach($ifdescrs as $ifdescr) {
+ $descr = convert_friendly_interface_to_real_interface_name($ifdescr);
+ $dev .= "dev \"$descr\"\n";
+ }
+ }
+
+ $config_file = <<<EOF
+#
+# This file was automatically generated by the pfSense
+# package management system. Changing this file
+# will lead to it being overwritten again when
+# the package manage resyncs.
+#
+####################################################
+# Bandwidthd.conf
+#
+# Commented out options are here to provide
+# documentation and represent defaults
+
+# Subnets to collect statistics on. Traffic that
+# matches none of these subnets will be ignored.
+# Syntax is either IP Subnet Mask or CIDR
+$subnets
+
+# Device to listen on
+# Bandwidthd listens on the first device it detects
+# by default. Run "bandwidthd -l" for a list of
+# devices.
+$dev
+
+###################################################
+# Options that don't usually get changed
+
+# An interval is 2.5 minutes, this is how many
+# intervals to skip before doing a graphing run
+$skip_inervals
+
+# Graph cutoff is how many k must be transfered by an
+# ip before we bother to graph it
+$graph_cutoff
+
+#Put interface in promiscuous mode to score to traffic
+#that may not be routing through the host machine.
+$promiscuous
+
+#Log data to cdf file htdocs/log.cdf
+$output_cdf
+
+#Read back the cdf file on startup
+$recover_cdf
+
+#Libpcap format filter string used to control what bandwidthd see's
+#Please always include "ip" in the string to avoid strange problems
+$filter_text
+
+#Draw Graphs - This default to true to graph the traffic bandwidthd is recording
+#Usually set this to false if you only want cdf output or
+#you are using the database output option. Bandwidthd will use very little
+#ram and cpu if this is set to false.
+$graph
+
+#Set META REFRESH seconds (default 150, use 0 to disable).
+$meta_refresh
+
+EOF;
+
+ $fd = fopen("/usr/local/bandwidthd/etc/bandwidthd.conf","w");
+ if(!$fd) {
+ log_error("could not open /usr/local/bandwidthd/etc/bandwidthd.conf for writing");
+ exit;
+ }
+ fwrite($fd, $config_file);
+ fclose($fd);
+
+ /* write out rc.d start/stop file */
+ write_rcfile(array(
+ "file" => "bandwidthd.sh",
+ "start" => "/usr/local/bandwidthd/bandwidthd /usr/local/bandwidthd/etc/bandwidthd.conf",
+ "stop" => "/usr/bin/killall bandwidthd"
+ )
+ );
+
+ exec("rm /usr/local/www/bandwidthd");
+ exec("/bin/ln -s /usr/local/bandwidthd/htdocs /usr/local/www/bandwidthd");
+
+ exec("echo \"Please start bandwidthd to populate this directory.\" > /usr/local/bandwidthd/htdocs/index.html");
+
+ conf_mount_ro();
+ config_unlock();
+
+ stop_service("bandwidthd");
+ start_service("bandwidthd");
+
+}
+
+?> \ No newline at end of file
diff --git a/config/bandwidthd/bandwidthd.xml b/config/bandwidthd/bandwidthd.xml
new file mode 100644
index 00000000..7d91ce77
--- /dev/null
+++ b/config/bandwidthd/bandwidthd.xml
@@ -0,0 +1,153 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>bandwidthd</name>
+ <version>1.0</version>
+ <title>Bandwidthd</title>
+ <aftersaveredirect>/pkg_edit.php?xml=bandwidthd.xml&amp;id=0</aftersaveredirect>
+ <include_file>/usr/local/pkg/bandwidthd.inc</include_file>
+ <menu>
+ <name>BandwidthD</name>
+ <tooltiptext></tooltiptext>
+ <section>Services</section>
+ <url>/pkg_edit.php?xml=bandwidthd.xml&amp;id=0</url>
+ </menu>
+ <service>
+ <name>bandwidthd</name>
+ <rcfile>bandwidthd.sh</rcfile>
+ <executable>bandwidthd</executable>
+ </service>
+ <tabs>
+ <tab>
+ <text>BandwidthD</text>
+ <url>/pkg_edit.php?xml=bandwidthd.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Access BandwidthD</text>
+ <url>/bandwidthd</url>
+ </tab>
+ </tabs>
+ <configpath>installedpackages->package->bandwidthd</configpath>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>077</chmod>
+ <item>http://www.pfsense.com/packages/config/bandwidthd/bandwidthd.inc</item>
+ </additional_files_needed>
+ <fields>
+ <field>
+ <fielddescr>interface</fielddescr>
+ <fieldname>active_interface</fieldname>
+ <description>The interface that bandwidthd will bind to.</description>
+ <type>interfaces_selection</type>
+ <required/>
+ <default_value>lan</default_value>
+ </field>
+ <field>
+ <fielddescr>Skip intervals</fielddescr>
+ <fieldname>skipintervals</fieldname>
+ <description></description>
+ <type>input</type>
+ <value>1024</value>
+ </field>
+ <field>
+ <fielddescr>Graph cutoff</fielddescr>
+ <fieldname>graphcutoff</fieldname>
+ <description>Graph cutoff is how many k must be transfered by an ip before we bother to graph it</description>
+ <type>input</type>
+ <value>1024</value>
+ </field>
+ <field>
+ <fielddescr>promiscuous</fielddescr>
+ <fieldname>promiscuous</fieldname>
+ <description>Put interface in promiscuous mode to score to traffic that may not be routing through the host machine.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>output_cdf</fielddescr>
+ <fieldname>outputcdf</fieldname>
+ <description>Log data to cdf file htdocs/log.cdf</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>recover_cdf</fielddescr>
+ <fieldname>recovercdf</fieldname>
+ <description>Read back the cdf file on startup</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>filter</fielddescr>
+ <fieldname>filter</fieldname>
+ <description>Libpcap format filter string used to control what bandwidthd see's. Please always include "ip" in the string to avoid strange problems.</description>
+ <type>input</type>
+ <value>ip</value>
+ </field>
+ <field>
+ <fielddescr>Draw Graphs</fielddescr>
+ <fieldname>drawgraphs</fieldname>
+ <description>This default to true to graph the traffic bandwidthd is recording. Usually set this to false if you only want cdf output or you are using the database output option. Bandwidthd will use very little ram and cpu if this is set to false.</description>
+ <type>checkbox</type>
+ <value>checked</value>
+ </field>
+ <field>
+ <fielddescr>Meta Refresh</fielddescr>
+ <fieldname>meta_refresh</fieldname>
+ <description>Set META REFRESH seconds (default 150, use 0 to disable).</description>
+ <type>input</type>
+ <value>150</value>
+ </field>
+ </fields>
+ <custom_php_resync_config_command>
+ bandwidthd_install_config();
+ </custom_php_resync_config_command>
+ <custom_php_install_command>
+ bandwidthd_install_config();
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ bandwidthd_install_deinstall();
+ </custom_php_deinstall_command>
+</packagegui>
diff --git a/config/bsdstats/bin/dig b/config/bsdstats/bin/dig
new file mode 100755
index 00000000..ae267007
--- /dev/null
+++ b/config/bsdstats/bin/dig
Binary files differ
diff --git a/config/bsdstats/bsdstats.xml b/config/bsdstats/bsdstats.xml
new file mode 100644
index 00000000..d66d6f58
--- /dev/null
+++ b/config/bsdstats/bsdstats.xml
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>bsdstats</name>
+ <version>0.1</version>
+ <title>BSDStats</title>
+ <!-- Menu is where this packages menu will appear -->
+ <menu>
+ <name>BSDStats</name>
+ <tooltiptext>BSDStats</tooltiptext>
+ <section>Diagnostics</section>
+ <url>http://bsdstats.hub.org/</url>
+ </menu>
+ <additional_files_needed>
+ <prefix>/usr/bin/</prefix>
+ <chmod>077</chmod>
+ <item>http://www.pfsense.com/packages/config/bsdstats/bin/dig</item>
+ </additional_files_needed>
+ <custom_php_install_command>
+ system("/bin/mkdir -p /usr/local/etc/periodic/monthly/");
+ system("/usr/bin/fetch -q -o /usr/local/etc/periodic/monthly/ http://www.bsdstats.org/downloads/300.statistics");
+ system("/bin/chmod a+rx /usr/local/etc/periodic/monthly/300.statistics");
+ if(!is_file("/usr/local/etc/periodic/monthly/300.statistics") {
+ update_status("Could not fetch 300.statistics from bsdstats.org");
+ update_output_window("Install failed. Please check dns, etc");
+ exit;
+ }
+ system("echo monthly_statistics_report_devices=yes >> /etc/periodic.conf");
+ system("echo monthly_statistics_enable=yes >> /etc/periodic.conf");
+ mwexec_bg("/usr/local/etc/periodic/monthly/300.statistics");
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ system("/bin/cat /etc/periodic.conf | grep -n \"monthly_statistics_report_devices\" >/tmp/periodic.conf");
+ system("/bin/cat /tmp/periodic.conf | grep -n \"monthly_statistics_enable\" >/etc/periodic.conf");
+ system("/bin/rm /usr/local/etc/periodic/monthly/300.statistics");
+ system("/bin/rm /tmp/periodic.conf");
+ system("/bin/rm /tmp/getid");
+ </custom_php_deinstall_command>
+</packagegui>
diff --git a/config/cg2/sample/i18n/messages_de.xml b/config/cg2/sample/i18n/messages_de.xml
new file mode 100644
index 00000000..0cfef583
--- /dev/null
+++ b/config/cg2/sample/i18n/messages_de.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<po creationdate ="2006-09-20 12:37+0100" translator="me@daniel.stefan.haischt.name">
+ <message msgid="hey, this is only meant for quick and dirty stuff, do NOT implement anything longer than 2 or 3 commands here! Btw, i was clicked."
+ msgstr="Hei, dies eignet sich nur f&#252;r Testzwecke. Benutze nur nur Quellcode der nicht mehr als 2 oder 3 Befehle umfasst! BTW, Ich wurde gedr&#252;ckt." />
+ <message msgid="Hi, don't abuse me, use include_javascript instead!"
+ msgstr="Hallo, missbrauche mich nicht. Nutze stattdessen include_javascript!" />
+</po> \ No newline at end of file
diff --git a/config/cg2/sample/i18n/messages_en.xml b/config/cg2/sample/i18n/messages_en.xml
new file mode 100644
index 00000000..1ee7d24d
--- /dev/null
+++ b/config/cg2/sample/i18n/messages_en.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<po creationdate ="2006-09-20 12:37+0100" translator="me@daniel.stefan.haischt.name">
+ <message msgid="hey, this is only meant for quick and dirty stuff, do NOT implement anything longer than 2 or 3 commands here! Btw, i was clicked."
+ msgstr="hey, this is only meant for quick and dirty stuff, do NOT implement anything longer than 2 or 3 commands here! Btw, i was clicked." />
+ <message msgid="Hi, don't abuse me, use include_javascript instead!"
+ msgstr="Hi, don't abuse me, use include_javascript instead!" />
+</po> \ No newline at end of file
diff --git a/config/cg2/sample/sample.inc b/config/cg2/sample/sample.inc
new file mode 100644
index 00000000..62ec59ab
--- /dev/null
+++ b/config/cg2/sample/sample.inc
@@ -0,0 +1,37 @@
+<?php
+//var_dump('BEING INCLUDED');
+
+function sample_on_load_event(&$widgets)
+{
+ /* Called when the form is just loaded. You receive the array widgets as
+ * argument, and can modify it to alter the behavior of the form. */
+ //var_dump('BEING LOADED');
+ //$widget =& $widgets[2];
+ $widget =& get_widget($widgets, 'mytextarea');
+ $widget->value='This example shows how to change the text inside a text box from within the include file, when the form is loaded.';
+}
+
+function sample_on_sync_event()
+{
+ /* This is called when the form is posted. You generally want to sync the
+ * configurations in the XML file to settings in files spread across the file
+ * system or maybe restart a service here. */
+ //var_dump('BEING SYNCED');
+}
+
+function sample_on_apply_event()
+{
+ /* This is called when a configuration has been changed and the user is
+ * prompted to apply the changes and clicks "Apply changes". */
+ var_dump('BEING APPLIED');
+}
+
+function sample_on_submit_event()
+{
+ /* This allows you to perform an action when an specific submit button is
+ * clicked. This should only be used when you have more than one submit
+ * button in the same form. Otherwise, <on_load_event> performs better and
+ * is cleaner. */
+ //var_dump('BEING SUBMITTED');
+}
+?>
diff --git a/config/cg2/sample/sample.xml b/config/cg2/sample/sample.xml
new file mode 100644
index 00000000..d851c54e
--- /dev/null
+++ b/config/cg2/sample/sample.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<coregui_master>
+<version>2.0</version>
+
+<title>A fancy example</title>
+
+<!--<include>sample.inc</include>-->
+<!--<tabs_callback>sample_generate_tabs</tabs_callback>-->
+<tab>
+ <label>My fancy tab</label>
+ <interface>sample_ui.xml</interface>
+</tab>
+<tab>
+ <label>Another fancy tab</label>
+ <interface>sample_ui2.xml</interface>
+</tab>
+
+</coregui_master>
diff --git a/config/cg2/sample/sample_ui.xml b/config/cg2/sample/sample_ui.xml
new file mode 100644
index 00000000..aebe8bfe
--- /dev/null
+++ b/config/cg2/sample/sample_ui.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<coregui_interface>
+<version>2.0</version>
+<config>sample</config>
+
+<include>sample.inc</include>
+<!--<include>sample2.inc</include>-->
+<include_javascript>sample.js</include_javascript>
+
+<element>
+ <type>form</type>
+ <on_load_event>sample_on_load_event</on_load_event>
+ <on_sync_event>sample_on_sync_event</on_sync_event>
+ <widget>
+ <type>header</type>
+ <label xml:lang="en-US">Headers are useful to separate stuff...</label>
+ </widget>
+ <widget>
+ <type>textbox</type>
+ <name>mytextbox</name>
+ <label xml:lang="en-US">My fancy textbox</label>
+ <description xml:lang="en-US">This is a textbox.</description>
+ <value xml:lang="en-US">Welcome to the world of coregui 2.0</value>
+ <required/>
+ </widget>
+ <widget>
+ <type>ipsec_select</type>
+ <name>ipsec</name>
+ <label xml:lang="en-US">IPsec selection</label>
+ <description xml:lang="en-US">IPsec selection widget test.</description>
+ <multiple/>
+ </widget>
+ <widget>
+ <type>select</type>
+ <name>sample_sel</name>
+ <label xml:lang="en-US">Sample selection</label>
+ <option>
+ <name>foo</name>
+ <label xml:lang="en-US">Foo</label>
+ </option>
+ <option>
+ <name>bar</name>
+ <label xml:lang="en-US">Bar</label>
+ </option>
+ </widget>
+ <widget>
+ <type>interfaces_select</type>
+ <name>inter_sel</name>
+ <label xml:lang="en-US">Sample interfaces select</label>
+ <multiple/>
+ </widget>
+ <widget>
+ <type>textarea</type>
+ <name>mytextarea</name>
+ <label xml:lang="en-US">My fancy textarea</label>
+ <description xml:lang="en-US">Just testing descriptions...</description>
+ <value xml:lang="en-US">This widget can not be edited!</value>
+ <read_only/>
+ </widget>
+ <widget>
+ <type>checkbox</type>
+ <name>mycheckbox</name>
+ <label xml:lang="en-US">A sample checkbox</label>
+ <caption xml:lang="en-US">Check this nice checkbox</caption>
+ <description xml:lang="en-US">Now checkboxes can have a caption as well.</description>
+ <on_check_javascript>_('hey, this is only meant for quick and dirty stuff, do NOT implement anything longer than 2 or 3 commands here! Btw, i was clicked.');</on_check_javascript>
+ </widget>
+ <widget>
+ <type>submit</type>
+ <name>mysubmit</name>
+ <caption xml:lang="en-US">Send something</caption>
+ <on_submit_event>sample_on_submit_event</on_submit_event>
+ <group_start/>
+ </widget>
+ <widget>
+ <type>button</type>
+ <name>mybutton</name>
+ <caption xml:lang="en-US">Cancel something</caption>
+ <description xml:lang="en-US">The description for the last element in a group is the description that matters.</description>
+ <on_click_javascript>_('Hi, don\'t abuse me, use include_javascript instead!');</on_click_javascript>
+ <group_end/>
+ </widget>
+ <widget>
+ <type>textbox</type>
+ <name>dummydummy</name>
+ <label xml:lang="en-US">Just some dummy text</label>
+ <do_not_display/>
+ </widget>
+ <widget>
+ <type>checkbox</type>
+ <name>anothercheckbox</name>
+ <label xml:lang="en-US">Another checkbox</label>
+ <caption xml:lang="en-US">Enable</caption>
+ <description xml:lang="en-US">Another checkbox, this time after a group, and disabled.</description>
+ <disabled/>
+ </widget>
+</element>
+
+<element>
+ <type>table</type>
+ <buttons>move,edit,delete,add</buttons>
+ <on_apply_event>sample_on_apply_event</on_apply_event>
+ <widget>
+ <type>checkbox</type>
+ <name>dummycheckbox</name>
+ <label xml:lang="en-US">Dummy checkbox</label>
+ </widget>
+ <widget>
+ <type>port</type>
+ <name>dummyport</name>
+ <label xml:lang="en-US">Port</label>
+ <description xml:lang="en-US">Enter a port here.</description>
+ <value>3128</value>
+ <required/>
+ </widget>
+ <widget>
+ <type>textbox</type>
+ <name>dummysetting</name>
+ <label xml:lang="en-US">Dummy setting</label>
+ <description xml:lang="en-US">This dummy setting will not show up in the table.</description>
+ <not_in_table/>
+ </widget>
+ <widget>
+ <type>textarea</type>
+ <name>longfield</name>
+ <label xml:lang="en-US">Very long field</label>
+ <description xml:lang="en-US">Very very very very very long field.</description>
+ <highlighted/>
+ </widget>
+</element>
+
+<element>
+ <type>form</type>
+ <widget>
+ <type>header</type>
+ <label xml:lang="en-US">...such as two different forms</label>
+ </widget>
+ <widget>
+ <type>button</type>
+ <name>mybutton</name>
+ <label xml:lang="en-US">A simple button</label>
+ <caption xml:lang="en-US">Another silly button</caption>
+ </widget>
+</element>
+
+<element>
+ <type>table</type>
+ <widget>
+ <label xml:lang="en-US">Silly test</label>
+ </widget>
+ <widget>
+ <label xml:lang="en-US">Another field</label>
+ </widget>
+</element>
+
+</coregui_interface>
diff --git a/config/cg2/sample/sample_ui2.xml b/config/cg2/sample/sample_ui2.xml
new file mode 100644
index 00000000..aa17d49d
--- /dev/null
+++ b/config/cg2/sample/sample_ui2.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<coregui_interface>
+<version>2.0</version>
+<config>sample2</config>
+
+<element>
+ <type>form</type>
+ <widget>
+ <type>textbox</type>
+ <name>mytextbox</name>
+ <label xml:lang="en-US">My fancy textbox</label>
+ <value>Welcome to the world of coregui 2.0</value>
+ <required/>
+ </widget>
+ <widget>
+ <type>textarea</type>
+ <name>mytextarea</name>
+ <label xml:lang="en-US">My fancy textarea</label>
+ <value>This widget will be encoded to the config</value>
+ <encode/>
+ </widget>
+ <widget>
+ <type>submit</type>
+ <name>mysubmit</name>
+ <caption xml:lang="en-US">Submit this now</caption>
+ </widget>
+</element>
+
+</coregui_interface>
diff --git a/config/clamav.inc b/config/clamav.inc
new file mode 100644
index 00000000..2e83888c
--- /dev/null
+++ b/config/clamav.inc
@@ -0,0 +1,263 @@
+<?php
+require_once('globals.inc');
+require_once('config.inc');
+require_once('service-utils.inc');
+require_once('pkg-utils.inc');
+require_once('pfsense-utils.inc');
+
+function clamav_install_command() {
+ global $g;
+ mwexec('rm -f /usr/local/etc/rc.d/clamav*');
+
+ $clamav_rundir = "{$g['varrun_path']}/clamav";
+
+ $pidfile = "$clamav_rundir/clamd.pid";
+ $rcfile = array();
+ $rcfile['file'] = 'clamd.sh';
+ $rcfile['start'] = "mkdir -p $clamav_rundir\n\tchown proxy:proxy $clamav_rundir\n\tclamd";
+ $rcfile['stop'] = "kill `cat $pidfile`";
+ write_rcfile($rcfile);
+
+ $pidfile = "$clamav_rundir/freshclam.pid";
+ $rcfile = array();
+ $rcfile['file'] = 'freshclam.sh';
+ $rcfile['start'] = "mkdir -p $clamav_rundir\n\tchown proxy:proxy $clamav_rundir\n\tfreshclam -d";
+ $rcfile['start'] = 'freshclam -d';
+ $rcfile['stop'] = "kill `cat $pidfile`";
+ write_rcfile($rcfile);
+
+ $dbdir = "{$g['vardb_path']}/clamav";
+ make_dirs($dbdir);
+ chown($dbdir, 'proxy');
+ $conf = <<<EOD
+DatabaseDirectory $dbdir
+PidFile $pidfile
+DatabaseOwner proxy
+AllowSupplementaryGroups
+DatabaseMirror database.clamav.net
+
+EOD;
+ file_put_contents('/usr/local/etc/freshclam.conf', $conf);
+
+ $static_output = "Fetching the virus database. This can take long. You can cancel this at any time by clicking the stop button in your browser.\n";
+ update_output_window($static_output);
+ $static_output .= system('freshclam');
+ update_output_window($static_output);
+ $static_output .= "Done!\n";
+ update_output_window($static_output);
+
+ start_service('freshclam');
+}
+
+function clamav_resync() {
+ global $g, $config;
+
+ $settings = $config['installedpackages']['clamav']['config'][0];
+
+ $clamav_rundir = "{$g['varrun_path']}/clamav";
+ $logfile = "{$g['varlog_path']}/clamd.log";
+ $pidfile = "$clamav_rundir/clamd.pid";
+ $tempdir = $g['tmp_path'];
+ $dbdir = "{$g['vardb_path']}/clamav";
+ $socket = "$clamav_rundir/clamd.socket";
+
+ $conf = <<<EOD
+LogFile $logfile
+LogTime
+PidFile $pidfile
+TemporaryDirectory $tempdir
+DatabaseDirectory $dbdir
+LocalSocket $socket
+FixStaleSocket
+User proxy
+AllowSupplementaryGroups
+ScanMail
+
+EOD;
+
+ if ($settings['expert_mode'] == 'on') $conf .= "DisableDefaultScanOptions";
+ else {
+ $options = array( 'brokenexec' => 'DetectBrokenExecutables',
+ 'scan_pe' => 'ScanPE',
+ 'scan_ole2' => 'ScanOLE2',
+ 'scan_html' => 'ScanHTML',
+ 'scan_archive' => 'ScanArchive');
+ foreach ($options as $option => $directive) {
+ if ($settings[$option] == 'on')
+ $conf .= "$directive\n";
+ }
+ }
+
+ file_put_contents('/usr/local/etc/clamd.conf', $conf);
+
+ restart_service('clamav');
+
+ if ($settings['scan_pop3'] == 'on') {
+ require_once('p3scan.inc');
+ p3scan_resync();
+ }
+
+ if ($settings['scan_smtp'] == 'on') {
+ require_once('clamsmtp.inc');
+ clamsmtp_resync();
+ }
+
+ if ($settings['scan_http'] == 'on') {
+ require_once('viralator.inc');
+ viralator_resync();
+ }
+}
+
+function clamav_before_form($pkg) {
+ global $config;
+
+ if (is_package_installed('p3scan')) {
+ $field = array();
+ $field['fieldname'] = 'scan_pop3';
+ $field['fielddescr'] = 'POP3 scanning';
+ $field['description'] = 'Enable POP3 scanning.';
+ $field['type'] = 'checkbox';
+ $field['required'] = true;
+ $field['enablefields'] = 'pop3_ifaces[]';
+ $pkg['fields']['field'][] = $field;
+
+ $field = array();
+ $field['fieldname'] = 'pop3_ifaces';
+ $field['fielddescr'] = 'POP3 interfaces';
+ $field['description'] = 'The POP3 proxy will bind to the selected interfaces';
+ $field['default_value'] = 'ALL';
+ $field['type'] = 'interfaces_selection';
+ $field['multiple'] = 'yes';
+ $pkg['fields']['field'][] = $field;
+ }
+
+ if (is_package_installed('clamsmtp')) {
+ $field = array();
+ $field['fieldname'] = 'scan_smtp';
+ $field['fielddescr'] = 'SMTP scanning';
+ $field['description'] = 'Enable SMTP scanning.';
+ $field['required'] = true;
+ $field['type'] = 'checkbox';
+ $field['enablefields'] = 'smtp_ifaces[],smtp_server,smtp_port';
+ $pkg['fields']['field'][] = $field;
+
+ $field = array();
+ $field['fieldname'] = 'smtp_ifaces';
+ $field['fielddescr'] = 'SMTP interfaces';
+ $field['description'] = 'The SMTP proxy will bind to the selected interfaces';
+ $field['default_value'] = 'ALL';
+ $field['type'] = 'interfaces_selection';
+ $field['multiple'] = 'yes';
+ $pkg['fields']['field'][] = $field;
+
+ $field = array();
+ $field['fieldname'] = 'smtp_server';
+ $field['fielddescr'] = 'SMTP server address';
+ $field['description'] = 'Enter the IP address of the local SMTP server.';
+ $field['type'] = 'input';
+ $pkg['fields']['field'][] = $field;
+
+ $field = array();
+ $field['fieldname'] = 'smtp_port';
+ $field['fielddescr'] = 'SMTP server port';
+ $field['description'] = 'Enter the port of the local SMTP server.';
+ $field['type'] = 'input';
+ $pkg['fields']['field'][] = $field;
+ }
+
+ if (is_package_installed('viralator')) {
+ $field = array();
+ $field['fieldname'] = 'scan_http';
+ $field['fielddescr'] = 'HTTP scanning';
+ $field['description'] = 'Enable HTTP scanning. Note that this filtering is triggered by the proxy server. Therefore, to transparently filter out HTTP viruses, you need to set up the proxy server in transparent mode.';
+ $field['required'] = 'yes';
+ $field['type'] = 'checkbox';
+ $field['enablefields'] = 'http_exts[],http_otherexts';
+ $pkg['fields']['field'][] = $field;
+
+ $field = array();
+ $field['fieldname'] = 'http_exts';
+ $field['fielddescr'] = 'Extensions to scan';
+ $field['description'] = 'Extensions to be scanned by the HTTP virus scanner';
+ $field['type'] = 'select';
+ $exts = array();
+ $exts['zip'] = 'Archives in the ZIP format';
+ $exts['rar'] = 'Archives in the RAR format';
+ $exts['arj'] = 'Archives in the ARJ format';
+ $exts['gz'] = 'Files compressed in the GZ format';
+ $exts['bz2'] = 'Files compressed in the BZIP2 format';
+ $exts['exe'] = 'Windows/DOS PE (EXE) executables';
+ $exts['com'] = 'DOS COM executables';
+ $exts['bat'] = 'DOS Batch files';
+ foreach ($exts as $ext => $desc)
+ $field['options']['option'][] = array('name' => "$desc (*.$ext)", 'value' => $ext);
+ $field['multiple'] = 'yes';
+ $pkg['fields']['field'][] = $field;
+
+ $field = array();
+ $field['fieldname'] = 'http_otherexts';
+ $field['fielddescr'] = 'Other extensions to scan';
+ $field['description'] = 'Comma-separated list of extensions to be scanned by the HTTP virus scanner (e.g.: txt,ppt,doc,wmv).';
+ $field['type'] = 'input';
+ $pkg['fields']['field'][] = $field;
+ }
+}
+
+function clamav_validate_input($post, $input_errors) {
+ if ($post['scan_smtp'] == 'on') {
+ require_once('clamsmtp.inc');
+ clamsmtp_validate_input($post, &$input_errors);
+ }
+
+ if (is_package_installed('viralator')) {
+ require_once('viralator.inc');
+ viralator_validate_input($post, &$input_errors);
+ }
+}
+
+function clamav_generate_rules($type) {
+ global $config;
+
+ if (!is_service_running('clamav')) return;
+
+ $rules = '';
+ $clamav_conf = $config['installedpackages']['clamav']['config'][0];
+ $sassassin_conf = $config['installedpackages']['sassassin']['config'][0];
+
+ $p3scan_enabled = (($clamav_conf['scan_pop3'] == 'on') || ($sassassin_conf['enable'] == 'on'));
+ if ($p3scan_enabled && is_service_running('p3scan')) {
+ $ifaces = explode(',', $clamav_conf['pop3_ifaces']);
+ $ifaces = array_map('convert_friendly_interface_to_real_interface_name', $ifaces);
+
+ switch($type) {
+ case 'nat':
+ foreach ($ifaces as $iface)
+ $rules .= "rdr on $iface proto tcp to port pop3 -> 127.0.0.1 port 8110\n";
+ break;
+ case 'filter':
+ foreach ($ifaces as $iface)
+ $rules .= "pass quick on $iface proto tcp to port pop3 flags S/SA keep state\n";
+ break;
+ default:
+ break;
+ }
+ }
+
+ if ($clamav_conf['scan_smtp'] && is_service_running('clamsmtp')) {
+ $ifaces = explode(',', $clamav_conf['pop3_ifaces']);
+ $ifaces = array_map('convert_friendly_interface_to_real_interface_name', $ifaces);
+
+ if ($type == 'nat') {
+ foreach ($ifaces as $iface)
+ $rules .= "rdr on $iface proto tcp to ($iface) port smtp -> 127.0.0.1 port 10025\n";
+ }
+
+ else {
+ foreach ($ifaces as $iface)
+ $rules .= "pass quick on $iface proto tcp to ($iface) port smtp flags S/SA keep state\n";
+ }
+ }
+
+ return ($rules);
+}
+?>
diff --git a/config/clamav.xml b/config/clamav.xml
new file mode 100644
index 00000000..483a32a6
--- /dev/null
+++ b/config/clamav.xml
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>clamav</name>
+ <version>none</version>
+ <title>Antivirus</title>
+ <include_file>clamav.inc</include_file>
+ <menu>
+ <name>Antivirus</name>
+ <tooltiptext>Configure antivirus settings</tooltiptext>
+ <section>Services</section>
+ <url>/pkg_edit.php?xml=clamav.xml&amp;id=0</url>
+ </menu>
+ <service>
+ <name>ClamAV</name>
+ <rcfile>clamd.sh</rcfile>
+ <executable>clamd</executable>
+ <description>The ClamAV antivirus.</description>
+ </service>
+ <service>
+ <name>FreshClam</name>
+ <rcfile>freshclam.sh</rcfile>
+ <executable>freshclam</executable>
+ <description>A daemon that periodically updates the ClamAV virus database.</description>
+ </service>
+ <additional_files_needed>
+ <item>http://www.pfsense.org/packages/config/clamav.inc</item>
+ </additional_files_needed>
+ <fields>
+ <field>
+ <fielddescr>Expert mode</fielddescr>
+ <fieldname>expert</fieldname>
+ <description>This enables the expert mode. Don't check this unless you are sure of what you are doing.</description>
+ <type>checkbox</type>
+ <enablefields>brokenexec,scan_pe,scan_ole2,scan_html,scan_archive</enablefields>
+ <required/>
+ </field>
+ <field>
+ <fielddescr>Detect broken executables</fielddescr>
+ <fieldname>brokenexec</fieldname>
+ <description>Try to detect broken executables.</description>
+ <type>checkbox</type>
+ <default_value>on</default_value>
+ </field>
+ <field>
+ <fielddescr>Scan PE</fielddescr>
+ <fieldname>scan_pe</fieldname>
+ <description>Scan files in 32-bit Windows' Portable Executable format.</description>
+ <type>checkbox</type>
+ <default_value>on</default_value>
+ </field>
+ <field>
+ <fielddescr>Scan OLE2</fielddescr>
+ <fieldname>scan_ole2</fieldname>
+ <description>Scan Microsoft Office document macros.</description>
+ <type>checkbox</type>
+ <default_value>on</default_value>
+ </field>
+ <field>
+ <fielddescr>Scan HTML</fielddescr>
+ <fieldname>scan_html</fieldname>
+ <description>Perform HTML normalization and decryption of Microsoft Script Encoder code.</description>
+ <type>checkbox</type>
+ <default_value>on</default_value>
+ </field>
+ <field>
+ <fielddescr>Scan archives</fielddescr>
+ <fieldname>scan_archive</fieldname>
+ <description>Try to uncompress archived files to scan their content.</description>
+ <type>checkbox</type>
+ <default_value>on</default_value>
+ </field>
+ </fields>
+ <custom_php_command_before_form>
+ clamav_before_form(&amp;$pkg);
+ </custom_php_command_before_form>
+ <custom_php_resync_config_command>
+ clamav_resync();
+ </custom_php_resync_config_command>
+ <custom_php_validation_command>
+ clamav_validate_input($post, &amp;$input_errors);
+ </custom_php_validation_command>
+ <custom_php_install_command>
+ clamav_install_command();
+ </custom_php_install_command>
+</packagegui>
diff --git a/config/clamsmtp.inc b/config/clamsmtp.inc
new file mode 100644
index 00000000..08d9e23b
--- /dev/null
+++ b/config/clamsmtp.inc
@@ -0,0 +1,54 @@
+<?php
+require_once('globals.inc');
+require_once('config.inc');
+require_once('service-utils.inc');
+require_once('filter.inc');
+
+function clamsmtp_install_command() {
+ global $g;
+
+ $clamav_rundir = "{$g['varrun_path']}/clamav";
+ $pidfile = "$clamav_rundir/clamsmtpd.pid";
+ $rcfile = array();
+ $rcfile['file'] = 'clamsmtp.sh';
+ $rcfile['start'] = "mkdir -p $clamav_rundir\n\tchown proxy:proxy $clamav_rundir\n\tclamsmtpd";
+ $rcfile['stop'] = "kill `cat $pidfile`";
+ write_rcfile($rcfile);
+
+ clamsmtp_resync();
+}
+
+function clamsmtp_validate_input($post, $input_errors) {
+ if (!is_ipaddr(trim($post['smtp_server'])))
+ $input_errors[] = 'The field \'SMTP server\' must contain a valid IP address.';
+ $port = trim($post['smtp_port']);
+ if (!is_numeric($port) || ($port < 0) || ($port > 65535))
+ $input_errors[] = 'The field \'SMTP server\' must contain a port ranging from 0 to 65535';
+}
+
+function clamsmtp_resync() {
+ global $g, $config;
+
+ $avconf = $config['installedpackages']['clamav']['config'][0];
+ if ($avconf['scan_smtp'] == 'on')
+ $outaddress = "{$avconf['smtp_server']}:{$avconf['smtp_port']}";
+ else
+ $outaddress = '127.0.0.1:25';
+ $clamav_rundir = "{$g['varrun_path']}/clamav";
+ $clamsocket = "$clamav_rundir/clamd.socket";
+ $pidfile = "$clamav_rundir/clamsmtpd.pid";
+ $conf = <<<EOD
+Listen: 127.0.0.1:10025
+OutAddress: $outaddress
+ClamAddress: $clamsocket
+User: proxy
+PidFile: $pidfile
+
+EOD;
+
+ file_put_contents('/usr/local/etc/clamsmtpd.conf', $conf);
+
+ restart_service('clamsmtp');
+ filter_configure();
+}
+?>
diff --git a/config/clamsmtp.xml b/config/clamsmtp.xml
new file mode 100644
index 00000000..16bb5d6d
--- /dev/null
+++ b/config/clamsmtp.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>none</name>
+ <version>none</version>
+ <title>none</title>
+ <include_file>clamsmtp.inc</include_file>
+ <service>
+ <name>clamsmtp</name>
+ <rcfile>clamsmtp.sh</rcfile>
+ <executable>clamsmtpd</executable>
+ <description>SMTP virus scanner.</description>
+ </service>
+ <additional_files_needed>
+ <item>http://www.pfsense.org/packages/config/clamsmtp.inc</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/bin/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.org/packages/All/clamsmtpd</item>
+ </additional_files_needed>
+ <custom_php_install_command>
+ clamsmtp_install_command();
+ </custom_php_install_command>
+</packagegui>
diff --git a/config/darkstat/darkstat.sh b/config/darkstat/darkstat.sh
new file mode 100644
index 00000000..a7706142
--- /dev/null
+++ b/config/darkstat/darkstat.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+rc_start() {
+ /usr/local/sbin/darkstat --detach
+}
+
+rc_stop() {
+ killall darkstat
+}
+
+case $1 in
+ start)
+ rc_start
+ ;;
+ stop)
+ rc_stop
+ ;;
+ restart)
+ rc_stop
+ rc_start
+ ;;
+esac
diff --git a/config/darkstat/darkstat.xml b/config/darkstat/darkstat.xml
new file mode 100644
index 00000000..7385048d
--- /dev/null
+++ b/config/darkstat/darkstat.xml
@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>Darkstat</name>
+ <version>3.0</version>
+ <title>Diagnostics: Darkstat</title>
+ <menu>
+ <name>Darkstat Settings</name>
+ <tooltiptext>Setup darkstat specific settings</tooltiptext>
+ <section>Diagnostics</section>
+ <url>/pkg_edit.php?xml=darkstat.xml&amp;id=0</url>
+ </menu>
+ <service>
+ <name>darkstat</name>
+ <rcfile>darkstat.sh</rcfile>
+ <executable>darkstat</executable>
+ </service>
+ <tabs>
+ <tab>
+ <text>Darkstat Settings</text>
+ <url>/pkg_edit.php?xml=darkstat.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Access Darkstat</text>
+ <url>http://$myurl:666</url>
+ </tab>
+ </tabs>
+ <fields>
+ <field>
+ <fielddescr>Interface</fielddescr>
+ <fieldname>interface_array</fieldname>
+ <type>interfaces_selection</type>
+ <size>3</size>
+ <value>lan</value>
+ <multiple>true</multiple>
+ </field>
+ </fields>
+ <custom_php_global_functions>
+ function sync_package_darkstat() {
+ $first = 0;
+ foreach($_POST['interface_array'] as $iface) {
+ $if = convert_friendly_interface_to_real_interface_name($iface);
+ if($if) {
+ $ifaces_final .= " -i " . $if;
+ $first = 1;
+ }
+ }
+ $start = "/usr/local/sbin/darkstat" . $ifaces_final . " -p 666 ";
+ write_rcfile(array(
+ "file" => "darkstat.sh",
+ "start" => $start,
+ "stop" => "/usr/bin/killall darkstat"
+ )
+ );
+ start_service("darkstat");
+ }
+ </custom_php_global_functions>
+ <custom_add_php_command>
+ sync_package_darkstat();
+ </custom_add_php_command>
+ <custom_php_resync_config_command>
+ sync_package_darkstat();
+ </custom_php_resync_config_command>
+</packagegui>
diff --git a/config/dashboard/dashboard.inc b/config/dashboard/dashboard.inc
new file mode 100644
index 00000000..b147632e
--- /dev/null
+++ b/config/dashboard/dashboard.inc
@@ -0,0 +1,38 @@
+<?php
+
+function dashboard_install() {
+ global $g, $config;
+ assign_privs();
+ if(!file_exists("/usr/local/www/index.php.before_dashboard")) {
+ /* backup the pre-dashboard index.php file */
+ mwexec("cp /usr/local/www/index.php /usr/local/www/index.php.before_dashboard");
+ /* backup the pre-dashboard fbegin.inc file */
+ mwexec("cp /usr/local/www/fbegin.inc /usr/local/www/fbegin.inc.before_dashboard");
+ }
+ mwexec("tar xzvpf /usr/local/pkg/widgets.tgz -C /");
+ assign_privs();
+}
+
+function dashboard_deinstall() {
+ global $g, $config;
+ assign_privs();
+ if(file_exists("/usr/local/www/index.php.before_dashboard")) {
+ /* restore the files prior to the dashboard package installation */
+ mwexec("cp /usr/local/www/index.php.before_dashboard /usr/local/www/index.php");
+ mwexec("cp /usr/local/www/fbegin.inc.before_dashboard /usr/local/www/fbegin.inc");
+ }
+ assign_privs();
+}
+
+function assign_privs() {
+ mwexec("chown root:wheel /usr/local/www/index.php");
+ mwexec("chown root:wheel /usr/local/www/fbegin.php");
+ mwexec("chown root:wheel /usr/local/www/graph_cpu.php");
+ mwexec("chown root:wheel /usr/local/www/stats.php");
+ mwexec("chmod a+rw /usr/local/www/index.php");
+ mwexec("chmod a+rw /usr/local/www/fbegin.php");
+ mwexec("chmod a+rw /usr/local/www/graph_cpu.php");
+ mwexec("chmod a+rw /usr/local/www/stats.php");
+}
+
+?> \ No newline at end of file
diff --git a/config/dashboard/dashboard.xml b/config/dashboard/dashboard.xml
new file mode 100644
index 00000000..a0e1b35a
--- /dev/null
+++ b/config/dashboard/dashboard.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>dashboard</name>
+ <version>0.2</version>
+ <title>Dashboard</title>
+ <include_file>/usr/local/pkg/dashboard.inc</include_file>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>077</chmod>
+ <item>http://www.pfsense.com/packages/config/dashboard/dashboard.inc</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>077</chmod>
+ <item>http://www.pfsense.com/packages/config/dashboard/binaries/widgets.tgz</item>
+ </additional_files_needed>
+ <custom_php_install_command>
+ dashboard_install();
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ dashboard_deinstall();
+ </custom_php_deinstall_command>
+</packagegui>
+
+
+
diff --git a/config/developers/developers.xml b/config/developers/developers.xml
new file mode 100644
index 00000000..b6850d54
--- /dev/null
+++ b/config/developers/developers.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>developers</name>
+ <version>0.1</version>
+ <title>Developers</title>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>077</chmod>
+ <item>http://www.pfsense.com/~sullrich/extra/developer_pkg.tgz</item>
+ </additional_files_needed>
+ <custom_php_install_command>
+ update_status("Extracing Developers package contents... This will take a bit!");
+ mwexec_bg("cd / &amp;&amp; tar xzpfU /usr/local/pkg/developer_pkg.tgz");
+ </custom_php_install_command>
+</packagegui>
+
+
+ \ No newline at end of file
diff --git a/config/diag_states_pt/diag_new_states.php b/config/diag_states_pt/diag_new_states.php
new file mode 100644
index 00000000..e0f1abec
--- /dev/null
+++ b/config/diag_states_pt/diag_new_states.php
@@ -0,0 +1,381 @@
+<?php
+/*
+ diag_new_staes.php
+ Copyright (C) 2002 Paul Taylor
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require_once("guiconfig.inc");
+
+$pgtitle = "Diagnostics: Show States";
+
+
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+
+function displayIP($ip, $col) {
+
+ global $viewPassThru;
+
+ switch ($col) {
+ case 'srcip':
+ if ($_GET['sfilter']) {
+ if ($_GET['sfilter'] == $ip)
+ return $ip;
+ }
+ else {
+ return '<a href="?sfilter='.$ip.$viewPassThru.'">'. $ip .'</a>';
+ }
+ break;
+
+ case 'dstip':
+ if ($_GET['dfilter']) {
+ if ($_GET['dfilter'] == $ip)
+ return $ip;
+ }
+ else {
+ return '<a href="?dfilter='.$ip.$viewPassThru.'">'. $ip .'</a>';
+ }
+ break;
+ }
+
+}
+
+function sortOrder($column) {
+
+ if ($_GET['order'] == $column) {
+ if ($_GET['sort'] == 'des')
+ return "&sort=asc";
+ return "&sort=des";
+ }
+ else
+ return "&sort=asc";
+}
+
+function stripPort($ip, $showPort = false) {
+ if (!$showPort) {
+ if (strpos($ip,':') > 0)
+ return substr($ip,0,strpos($ip,":"));
+ else
+ return ($ip);
+ }
+ else {
+ if (strpos($ip,':') > 0) {
+ return substr($ip,(strpos($ip,":")+1));
+ }
+ else
+ return "&nbsp;";
+ }
+}
+
+// sfilter and dfilter allow setting of source and dest IP filters
+// on the output. $filterPassThru allows these source and dest
+// filters to be passed on in the column sorting links.
+if (($_GET['sfilter']) or ($_GET['dfilter'])) {
+
+ $filter = '';
+ if ($_GET['sfilter']) {
+ if (is_ipaddr($_GET['sfilter'])) {
+ $sfilter = $_GET['sfilter'];
+ $filterPassThru = '&sfilter=' . $_GET['sfilter'];
+ }
+ else
+ unset ($_GET['sfilter']);
+ }
+ if ($_GET['dfilter']) {
+ if (is_ipaddr($_GET['dfilter'])) {
+ $dfilter = $_GET['dfilter'];
+ $filterPassThru = '&dfilter=' . $_GET['dfilter'];
+ }
+ else
+ unset ($_GET['dfilter']);
+ }
+}
+
+$dataRows = 300;
+
+$rawdata = array();
+
+/* get our states */
+// 1 2 3 4 5 6 7 8
+//12345678901234567890123456789012345678901234567890123456789012345678901234567890
+// [3] => PR D SRC DEST STATE AGE EXP PKTS BYTES
+// [4] => icmp O 192.168.112.94:16734 192.168.112.1:0 0:0 12 2 10 840
+// [5] => tcp I 192.168.111.99:61221 192.168.111.150:22 4:4 710 86399 726 242K
+// -w 132 sets width of data to 132
+// $dataRows defaults to 300 for embedded hardware
+exec("echo q | /usr/local/sbin/pftop -w 132 $dataRows",$rawdata);
+
+// exporting TERM set to nothing gets you a "dumb" term. echo q to pftop makes it
+// quit out after displaying the first page of data.
+
+// Get top line with total state data
+$topDataLine = $rawdata[2];
+//pfTop: Up State 1-5/5, View: default, Order: none
+$slashPos = strpos($topDataLine,'/') + 1;
+$commaPos = strpos($topDataLine,',');
+if (($slashPos > 1) and ($commaPos > 1)) {
+ $totalStates = substr($topDataLine,$slashPos,($commaPos - $slashPos));
+} else $totalStates = 0;
+
+// Get rid of the header data
+unset($rawdata[0],$rawdata[1],$rawdata[2],$rawdata[3]);
+
+if (isset($rawdata)) {
+ $count = 0;
+ foreach ($rawdata as $line) {
+ if (!strlen(trim($line)) < 70)
+ {
+//PR DIR SRC DEST STATE AGE EXP PKTS BYTES
+//tcp Out 192.168.111.99:62831 66.84.12.81:110 FIN_WAIT_2:FIN_WAIT_2 00:01:20 00:00:11 28 1933
+// 0 1 2 3 4 5 6 7 8
+ $split = preg_split("/\s+/", trim($line));
+
+ $data[$count]['protocol'] = $split[0];
+ $data[$count]['dir'] = strtolower($split[1]);
+ $srcTmp = $split[2];
+ $data[$count]['srcip'] = stripPort($srcTmp);
+ $data[$count]['srcport'] = stripPort($srcTmp,true);
+ $dstTmp = $split[3];
+ $data[$count]['expire'] = $split[6];
+ $data[$count]['dstip'] = stripPort($dstTmp);
+ $data[$count]['dstport'] = stripPort($dstTmp,true);
+ $data[$count]['packets'] = $split[7];
+ $data[$count]['bytes'] = $split[8];
+ $count++;
+ }
+ }
+ // Clear the statistics snapshot files, which track the packets and bytes of connections
+ if (isset($_GET['clear']))
+ {
+ if (file_exists('/tmp/packets'))
+ unlink('/tmp/packets');
+ if (file_exists('/tmp/bytes'))
+ unlink('/tmp/bytes');
+
+ // Redirect so we don't hit "clear" every time we refresh the screen.
+ header("Location: diag_new_states.php?".$filterPassThru);
+ exit;
+ }
+
+ // Create a new set of stats snapshot files
+ if (isset($_GET['new']))
+ {
+ $packets = array();
+ $bytes = array();
+
+ // Create variables to let us later quickly access this data
+ if (is_array($data)) {
+ foreach ($data as $row) {
+ $packets[$row['srcip']][$row['srcport']][$row['dstip']][$row['dstport']][$row['protocol']] = $row['packets'];
+ $bytes[$row['srcip']][$row['srcport']][$row['dstip']][$row['dstport']][$row['protocol']] = $row['bytes'];
+ }
+ }
+
+ // Write the files out
+ writeStats("packets",$packets);
+ writeStats("bytes",$bytes);
+
+ // If we're in view mode, pass that on.
+ if (isset($_GET['view']))
+ $filterPassThru .= "&view=1";
+
+ // Redirect so we don't hit "new" every time we refresh the screen.
+ header("Location: diag_new_states.php?&order=bytes&sort=des".$filterPassThru);
+ exit;
+ }
+
+ // View the delta from the last snapshot against the current data.
+ if (isset($_GET['view']))
+ {
+
+ // Read the stats data files
+ readStats("packets",$packets);
+ readStats("bytes",$bytes);
+
+ if (is_array($data)) {
+ foreach ($data as $key => $row) {
+ if (isset($packets[$row['srcip']][$row['srcport']][$row['dstip']][$row['dstport']][$row['protocol']]))
+ {
+ if (isset($bytes[$row['srcip']][$row['srcport']][$row['dstip']][$row['dstport']][$row['protocol']]))
+ {
+ $tempPackets = $data[$key]['packets'] - $packets[$row['srcip']][$row['srcport']][$row['dstip']][$row['dstport']][$row['protocol']];
+ $tempBytes = $data[$key]['bytes'] - $bytes[$row['srcip']][$row['srcport']][$row['dstip']][$row['dstport']][$row['protocol']];
+ if (($tempPackets > -1) && ($tempBytes > -1))
+ {
+ $data[$key]['packets'] = $tempPackets;
+ $data[$key]['bytes'] = $tempBytes;
+ }
+ }
+ }
+
+ }
+ }
+
+ $filterPassThru .= "&view=1";
+ $viewPassThru = "&view=1";
+ }
+
+ // Sort it by the selected order
+ if ($_GET['order']) {
+ natsort2d($data,$_GET['order']);
+ if ($_GET['sort'])
+ {
+ if ($_GET['sort'] == "des")
+ $data = array_reverse($data);
+ }
+ }
+}
+
+function natsort2d( &$arrIn, $index = null )
+{
+
+ $arrTemp = array();
+ $arrOut = array();
+
+ if (is_array($arrIn)) {
+ foreach ( $arrIn as $key=>$value ) {
+
+ reset($value);
+ $arrTemp[$key] = is_null($index)
+ ? current($value)
+ : $value[$index];
+ }
+ }
+
+ natsort($arrTemp);
+
+ foreach ( $arrTemp as $key=>$value ) {
+ $arrOut[$key] = $arrIn[$key];
+ }
+
+ $arrIn = $arrOut;
+
+}
+
+function writeStats($fname, &$data) {
+ $fname = "/tmp/" . $fname;
+ if (file_exists($fname))
+ unlink($fname);
+ $file = fopen($fname, 'a');
+ fwrite($file, serialize($data));
+ fclose($file);
+}
+
+function readStats($fname, &$data) {
+ $fname = "/tmp/" . $fname;
+ if (file_exists($fname))
+ {
+ $file = fopen($fname,'r');
+ $data = unserialize(fread($file, filesize($fname)));
+ fclose($file);
+ }
+}
+
+// Get timestamp of snapshot file, if it exists, for display later.
+if (!(file_exists('/tmp/packets'))) {
+ $lastSnapshot = "Never";
+}
+else {
+ $lastSnapshot = strftime("%m/%d/%y %H:%M:%S",filectime('/tmp/packets'));
+}
+// The next include must be here because we use redirection above
+include("head.inc");
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<script src="/javascript/scriptaculous/prototype.js" type="text/javascript"></script>
+<script src="/javascript/scriptaculous/scriptaculous.js" type="text/javascript"></script>
+<script src="/javascript/sorttable.js" type="text/javascript"></script>
+
+<?php include("fbegin.inc"); ?>
+<p class="pgtitle"><?=$pgtitle?></p>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="listhdrr" colspan="9">Statistics snapshot control</td>
+ </tr>
+ <tr>
+ <?php if (($lastSnapshot!='Never') && (!isset($_GET['view']))) :?>
+ <td class="listlr"><a href="?view=1&order=bytes&sort=des<?=$filterPassThru;?>">View delta</a></td>
+ <td class="listr"><a href="?new=1<?=$filterPassThru;?>">Start new</a></td>
+ <td class="listr"><a href="?clear=1">Clear snapshot</a></td>
+ <td class="listr" colspan="6" align="right">Last statistics snapshot: <?=$lastSnapshot;?></td>
+ <?php endif; ?>
+ <?php if (($lastSnapshot!='Never') && (isset($_GET['view']))) :?>
+ <td class="listlr"><a href="?new=1<?=$filterPassThru;?>">Start new</a></td>
+ <td class="listr"><a href="?clear=1">Clear</a></td>
+ <td class="listr" colspan="7" align="right"><span class="red">Viewing delta of statistics snapshot: <?=$lastSnapshot;?></span></td>
+ <?php endif; ?>
+ <?php if ($lastSnapshot=='Never') :?>
+ <td class="listlr"><a href="?new=1<?=$filterPassThru;?>">Start new</a></td>
+ <td class="listr" colspan="8" align="right">Last statistics snapshot: <?=$lastSnapshot;?></td>
+ <?php endif; ?>
+ </tr>
+ <tr>
+ <td colspan="8">&nbsp;</td>
+ </tr>
+ <tr>
+ <td class="listhdrr"><a href="?order=srcip<?=sortOrder('srcip');echo $filterPassThru;?>">Source</a></td>
+ <td class="listhdrr"><a href="?order=srcport<?=sortOrder('srcport');echo $filterPassThru;?>">Port</a></td>
+ <td class="listhdrr"><a href="?order=dir<?=sortOrder('dir');echo $filterPassThru;?>">Dir</a></td>
+ <td class="listhdrr"><a href="?order=dstip<?=sortOrder('dstip');echo $filterPassThru;?>">Destination</a></td>
+ <td class="listhdrr"><a href="?order=dstport<?=sortOrder('dstport');echo $filterPassThru;?>">Port</a></td>
+ <td class="listhdrr"><a href="?order=protocol<?=sortOrder('protocol');echo $filterPassThru;?>">Protocol</a></td>
+ <td class="listhdrr" align="right"><a href="?order=packets<?=sortOrder('packets');echo $filterPassThru;?>">Packets</a></td>
+ <td class="listhdrr" align="right"><a href="?order=bytes<?=sortOrder('bytes');echo $filterPassThru;?>">Bytes</a></td>
+ <td class="listhdr" align="right"><a href="?order=expire<?=sortOrder('expire');echo $filterPassThru;?>">Expires</a></td>
+ <td class="list"></td>
+ </tr>
+<?php $count = 0;
+if (is_array($data)): foreach ($data as $entry):
+ if ((!isset($sfilter) and (!isset($dfilter))) or
+ ((isset($sfilter)) and ($entry['srcip']==$sfilter)) or
+ ((isset($dfilter)) and ($entry['dstip']==$dfilter))):
+ ?>
+ <tr>
+ <td class="listlr"><?=displayIP($entry['srcip'],'srcip');?></td>
+ <td class="listr"><?=$entry['srcport'];?></td>
+ <td class="listr"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_<?=$entry['dir'];?>.gif" width="11" height="11" style="margin-top: 2px"></td>
+ <td class="listr"><?=displayIP($entry['dstip'],'dstip');?></td>
+ <td class="listr"><?=$entry['dstport'];?></td>
+ <td class="listr"><?=$entry['protocol'];?></td>
+ <td class="listr" align="right"><?=$entry['packets'];?></td>
+ <td class="listr" align="right"><?=$entry['bytes'];?></td>
+ <td class="listr" align="right"><?=$entry['expire'];?></td>
+ </tr>
+<?php $count++; endif; endforeach; endif; ?>
+</table>
+<br><strong>Firewall connection states displayed: <?=$count;?>/<?=$totalStates;?></strong>
+<?php if ($filterPassThru): ?>
+<p>
+<form action="diag_new_states.php" method="GET">
+<input type="hidden" name="order" value="bytes">
+<input type="hidden" name="sort" value="des">
+<input type="submit" class="formbtn" value="Unfilter View">
+</form>
+</p>
+<?php endif; ?>
+<?php include("fend.inc"); ?>
+</body>
+</html> \ No newline at end of file
diff --git a/config/diag_states_pt/diag_new_states.xml b/config/diag_states_pt/diag_new_states.xml
new file mode 100644
index 00000000..b8ea9dc3
--- /dev/null
+++ b/config/diag_states_pt/diag_new_states.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>diag_new_states</name>
+ <version>0.2</version>
+ <title>Diagnostics: States New</title>
+ <menu>
+ <name>States New</name>
+ <tooltiptext>States by Paul Taylor</tooltiptext>
+ <section>Diagnostics</section>
+ <url>diag_new_states.php</url>
+ </menu>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.org/packages/config/diag_states_pt/diag_new_states.php</item>
+ </additional_files_needed>
+ <custom_php_deinstall_command>
+ mwexec("rm /usr/local/www/diag_new_states.php");
+ </custom_php_deinstall_command>
+</packagegui>
diff --git a/config/doorman.xml b/config/doorman.xml
new file mode 100644
index 00000000..64f35087
--- /dev/null
+++ b/config/doorman.xml
@@ -0,0 +1,157 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>doorman</name>
+ <version>none</version>
+ <title>doorman: Settings</title>
+ <aftersaveredirect>pkg_edit.php?xml=doorman.xml&amp;id=0</aftersaveredirect>
+ <menu>
+ <name>doorman</name>
+ <tooltiptext>Modify doorman settings and users.</tooltiptext>
+ <section>Services</section>
+ <configfile>doorman.xml</configfile>
+ <url>/pkg_edit.php?xml=doorman.xml&amp;id=0</url>
+ </menu>
+ <service>
+ <name>doorman</name>
+ <rcfile>doorman.sh</rcfile>
+ <executable>doormand</executable>
+ </service>
+ <tabs>
+ <tab>
+ <text>Settings</text>
+ <url>/pkg_edit.php?xml=doorman.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Users</text>
+ <url>/pkg.php?xml=doormanusers.xml</url>
+ </tab>
+ </tabs>
+ <configpath>installedpackages->package->$packagename->configuration->settings</configpath>
+ <additional_files_needed>
+ <item>http://www.pfsense.com/packages/config/doormanusers.xml</item>
+ </additional_files_needed>
+ <fields>
+ <field>
+ <fielddescr>Initial connection timeout</fielddescr>
+ <fieldname>initdelay</fieldname>
+ <description>Enter the desired number of *microseconds* to wait for a complete 3-way handshake between the client and requested service. (default one half second)</description>
+ <type>input</type>
+ <value>500000</value>
+ </field>
+ <field>
+ <fielddescr>Connection check interval</fielddescr>
+ <fieldname>checkdelay</fieldname>
+ <description>Enter the desired number of *seconds* between checking for broken connections. (default 5 seconds)</description>
+ <type>input</type>
+ <value>5</value>
+ </field>
+ <field>
+ <fielddescr>Connection initiation timeout</fielddescr>
+ <fieldname>inittimeout</fieldname>
+ <description>Enter the desired number of *seconds* to wait for a connection to be established after a successful knock.i (default 10 seconds)</description>
+ <type>input</type>
+ <value>10</value>
+ </field>
+ <!--
+ <field>
+ <fielddescr>Listening interface(s)</fielddescr>
+ <fieldname>interface</fieldname>
+ <description>Select the interfaces that doormand should listen on. (default WAN)</description>
+ <value>wan</value>
+ <type>interfaces_selection</type>
+ </field>
+ -->
+ <field>
+ <fielddescr>Listening port</fielddescr>
+ <fieldname>port</fieldname>
+ <description>Enter the port that doormand should listen on. (default 1001)</description>
+ <type>input</type>
+ <value>1001</value>
+ </field>
+ </fields>
+ <custom_php_global_functions>
+ function sync_package_doorman() {
+ conf_mount_rw();
+ config_lock();
+ global $config;
+ $fout = fopen("/usr/local/etc/doormand/doormand.cf","w");
+ fwrite($fout, "# This file was automatically generated by the pfSense\n# package management system.\n\n");
+ /*
+ * $int = convert_friendly_interface_to_real_interface_name($_POST['interface']);
+ * fwrite($fout, "interface " . $int . "\n");
+ */
+ fwrite($fout, "interface " . $config['interfaces']['wan']['if'] . "\n");
+ if($_POST['port'] != "") fwrite($fout, "port " . $_POST['port'] . "\n");
+ if($_POST['inittimeout'] != "") fwrite($fout, "waitfor " . $_POST['inittimeout'] . "\n");
+ if($_POST['initdelay'] != "") fwrite($fout, "connection_delay_1 " . $_POST['initdelay'] . "\n");
+ if($_POST['checkdelay'] != "") fwrite($fout, "connection_delay_2 " . $_POST['checkdelay'] . "\n");
+ fwrite($fout, "pidfile /var/run/doormand.pid\nlogfile /var/log/messages\nloglevel NOTICE\nguestlist /usr/local/etc/doormand/guestlist\nfirewall-add /usr/local/etc/doormand/pfctl_add\nfirewall-del /usr/local/etc/doormand/pfctl_del\ntag-queue-length 100000\ntag-queue /var/doorman_tag_queue\ntag-db /var/doorman_tag_db.db\n");
+ fwrite($fout, "hash-archive-size 50000\n");
+ fwrite($fout, "hash-archive /tmp/doormand.hash-archive\n");
+ fclose($fout);
+ restart_service("doorman");
+ conf_mount_ro();
+ config_unlock();
+ }
+ </custom_php_global_functions>
+ <custom_add_php_command>
+ sync_package_doorman();
+ </custom_add_php_command>
+ <custom_php_install_command>
+ global $config;
+ $start = "/usr/local/sbin/doormand -D &amp;";
+ write_rcfile(array(
+ "file" => "doorman.sh",
+ "start" => $start,
+ "stop" => "/usr/bin/killall doormand"
+ )
+ );
+ </custom_php_install_command>
+</packagegui>
+
diff --git a/config/doormanusers.xml b/config/doormanusers.xml
new file mode 100644
index 00000000..a1887b28
--- /dev/null
+++ b/config/doormanusers.xml
@@ -0,0 +1,142 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>doormanusers</name>
+ <version>none</version>
+ <title>Doorman: Users</title>
+ <menu>
+ <name>Doorman</name>
+ <tooltiptext>Modify doormand settings and users.</tooltiptext>
+ <section>Services</section>
+ <configfile>doorman.xml</configfile>
+ <url>/pkg_edit.php?xml=doorman.xml&amp;id=0</url>
+ </menu>
+ <tabs>
+ <tab>
+ <text>Settings</text>
+ <url>/pkg_edit.php?xml=doorman.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Users</text>
+ <url>/pkg.php?xml=doormanusers.xml</url>
+ <active/>
+ </tab>
+ </tabs>
+ <configpath>installedpackages->package->$packagename->configuration->settings</configpath>
+ <adddeleteeditpagefields>
+ <columnitem>
+ <fielddescr>Username</fielddescr>
+ <fieldname>username</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Ports</fielddescr>
+ <fieldname>ports</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Addresses</fielddescr>
+ <fieldname>addresses</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Description</fielddescr>
+ <fieldname>description</fieldname>
+ </columnitem>
+ </adddeleteeditpagefields>
+ <fields>
+ <field>
+ <fielddescr>Username</fielddescr>
+ <fieldname>username</fieldname>
+ <description>Enter the username here. This may be up to 32 characters in length.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Password</fielddescr>
+ <fieldname>password</fieldname>
+ <description>Enter the password here. This may be up to 64 characters in length.</description>
+ <type>password</type>
+ </field>
+ <field>
+ <fielddescr>Allowed ports</fielddescr>
+ <fieldname>ports</fieldname>
+ <description>Enter a whitespace-delimited list of the ports or service names *to* which this user may connect.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Allowed addresses</fielddescr>
+ <fieldname>addresses</fieldname>
+ <description>Enter a whitespace-delimited list of the IP addresses or hostnames *from* which this user may connect. Addresses may be unique or expressed as ranges using CIDR notation.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Description</fielddescr>
+ <fieldname>description</fieldname>
+ <description>Enter a description for this user here.</description>
+ <type>input</type>
+ </field>
+ </fields>
+ <custom_php_global_functions>
+ function sync_package_doorman_users() {
+ if ($_POST == "") $_POST = $config['installedpackages']['doormanusers']['config'];
+ conf_mount_rw();
+ config_lock();
+ global $config;
+ $fout = fopen("/usr/local/etc/doormand/guestlist","w");
+ fwrite($fout, "# This file was automatically generated by the pfSense\n# package management system.\n\n");
+ if($config['installedpackages']['doormanusers'])
+ foreach($config['installedpackages']['doormanusers']['config'] as $rowhelper) {
+ fwrite($fout, $rowhelper['username'] . "\t" . $rowhelper['password'] . "\n\t" . $rowhelper['ports'] . "\n\t" . $rowhelper['addresses'] . "\n\n");
+ }
+ fclose($fout);
+ restart_service("doorman");
+ conf_mount_ro();
+ config_unlock();
+ }
+ </custom_php_global_functions>
+ <custom_add_php_command>
+ sync_package_doorman_users();
+ </custom_add_php_command>
+</packagegui>
+
diff --git a/config/dspam/conf.default/config.xml b/config/dspam/conf.default/config.xml
new file mode 100644
index 00000000..4b33662e
--- /dev/null
+++ b/config/dspam/conf.default/config.xml
@@ -0,0 +1,1020 @@
+<?xml version="1.0"?>
+<!-- pfSense default system configuration -->
+<pfsense>
+ <version>2.1</version>
+ <lastchange></lastchange>
+ <theme>nione</theme>
+ <system>
+ <disablenatreflection/>
+ <optimization>normal</optimization>
+ <hostname>nione</hostname>
+ <domain>local</domain>
+ <dnsserver></dnsserver>
+ <dnsallowoverride/>
+ <timezone>Etc/UTC</timezone>
+ <time-update-interval>300</time-update-interval>
+ <timeservers>pool.ntp.org</timeservers>
+ <group>
+ <name>admins</name>
+ <description>System Administrators</description>
+ <scope>system</scope>
+ <pages>ANY</pages>
+ <home>index.php</home>
+ </group>
+ <group>
+ <name>dspam_users</name>
+ <description>DSPAM Users</description>
+ <scope>user</scope>
+ <home>dspam.php</home>
+ <pages>
+ <page>dspam.php</page>
+ <page>wizard.php</page>
+ <page>system_usermanager.php</page>
+ <page>license.php</page>
+ <page>pkg.php</page>
+ <page>pkg_edit.php</page>
+ <page>index.php</page>
+ <page>dspam_alerts.xml</page>
+ <page>dspam.xml</page>
+ <page>dspam-perf.php</page>
+ <page>dspam-prefs.php</page>
+ <page>dspam-train.php</page>
+ <page>dspam-quarantine.php</page>
+ <page>dspam-viewmsg.php</page>
+ <page>dspam-hfragment.php</page>
+ <page>dspam-history.php</page>
+ <page>dspam-analysis-graph.php</page>
+ <page>dspam-analysis.php</page>
+ <page>ifstats.php</page>
+ <page>xmlrpc.php</page>
+ <page>preload.php</page>
+ <page>functions.inc.php</page>
+ <page>javascript.inc.php</page>
+ <page>sajax.class.php</page>
+ </pages>
+ </group>
+ <group>
+ <name>dspam_admins</name>
+ <description>DSPAM Administrators</description>
+ <scope>user</scope>
+ <home>dspam.php</home>
+ <pages>
+ <page>dspam.php</page>
+ <page>dspam_wizard.xml</page>
+ <page>wizard.php</page>
+ <page>system_usermanager.php</page>
+ <page>license.php</page>
+ <page>pkg.php</page>
+ <page>pkg_edit.php</page>
+ <page>index.php</page>
+ <page>status_services.php</page>
+ <page>dspam-admin-prefs.php</page>
+ <page>dspam_alerts.xml</page>
+ <page>dspam.xml</page>
+ <page>dspam-perf.php</page>
+ <page>dspam-prefs.php</page>
+ <page>dspam-train.php</page>
+ <page>dspam-admin-stats.php</page>
+ <page>dspam-admin-graph.php</page>
+ <page>dspam-admin.php</page>
+ <page>dspam-quarantine.php</page>
+ <page>dspam-viewmsg.php</page>
+ <page>dspam-hfragment.php</page>
+ <page>dspam-history.php</page>
+ <page>dspam-analysis-graph.php</page>
+ <page>dspam-analysis.php</page>
+ <page>dspam-settings-algo.php</page>
+ <page>dspam-settings-bmta.php</page>
+ <page>dspam-settings-feat.php</page>
+ <page>dspam-settings-prefs.php</page>
+ <page>dspam-settings-header.php</page>
+ <page>dspam-settings-overr.php</page>
+ <page>dspam-settings-spwd.php</page>
+ <page>dspam-settings-tuser.php</page>
+ <page>dspam-settings.php</page>
+ <page>p3scan-pf-emer.xml</page>
+ <page>p3scan-pf.xml</page>
+ <page>p3scan-pf-msg.xml</page>
+ <page>p3scan-pf-spam.xml</page>
+ <page>p3scan-pf-vir.xml</page>
+ <page>p3scan-pf-transex.xml</page>
+ <page>ifstats.php</page>
+ <page>xmlrpc.php</page>
+ <page>preload.php</page>
+ <page>functions.inc.php</page>
+ <page>javascript.inc.php</page>
+ <page>sajax.class.php</page>
+ </pages>
+ </group>
+ <user>
+ <name>admin</name>
+ <fullname>System Administrator</fullname>
+ <scope>system</scope>
+ <groupname>admins</groupname>
+ <password>$1$pHZLmGLm$rtBJza55tMwVbJNkr0qCz/</password>
+ <priv>
+ <id>lockwc</id>
+ <name>Lock webConfigurator</name>
+ <descr>Indicates whether this user will lock access to the webConfigurator for other users.</descr>
+ </priv>
+ <priv>
+ <id>lock-ipages</id>
+ <name>Lock individual pages</name>
+ <descr>Indicates whether this user will lock individual HTML pages after having accessed a particular page(the lock will be freed if the user leaves or saves the page form).</descr>
+ </priv>
+ <priv>
+ <id>hasshell</id>
+ <name>Has shell access</name>
+ <descr>Indicates whether this user is able to login for example via SSH.</descr>
+ </priv>
+ <priv>
+ <id>isroot</id>
+ <name>Is root user</name>
+ <descr>This user is associated with the UNIX root user (you should associate this privilege only with one single user).</descr>
+ </priv>
+ </user>
+ <user>
+ <name>dspamadm</name>
+ <fullname>DSPAM Administrator</fullname>
+ <scope>user</scope>
+ <groupname>dspam_admins</groupname>
+ <password>$1$utl.fBcK$ZDnGqMSm2fJHi8vxQ6EfT1</password>
+ </user>
+ <webgui>
+ <protocol>http</protocol>
+ <!--
+ <port></port>
+ <certificate></certificate>
+ <private-key></private-key>
+ <noassigninterfaces/>
+ <expanddiags/>
+ <noantilockout></noantilockout>
+ -->
+ </webgui>
+ <!-- <disableconsolemenu/> -->
+ <!-- <disablefirmwarecheck/> -->
+ <!-- <shellcmd></shellcmd> -->
+ <!-- <earlyshellcmd></earlyshellcmd> -->
+ <!-- <harddiskstandby></harddiskstandby> -->
+ </system>
+ <interfaces>
+ <lan>
+ <if>sis0</if>
+ <ipaddr>192.168.1.1</ipaddr>
+ <subnet>24</subnet>
+ <media></media>
+ <mediaopt></mediaopt>
+ <bandwidth>100</bandwidth>
+ <bandwidthtype>Mb</bandwidthtype>
+ <!--
+ <wireless>
+ *see below (opt[n])*
+ </wireless>
+ -->
+ </lan>
+ <wan>
+ <if>sis1</if>
+ <mtu></mtu>
+ <ipaddr>dhcp</ipaddr>
+ <!-- *or* ipv4-address *or* 'pppoe' *or* 'pptp' *or* 'bigpond' -->
+ <subnet></subnet>
+ <gateway></gateway>
+ <blockpriv/>
+ <disableftpproxy/>
+ <dhcphostname></dhcphostname>
+ <media></media>
+ <mediaopt></mediaopt>
+ <bandwidth>100</bandwidth>
+ <bandwidthtype>Mb</bandwidthtype>
+ <!--
+ <wireless>
+ *see below (opt[n])*
+ </wireless>
+ -->
+ </wan>
+ <!--
+ <opt[n]>
+ <enable/>
+ <descr></descr>
+ <if></if>
+ <ipaddr></ipaddr>
+ <subnet></subnet>
+ <media></media>
+ <mediaopt></mediaopt>
+ <bridge>lan|wan|opt[n]</bridge>
+ <wireless>
+ <mode>hostap *or* bss *or* ibss</mode>
+ <ssid></ssid>
+ <channel></channel>
+ <wep>
+ <enable/>
+ <key>
+ <txkey/>
+ <value></value>
+ </key>
+ </wep>
+ </wireless>
+ </opt[n]>
+ -->
+ </interfaces>
+ <!--
+ <vlans>
+ <vlan>
+ <tag></tag>
+ <if></if>
+ <descr></descr>
+ </vlan>
+ </vlans>
+ -->
+ <staticroutes>
+ <!--
+ <route>
+ <interface>lan|opt[n]|pptp</interface>
+ <network>xxx.xxx.xxx.xxx/xx</network>
+ <gateway>xxx.xxx.xxx.xxx</gateway>
+ <descr></descr>
+ </route>
+ -->
+ </staticroutes>
+ <pppoe>
+ <username></username>
+ <password></password>
+ <provider></provider>
+ <!--
+ <ondemand/>
+ <timeout></timeout>
+ -->
+ </pppoe>
+ <pptp>
+ <username></username>
+ <password></password>
+ <local></local>
+ <subnet></subnet>
+ <remote></remote>
+ <!--
+ <ondemand/>
+ <timeout></timeout>
+ -->
+ </pptp>
+ <bigpond>
+ <username></username>
+ <password></password>
+ <authserver></authserver>
+ <authdomain></authdomain>
+ <minheartbeatinterval></minheartbeatinterval>
+ </bigpond>
+ <dyndns>
+ <!-- <enable/> -->
+ <type>dyndns</type>
+ <username></username>
+ <password></password>
+ <host></host>
+ <mx></mx>
+ <!-- <wildcard/> -->
+ </dyndns>
+ <dhcpd>
+ <lan>
+ <enable/>
+ <range>
+ <from>192.168.1.100</from>
+ <to>192.168.1.199</to>
+ </range>
+ <!--
+ <winsserver>xxx.xxx.xxx.xxx</winsserver>
+ <defaultleasetime></defaultleasetime>
+ <maxleasetime></maxleasetime>
+ <gateway>xxx.xxx.xxx.xxx</gateway>
+ <domain></domain>
+ <dnsserver></dnsserver>
+ <next-server></next-server>
+ <filename></filename>
+ -->
+ </lan>
+ <!--
+ <opt[n]>
+ ...
+ </opt[n]>
+ -->
+ <!--
+ <staticmap>
+ <mac>xx:xx:xx:xx:xx:xx</mac>
+ <ipaddr>xxx.xxx.xxx.xxx</ipaddr>
+ <descr></descr>
+ </staticmap>
+ -->
+ </dhcpd>
+ <pptpd>
+ <mode><!-- off *or* server *or* redir --></mode>
+ <redir></redir>
+ <localip></localip>
+ <remoteip></remoteip>
+ <!-- <accounting/> -->
+ <!--
+ <user>
+ <name></name>
+ <password></password>
+ </user>
+ -->
+ </pptpd>
+ <ovpn>
+ <!--
+ <server>
+ <enable/>
+ <ca_cert></ca_cert>
+ <srv_cert></srv_cert>
+ <srv_key></srv_key>
+ <dh_param></dh_param>
+ <verb></verb>
+ <tun_iface></tun_iface>
+ <port></port>
+ <bind_iface></bind_iface>
+ <cli2cli/>
+ <maxcli></maxcli>
+ <prefix></prefix>
+ <ipblock></ipblock>
+ <crypto></crypto>
+ <dupcn/>
+ <psh_options>
+ <redir></redir>
+ <redir_loc></redir_loc>
+ <rte_delay></rte_delay>
+ <ping></ping>
+ <pingrst></pingrst>
+ <pingexit></pingexit>
+ <inact></inact>
+ </psh_options>
+ </server>
+ <client>
+ <tunnel></tunnel>
+ <ca_cert></ca_cert>
+ <cli_cert></cli_cert>
+ <cli_key></cli_key>
+ <type></type>
+ <tunnel>
+ <if></if>
+ <proto></proto>
+ <cport></cport>
+ <saddr></saddr>
+ <sport></sport>
+ <crypto></crypto>
+ </tunnel>
+ </client>
+ -->
+ </ovpn>
+ <dnsmasq>
+ <enable/>
+ <!--
+ <hosts>
+ <host></host>
+ <domain></domain>
+ <ip></ip>
+ <descr></descr>
+ </hosts>
+ -->
+ </dnsmasq>
+ <snmpd>
+ <!-- <enable/> -->
+ <syslocation></syslocation>
+ <syscontact></syscontact>
+ <rocommunity>public</rocommunity>
+ </snmpd>
+ <diag>
+ <ipv6nat>
+ <!-- <enable/> -->
+ <ipaddr></ipaddr>
+ </ipv6nat>
+ </diag>
+ <bridge>
+ <!-- <filteringbridge/> -->
+ </bridge>
+ <syslog>
+ <!--
+ <reverse/>
+ <enable/>
+ <remoteserver>xxx.xxx.xxx.xxx</remoteserver>
+ <filter/>
+ <dhcp/>
+ <system/>
+ <nologdefaultblock/>
+ -->
+ </syslog>
+ <!--
+ <captiveportal>
+ <enable/>
+ <interface>lan|opt[n]</interface>
+ <idletimeout>minutes</idletimeout>
+ <timeout>minutes</timeout>
+ <page>
+ <htmltext></htmltext>
+ <errtext></errtext>
+ </page>
+ <httpslogin/>
+ <httpsname></httpsname>
+ <certificate></certificate>
+ <private-key></private-key>
+ <redirurl></redirurl>
+ <radiusip></radiusip>
+ <radiusport></radiusport>
+ <radiuskey></radiuskey>
+ <nomacfilter/>
+ </captiveportal>
+ -->
+ <nat>
+ <ipsecpassthru>
+ <enable/>
+ </ipsecpassthru>
+ <!--
+ <rule>
+ <interface></interface>
+ <external-address></external-address>
+ <protocol></protocol>
+ <external-port></external-port>
+ <target></target>
+ <local-port></local-port>
+ <descr></descr>
+ </rule>
+ -->
+ <!--
+ <onetoone>
+ <interface></interface>
+ <external>xxx.xxx.xxx.xxx</external>
+ <internal>xxx.xxx.xxx.xxx</internal>
+ <subnet></subnet>
+ <descr></descr>
+ </onetoone>
+ -->
+ <!--
+ <advancedoutbound>
+ <enable/>
+ <rule>
+ <interface></interface>
+ <source>
+ <network>xxx.xxx.xxx.xxx/xx</network>
+ </source>
+ <destination>
+ <not/>
+ <any/>
+ *or*
+ <network>xxx.xxx.xxx.xxx/xx</network>
+ </destination>
+ <target>xxx.xxx.xxx.xxx</target>
+ <descr></descr>
+ </rule>
+ </advancedoutbound>
+ -->
+ <!--
+ <servernat>
+ <ipaddr></ipaddr>
+ <descr></descr>
+ </servernat>
+ -->
+ </nat>
+ <filter>
+ <!-- <tcpidletimeout></tcpidletimeout> -->
+ <rule>
+ <type>pass</type>
+ <descr>Default LAN -&gt; any</descr>
+ <interface>lan</interface>
+ <source>
+ <network>lan</network>
+ </source>
+ <destination>
+ <any/>
+ </destination>
+ </rule>
+ <!-- rule syntax:
+ <rule>
+ <disabled/>
+ <type>pass|block|reject</type>
+ <descr>...</descr>
+ <interface>lan|opt[n]|wan|pptp</interface>
+ <protocol>tcp|udp|tcp/udp|...</protocol>
+ <icmptype></icmptype>
+ <source>
+ <not/>
+
+ <address>xxx.xxx.xxx.xxx(/xx) or alias</address>
+ *or*
+ <network>lan|opt[n]|pptp</network>
+ *or*
+ <any/>
+
+ <port>a[-b]</port>
+ </source>
+ <destination>
+ *same as for source*
+ </destination>
+ <frags/>
+ <log/>
+ </rule>
+ -->
+ </filter>
+ <shaper>
+ <!-- <enable/> -->
+ <!-- <schedulertype>hfsc</schedulertype> -->
+ <!-- rule syntax:
+ <rule>
+ <disabled/>
+ <descr></descr>
+
+ <targetpipe>number (zero based)</targetpipe>
+ *or*
+ <targetqueue>number (zero based)</targetqueue>
+
+ <interface>lan|wan|opt[n]|pptp</interface>
+ <protocol>tcp|udp</protocol>
+ <direction>in|out</direction>
+ <source>
+ <not/>
+
+ <address>xxx.xxx.xxx.xxx(/xx)</address>
+ *or*
+ <network>lan|opt[n]|pptp</network>
+ *or*
+ <any/>
+
+ <port>a[-b]</port>
+ </source>
+ <destination>
+ *same as for source*
+ </destination>
+
+ <iplen>from[-to]</iplen>
+ <iptos>(!)lowdelay,throughput,reliability,mincost,congestion</iptos>
+ <tcpflags>(!)fin,syn,rst,psh,ack,urg</tcpflags>
+ </rule>
+ <pipe>
+ <descr></descr>
+ <bandwidth></bandwidth>
+ <delay></delay>
+ <mask>source|destination</mask>
+ </pipe>
+ <queue>
+ <descr></descr>
+ <targetpipe>number (zero based)</targetpipe>
+ <weight></weight>
+ <mask>source|destination</mask>
+ </queue>
+ -->
+ </shaper>
+ <ipsec>
+ <preferredoldsa/>
+ <!-- <enable/> -->
+ <!-- syntax:
+ <tunnel>
+ <disabled/>
+ <auto/>
+ <descr></descr>
+ <interface>lan|wan|opt[n]</interface>
+ <local-subnet>
+ <address>xxx.xxx.xxx.xxx(/xx)</address>
+ *or*
+ <network>lan|opt[n]</network>
+ </local-subnet>
+ <remote-subnet>xxx.xxx.xxx.xxx/xx</remote-subnet>
+ <remote-gateway></remote-gateway>
+ <p1>
+ <mode></mode>
+ <myident>
+ <myaddress/>
+ *or*
+ <address>xxx.xxx.xxx.xxx</address>
+ *or*
+ <fqdn>the.fq.dn</fqdn>
+ </myident>
+ <encryption-algorithm></encryption-algorithm>
+ <hash-algorithm></hash-algorithm>
+ <dhgroup></dhgroup>
+ <lifetime></lifetime>
+ <pre-shared-key></pre-shared-key>
+ </p1>
+ <p2>
+ <protocol></protocol>
+ <encryption-algorithm-option></encryption-algorithm-option>
+ <hash-algorithm-option></hash-algorithm-option>
+ <pfsgroup></pfsgroup>
+ <lifetime></lifetime>
+ </p2>
+ </tunnel>
+ <mobileclients>
+ <enable/>
+ <p1>
+ <mode></mode>
+ <myident>
+ <myaddress/>
+ *or*
+ <address>xxx.xxx.xxx.xxx</address>
+ *or*
+ <fqdn>the.fq.dn</fqdn>
+ </myident>
+ <encryption-algorithm></encryption-algorithm>
+ <hash-algorithm></hash-algorithm>
+ <dhgroup></dhgroup>
+ <lifetime></lifetime>
+ </p1>
+ <p2>
+ <protocol></protocol>
+ <encryption-algorithm-option></encryption-algorithm-option>
+ <hash-algorithm-option></hash-algorithm-option>
+ <pfsgroup></pfsgroup>
+ <lifetime></lifetime>
+ </p2>
+ </mobileclients>
+ <mobilekey>
+ <ident></ident>
+ <pre-shared-key></pre-shared-key>
+ </mobilekey>
+ -->
+ </ipsec>
+ <aliases>
+ <!--
+ <alias>
+ <name></name>
+ <address>xxx.xxx.xxx.xxx(/xx)</address>
+ <descr></descr>
+ </alias>
+ -->
+ </aliases>
+ <proxyarp>
+ <!--
+ <proxyarpnet>
+ <network>xxx.xxx.xxx.xxx/xx</network>
+ *or*
+ <range>
+ <from>xxx.xxx.xxx.xxx</from>
+ <to>xxx.xxx.xxx.xxx</to>
+ </range>
+ </proxyarpnet>
+ -->
+ </proxyarp>
+ <wol>
+ <!--
+ <wolentry>
+ <interface>lan|opt[n]</interface>
+ <mac>xx:xx:xx:xx:xx:xx</mac>
+ <descr></descr>
+ </wolentry>
+ -->
+ </wol>
+ <installedpackages>
+ <dspam>
+ <config>
+ <!-- ============================================ -->
+ <!-- == Database Settings == -->
+ <!-- ============================================ -->
+ <storage-driver>mysql</storage-driver>
+ <dbsettings>
+ <mysql-server>/tmp/mysql.sock</mysql-server>
+ <mysql-port />
+ <mysql-user>dspam</mysql-user>
+ <mysql-password>dspam</mysql-password>
+ <mysql-database>dspam</mysql-database>
+ <mysql-ccache>10</mysql-ccache>
+ <mysql-compress>yes</mysql-compress>
+ <mysql-uid>yes</mysql-uid>
+ </dbsettings>
+ <!-- ============================================ -->
+ <!-- == Delivery Settings == -->
+ <!-- ============================================ -->
+ <tdelivery-agent>mail</tdelivery-agent>
+ <tcpip-delivery>yes</tcpip-delivery>
+ <tcpip-delivery-host>192.168.1.6</tcpip-delivery-host>
+ <tcpip-delivery-port>24</tcpip-delivery-port>
+ <tcpip-delivery-ident>localhost</tcpip-delivery-ident>
+ <tcpip-delivery-proto>smtp</tcpip-delivery-proto>
+ <delivery-onfail>error</delivery-onfail>
+ <!-- ============================================ -->
+ <!-- == DSPAM Privileges == -->
+ <!-- ============================================ -->
+ <tuser>
+ <name>root</name>
+ <descr>root desc</descr>
+ </tuser>
+ <tuser>
+ <name>mail</name>
+ <descr>mail desc</descr>
+ </tuser>
+ <tuser>
+ <name>mailnull</name>
+ <descr>mailnull desc</descr>
+ </tuser>
+ <tuser>
+ <name>smmsp</name>
+ <descr>smmsp desc</descr>
+ </tuser>
+ <tuser>
+ <name>daemon</name>
+ <descr>daemon desc</descr>
+ </tuser>
+ <!-- ============================================ -->
+ <!-- == DSPAM Engine Settings == -->
+ <!-- ============================================ -->
+ <training-mode>teft</training-mode>
+ <test-cond-training>yes</test-cond-training>
+ <feature>
+ <name>chained</name>
+ <descr>feat desc</descr>
+ </feature>
+ <feature>
+ <name>whitelist</name>
+ <descr>whitelist desc</descr>
+ </feature>
+ <algorithm>
+ <name>graham</name>
+ <descr>naive desc</descr>
+ </algorithm>
+ <algorithm>
+ <name>burton</name>
+ <descr>naive desc</descr>
+ </algorithm>
+ <pvalue>graham</pvalue>
+ <improbability-drive>yes</improbability-drive>
+ <preference>
+ <value>&quot;spamAction=quarantine&quot;</value>
+ <descr>desc</descr>
+ </preference>
+ <preference>
+ <value>&quot;signatureLocation=message&quot;</value>
+ <descr>&apos;message&apos; or &apos;headers&apos;</descr>
+ </preference>
+ <preference>
+ <value>&quot;showFactors=on&quot;</value>
+ <descr>desc</descr>
+ </preference>
+ <override>
+ <value>trainingMode</value>
+ <descr>tmode desc</descr>
+ </override>
+ <override>
+ <value>spamAction spamSubject</value>
+ <descr>desc</descr>
+ </override>
+ <override>
+ <value>statisticalSedation</value>
+ <descr>desc</descr>
+ </override>
+ <override>
+ <value>enableBNR</value>
+ <descr>desc</descr>
+ </override>
+ <override>
+ <value>enableWhitelist</value>
+ <descr>desc</descr>
+ </override>
+ <override>
+ <value>signatureLocation</value>
+ <descr>desc</descr>
+ </override>
+ <override>
+ <value>showFactors</value>
+ <descr>desc</descr>
+ </override>
+ <override>
+ <value>optIn optOut</value>
+ <descr>desc</descr>
+ </override>
+ <override>
+ <value>whitelistThreshold</value>
+ <descr>desc</descr>
+ </override>
+ <!-- ============================================ -->
+ <!-- == Miscellaneous Settings == -->
+ <!-- ============================================ -->
+ <failover-attempts>1</failover-attempts>
+ <notification-email>yes</notification-email>
+ <dspam-contact>support</dspam-contact>
+ <!-- ============================================ -->
+ <!-- == Maintainance Settings == -->
+ <!-- ============================================ -->
+ <purge-signatures>14</purge-signatures>
+ <purge-neutral>90</purge-neutral>
+ <purge-unused>90</purge-unused>
+ <purge-hapaxes>30</purge-hapaxes>
+ <purge-hits-1s>15</purge-hits-1s>
+ <purge-hits-1i>15</purge-hits-1i>
+ <!-- ============================================ -->
+ <!-- == System Settings == -->
+ <!-- ============================================ -->
+ <local-mx>127.0.0.1</local-mx>
+ <system-log>yes</system-log>
+ <user-log>yes</user-log>
+ <filter-opt>out</filter-opt>
+ <parse-to-headers>yes</parse-to-headers>
+ <change-mode-on-parse>yes</change-mode-on-parse>
+ <max-message-size>307200</max-message-size>
+ <processor-bias>yes</processor-bias>
+ <!-- ============================================ -->
+ <!-- == ClamAV Engine Settings == -->
+ <!-- ============================================ -->
+ <clamav-enable>yes</clamav-enable>
+ <clamav-port>3310</clamav-port>
+ <clamav-host>127.0.0.1</clamav-host>
+ <clamav-response>accept</clamav-response>
+ <!-- ============================================ -->
+ <!-- == DSPAM Daemon Settings (Server) == -->
+ <!-- ============================================ -->
+ <dspam-server-port>24</dspam-server-port>
+ <dspam-server-queue-size>32</dspam-server-queue-size>
+ <dspam-server-pid>/var/run/dspam/dspam.pid</dspam-server-pid>
+ <dspam-server-mode>standard</dspam-server-mode>
+ <dspam-server-params>--deliver=innocent -d %u</dspam-server-params>
+ <dspam-server-id>abysseleven.abyssworld.de</dspam-server-id>
+ <dspam-server-socket>/var/run/dspam/dspam.sock</dspam-server-socket>
+ </config>
+ </dspam>
+ <package>
+ <name>dspam</name>
+ <website>http://dspam.nuclearelephant.com/</website>
+ <descr>
+ DSPAM is a scalable and open-source content-based spam filter designed for multi-user enterprise systems.
+ On a properly configured system, many users experience results between 99.5% - 99.95%, or one error for
+ every 200 to 2000 messages. DSPAM supports many different MTAs and can also be deployed as a stand-alone
+ SMTP appliance.
+ </descr>
+ <config_file>http://www.abyssworld.de/packages/config/dspam.xml</config_file>
+ <depends_on_package_base_url>http://www.abyssworld.de/packages/All/</depends_on_package_base_url>
+ <depends_on_package>dspam-devel-3.6.4.20060315.1518.tbz</depends_on_package>
+ <version>3.6.6</version>
+ <status>ALPHA</status>
+ <maintainer>me@daniel.stefan.haischt.name</maintainer>
+ <logging>
+ <facilityname>dspam</facilityname>
+ </logging>
+ </package>
+ <package>
+ <name>p3scan-pf</name>
+ <descr>A transparent POP3-Proxy with virus-scanning- and spam-scanning-capabilities.</descr>
+ <website>http://www.undergroundsecurity.com/p3scan/</website>
+ <category>Security</category>
+ <version>0.1</version>
+ <status>ALPHA</status>
+ <maintainer>fernando@netfilter.com.br</maintainer>
+ <depends_on_package_base_url>http://www.pfsense.com/packages/All/</depends_on_package_base_url>
+ <depends_on_package>p3scan-pf-2.3.2.tbz</depends_on_package>
+ <config_file>http://www.pfsense.org/packages/config/p3scan-pf/p3scan-pf.xml</config_file>
+ <configurationfile>p3scan-pf.xml</configurationfile>
+ </package>
+ <package>
+ <name>mysql</name>
+ <website>http://www.mysql.com/</website>
+ <descr>
+ MySQL RDBMS.
+ </descr>
+ <config_file>http://www.abyssworld.de/packages/config/mysql.xml</config_file>
+ <depends_on_package_base_url>http://www.abyssworld.de/packages/All/</depends_on_package_base_url>
+ <depends_on_package>mysql-server-5.0.21.tbz</depends_on_package>
+ <version>5.0.21</version>
+ <status>ALPHA</status>
+ <maintainer>me@daniel.stefan.haischt.name</maintainer>
+ <logging>
+ <facilityname>mysql</facilityname>
+ </logging>
+ </package>
+ <package>
+ <name>clamav</name>
+ <website>http://www.clamav.net/</website>
+ <descr>
+ Clam Antivirus.
+ </descr>
+ <config_file>http://www.abyssworld.de/packages/config/clamav.xml</config_file>
+ <depends_on_package_base_url>http://www.abyssworld.de/packages/All/</depends_on_package_base_url>
+ <depends_on_package>clamav-devel-20060503_1.tbz</depends_on_package>
+ <version>20060503_1</version>
+ <status>ALPHA</status>
+ <maintainer>me@daniel.stefan.haischt.name</maintainer>
+ <logging>
+ <facilityname>clamav</facilityname>
+ </logging>
+ </package>
+ <package>
+ <name>sshterm</name>
+ <descr>
+ This is a package of the SSHTools SSHTerm Java Applet. SSHTools is a
+ suite of Java SSH applications providing a Java SSH API,
+ SSH Terminal, SSH secured VNC client, SFTP client and SSH Daemon.
+ </descr>
+ <website>http://sourceforge.net/projects/sshtools/</website>
+ <category>Security</category>
+ <version>0.1</version>
+ <status>ALPHA</status>
+ <maintainer>me@daniel.stefan.haischt.name</maintainer>
+ <depends_on_package_base_url>http://www.pfsense.com/packages/All/</depends_on_package_base_url>
+ <depends_on_package>sshtools-0.2.2.tbz</depends_on_package>
+ <config_file>http://www.pfsense.org/packages/config/sshterm/sshterm.xml</config_file>
+ <configurationfile>sshterm.xml</configurationfile>
+ </package>
+ <menu>
+ <name>POP3 Proxy</name>
+ <section>Services</section>
+ <configfile>p3scan-pf.xml</configfile>
+ <url>/pkg_edit.php?xml=p3scan-pf.xml&amp;id=0</url>
+ <tooltiptext>A transparent POP3-Proxy with virus-scanning capabilities</tooltiptext>
+ </menu>
+ <menu>
+ <name>DSPAM</name>
+ <section>Services</section>
+ <configfile>dspam.inc</configfile>
+ <url>/dspam.php</url>
+ </menu>
+ <menu>
+ <name>DSPAM Wizard</name>
+ <section>Services</section>
+ <configfile>dspam.inc</configfile>
+ <url>/wizard.php?xml=dspam_wizard.xml</url>
+ </menu>
+ <menu>
+ <name>Shell</name>
+ <section>Diagnostics</section>
+ <configfile>sshterm.xml</configfile>
+ <url>/diag_shell.php</url>
+ </menu>
+ <service>
+ <name>dspam</name>
+ <description>DSPAM content-based spam filter</description>
+ <rcfile>dspam.sh</rcfile>
+ <executable>dspam</executable>
+ </service>
+ <service>
+ <name>clamd</name>
+ <description>Clam AntiVirus Scanner</description>
+ <rcfile>010.clamav-clamd.sh</rcfile>
+ <executable>clamd</executable>
+ </service>
+ <service>
+ <description>Deamon that receives new AntiVirus signatures</description>
+ <name>freshclam</name>
+ <rcfile>020.clamav-freshclam.sh</rcfile>
+ <executable>freshclam</executable>
+ </service>
+ <service>
+ <name>mysql</name>
+ <description>MySQL RDBMS</description>
+ <rcfile>000.mysql.sh</rcfile>
+ <executable>mysqld_safe</executable>
+ </service>
+ <service>
+ <name>p3scan-pf</name>
+ <description>
+ p3scan is a pop3 antivirus proxy that can be used completely transparently with any pop3 mail client.
+ </description>
+ <rcfile>030.p3scan.sh</rcfile>
+ <executable>p3scan</executable>
+ </service>
+ </installedpackages>
+ <cron>
+ <item>
+ <minute>0</minute>
+ <hour>*</hour>
+ <mday>*</mday>
+ <month>*</month>
+ <wday>*</wday>
+ <who>root</who>
+ <command>/usr/bin/nice -n20 newsyslog</command>
+ </item>
+ <item>
+ <minute>1,31</minute>
+ <hour>0-5</hour>
+ <mday>*</mday>
+ <month>*</month>
+ <wday>*</wday>
+ <who>root</who>
+ <command>/usr/bin/nice -n20 adjkerntz -a</command>
+ </item>
+ <item>
+ <minute>1</minute>
+ <hour>*</hour>
+ <mday>1</mday>
+ <month>*</month>
+ <wday>*</wday>
+ <who>root</who>
+ <command>/usr/bin/nice -n20 /etc/rc.update_bogons.sh</command>
+ </item>
+ <item>
+ <minute>*/60</minute>
+ <hour>*</hour>
+ <mday>*</mday>
+ <month>*</month>
+ <wday>*</wday>
+ <who>root</who>
+ <command>/usr/bin/nice -n20 /usr/local/sbin/expiretable -v -t 3600 sshlockout</command>
+ </item>
+ <item>
+ <minute>1</minute>
+ <hour>1</hour>
+ <mday>*</mday>
+ <month>*</month>
+ <wday>*</wday>
+ <who>root</who>
+ <command>/usr/bin/nice -n20 /etc/rc.dyndns.update</command>
+ </item>
+ <item>
+ <minute>*/5</minute>
+ <hour>*</hour>
+ <mday>*</mday>
+ <month>*</month>
+ <wday>*</wday>
+ <who>root</who>
+ <command>/usr/bin/nice -n20 /etc/ping_hosts.sh</command>
+ </item>
+ </cron>
+</pfsense>
diff --git a/config/dspam/pear/Image/Canvas.php b/config/dspam/pear/Image/Canvas.php
new file mode 100644
index 00000000..e669807a
--- /dev/null
+++ b/config/dspam/pear/Image/Canvas.php
@@ -0,0 +1,733 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Canvas
+ *
+ * Canvas based creation of images to facilitate different output formats
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Canvas
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212
+ */
+
+/**
+ * Specfies the path to the system location of font files.
+ *
+ * Remember trailing slash!
+ *
+ * This is set by default on Windows systems to %SystemRoot%\Fonts\
+ */
+if (!defined('IMAGE_CANVAS_SYSTEM_FONT_PATH')) {
+ if (isset($_SERVER['SystemRoot'])) {
+ define('IMAGE_CANVAS_SYSTEM_FONT_PATH', $_SERVER['SystemRoot'] . '/Fonts/');
+ } else {
+ /**
+ * @ignore
+ */
+ define('IMAGE_CANVAS_SYSTEM_FONT_PATH', '');
+ }
+}
+
+/**
+ * Class for handling different output formats
+ *
+ * @category Images
+ * @package Image_Canvas
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212
+ * @abstract
+ */
+class Image_Canvas
+{
+
+ /**
+ * The leftmost pixel of the element on the canvas
+ * @var int
+ * @access private
+ */
+ var $_left = 0;
+
+ /**
+ * The topmost pixel of the element on the canvas
+ * @var int
+ * @access private
+ */
+ var $_top = 0;
+
+ /**
+ * The width of the graph
+ * @var int
+ * @access private
+ */
+ var $_width = 0;
+
+ /**
+ * The height of the graph
+ * @var int
+ * @access private
+ */
+ var $_height = 0;
+
+ /**
+ * Polygon vertex placeholder
+ * @var array
+ * @access private
+ */
+ var $_polygon = array();
+
+ /**
+ * The thickness of the line(s)
+ * @var int
+ * @access private
+ */
+ var $_thickness = 1;
+
+ /**
+ * The line style
+ * @var mixed
+ * @access private
+ */
+ var $_lineStyle = 'transparent';
+
+ /**
+ * The fill style
+ * @var mixed
+ * @access private
+ */
+ var $_fillStyle = 'transparent';
+
+ /**
+ * The font options
+ * @var array
+ * @access private
+ */
+ var $_font = array();
+
+ /**
+ * The default font
+ * @var array
+ * @access private
+ */
+ var $_defaultFont = array('name' => 'Courier New', 'color' => 'black', 'size' => 9);
+
+ /**
+ * Create the canvas.
+ *
+ * Parameters available:
+ *
+ * 'width' The width of the graph on the canvas
+ *
+ * 'height' The height of the graph on the canvas
+ *
+ * 'left' The left offset of the graph on the canvas
+ *
+ * 'top' The top offset of the graph on the canvas
+ *
+ * @param array $params Parameter array
+ * @abstract
+ */
+ function Image_Canvas($params)
+ {
+ if (isset($params['left'])) {
+ $this->_left = $params['left'];
+ }
+
+ if (isset($params['top'])) {
+ $this->_top = $params['top'];
+ }
+
+ if (isset($params['width'])) {
+ $this->_width = $params['width'];
+ }
+
+ if (isset($params['height'])) {
+ $this->_height = $params['height'];
+ }
+
+ $this->setDefaultFont($this->_defaultFont);
+ }
+
+ /**
+ * Get the x-point from the relative to absolute coordinates
+ *
+ * @param float $x The relative x-coordinate (in percentage of total width)
+ * @return float The x-coordinate as applied to the canvas
+ * @access private
+ */
+ function _getX($x)
+ {
+ return floor($this->_left + $x);
+ }
+
+ /**
+ * Get the y-point from the relative to absolute coordinates
+ *
+ * @param float $y The relative y-coordinate (in percentage of total width)
+ * @return float The y-coordinate as applied to the canvas
+ * @access private
+ */
+ function _getY($y)
+ {
+ return floor($this->_top + $y);
+ }
+
+ /**
+ * Get the width of the canvas
+ *
+ * @return int The width
+ */
+ function getWidth()
+ {
+ return $this->_width;
+ }
+
+ /**
+ * Get the height of the canvas
+ *
+ * @return int The height
+ */
+ function getHeight()
+ {
+ return $this->_height;
+ }
+
+ /**
+ * Sets the thickness of the line(s) to be drawn
+ *
+ * @param int $thickness The actual thickness (in pixels)
+ */
+ function setLineThickness($thickness)
+ {
+ $this->_thickness = $thickness;
+ }
+
+ /**
+ * Sets the color of the line(s) to be drawn
+ *
+ * @param mixed $color The color of the line
+ */
+ function setLineColor($color)
+ {
+ $this->_lineStyle = $color;
+ }
+
+ /**
+ * Sets the style of the filling of drawn objects.
+ *
+ * This method gives simple access to setFillColor(), setFillImage() and
+ * setGradientFill()
+ *
+ * @param mixed $fill The fill style
+ */
+ function setFill($fill)
+ {
+ if (is_array($fill)) {
+ $this->setGradientFill($fill);
+ } elseif (file_exists($fill)) {
+ $this->setFillImage($fill);
+ } else {
+ $this->setFillColor($fill);
+ }
+ }
+
+ /**
+ * Sets the color of the filling of drawn objects
+ *
+ * @param mixed $color The fill color
+ */
+ function setFillColor($color)
+ {
+ $this->_fillStyle = $color;
+ }
+
+ /**
+ * Sets an image that should be used for filling
+ *
+ * @param string $filename The filename of the image to fill with
+ */
+ function setFillImage($filename)
+ {
+ }
+
+ /**
+ * Sets a gradient fill
+ *
+ * @param array $gradient Gradient fill options
+ */
+ function setGradientFill($gradient)
+ {
+ $this->_fillStyle = $gradient;
+ }
+
+ /**
+ * Sets the font options.
+ *
+ * The $font array may have the following entries:
+ *
+ * 'name' The name of the font. This name must either be supported
+ * natively by the canvas or mapped to a font using the font-mapping scheme
+ *
+ * 'size' Size in pixels
+ *
+ * 'angle' The angle with which to write the text
+ *
+ * @param array $fontOptions The font options.
+ */
+ function setFont($fontOptions)
+ {
+ $this->_font = $fontOptions;
+
+ if (!isset($this->_font['color'])) {
+ $this->_font['color'] = 'black';
+ }
+
+ if (!(isset($this->_font['angle'])) || ($this->_font['angle'] === false)) {
+ $this->_font['angle'] = 0;
+ }
+
+ if (isset($this->_font['angle'])) {
+ if ((($this->_font['angle'] > 45) && ($this->_font['angle'] < 135)) ||
+ (($this->_font['angle'] > 225) && ($this->_font['angle'] < 315))
+ ) {
+ $this->_font['vertical'] = true;
+ }
+ }
+
+ if ((!isset($this->_font['file'])) && (isset($this->_font['name']))) {
+ include_once 'Image/Canvas/Tool.php';
+ $this->_font['file'] = Image_Canvas_Tool::fontMap($this->_font['name']);
+ }
+ }
+
+ /**
+ * Sets the default font options.
+ *
+ * The $font array may have the following entries:
+ *
+ * 'name' The name of the font. This name must either be supported
+ * natively by the canvas or mapped to a font using the font-mapping scheme
+ *
+ * 'size' Size in pixels
+ *
+ * 'angle' The angle with which to write the text
+ *
+ * @param array $fontOptions The font options.
+ */
+ function setDefaultFont($fontOptions)
+ {
+ $this->setFont($fontOptions);
+ $this->_defaultFont = $this->_font;
+ }
+
+ /**
+ * Resets the canvas.
+ *
+ * Includes fillstyle, linestyle, thickness and polygon
+ *
+ * @access private
+ */
+ function _reset()
+ {
+ $this->_lineStyle = false;
+ $this->_fillStyle = false;
+ $this->_thickness = 1;
+ $this->_polygon = array();
+ $this->_font = $this->_defaultFont;
+ }
+
+ /**
+ * Reset the canvas.
+ *
+ * Includes fillstyle, linestyle, thickness and polygon
+ */
+ function reset()
+ {
+ $this->_reset();
+ }
+
+ /**
+ * Draw a line end
+ *
+ * Parameter array:
+ * 'x': int X point
+ * 'y': int Y point
+ * 'end': string The end type of the end
+ * 'angle': int [optional] The angle with which to draw the end
+ * @param array $params Parameter array
+ */
+ function drawEnd($params)
+ {
+ }
+
+ /**
+ * Draw a line
+ *
+ * Parameter array:
+ * 'x0': int X start point
+ * 'y0': int Y start point
+ * 'x1': int X end point
+ * 'y1': int Y end point
+ * 'end0': string [optional] The end type of end0 (the start)
+ * 'end1': string [optional] The end type of end1 (the end)
+ * 'size0': int [optional] The size of end0
+ * 'size1': int [optional] The size of end1
+ * 'color': mixed [optional] The line color
+ * @param array $params Parameter array
+ */
+ function line($params)
+ {
+ $x0 = $this->_getX($params['x0']);
+ $y0 = $this->_getY($params['y0']);
+ $x1 = $this->_getX($params['x1']);
+ $y1 = $this->_getY($params['y1']);
+ if (isset($params['end0'])) {
+ $angle = Image_Canvas_Tool::getAngle($x1, $y1, $x0, $y0);
+ $this->drawEnd(
+ array(
+ 'end' => $params['end0'],
+ 'x' => $params['x0'],
+ 'y' => $params['y0'],
+ 'angle' => $angle,
+ 'color' => (isset($params['color0']) ? $params['color0'] : false),
+ 'size' => $params['size0']
+ )
+ );
+ }
+ if (isset($params['end1'])) {
+ $angle = Image_Canvas_Tool::getAngle($x0, $y0, $x1, $y1);
+ //print "<pre>"; var_dump($params, $angle); print "</pre>";
+ $this->drawEnd(
+ array(
+ 'end' => $params['end1'],
+ 'x' => $params['x1'],
+ 'y' => $params['y1'],
+ 'angle' => $angle,
+ 'color' => (isset($params['color1']) ? $params['color1'] : false),
+ 'size' => $params['size1']
+ )
+ );
+ }
+ $this->_reset();
+ }
+
+ /**
+ * Adds vertex to a polygon
+ *
+ * Parameter array:
+ * 'x': int X point
+ * 'y': int Y point
+ * 'url': string [optional] URL to link the vertex to (must be used with 'map_vertices' in polygon() on a canvas that support image maps)
+ * 'alt': string [optional] Alternative text to show in the image map (must be used with 'map_vertices' in polygon() on a canvas that support image maps)
+ * 'target': string [optional] The link target on the image map (must be used with 'map_vertices' in polygon() on a canvas that support image maps)
+ * 'mapsize': int [optional] The size of the "map", i.e. the size of the hot spot (must be used with 'map_vertices' in polygon() on a canvas that support image maps)
+ * @param array $params Parameter array
+ */
+ function addVertex($params)
+ {
+ $params['X'] = $this->_getX($params['x']);
+ $params['Y'] = $this->_getY($params['y']);
+ $this->_polygon[] = $params;
+ }
+
+ /**
+ * Adds "splined" vertex to a polygon
+ *
+ * Parameter array:
+ * 'x': int X point
+ * 'y': int Y point
+ * 'p1x': int X Control point 1
+ * 'p1y': int Y Control point 1
+ * 'p2x': int X Control point 2
+ * 'p2y': int Y Control point 2
+ * 'url': string [optional] URL to link the vertex to (must be used with 'map_vertices' in polygon() on a canvas that support image maps)
+ * 'alt': string [optional] Alternative text to show in the image map (must be used with 'map_vertices' in polygon() on a canvas that support image maps)
+ * 'target': string [optional] The link target on the image map (must be used with 'map_vertices' in polygon() on a canvas that support image maps)
+ * 'mapsize': int [optional] The size of the "map", i.e. the size of the hot spot (must be used with 'map_vertices' in polygon() on a canvas that support image maps)
+ * @param array $params Parameter array
+ */
+ function addSpline($params)
+ {
+ $params['X'] = $this->_getX($params['x']);
+ $params['Y'] = $this->_getY($params['y']);
+ $params['P1X'] = $this->_getX($params['p1x']);
+ $params['P1Y'] = $this->_getY($params['p1y']);
+ $params['P2X'] = $this->_getX($params['p2x']);
+ $params['P2Y'] = $this->_getY($params['p2y']);
+ $this->_polygon[] = $params;
+ }
+
+ /**
+ * Draws a polygon
+ *
+ * Parameter array:
+ * 'connect': bool [optional] Specifies whether the start point should be
+ * connected to the endpoint (closed polygon) or not (connected line)
+ * 'fill': mixed [optional] The fill color
+ * 'line': mixed [optional] The line color
+ * @param array $params Parameter array
+ */
+ function polygon($params)
+ {
+ $this->_reset();
+ }
+
+ /**
+ * Draw a rectangle
+ *
+ * Parameter array:
+ * 'x0': int X start point
+ * 'y0': int Y start point
+ * 'x1': int X end point
+ * 'y1': int Y end point
+ * 'fill': mixed [optional] The fill color
+ * 'line': mixed [optional] The line color
+ * @param array $params Parameter array
+ */
+ function rectangle($params)
+ {
+ $this->_reset();
+ }
+
+ /**
+ * Draw an ellipse
+ *
+ * Parameter array:
+ * 'x': int X center point
+ * 'y': int Y center point
+ * 'rx': int X radius
+ * 'ry': int Y radius
+ * 'fill': mixed [optional] The fill color
+ * 'line': mixed [optional] The line color
+ * @param array $params Parameter array
+ */
+ function ellipse($params)
+ {
+ $this->_reset();
+ }
+
+ /**
+ * Draw a pie slice
+ *
+ * Parameter array:
+ * 'x': int X center point
+ * 'y': int Y center point
+ * 'rx': int X radius
+ * 'ry': int Y radius
+ * 'v1': int The starting angle (in degrees)
+ * 'v2': int The end angle (in degrees)
+ * 'srx': int [optional] Starting X-radius of the pie slice (i.e. for a doughnut)
+ * 'sry': int [optional] Starting Y-radius of the pie slice (i.e. for a doughnut)
+ * 'fill': mixed [optional] The fill color
+ * 'line': mixed [optional] The line color
+ * @param array $params Parameter array
+ */
+ function pieslice($params)
+ {
+ $this->_reset();
+ }
+
+ /**
+ * Get the width of a text,
+ *
+ * @param string $text The text to get the width of
+ * @return int The width of the text
+ */
+ function textWidth($text)
+ {
+ }
+
+ /**
+ * Get the height of a text,
+ *
+ * @param string $text The text to get the height of
+ * @return int The height of the text
+ */
+ function textHeight($text)
+ {
+ }
+
+ /**
+ * Writes text
+ *
+ * Parameter array:
+ * 'x': int X-point of text
+ * 'y': int Y-point of text
+ * 'text': string The text to add
+ * 'alignment': array [optional] Alignment
+ * 'color': mixed [optional] The color of the text
+ */
+ function addText($params)
+ {
+ $this->_reset();
+ }
+
+ /**
+ * Overlay image
+ *
+ * Parameter array:
+ * 'x': int X-point of overlayed image
+ * 'y': int Y-point of overlayed image
+ * 'filename': string The filename of the image to overlay
+ * 'width': int [optional] The width of the overlayed image (resizing if possible)
+ * 'height': int [optional] The height of the overlayed image (resizing if possible)
+ * 'alignment': array [optional] Alignment
+ */
+ function image($params)
+ {
+ }
+
+ /**
+ * Set clipping to occur
+ *
+ * Parameter array:
+ *
+ * 'x0': int X point of Upper-left corner
+ * 'y0': int X point of Upper-left corner
+ * 'x1': int X point of lower-right corner
+ * 'y1': int Y point of lower-right corner
+ */
+ function setClipping($params = false)
+ {
+ }
+
+ /**
+ * Start a group.
+ *
+ * What this does, depends on the canvas/format.
+ *
+ * @param string $name The name of the group
+ */
+ function startGroup($name = false)
+ {
+ }
+
+ /**
+ * End the "current" group.
+ *
+ * What this does, depends on the canvas/format.
+ */
+ function endGroup()
+ {
+ }
+
+ /**
+ * Output the result of the canvas to the browser
+ *
+ * @param array $params Parameter array, the contents and meaning depends on the actual Canvas
+ * @abstract
+ */
+ function show($params = false)
+ {
+ if ($params === false) {
+ header('Expires: Tue, 2 Jul 1974 17:41:00 GMT'); // Date in the past
+ header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT'); // always modified
+ header('Cache-Control: no-cache, must-revalidate'); // HTTP/1.1
+ header('Pragma: no-cache');
+ }
+ }
+
+ /**
+ * Save the result of the canvas to a file
+ *
+ * Parameter array:
+ * 'filename': string The file to output to
+ * @param array $params Parameter array, the contents and meaning depends on the actual Canvas
+ * @abstract
+ */
+ function save($params = false)
+ {
+ }
+
+ /**
+ * Get a canvas specific HTML tag.
+ *
+ * This method implicitly saves the canvas to the filename in the
+ * filesystem path specified and parses it as URL specified by URL path
+ *
+ * Parameter array:
+ * 'filename': string
+ * 'filepath': string Path to the file on the file system. Remember the final slash
+ * 'urlpath': string Path to the file available through an URL. Remember the final slash
+ */
+ function toHtml($params)
+ {
+ $this->save(array('filename' => $params['filepath'] . $params['filename']));
+ }
+
+ /**
+ * Canvas factory method.
+ *
+ * Supported canvass are:
+ *
+ * 'png': output in PNG format (using GD)
+ *
+ * 'jpg': output in JPEG format (using GD)
+ *
+ * 'pdf': output in PDF format (using PDFlib)
+ *
+ * 'svg': output in SVG format
+ *
+ * 'imagemap': output as a html image map
+ *
+ * An example of usage:
+ *
+ * <code>
+ * <?php
+ * $Canvas =& Image_Graph::factory('png',
+ * array('width' => 800, 'height' => 600, 'antialias' => 'native')
+ * );
+ * ?>
+ * </code>
+ *
+ * @param string $canvas The canvas type
+ * @param array $params The parameters for the canvas constructor
+ * @return Image_Canvas The newly created canvas
+ * @static
+ */
+ function &factory($canvas, $params)
+ {
+ $canvas = strtoupper($canvas);
+
+ if (($canvas == 'PNG') || ($canvas == 'GD')) {
+ $canvas = 'GD_PNG';
+ }
+ if (($canvas == 'JPG') || ($canvas == 'JPEG')) {
+ $canvas = 'GD_JPG';
+ }
+
+ if ($canvas == 'IMAGEMAP') {
+ $canvas = 'ImageMap';
+ }
+
+ $class = 'Image_Canvas_'. $canvas;
+ include_once 'Image/Canvas/'. str_replace('_', '/', $canvas) . '.php';
+
+ $obj =& new $class($params);
+ return $obj;
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Canvas/Color.php b/config/dspam/pear/Image/Canvas/Color.php
new file mode 100644
index 00000000..0ac78553
--- /dev/null
+++ b/config/dspam/pear/Image/Canvas/Color.php
@@ -0,0 +1,182 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP Version 4 |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.02 of the PHP license, |
+// | that is bundled with this package in the file LICENSE, and is |
+// | available at through the world-wide-web at |
+// | http://www.php.net/license/2_02.txt. |
+// | If you did not receive a copy of the PHP license and are unable to |
+// | obtain it through the world-wide-web, please send a note to |
+// | license@php.net so we can mail you a copy immediately. |
+// +----------------------------------------------------------------------+
+// | Author: Stefan Neufeind <pear.neufeind@speedpartner.de> |
+// +----------------------------------------------------------------------+
+//
+// $Id$
+
+/**
+* Class for color-handling
+*
+* @author Stefan Neufeind <pear.neufeind@speedpartner.de>
+* @package Image_Canvas
+* @category images
+* @license The PHP License, version 2.02
+*/
+
+/**
+* Color class to be extended; from package PEAR::Image_Color
+*/
+require_once 'Image/Color.php';
+
+/**
+* Class for color-handling
+*
+* This is used to extend the functionality of the current PEAR::Image_Color v0.4.
+* I hope to be allowed to incorporate some of the improvements in a new Image_Color release.
+*
+* @author Stefan Neufeind <pear.neufeind@speedpartner.de>
+* @package Image_Canvas
+* @access public
+*/
+class Image_Canvas_Color extends Image_Color
+{
+ /**
+ * Allocates a color in the given image.
+ *
+ * Userdefined color specifications get translated into
+ * an array of rgb values.
+ *
+ * @param resource GD-resource
+ * @param mixed any color representation supported by color2RGB()
+ * @return resource Image color handle
+ * @see color2RGB()
+ * @access public
+ * @static
+ */
+ function allocateColor(&$img, $color)
+ {
+ $color = Image_Canvas_Color::color2RGB($color);
+
+ if (($color[3] == 255) || (!function_exists("imagecolorallocatealpha"))) {
+ return imagecolorallocate($img, $color[0], $color[1], $color[2]);
+ } else {
+ return imagecolorallocatealpha($img, $color[0], $color[1], $color[2], 127-round(($color[3]*127)/255));
+ }
+ }
+
+ /**
+ * Convert any color-representation into an array of 4 ints (RGBA).
+ *
+ * Userdefined color specifications get translated into
+ * an array of rgb values.
+ *
+ * @param mixed any color representation supported by Image_Canvas_Color::color2RGB()
+ * @return array Array of 4 ints (RGBA-representation)
+ * @access public
+ * @static
+ */
+ function color2RGB($color)
+ {
+ if (is_array($color)) {
+ if (!is_numeric($color[0])) {
+ return null; // error
+ }
+ if (count($color) == 3) { // assume RGB-color
+
+ // 255 = alpha-value; full opaque
+ return array((int) $color[0],
+ (int) $color[1],
+ (int) $color[2],
+ 255);
+ }
+ if (count($color) == 4) { // assume RGBA-color
+
+ // 255 = alpha-value; full opaque
+ return array((int) $color[0],
+ (int) $color[1],
+ (int) $color[2],
+ (int) $color[3]);
+ }
+ return null; // error
+ } elseif (is_string($color)) {
+ $alphaPos = strpos($color, '@');
+ if ($alphaPos === false) {
+ $alpha = 255;
+ } else {
+ $alphaFloat = (float) substr($color, $alphaPos+1);
+ // restrict to range 0..1
+ $alphaFloat = max(min($alphaFloat, 1), 0);
+ $alpha = (int) round((float) 255 * $alphaFloat);
+ $color = substr($color, 0, $alphaPos);
+ }
+ if ($color[0] == '#') { // hex-color given, e.g. #FFB4B4
+ $tempColor = parent::hex2rgb($color);
+ return array((int) $tempColor[0],
+ (int) $tempColor[1],
+ (int) $tempColor[2],
+ $alpha);
+ }
+ if (strpos($color,'%') !== false) {
+ $tempColor = parent::percentageColor2RGB($color);
+ return array((int) $tempColor[0],
+ (int) $tempColor[1],
+ (int) $tempColor[2],
+ $alpha);
+ } else {
+ $tempColor = parent::namedColor2RGB($color);
+ return array((int) $tempColor[0],
+ (int) $tempColor[1],
+ (int) $tempColor[2],
+ $alpha);
+ }
+ } else {
+ return null; // error
+ }
+ }
+
+ /**
+ * getRange
+ * Given a degree, you can get the range of colors between one color and
+ * another color.
+ *
+ * @access public
+ * @param string How much each 'step' between the colors we should take.
+ * @return array Returns an array of all the colors, one element for each color.
+ */
+ function getRange ($degrees)
+ {
+ $tempColors = parent::getRange($degrees);
+
+ // now add alpha-channel information
+ $steps = count($tempColors);
+ for($counter=0;$counter<$steps;$counter++) {
+ $tempColors[$counter] = parent::hex2rgb($tempColors[$counter]);
+ unset($tempColors[$counter]['hex']);
+ $tempColors[$counter][3] = (int) round(
+ (((float) $this->color1[3]*($steps-$counter))+
+ ((float) $this->color2[3]*($counter))
+ ) / $steps
+ );
+ }
+
+ return $tempColors;
+ }
+
+ /**
+ * Internal method to correctly set the colors.
+ *
+ * @param mixed color 1
+ * @param mixed color 2
+ * @access private
+ */
+ function _setColors ( $col1, $col2 )
+ {
+ $this->color1 = Image_Canvas_Color::color2RGB($col1);
+ $this->color2 = Image_Canvas_Color::color2RGB($col2);
+ }
+}
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Canvas/Fonts/README b/config/dspam/pear/Image/Canvas/Fonts/README
new file mode 100644
index 00000000..0a836147
--- /dev/null
+++ b/config/dspam/pear/Image/Canvas/Fonts/README
@@ -0,0 +1,12 @@
+This is where the font files are located.
+
+Font files can be found at:
+
+MS CoreFonts
+ http://corefonts.sourceforge.net/
+
+Divide By Zero (most are cartoonish)
+ http://fonts.tom7.com/
+
+MING FDB Fonts
+ http://ming.sf.net/ \ No newline at end of file
diff --git a/config/dspam/pear/Image/Canvas/Fonts/fontmap.txt b/config/dspam/pear/Image/Canvas/Fonts/fontmap.txt
new file mode 100644
index 00000000..ccec67dd
--- /dev/null
+++ b/config/dspam/pear/Image/Canvas/Fonts/fontmap.txt
@@ -0,0 +1,25 @@
+Arial,arial.ttf
+Arial Bold,arialbd.ttf
+Arial Bold Italic,arialbi.ttf
+Arial Italic,ariali.ttf
+Courier New,cour.ttf
+Courier New Bold,courbd.ttf
+Courier New Bold Italic,courbi.ttf
+Courier New Italic,couri.ttf
+Garamond,gara.ttf
+Garamond Bold,garabd.ttf
+Garamond Italic,garait.ttf
+Gothic,gothic.ttf
+Gothic Bold,gothicb.ttf
+Gothic Bold Italic,gothicbi.ttf
+Gothic Italic,gothici.ttf
+Sans Serif,micross.ttf
+Reference Sans Serif,refsan.ttf
+Times New Roman,times.ttf
+Times New Roman Bold,timesbd.ttf
+Times New Roman Bold Italic,timesbi.ttf
+Times New Roman Italic,timesi.ttf
+Verdana,verdana.ttf
+Verdana Bold,verdanab.ttf
+Verdana Bold Italic,verdanaz.ttf
+Verdana Italic,verdanai.ttf \ No newline at end of file
diff --git a/config/dspam/pear/Image/Canvas/GD.php b/config/dspam/pear/Image/Canvas/GD.php
new file mode 100644
index 00000000..40132899
--- /dev/null
+++ b/config/dspam/pear/Image/Canvas/GD.php
@@ -0,0 +1,1693 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Canvas
+ *
+ * Class for handling output in GD compatible format.
+ *
+ * Supported formats are PNG, JPEG, GIF and WBMP.
+ *
+ * Requires PHP extension GD
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Canvas
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212
+ */
+
+/**
+ * Include file Image/Canvas.php
+ */
+require_once 'Image/Canvas/WithMap.php';
+
+/**
+ * Include file Image/Canvas/Color.php
+ */
+require_once 'Image/Canvas/Color.php';
+
+/**
+ * Canvas class to output using PHP GD support.
+ *
+ * @category Images
+ * @package Image_Canvas
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212
+ * @abstract
+ */
+class Image_Canvas_GD extends Image_Canvas_WithMap
+{
+
+ /**
+ * The canvas of the graph
+ * @var resource
+ * @access private
+ */
+ var $_canvas;
+
+ /**
+ * The canvas to use for tiled filling
+ * @var resource
+ * @access private
+ */
+ var $_tileImage = null;
+
+ /**
+ * Is version GD2 installed?
+ * @var bool
+ * @access private
+ */
+ var $_gd2 = true;
+
+ /**
+ * Antialiasing?
+ *
+ * Possible values 'off', 'driver' and 'native'
+ *
+ * @var string
+ * @access private
+ */
+ var $_antialias = 'off';
+
+ var $_alpha = false;
+
+ var $_clipping = array();
+
+ /**
+ * Create the GD canvas.
+ *
+ * Parameters available:
+ *
+ * 'width' The width of the graph on the canvas
+ *
+ * 'height' The height of the graph on the canvas
+ *
+ * 'left' The left offset of the graph on the canvas
+ *
+ * 'top' The top offset of the graph on the canvas
+ *
+ * 'antialias' = 'native' enables native GD antialiasing - this
+ * method has no severe impact on performance (approx +5%). Requires PHP
+ * 4.3.2 (with bundled GD2)
+ *
+ * 'antialias' = {true|'driver'} Image_Graph implemented method. This method
+ * has a severe impact on performance, drawing an antialiased line this
+ * way is about XX times slower, with an overall performance impact of
+ * about +40%. The justification for this method is that if native support
+ * is not available this can be used, it is also a future feature that this
+ * method for antialiasing will support line styles.
+ *
+ * Use antialiased for best results with a line/area chart having just a few
+ * datapoints. Native antialiasing does not provide a good appearance with
+ * short lines, as for example with smoothed charts. Antialiasing does not
+ * (currently) work with linestyles, neither native nor driver method!
+ *
+ * 'noalpha' = true If alpha blending is to be disabled
+ *
+ * 'filename' An image to open, on which the graph is created on
+ *
+ * 'gd' A GD resource to add the image to, use this option to continue
+ * working on an already existing GD resource. Make sure this is passed 'by-
+ * reference' (using &amp;)
+ *
+ * 'usemap' Initialize an image map
+ *
+ * 'gd' and 'filename' are mutually exclusive with 'gd' as preference
+ *
+ * 'width' and 'height' are required unless 'filename' or 'gd' are
+ * specified, in which case the width and height are taken as the actual
+ * image width/height. If the latter is the case and 'left' and/or 'top' was
+ * also specified, the actual 'width'/'height' are altered so that the graph
+ * fits inside the canvas (i.e 'height' = actual height - top, etc.)
+ *
+ * @param array $param Parameter array
+ */
+ function Image_Canvas_GD($param)
+ {
+ include_once 'Image/Canvas/Color.php';
+
+ parent::Image_Canvas_WithMap($param);
+
+ $this->_gd2 = ($this->_version() == 2);
+ $this->_font = array('font' => 1, 'color' => 'black');
+
+ if ((isset($param['gd'])) && (is_resource($param['gd']))) {
+ $this->_canvas =& $param['gd'];
+ } elseif (isset($param['filename'])) {
+ $this->_canvas =& $this->_getGD($param['filename']);
+ } else {
+ if ($this->_gd2) {
+ $this->_canvas = ImageCreateTrueColor(
+ $this->_width,
+ $this->_height
+ );
+ if ((!isset($param['noalpha'])) || ($param['noalpha'] !== true)) {
+ ImageAlphaBlending($this->_canvas, true);
+ $this->_alpha = true;
+ }
+ } else {
+ $this->_canvas = ImageCreate($this->_width, $this->_height);
+ }
+ }
+
+ if (isset($param['antialias'])) {
+ $this->_antialias = $param['antialias'];
+ }
+
+ if ($this->_antialias === true) {
+ $this->_antialias = 'driver';
+ }
+
+ if (($this->_gd2) && ($this->_antialias === 'native')) {
+ ImageAntialias($this->_canvas, true);
+ }
+ }
+
+ /**
+ * Get an GD image resource from a file
+ *
+ * @param string $filename
+ * @return mixed The GD image resource
+ * @access private
+ */
+ function &_getGD($filename)
+ {
+ $info = getimagesize($filename);
+
+ $result = null;
+ switch($info[2]) {
+ case IMG_PNG:
+ $result =& ImageCreateFromPNG($filename);
+ break;
+
+ case IMG_JPG:
+ $result =& ImageCreateFromJPEG($filename);
+ break;
+
+ case IMG_GIF:
+ $result =& ImageCreateFromGIF($filename);
+ break;
+ }
+ return $result;
+ }
+
+ /**
+ * Get the color index for the RGB color
+ *
+ * @param int $color The color
+ * @return int The GD image index of the color
+ * @access private
+ */
+ function _color($color = false)
+ {
+ if (($color === false) || ($color === 'opague') || ($color === 'transparent')) {
+ return ImageColorTransparent($this->_canvas);
+ } else {
+ return Image_Canvas_Color::allocateColor($this->_canvas, $color);
+ }
+ }
+
+ /**
+ * Get the GD applicable linestyle
+ *
+ * @param mixed $lineStyle The line style to return, false if the one
+ * explicitly set
+ * @return mixed A GD compatible linestyle
+ * @access private
+ */
+ function _getLineStyle($lineStyle = false)
+ {
+ if ($this->_gd2) {
+ ImageSetThickness($this->_canvas, $this->_thickness);
+ }
+
+ if ($lineStyle == 'transparent') {
+ return false;
+ } elseif ($lineStyle === false) {
+ if (is_array($this->_lineStyle)) {
+ $colors = array();
+ foreach ($this->_lineStyle as $color) {
+ if ($color === 'transparent') {
+ $color = false;
+ }
+ $colors[] = $this->_color($color);
+ }
+ ImageSetStyle($this->_canvas, $colors);
+ return IMG_COLOR_STYLED;
+ } else {
+ return $this->_color($this->_lineStyle);
+ }
+ } else {
+ return $this->_color($lineStyle);
+ }
+ }
+
+ /**
+ * Get the GD applicable fillstyle
+ *
+ * @param mixed $fillStyle The fillstyle to return, false if the one
+ * explicitly set
+ * @return mixed A GD compatible fillstyle
+ * @access private
+ */
+ function _getFillStyle($fillStyle = false, $x0 = 0, $y0 = 0, $x1 = 0, $y1 = 0)
+ {
+ if ($this->_tileImage != null) {
+ ImageDestroy($this->_tileImage);
+ $this->_tileImage = null;
+ }
+ if ($fillStyle == 'transparent') {
+ return false;
+ } elseif ($fillStyle === false) {
+ if (is_resource($this->_fillStyle)) {
+ $x = min($x0, $x1);
+ $y = min($y0, $y1);
+ $w = abs($x1 - $x0) + 1;
+ $h = abs($y1 - $y0) + 1;
+ if ($this->_gd2) {
+ $this->_tileImage = ImageCreateTrueColor(
+ $this->getWidth(),
+ $this->getHeight()
+ );
+
+ ImageCopyResampled(
+ $this->_tileImage,
+ $this->_fillStyle,
+ $x,
+ $y,
+ 0,
+ 0,
+ $w,
+ $h,
+ ImageSX($this->_fillStyle),
+ ImageSY($this->_fillStyle)
+ );
+ } else {
+ $this->_tileImage = ImageCreate(
+ $this->getWidth(),
+ $this->getHeight()
+ );
+
+ ImageCopyResized(
+ $this->_tileImage,
+ $this->_fillStyle,
+ $x,
+ $y,
+ 0,
+ 0,
+ $w,
+ $h,
+ ImageSX($this->_fillStyle),
+ ImageSY($this->_fillStyle)
+ );
+ }
+ ImageSetTile($this->_canvas, $this->_tileImage);
+ return IMG_COLOR_TILED;
+ } elseif ((is_array($this->_fillStyle)) && (isset($this->_fillStyle['direction']))) {
+ $width = abs($x1 - $x0) + 1;
+ $height = abs($y1 - $y0) + 1;
+
+ switch ($this->_fillStyle['direction']) {
+ case 'horizontal':
+ $count = $width;
+ break;
+
+ case 'vertical':
+ $count = $height;
+ break;
+
+ case 'horizontal_mirror':
+ $count = $width / 2;
+ break;
+
+ case 'vertical_mirror':
+ $count = $height / 2;
+ break;
+
+ case 'diagonal_tl_br':
+ case 'diagonal_bl_tr':
+ $count = sqrt($width * $width + $height * $height);
+ break;
+
+ case 'radial':
+ $count = max($width, $height, sqrt($width * $width + $height * $height)) + 1;
+ break;
+
+ }
+
+ $count = round($count);
+
+ if ($this->_gd2) {
+ $this->_tileImage = ImageCreateTrueColor(
+ $this->getWidth(),
+ $this->getHeight()
+ );
+ } else {
+ $this->_tileImage = ImageCreate(
+ $this->getWidth(),
+ $this->getHeight()
+ );
+ }
+
+
+ $startColor = Image_Canvas_Color::color2RGB(
+ ($this->_fillStyle['direction'] == 'radial' ?
+ $this->_fillStyle['end'] :
+ $this->_fillStyle['start']
+ )
+ );
+ $endColor = Image_Canvas_Color::color2RGB(
+ ($this->_fillStyle['direction'] == 'radial' ?
+ $this->_fillStyle['start'] :
+ $this->_fillStyle['end']
+ )
+ );
+
+ $redIncrement = ($endColor[0] - $startColor[0]) / $count;
+ $greenIncrement = ($endColor[1] - $startColor[1]) / $count;
+ $blueIncrement = ($endColor[2] - $startColor[2]) / $count;
+
+ $color = false;
+ for ($i = 0; $i < $count; $i ++) {
+ unset($color);
+ if ($i == 0) {
+ $color = $startColor;
+ unset($color[3]);
+ } else {
+ $color[0] = round(($redIncrement * $i) +
+ $redIncrement + $startColor[0]);
+ $color[1] = round(($greenIncrement * $i) +
+ $greenIncrement + $startColor[1]);
+ $color[2] = round(($blueIncrement * $i) +
+ $blueIncrement + $startColor[2]);
+ }
+ $color = Image_Canvas_Color::allocateColor(
+ $this->_tileImage,
+ $color
+ );
+
+ switch ($this->_fillStyle['direction']) {
+ case 'horizontal':
+ ImageLine($this->_tileImage,
+ $x0 + $i,
+ $y0,
+ $x0 + $i,
+ $y1, $color);
+ break;
+
+ case 'vertical':
+ ImageLine($this->_tileImage,
+ $x0,
+ $y1 - $i,
+ $x1,
+ $y1 - $i, $color);
+ break;
+
+ case 'horizontal_mirror':
+ if (($x0 + $i) <= ($x1 - $i)) {
+ ImageLine($this->_tileImage,
+ $x0 + $i,
+ $y0,
+ $x0 + $i,
+ $y1, $color);
+
+ ImageLine($this->_tileImage,
+ $x1 - $i,
+ $y0,
+ $x1 - $i,
+ $y1, $color);
+ }
+ break;
+
+ case 'vertical_mirror':
+ if (($y0 + $i) <= ($y1 - $i)) {
+ ImageLine($this->_tileImage,
+ $x0,
+ $y0 + $i,
+ $x1,
+ $y0 + $i, $color);
+ ImageLine($this->_tileImage,
+ $x0,
+ $y1 - $i,
+ $x1,
+ $y1 - $i, $color);
+ }
+ break;
+
+ case 'diagonal_tl_br':
+ if (($i > $width) && ($i > $height)) {
+ $polygon = array (
+ $x1, $y0 + $i - $width - 1,
+ $x1, $y1,
+ $x0 + $i - $height - 1, $y1);
+ } elseif ($i > $width) {
+ $polygon = array (
+ $x0, $y0 + $i,
+ $x0, $y1,
+ $x1, $y1,
+ $x1, $y0 + $i - $width - 1);
+ } elseif ($i > $height) {
+ $polygon = array (
+ $x0 + $i - $height - 1, $y1,
+ $x1, $y1,
+ $x1, $y0,
+ $x0 + $i, $y0);
+ } else {
+ $polygon = array (
+ $x0, $y0 + $i,
+ $x0, $y1,
+ $x1, $y1,
+ $x1, $y0,
+ $x0 + $i, $y0);
+ }
+ ImageFilledPolygon(
+ $this->_tileImage,
+ $polygon,
+ count($polygon) / 2,
+ $color
+ );
+ break;
+
+ case 'diagonal_bl_tr':
+ if (($i > $width) && ($i > $height)) {
+ $polygon = array (
+ $x1, $y1 - $i + $width - 1,
+ $x1, $y0,
+ $x0 + $i - $height - 1, $y0);
+ } elseif ($i > $width) {
+ $polygon = array (
+ $x0, $y1 - $i,
+ $x0, $y0,
+ $x1, $y0,
+ $x1, $y1 - $i + $width - 1);
+ } elseif ($i > $height) {
+ $polygon = array (
+ $x0 + $i - $height - 1, $y0,
+ $x1, $y0,
+ $x1, $y1,
+ $x0 + $i, $y1);
+ } else {
+ $polygon = array (
+ $x0, $y1 - $i,
+ $x0, $y0,
+ $x1, $y0,
+ $x1, $y1,
+ $x0 + $i, $y1);
+ }
+ ImageFilledPolygon(
+ $this->_tileImage,
+ $polygon,
+ count($polygon) / 2,
+ $color
+ );
+ break;
+
+ case 'radial':
+ if (($this->_gd2) && ($i < $count)) {
+ ImageFilledEllipse(
+ $this->_tileImage,
+ $x0 + $width / 2,
+ $y0 + $height / 2,
+ $count - $i,
+ $count - $i,
+ $color
+ );
+ }
+ break;
+ }
+ }
+ ImageSetTile($this->_canvas, $this->_tileImage);
+ return IMG_COLOR_TILED;
+ } else {
+ return $this->_color($this->_fillStyle);
+ }
+ } else {
+ return $this->_color($fillStyle);
+ }
+ }
+
+ /**
+ * Sets an image that should be used for filling
+ *
+ * @param string $filename The filename of the image to fill with
+ */
+ function setFillImage($filename)
+ {
+ $this->_fillStyle =& $this->_getGD($filename);
+ }
+
+ /**
+ * Sets the font options.
+ *
+ * The $font array may have the following entries:
+ *
+ * 'ttf' = the .ttf file (either the basename, filename or full path)
+ * If 'ttf' is specified, then the following can be specified
+ *
+ * 'size' = size in pixels
+ *
+ * 'angle' = the angle with which to write the text
+ *
+ * @param array $font The font options.
+ */
+ function setFont($fontOptions)
+ {
+ parent::setFont($fontOptions);
+
+ if (isset($this->_font['ttf'])) {
+ $this->_font['file'] = str_replace('\\', '/', Image_Canvas_Tool::fontMap($this->_font['ttf']));
+ } elseif (!isset($this->_font['font'])) {
+ $this->_font['font'] = 1;
+ }
+
+ if (!isset($this->_font['color'])) {
+ $this->_font['color'] = 'black';
+ }
+
+ if ((isset($this->_font['angle'])) && ($this->_font['angle'] === false)) {
+ $this->_font['angle'] = 0;
+ }
+ }
+
+ /**
+ * Calculate pixels on a line
+ *
+ * @param int $x0 X start point
+ * @param int $y0 X start point
+ * @param int $x1 X end point
+ * @param int $y1 Y end point
+ * @return array An associated array of x,y points with all pixels on the
+ * line
+ * @access private
+ */
+ function &_linePixels($x0, $y0, $x1, $y1)
+ {
+ $pixels = array();
+ if (abs($x0 - $x1) > abs($y0 - $y1)) {
+ if ($x1 != $x0) {
+ $m = ($y1 - $y0) / ($x1 - $x0);
+ } else {
+ $m = 0;
+ }
+ $b = $y0 - $m * $x0;
+ $strx = min($x0, $x1);
+ $endx = max($x0, $x1);
+ for ($x = $strx; $x <= $endx; $x++) {
+ $pixels[] = array('X' => $x, 'Y' => ($m * $x + $b));
+ }
+ } else {
+ if ($y1 != $y0) {
+ $m = ($x1 - $x0) / ($y1 - $y0);
+ } else {
+ $m = 0;
+ }
+ $b = $x0 - $m * $y0;
+ $stry = min($y0, $y1);
+ $endy = max($y0, $y1);
+ for ($y = $stry; $y <= $endy; $y++) {
+ $pixels[] = array('X' => ($m * $y + $b), 'Y' => $y);
+ }
+ }
+ return $pixels;
+ }
+
+ /**
+ * Draws an antialiased line
+ *
+ * @param int $x0 X start point
+ * @param int $y0 X start point
+ * @param int $x1 X end point
+ * @param int $y1 Y end point
+ * @param mixed $color The line color, can be omitted
+ * @access private
+ */
+ function _antialiasedLine($x0, $y0, $x1, $y1, $color = false)
+ {
+ if (($line = $this->_getLineStyle($color)) !== false) {
+ if ($line >= 0) {
+ $line = ImageColorsForIndex($this->_canvas, $line);
+ $pixels = &$this->_linePixels($x0, $y0, $x1, $y1);
+ foreach ($pixels as $point) {
+ $this->_antialiasedPixel($point['X'], $point['Y'], $line);
+ }
+ unset($pixels);
+ }
+ }
+ }
+
+
+ /**
+ * Draws an antialiased pixel
+ *
+ * @param int $x X point
+ * @param int $y Y point
+ * @param mixed $color The pixel color
+ * @access private
+ */
+ function _antialiasedPixel($x, $y, $color)
+ {
+ $fx = floor($x);
+ $fy = floor($y);
+ $cx = ceil($x);
+ $cy = ceil($y);
+ $xa = $x - $fx;
+ $xb = $cx - $x;
+ $ya = $y - $fy;
+ $yb = $cy - $y;
+ if (($cx == $fx) && ($cy == $fy)) {
+ $this->_antialisedSubPixel($fx, $fy, 0.0, 1.0, $color);
+ } else {
+ $this->_antialisedSubPixel($fx, $fy, $xa + $ya, $xb + $yb, $color);
+ if ($cy != $fy) {
+ $this->_antialisedSubPixel($fx, $cy, $xa + $yb, $xb + $ya, $color);
+ }
+ if ($cx != $fx) {
+ $this->_antialisedSubPixel($cx, $fy, $xb + $ya, $xa + $yb, $color);
+ if ($cy != $fy) {
+ $this->_antialisedSubPixel($cx, $cy, $xb + $yb, $xa + $ya, $color);
+ }
+ }
+ }
+ }
+
+ /**
+ * Antialias'es the pixel around x,y with weights a,b
+ *
+ * @param int $x X point
+ * @param int $y Y point
+ * @param int $a The weight of the current color
+ * @param int $b The weight of the applied/wanted color
+ * @param mixed $color The pixel color
+ * @access private
+ */
+ function _antialisedSubPixel($x, $y, $a, $b, $color)
+ {
+ $x = $this->_getX($x);
+ $y = $this->_getX($y);
+ if (($x >=0 ) && ($y >= 0) && ($x < $this->getWidth()) && ($y < $this->getHeight())) {
+ $tempColor = ImageColorsForIndex($this->_canvas, ImageColorAt($this->_canvas, $x, $y));
+
+ $newColor[0] = min(255, round($tempColor['red'] * $a + $color['red'] * $b));
+ $newColor[1] = min(255, round($tempColor['green'] * $a + $color['green'] * $b));
+ $newColor[2] = min(255, round($tempColor['blue'] * $a + $color['blue'] * $b));
+ //$newColor[3] = 0;
+ $color = '#';
+ foreach ($newColor as $acolor) {
+ $color .= sprintf('%02s', dechex($acolor));
+ }
+ $newColor = $this->_color($color);//,'rgb(' . $newColor[0] . ',' . $newColor[1] . ',' . $newColor[2] .')';
+
+ ImageSetPixel($this->_canvas, $x, $y, $newColor);
+ }
+ }
+
+
+ /**
+ * Draw a line end
+ *
+ * Parameter array:
+ *
+ * 'x': int X point
+ *
+ * 'y': int Y point
+ *
+ * 'end': string The end type of the end
+ *
+ * 'size': int The size of the end
+ *
+ * 'color': string The color of the end
+ *
+ * 'angle': int [optional] The angle with which to draw the end
+ *
+ * @param array $params Parameter array
+ */
+ function drawEnd($params)
+ {
+ $x = $this->_getX($params['x']);
+ $y = $this->_getY($params['y']);
+ $size = $params['size'];
+ //var_dump($params);
+ $angle = deg2rad((isset($params['angle']) ? $params['angle'] : 0));
+ $pi2 = pi() / 2;
+ switch ($params['end']) {
+ case 'lollipop':
+ case 'circle':
+ $this->ellipse(
+ array(
+ 'x' => $x,
+ 'y' => $y,
+ 'rx' => $size / 2,
+ 'ry' => $size / 2,
+ 'fill' => $params['color'],
+ 'line' => $params['color']
+ )
+ );
+ break;
+ case 'diamond':
+ $x0 = round($params['x'] + cos($angle) * $size * 0.65);
+ $y0 = round($params['y'] - sin($angle) * $size * 0.65);
+ $shape = array(
+ $x0 + round(cos($angle) * $size * 0.65),
+ $y0 - round(sin($angle) * $size * 0.65),
+ $x0 + round(cos($angle + $pi2) * $size * 0.65),
+ $y0 - round(sin($angle + $pi2) * $size * 0.65),
+ $x0 + round(cos($angle + pi()) * $size * 0.65),
+ $y0 - round(sin($angle + pi()) * $size * 0.65),
+ $x0 + round(cos($angle + 3 * $pi2) * $size * 0.65),
+ $y0 - round(sin($angle + 3 * $pi2) * $size * 0.65)
+ );
+ break;
+ case 'line':
+ $this->line(
+ array(
+ 'x0' => $x + round(cos($angle + $pi2) * $size / 2),
+ 'y0' => $y - round(sin($angle + $pi2) * $size / 2),
+ 'x1' => $x + round(cos($angle + 3 * $pi2) * $size / 2),
+ 'y1' => $y - round(sin($angle + 3 * $pi2) * $size / 2),
+ 'color' => $params['color']
+ )
+ );
+ break;
+ case 'box':
+ case 'rectangle':
+ $x0 = round($params['x'] + cos($angle) * $size / 2);
+ $y0 = round($params['y'] - sin($angle) * $size / 2);
+ $pi4 = pi() / 4;
+ $shape = array(
+ $x0 + round(cos($angle + $pi4) * $size / 2),
+ $y0 - round(sin($angle + $pi4) * $size / 2),
+ $x0 + round(cos($angle + $pi2 + $pi4) * $size / 2),
+ $y0 - round(sin($angle + $pi2 + $pi4) * $size / 2),
+ $x0 + round(cos($angle + pi() + $pi4) * $size / 2),
+ $y0 - round(sin($angle + pi() + $pi4) * $size / 2),
+ $x0 + round(cos($angle + 3 * $pi2 + $pi4) * $size / 2),
+ $y0 - round(sin($angle + 3 * $pi2 + $pi4) * $size / 2)
+ );
+ break;
+ case 'arrow':
+ $shape = array(
+ $x + cos($angle) * $size,
+ $y - sin($angle) * $size,
+ $x + cos($angle + $pi2) * $size * 0.4,
+ $y - sin($angle + $pi2) * $size * 0.4,
+ $x + cos($angle + 3 * $pi2) * $size * 0.4,
+ $y - sin($angle + 3 * $pi2) * $size * 0.4,
+ );
+ break;
+ case 'arrow2':
+ $shape = array(
+ $x + round(cos($angle) * $size),
+ $y - round(sin($angle) * $size),
+ $x + round(cos($angle + $pi2 + deg2rad(45)) * $size),
+ $y - round(sin($angle + $pi2 + deg2rad(45)) * $size),
+ $x,
+ $y,
+ $x + round(cos($angle + 3 * $pi2 - deg2rad(45)) * $size),
+ $y - round(sin($angle + 3 * $pi2 - deg2rad(45)) * $size),
+ );
+ break;
+ }
+
+ if (isset($shape)) {
+ // output the shape
+ if (($fill = $this->_getFillStyle($params['color'])) !== false) {
+ ImageFilledPolygon($this->_canvas, $shape, count($shape)/2, $fill);
+ }
+ }
+ parent::drawEnd($params);
+ }
+
+ /**
+ * Draw a line
+ *
+ * Parameter array:
+ *
+ * 'x0': int X start point
+ *
+ * 'y0': int Y start point
+ *
+ * 'x1': int X end point
+ *
+ * 'y1': int Y end point
+ *
+ * 'color': mixed [optional] The line color
+ *
+ * @param array $params Parameter array
+ */
+ function line($params)
+ {
+ $x0 = $this->_getX($params['x0']);
+ $y0 = $this->_getY($params['y0']);
+ $x1 = $this->_getX($params['x1']);
+ $y1 = $this->_getY($params['y1']);
+ $color = (isset($params['color']) ? $params['color'] : false);
+
+ $x0 = $this->_getX($x0);
+ $y0 = $this->_getY($y0);
+ $x1 = $this->_getX($x1);
+ $y1 = $this->_getY($y1);
+ if (($this->_antialias === 'driver') && ($x0 != $x1) && ($y0 != $y1)) {
+ $this->_antialiasedLine($x0, $y0, $x1, $y1, $color);
+ } elseif (($line = $this->_getLineStyle($color)) !== false) {
+ ImageLine($this->_canvas, $x0, $y0, $x1, $y1, $line);
+ }
+ parent::line($params);
+ }
+
+ /**
+ * Parameter array:
+ *
+ * 'connect': bool [optional] Specifies whether the start point should be
+ * connected to the endpoint (closed polygon) or not (connected line)
+ *
+ * 'fill': mixed [optional] The fill color
+ *
+ * 'line': mixed [optional] The line color
+ * @param array $params Parameter array
+ */
+ function polygon($params)
+ {
+ include_once 'Image/Canvas/Tool.php';
+
+ $connectEnds = (isset($params['connect']) ? $params['connect'] : false);
+ $fillColor = (isset($params['fill']) ? $params['fill'] : false);
+ $lineColor = (isset($params['line']) ? $params['line'] : false);
+
+ if (!$connectEnds) {
+ $fillColor = 'transparent';
+ }
+ $style = $this->_getLineStyle($lineColor) . $this->_getFillStyle($fillColor);
+
+ $lastPoint = false;
+ foreach ($this->_polygon as $point) {
+ if (($lastPoint) && (isset($lastPoint['P1X'])) &&
+ (isset($lastPoint['P1Y'])) && (isset($lastPoint['P2X'])) &&
+ (isset($lastPoint['P2Y'])))
+ {
+ $dx = abs($point['X'] - $lastPoint['X']);
+ $dy = abs($point['Y'] - $lastPoint['Y']);
+ $d = sqrt($dx * $dx + $dy * $dy);
+ if ($d > 0) {
+ $interval = 1 / $d;
+ for ($t = 0; $t <= 1; $t = $t + $interval) {
+ $x = Image_Canvas_Tool::bezier(
+ $t,
+ $lastPoint['X'],
+ $lastPoint['P1X'],
+ $lastPoint['P2X'],
+ $point['X']
+ );
+
+ $y = Image_Canvas_Tool::bezier(
+ $t,
+ $lastPoint['Y'],
+ $lastPoint['P1Y'],
+ $lastPoint['P2Y'],
+ $point['Y']
+ );
+
+ if (!isset($low['X'])) {
+ $low['X'] = $x;
+ } else {
+ $low['X'] = min($x, $low['X']);
+ }
+ if (!isset($high['X'])) {
+ $high['X'] = $x;
+ } else {
+ $high['X'] = max($x, $high['X']);
+ }
+ if (!isset($low['Y'])) {
+ $low['Y'] = $y;
+ } else {
+ $low['Y'] = min($y, $low['Y']);
+ }
+ if (!isset($high['Y'])) {
+ $high['Y'] = $y;
+ } else {
+ $high['Y'] = max($y, $high['Y']);
+ }
+ $polygon[] = $x;
+ $polygon[] = $y;
+ }
+ if (($t - $interval) < 1) {
+ $x = Image_Canvas_Tool::bezier(
+ 1,
+ $lastPoint['X'],
+ $lastPoint['P1X'],
+ $lastPoint['P2X'],
+ $point['X']
+ );
+
+ $y = Image_Canvas_Tool::bezier(
+ 1,
+ $lastPoint['Y'],
+ $lastPoint['P1Y'],
+ $lastPoint['P2Y'],
+ $point['Y']
+ );
+
+ $polygon[] = $x;
+ $polygon[] = $y;
+ }
+ }
+ } else {
+ if (!isset($low['X'])) {
+ $low['X'] = $point['X'];
+ } else {
+ $low['X'] = min($point['X'], $low['X']);
+ }
+ if (!isset($high['X'])) {
+ $high['X'] = $point['X'];
+ } else {
+ $high['X'] = max($point['X'], $high['X']);
+ }
+ if (!isset($low['Y'])) {
+ $low['Y'] = $point['Y'];
+ } else {
+ $low['Y'] = min($point['Y'], $low['Y']);
+ }
+ if (!isset($high['Y'])) {
+ $high['Y'] = $point['Y'];
+ } else {
+ $high['Y'] = max($point['Y'], $high['Y']);
+ }
+
+ $polygon[] = $point['X'];
+ $polygon[] = $point['Y'];
+ }
+ $lastPoint = $point;
+ }
+
+ if ((isset($polygon)) && (is_array($polygon))) {
+ if ($connectEnds) {
+ if (($fill = $this->_getFillStyle($fillColor, $low['X'], $low['Y'], $high['X'], $high['Y'])) !== false) {
+ ImageFilledPolygon($this->_canvas, $polygon, count($polygon)/2, $fill);
+ }
+ if ($this->_antialias === 'driver') {
+ $pfirst = $p0 = false;
+ reset($polygon);
+
+ while (list(, $x) = each($polygon)) {
+ list(, $y) = each($polygon);
+ if ($p0 !== false) {
+ $this->_antialiasedLine($p0['X'], $p0['Y'], $x, $y, $lineColor);
+ }
+ if ($pfirst === false) {
+ $pfirst = array('X' => $x, 'Y' => $y);
+ }
+ $p0 = array('X' => $x, 'Y' => $y);;
+ }
+
+ $this->_antialiasedLine($p0['X'], $p0['Y'], $pfirst['X'], $pfirst['Y'], $lineColor);
+ } elseif (($line = $this->_getLineStyle($lineColor)) !== false) {
+ ImagePolygon($this->_canvas, $polygon, count($polygon)/2, $line);
+ }
+ } else {
+ $prev_point = false;
+ if ($this->_antialias === 'driver') {
+ reset($polygon);
+ while (list(, $x) = each($polygon)) {
+ list(, $y) = each($polygon);
+ if ($prev_point) {
+ $this->_antialiasedLine(
+ $prev_point['X'],
+ $prev_point['Y'],
+ $x,
+ $y,
+ $lineColor
+ );
+ }
+ $prev_point = array('X' => $x, 'Y' => $y);;
+ }
+ } elseif (($line = $this->_getLineStyle($lineColor)) !== false) {
+ reset($polygon);
+ while (list(, $x) = each($polygon)) {
+ list(, $y) = each($polygon);
+ if ($prev_point) {
+ ImageLine(
+ $this->_canvas,
+ $prev_point['X'],
+ $prev_point['Y'],
+ $x,
+ $y,
+ $line
+ );
+ }
+ $prev_point = array('X' => $x, 'Y' => $y);;
+ }
+ }
+ }
+ }
+
+ parent::polygon($params);
+ }
+
+ /**
+ * Draw a rectangle
+ *
+ * Parameter array:
+ *
+ * 'x0': int X start point
+ *
+ * 'y0': int Y start point
+ *
+ * 'x1': int X end point
+ *
+ * 'y1': int Y end point
+ *
+ * 'fill': mixed [optional] The fill color
+ *
+ * 'line': mixed [optional] The line color
+ *
+ * @param array $params Parameter array
+ */
+ function rectangle($params)
+ {
+ $x0 = $this->_getX($params['x0']);
+ $y0 = $this->_getY($params['y0']);
+ $x1 = $this->_getX($params['x1']);
+ $y1 = $this->_getY($params['y1']);
+ $fillColor = (isset($params['fill']) ? $params['fill'] : false);
+ $lineColor = (isset($params['line']) ? $params['line'] : false);
+
+ if (($fill = $this->_getFillStyle($fillColor, $x0, $y0, $x1, $y1)) !== false) {
+ ImageFilledRectangle($this->_canvas, $x0, $y0, $x1, $y1, $fill);
+ }
+
+ if (($line = $this->_getLineStyle($lineColor)) !== false) {
+ ImageRectangle($this->_canvas, $x0, $y0, $x1, $y1, $line);
+ }
+
+ parent::rectangle($params);
+ }
+
+ /**
+ * Draw an ellipse
+ *
+ * Parameter array:
+ *
+ * 'x': int X center point
+ *
+ * 'y': int Y center point
+ *
+ * 'rx': int X radius
+ *
+ * 'ry': int Y radius
+ *
+ * 'fill': mixed [optional] The fill color
+ *
+ * 'line': mixed [optional] The line color
+ *
+ * @param array $params Parameter array
+ */
+ function ellipse($params)
+ {
+ $x = $this->_getX($params['x']);
+ $y = $this->_getY($params['y']);
+ $rx = $this->_getX($params['rx']);
+ $ry = $this->_getY($params['ry']);
+ $fillColor = (isset($params['fill']) ? $params['fill'] : false);
+ $lineColor = (isset($params['line']) ? $params['line'] : false);
+
+ if (($fill = $this->_getFillStyle($fillColor, $x - $rx, $y - $ry, $x + $rx, $y + $ry)) !== false) {
+ ImageFilledEllipse($this->_canvas, $x, $y, $rx * 2, $ry * 2, $fill);
+ }
+
+ if (($line = $this->_getLineStyle($lineColor)) !== false) {
+ ImageEllipse($this->_canvas, $x, $y, $rx * 2, $ry * 2, $line);
+ }
+ parent::ellipse($params);
+ }
+
+ /**
+ * Draw a pie slice
+ *
+ * Parameter array:
+ *
+ * 'x': int X center point
+ *
+ * 'y': int Y center point
+ *
+ * 'rx': int X radius
+ *
+ * 'ry': int Y radius
+ *
+ * 'v1': int The starting angle (in degrees)
+ *
+ * 'v2': int The end angle (in degrees)
+ *
+ * 'srx': int [optional] Starting X-radius of the pie slice (i.e. for a doughnut)
+ *
+ * 'sry': int [optional] Starting Y-radius of the pie slice (i.e. for a doughnut)
+ *
+ * 'fill': mixed [optional] The fill color
+ *
+ * 'line': mixed [optional] The line color
+ *
+ * @param array $params Parameter array
+ */
+ function pieslice($params)
+ {
+ $x = $this->_getX($params['x']);
+ $y = $this->_getY($params['y']);
+ $rx = $params['rx'];
+ $ry = $params['ry'];
+ $v1 = $params['v1'];
+ $v2 = $params['v2'];
+ $srx = (isset($params['srx']) ? $params['srx'] : 0);
+ $sry = (isset($params['sry']) ? $params['sry'] : 0);
+ $fillColor = (isset($params['fill']) ? $params['fill'] : false);
+ $lineColor = (isset($params['line']) ? $params['line'] : false);
+
+ $dA = 0.1;
+
+ if (($srx !== false) && ($sry !== false)) {
+ $angle = max($v1, $v2);
+ while ($angle >= min($v1, $v2)) {
+ $polygon[] = ($x + $srx * cos(deg2rad($angle % 360)));
+ $polygon[] = ($y + $sry * sin(deg2rad($angle % 360)));
+ $angle -= $dA;
+ }
+ if (($angle + $dA) > min($v1, $v2)) {
+ $polygon[] = ($x + $srx * cos(deg2rad(min($v1, $v2) % 360)));
+ $polygon[] = ($y + $sry * sin(deg2rad(min($v1, $v2) % 360)));
+ }
+ } else {
+ $polygon[] = $x;
+ $polygon[] = $y;
+ }
+
+ $angle = min($v1, $v2);
+ while ($angle <= max($v1, $v2)) {
+ $polygon[] = ($x + $rx * cos(deg2rad($angle % 360)));
+ $polygon[] = ($y + $ry * sin(deg2rad($angle % 360)));
+ $angle += $dA;
+ }
+
+ if (($angle - $dA) < max($v1, $v2)) {
+ $polygon[] = ($x + $rx * cos(deg2rad(max($v1, $v2) % 360)));
+ $polygon[] = ($y + $ry * sin(deg2rad(max($v1, $v2) % 360)));
+ }
+
+ if (($fill = $this->_getFillStyle($fillColor, $x - $rx - 1, $y - $ry - 1, $x + $rx + 1, $y + $ry + 1)) !== false) {
+ ImageFilledPolygon($this->_canvas, $polygon, count($polygon) / 2, $fill);
+ }
+
+ if (($line = $this->_getLineStyle($lineColor)) !== false) {
+ ImagePolygon($this->_canvas, $polygon, count($polygon) / 2, $line);
+ }
+
+ parent::pieSlice($params);
+ }
+
+ /**
+ * Get the width of a text,
+ *
+ * @param string $text The text to get the width of
+ * @return int The width of the text
+ */
+ function textWidth($text)
+ {
+ if (isset($this->_font['file'])) {
+ $angle = 0;
+ if (isset($this->_font['angle'])) {
+ $angle = $this->_font['angle'];
+ }
+
+ $width = 0;
+ $lines = explode("\n", $text);
+ foreach ($lines as $line) {
+ $bounds = ImageTTFBBox(
+ $this->_font['size'],
+ $angle,
+ $this->_font['file'],
+ $text
+ );
+
+ $x0 = min($bounds[0], $bounds[2], $bounds[4], $bounds[6]);
+ $x1 = max($bounds[0], $bounds[2], $bounds[4], $bounds[6]);
+ $width = max(abs($x0 - $x1), $width);
+ }
+ return $width;
+ } else {
+ if ((isset($this->_font['vertical'])) && ($this->_font['vertical'])) {
+ return ImageFontHeight($this->_font['font']) * (substr_count($text, "\n") + 1);
+ } else {
+ $width = 0;
+ $lines = explode("\n", $text);
+ foreach ($lines as $line) {
+ $width = max($width, ImageFontWidth($this->_font['font']) * strlen($line));
+ }
+ return $width;
+ }
+ }
+ }
+
+ /**
+ * Get the height of a text.
+ *
+ * Note! This method can give some peculiar results, since ImageTTFBBox() returns the total
+ * bounding box of a text, where ImageTTF() writes the text on the baseline of the text, that
+ * is 'g', 'p', 'q' and other letters that dig under the baseline will appear to have a larger
+ * height than they actually do. Have a look at the tests/text.php test case - the first two
+ * columns, 'left and 'center', both look alright, whereas the last column, 'right', appear
+ * with a larger space between the first text and the second. This is because the total height
+ * is actually smaller by exactly the number of pixels that the 'g' digs under the baseline.
+ * Remove the 'g' from the text and they appear correct.
+ *
+ * @param string $text The text to get the height of
+ * @param bool $force Force the method to calculate the size
+ * @return int The height of the text
+ */
+ function textHeight($text, $force = false)
+ {
+ if (isset($this->_font['file'])) {
+ $angle = 0;
+ if (isset($this->_font['angle'])) {
+ $angle = $this->_font['angle'];
+ }
+
+ $linebreaks = substr_count($text, "\n");
+ if (($angle == 0) && ($linebreaks == 0) && ($force === false)) {
+ /*
+ * if the angle is 0 simply return the size, due to different
+ * heights for example for x-axis labels, making the labels
+ * _not_ appear as written on the same baseline
+ */
+ return $this->_font['size'] + 2;
+ }
+
+ $height = 0;
+ $lines = explode("\n", $text);
+ foreach ($lines as $line) {
+ $bounds = ImageTTFBBox(
+ $this->_font['size'],
+ $angle,
+ $this->_font['file'],
+ $line
+ );
+
+ $y0 = min($bounds[1], $bounds[3], $bounds[5], $bounds[7]);
+ $y1 = max($bounds[1], $bounds[3], $bounds[5], $bounds[7]);
+ $height += abs($y0 - $y1);
+ }
+ return $height + $linebreaks * 2;
+ } else {
+ if ((isset($this->_font['vertical'])) && ($this->_font['vertical'])) {
+ $width = 0;
+ $lines = explode("\n", $text);
+ foreach ($lines as $line) {
+ $width = max($width, ImageFontWidth($this->_font['font']) * strlen($line));
+ }
+ return $width;
+ } else {
+ return ImageFontHeight($this->_font['font']) * (substr_count($text, "\n") + 1);
+ }
+ }
+ }
+
+ /**
+ * Writes text
+ *
+ * Parameter array:
+ *
+ * 'x': int X-point of text
+ *
+ * 'y': int Y-point of text
+ *
+ * 'text': string The text to add
+ *
+ * 'alignment': array [optional] Alignment
+ *
+ * 'color': mixed [optional] The color of the text
+ */
+ function addText($params)
+ {
+ $x0 = $this->_getX($params['x']);
+ $y0 = $this->_getY($params['y']);
+ $text = $params['text'];
+ $color = (isset($params['color']) ? $params['color'] : false);
+ $alignment = (isset($params['alignment']) ? $params['alignment'] : false);
+
+ $text = str_replace("\r", '', $text);
+
+ if (!is_array($alignment)) {
+ $alignment = array('vertical' => 'top', 'horizontal' => 'left');
+ }
+
+ if (!isset($alignment['vertical'])) {
+ $alignment['vertical'] = 'top';
+ }
+
+ if (!isset($alignment['horizontal'])) {
+ $alignment['horizontal'] = 'left';
+ }
+
+ if ($alignment['vertical'] == 'bottom') {
+ $y0 = $y0 - $this->textHeight($text, true);
+ } elseif ($alignment['vertical'] == 'center') {
+ $y0 = $y0 - ($this->textHeight($text, true) / 2);
+ }
+
+ $lines = explode("\n", $text);
+ foreach ($lines as $line) {
+ $textWidth = $this->textWidth($line);
+ $textHeight = $this->textHeight($line, true);
+
+ $x = $x0;
+ $y = $y0;
+
+ $y0 += $textHeight + 2;
+
+ if ($alignment['horizontal'] == 'right') {
+ $x = $x - $textWidth;
+ } elseif ($alignment['horizontal'] == 'center') {
+ $x = $x - ($textWidth / 2);
+ }
+
+ if (($color === false) && (isset($this->_font['color']))) {
+ $color = $this->_font['color'];
+ }
+
+ if ($color != 'transparent') {
+ if (isset($this->_font['file'])) {
+ if (($this->_font['angle'] < 180) && ($this->_font['angle'] >= 0)) {
+ $y += $textHeight;
+ }
+ if (($this->_font['angle'] >= 90) && ($this->_font['angle'] < 270)) {
+ $x += $textWidth;
+ }
+
+ ImageTTFText(
+ $this->_canvas,
+ $this->_font['size'],
+ $this->_font['angle'],
+ $x,
+ $y,
+ $this->_color($color),
+ $this->_font['file'],
+ $line
+ );
+
+ } else {
+ if ((isset($this->_font['vertical'])) && ($this->_font['vertical'])) {
+ ImageStringUp(
+ $this->_canvas,
+ $this->_font['font'],
+ $x,
+ $y + $this->textHeight($text),
+ $line,
+ $this->_color($color)
+ );
+ } else {
+ ImageString(
+ $this->_canvas,
+ $this->_font['font'],
+ $x,
+ $y,
+ $line,
+ $this->_color($color)
+ );
+ }
+ }
+ }
+ }
+ parent::addText($params);
+ }
+
+ /**
+ * Overlay image
+ *
+ * Parameter array:
+ *
+ * 'x': int X-point of overlayed image
+ *
+ * 'y': int Y-point of overlayed image
+ *
+ * 'filename': string The filename of the image to overlay
+ *
+ * 'width': int [optional] The width of the overlayed image (resizing if possible)
+ *
+ * 'height': int [optional] The height of the overlayed image (resizing if possible)
+ *
+ * 'alignment': array [optional] Alignment
+ */
+ function image($params)
+ {
+ $x = $this->_getX($params['x']);
+ $y = $this->_getY($params['y']);
+ $filename = $params['filename'];
+ $width = (isset($params['width']) ? $params['width'] : false);
+ $height = (isset($params['height']) ? $params['height'] : false);
+ $alignment = (isset($params['alignment']) ? $params['alignment'] : false);
+
+ if (!is_array($alignment)) {
+ $alignment = array('vertical' => 'top', 'horizontal' => 'left');
+ }
+
+ if (!isset($alignment['vertical'])) {
+ $alignment['vertical'] = 'top';
+ }
+
+ if (!isset($alignment['horizontal'])) {
+ $alignment['horizontal'] = 'left';
+ }
+
+ if (file_exists($filename)) {
+ if (strtolower(substr($filename, -4)) == '.png') {
+ $image = ImageCreateFromPNG($filename);
+ } elseif (strtolower(substr($filename, -4)) == '.gif') {
+ $image = ImageCreateFromGIF($filename);
+ } else {
+ $image = ImageCreateFromJPEG($filename);
+ }
+
+ $imgWidth = ImageSX($image);
+ $imgHeight = ImageSY($image);
+
+ $outputWidth = ($width !== false ? $width : $imgWidth);
+ $outputHeight = ($height !== false ? $height : $imgHeight);
+
+ if ($alignment['horizontal'] == 'right') {
+ $x -= $outputWidth;
+ } elseif ($alignment['horizontal'] == 'center') {
+ $x -= $outputWidth / 2;
+ }
+
+ if ($alignment['vertical'] == 'bottom') {
+ $y -= $outputHeight;
+ } elseif ($alignment['vertical'] == 'center') {
+ $y -= $outputHeight / 2;
+ }
+
+ if ((($width !== false) && ($width != $imgWidth)) ||
+ (($height !== false) && ($height != $imgHeight)))
+ {
+ if ($this->_gd2) {
+ ImageCopyResampled(
+ $this->_canvas,
+ $image,
+ $x,
+ $y,
+ 0,
+ 0,
+ $width,
+ $height,
+ $imgWidth,
+ $imgHeight
+ );
+ } else {
+ ImageCopyResized(
+ $this->_canvas,
+ $image,
+ $x,
+ $y,
+ 0,
+ 0,
+ $width,
+ $height,
+ $imgWidth,
+ $imgHeight
+ );
+ }
+ } else {
+ ImageCopy(
+ $this->_canvas,
+ $image,
+ $x,
+ $y,
+ 0,
+ 0,
+ $imgWidth,
+ $imgHeight
+ );
+ }
+ ImageDestroy($image);
+ }
+ parent::image($params);
+ }
+
+ /**
+ * Set clipping to occur
+ *
+ * Parameter array:
+ *
+ * 'x0': int X point of Upper-left corner
+ * 'y0': int X point of Upper-left corner
+ * 'x1': int X point of lower-right corner
+ * 'y1': int Y point of lower-right corner
+ */
+ function setClipping($params = false)
+ {
+ if ($params === false) {
+ $index = count($this->_clipping) - 1;
+ if (isset($this->_clipping[$index])) {
+ $params = $this->_clipping[$index];
+ $canvas = $params['canvas'];
+ ImageCopy(
+ $canvas,
+ $this->_canvas,
+ min($params['x0'], $params['x1']),
+ min($params['y0'], $params['y1']),
+ min($params['x0'], $params['x1']),
+ min($params['y0'], $params['y1']),
+ abs($params['x1'] - $params['x0'] + 1),
+ abs($params['y1'] - $params['y0'] + 1)
+ );
+ $this->_canvas = $canvas;
+ unset($this->_clipping[$index]);
+ }
+ }
+ else {
+ $params['canvas'] = $this->_canvas;
+
+ if ($this->_gd2) {
+ $this->_canvas = ImageCreateTrueColor(
+ $this->_width,
+ $this->_height
+ );
+ if ($this->_alpha) {
+ ImageAlphaBlending($this->_canvas, true);
+ }
+ } else {
+ $this->_canvas = ImageCreate($this->_width, $this->_height);
+ }
+
+ if (($this->_gd2) && ($this->_antialias === 'native')) {
+ ImageAntialias($this->_canvas, true);
+ }
+
+ ImageCopy($this->_canvas, $params['canvas'], 0, 0, 0, 0, $this->_width, $this->_height);
+
+ $this->_clipping[count($this->_clipping)] = $params;
+ }
+ }
+
+ /**
+ * Get a canvas specific HTML tag.
+ *
+ * This method implicitly saves the canvas to the filename in the
+ * filesystem path specified and parses it as URL specified by URL path
+ *
+ * Parameter array:
+ *
+ * 'filename' string
+ *
+ * 'filepath': string Path to the file on the file system. Remember the final slash
+ *
+ * 'urlpath': string Path to the file available through an URL. Remember the final slash
+ *
+ * 'alt': string [optional] Alternative text on image
+ *
+ * 'cssclass': string [optional] The CSS Stylesheet class
+ *
+ * 'border': int [optional] The border width on the image
+ */
+ function toHtml($params)
+ {
+ parent::toHtml($params);
+ return '<img src="' . $params['urlpath'] . $params['filename'] . '"' .
+ (isset($params['alt']) ? ' alt="' . $params['alt'] . '"' : '') .
+ (isset($params['cssclass']) ? ' class="' . $params['cssclass'] . '"' : '') .
+ (isset($params['border']) ? ' border="' . $params['border'] . '"' : '') .
+ (isset($this->_imageMap) ? ' usemap="#' . $params['filename'] . '"' : '') . '>' .
+ (isset($this->_imageMap) ? "\n" . $this->_imageMap->toHtml(array('name' => $params['filename'])) : '');
+ }
+
+ /**
+ * Resets the canvas.
+ *
+ * Include fillstyle, linestyle, thickness and polygon
+ * @access private
+ */
+ function _reset()
+ {
+ if ($this->_gd2) {
+ ImageSetThickness($this->_canvas, 1);
+ }
+ if ($this->_tileImage != null) {
+ ImageDestroy($this->_tileImage);
+ $this->_tileImage = null;
+ }
+ parent::_reset();
+ $this->_font = array('font' => 1, 'color' => 'black');
+ }
+
+ /**
+ * Check which version of GD is installed
+ *
+ * @return int 0 if GD isn't installed, 1 if GD 1.x is installed and 2 if GD
+ * 2.x is installed
+ * @access private
+ */
+ function _version()
+ {
+ $result = false;
+ if (function_exists('gd_info')) {
+ $info = gd_info();
+ $version = $info['GD Version'];
+ } else {
+ ob_start();
+ phpinfo(8);
+ $php_info = ob_get_contents();
+ ob_end_clean();
+
+ if (ereg("<td[^>]*>GD Version *<\/td><td[^>]*>([^<]*)<\/td>",
+ $php_info, $result))
+ {
+ $version = $result[1];
+ }
+ }
+
+ if (ereg('1\.[0-9]{1,2}', $version)) {
+ return 1;
+ } elseif (ereg('2\.[0-9]{1,2}', $version)) {
+ return 2;
+ } else {
+ return 0;
+ }
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Canvas/GD/JPG.php b/config/dspam/pear/Image/Canvas/GD/JPG.php
new file mode 100644
index 00000000..ef78aeca
--- /dev/null
+++ b/config/dspam/pear/Image/Canvas/GD/JPG.php
@@ -0,0 +1,119 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Canvas
+ *
+ * Canvas class to handle JPEG format.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Canvas
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212
+ */
+
+/**
+ * Include file Image/Canvas/GD.php
+ */
+require_once 'Image/Canvas/GD.php';
+
+/**
+ * JPEG Canvas class.
+ *
+ * @category Images
+ * @package Image_Canvas
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212
+ */
+class Image_Canvas_GD_JPG extends Image_Canvas_GD
+{
+
+ /**
+ * The JPEG quality
+ * @var int
+ * @access private
+ */
+ var $_quality = 75;
+
+ /**
+ * Create the JPEG canvas
+ *
+ * Additional parameters other than those available for common {@link
+ * Image_Graph_Canvas_GD} class are:
+ *
+ * 'quality' The JPEG quality in as a percentage value from 0 (lowest
+ * quality, smallest file) to 100 (highest quality, biggest file)
+ *
+ * @param array $param Parameter array
+ */
+ function Image_Canvas_GD_JPG($param)
+ {
+ parent::Image_Canvas_GD($param);
+
+ if (isset($param['quality'])) {
+ $this->_quality = max(0, min(100, $param['quality']));
+ }
+
+ $this->rectangle(
+ array(
+ 'x0' => $this->_left,
+ 'y0' => $this->_top,
+ 'x1' => $this->_left + $this->_width - 1,
+ 'y1' => $this->_top + $this->_height - 1,
+ 'fill' => 'white',
+ 'line' => 'transparent'
+ )
+ );
+ }
+
+ /**
+ * Output the result of the canvas
+ *
+ * @param array $param Parameter array
+ * @abstract
+ */
+ function show($param = false)
+ {
+ parent::show($param);
+ header('Content-type: image/jpg');
+ header('Content-Disposition: inline; filename = \"'. basename($_SERVER['PHP_SELF'], '.php') . '.jpg\"');
+ ImageJPEG($this->_canvas, '', $this->_quality);
+ ImageDestroy($this->_canvas);
+ }
+
+ /**
+ * Output the result of the canvas
+ *
+ * @param array $param Parameter array
+ * @abstract
+ */
+ function save($param = false)
+ {
+ parent::save($param);
+ ImageJPEG($this->_canvas, $param['filename'], $this->_quality);
+ ImageDestroy($this->_canvas);
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Canvas/GD/PNG.php b/config/dspam/pear/Image/Canvas/GD/PNG.php
new file mode 100644
index 00000000..75184d8c
--- /dev/null
+++ b/config/dspam/pear/Image/Canvas/GD/PNG.php
@@ -0,0 +1,125 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Canvas
+ *
+ * Canvas class to handle PNG format.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Canvas
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212
+ */
+
+/**
+ * Include file Image/Canvas/GD.php
+ */
+require_once 'Image/Canvas/GD.php';
+
+/**
+ * PNG Canvas class.
+ *
+ * @category Images
+ * @package Image_Canvas
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212
+ */
+class Image_Canvas_GD_PNG extends Image_Canvas_GD
+{
+
+ /**
+ * Create the PNG canvas
+ *
+ * @param array $param Parameter array
+ */
+ function Image_Canvas_GD_PNG($param)
+ {
+ parent::Image_Canvas_GD($param);
+
+ if ((isset($param['transparent'])) && ($param['transparent']) &&
+ ($this->_gd2)
+ ) {
+ if ($param['transparent'] === true) {
+ $transparent = '#123ABD';
+ } else {
+ $transparent = $param['transparent'];
+ }
+ $color = $this->_color($transparent);
+ $trans = ImageColorTransparent($this->_canvas, $color);
+
+ $this->rectangle(
+ array(
+ 'x0' => $this->_left,
+ 'y0' => $this->_top,
+ 'x1' => $this->_left + $this->_width - 1,
+ 'y1' => $this->_top + $this->_height - 1,
+ 'fill' => 'opague',
+ 'line' => 'transparent'
+ )
+ );
+ } else {
+ $this->rectangle(
+ array(
+ 'x0' => $this->_left,
+ 'y0' => $this->_top,
+ 'x1' => $this->_left + $this->_width - 1,
+ 'y1' => $this->_top + $this->_height - 1,
+ 'fill' => 'white',
+ 'line' => 'transparent'
+ )
+ );
+ }
+ }
+
+ /**
+ * Output the result of the canvas
+ *
+ * @param array $param Parameter array
+ * @abstract
+ */
+ function show($param = false)
+ {
+ parent::show($param);
+ header('Content-type: image/png');
+ header('Content-Disposition: inline; filename = \"'. basename($_SERVER['PHP_SELF'], '.php') . '.png\"');
+ ImagePNG($this->_canvas);
+ ImageDestroy($this->_canvas);
+ }
+
+ /**
+ * Output the result of the canvas
+ *
+ * @param array $param Parameter array
+ * @abstract
+ */
+ function save($param = false)
+ {
+ parent::save($param);
+ ImagePNG($this->_canvas, $param['filename']);
+ ImageDestroy($this->_canvas);
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Canvas/ImageMap.php b/config/dspam/pear/Image/Canvas/ImageMap.php
new file mode 100644
index 00000000..e69f3de2
--- /dev/null
+++ b/config/dspam/pear/Image/Canvas/ImageMap.php
@@ -0,0 +1,354 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Canvas
+ *
+ * Class for handling output as a HTML imagemap
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Canvas
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212
+ */
+
+/**
+ * Class for handling output as a HTML imagemap
+ *
+ * @category Images
+ * @package Image_Canvas
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212
+ * @since version 0.2.0
+ */
+class Image_Canvas_ImageMap extends Image_Canvas
+{
+
+ /**
+ * The image map (if any)
+ * @var array
+ * @access private
+ */
+ var $_map = array();
+
+ /**
+ * Add a map tag
+ * @param string $shape The shape, either rect, circle or polygon
+ * @param string $coords The list of coordinates for the shape
+ * @param array $params Parameter array
+ */
+ function _addMapTag($shape, $coords, $params)
+ {
+ if (isset($params['url'])) {
+ $url = $params['url'];
+ $target = (isset($params['target']) ? $params['target'] : false);
+ $alt = (isset($params['alt']) ? $params['alt'] : false);
+
+ $tags = '';
+ if (isset($params['htmltags'])) {
+ foreach ($params['htmltags'] as $key => $value) {
+ $tags .= ' ';
+ if (strpos($value, '"') !== false) {
+ $tags .= $key . '=\'' . $value . '\'';
+ } else {
+ $tags .= $key . '="' . $value . '"';
+ }
+ }
+ }
+
+ $this->_map[] =
+ '<area shape="' . $shape . '" coords="' . $coords . '" href="' . $url . '"' .
+ ($target ? ' target="' . $target . '"' : '') .
+ ($alt ? ' alt="' . $alt . '"' : '') .
+ (isset($params['id']) ? ' id="' . $params['id'] . '"' : '') .
+ $tags .
+ '>';
+ }
+ }
+
+ /**
+ * Draw a line
+ *
+ * Parameter array:
+ * 'x0': int X start point
+ * 'y0': int Y start point
+ * 'x1': int X end point
+ * 'y1': int Y end point
+ * 'color': mixed [optional] The line color
+ * 'mapsize': int [optional] The size of the image map (surrounding the line)
+ * @param array $params Parameter array
+ */
+ function line($params)
+ {
+ if (isset($params['url'])) {
+ $mapsize = (isset($params['mapsize']) ? $params['mapsize'] : 2);
+ $this->_addMapTag(
+ 'polygon',
+ $this->_getX($params['x0'] - $mapsize) . ',' .
+ $this->_getY($params['y0'] - $mapsize) . ',' .
+ $this->_getX($params['x1'] + $mapsize) . ',' .
+ $this->_getY($params['y1'] - $mapsize) . ',' .
+
+ $this->_getX($params['x1'] + $mapsize) . ',' .
+ $this->_getY($params['y1'] + $mapsize) . ',' .
+ $this->_getX($params['x0'] - $mapsize) . ',' .
+ $this->_getY($params['y0'] + $mapsize),
+ $params
+ );
+ }
+ parent::line($params);
+ }
+
+ /**
+ * Draws a polygon
+ *
+ * Parameter array:
+ * 'connect': bool [optional] Specifies whether the start point should be
+ * connected to the endpoint (closed polygon) or not (connected line)
+ * 'fill': mixed [optional] The fill color
+ * 'line': mixed [optional] The line color
+ * 'map_vertices': bool [optional] Specifies whether the image map should map the vertices instead of the polygon as a whole
+ * 'url': string [optional] URL to link the polygon as a whole to (also used for default in case 'map_vertices' is used)
+ * 'alt': string [optional] Alternative text to show in the image map (also used for default in case 'map_vertices' is used)
+ * 'target': string [optional] The link target on the image map (also used for default in case 'map_vertices' is used)
+ * @param array $params Parameter array
+ */
+ function polygon($params)
+ {
+ if ((isset($params['map_vertices'])) && ($params['map_vertices'] === true)) {
+ $mapsize = (isset($params['mapsize']) ? $params['mapsize'] : 2);
+ foreach ($this->_polygon as $point) {
+ $vertex_param = $params;
+ if (isset($point['url'])) {
+ $vertex_param['url'] = $point['url'];
+ }
+ if (isset($point['target'])) {
+ $vertex_param['target'] = $point['target'];
+ }
+ if (isset($point['alt'])) {
+ $vertex_param['alt'] = $point['alt'];
+ }
+ $vertex_mapsize = $mapsize;
+ if (isset($point['mapsize'])) {
+ $vertex_mapsize = $point['mapsize'];
+ }
+ if (isset($point['htmltags'])) {
+ $vertex_param['htmltags'] = $point['htmltags'];
+ }
+ $this->_addMapTag(
+ 'circle',
+ $this->_getX($point['X']) . ',' .
+ $this->_getY($point['Y']) . ',' .
+ $mapsize,
+ $vertex_param
+ );
+ }
+ }
+ else if (isset($params['url'])) {
+ $points = '';
+ foreach ($this->_polygon as $point) {
+ if ($points != '') {
+ $points .= ',';
+ }
+ $points .= $this->_getX($point['X']) . ',' . $this->_getY($point['Y']);
+ }
+ $this->_addMapTag('polygon', $points, $params);
+ }
+ parent::polygon($params);
+ }
+
+ /**
+ * Draw a rectangle
+ *
+ * Parameter array:
+ * 'x0': int X start point
+ * 'y0': int Y start point
+ * 'x1': int X end point
+ * 'y1': int Y end point
+ * 'fill': mixed [optional] The fill color
+ * 'line': mixed [optional] The line color
+ * @param array $params Parameter array
+ */
+ function rectangle($params)
+ {
+ if (isset($params['url'])) {
+ $this->_addMapTag(
+ 'rect',
+ $this->_getX($params['x0']) . ',' .
+ $this->_getY($params['y0']) . ',' .
+ $this->_getX($params['x1']) . ',' .
+ $this->_getY($params['y1']),
+ $params
+ );
+ }
+ parent::rectangle($params);
+ }
+
+ /**
+ * Draw an ellipse
+ *
+ * Parameter array:
+ * 'x': int X center point
+ * 'y': int Y center point
+ * 'rx': int X radius
+ * 'ry': int Y radius
+ * 'fill': mixed [optional] The fill color
+ * 'line': mixed [optional] The line color
+ * @param array $params Parameter array
+ */
+ function ellipse($params)
+ {
+ if (isset($params['url'])) {
+ if ($params['rx'] == $params['ry']) {
+ $this->_addMapTag(
+ 'circle',
+ $this->_getX($params['x']) . ',' .
+ $this->_getY($params['y']) . ',' .
+ $this->_getX($params['rx']),
+ $params
+ );
+ } else {
+ $points = '';
+ for ($v = 0; $v <= 360; $v += 30) {
+ if ($points != '') {
+ $points .= ',';
+ }
+ $points .=
+ round($this->_getX($params['x']) + $this->_getX($params['rx']) * cos(deg2rad($v % 360))) . ',' .
+ round($this->_getY($params['y']) + $this->_getX($params['ry']) * sin(deg2rad($v % 360)));
+ }
+ $this->_addMapTag(
+ 'polygon',
+ $points,
+ $params
+ );
+ }
+ }
+ parent::ellipse($params);
+ }
+
+ /**
+ * Draw a pie slice
+ *
+ * Parameter array:
+ * 'x': int X center point
+ * 'y': int Y center point
+ * 'rx': int X radius
+ * 'ry': int Y radius
+ * 'v1': int The starting angle (in degrees)
+ * 'v2': int The end angle (in degrees)
+ * 'srx': int [optional] Starting X-radius of the pie slice (i.e. for a doughnut)
+ * 'sry': int [optional] Starting Y-radius of the pie slice (i.e. for a doughnut)
+ * 'fill': mixed [optional] The fill color
+ * 'line': mixed [optional] The line color
+ * @param array $params Parameter array
+ */
+ function pieslice($params)
+ {
+ if (isset($params['url'])) {
+ $x = $this->_getX($params['x']);
+ $y = $this->_getY($params['y']);
+ $rx = $params['rx'];
+ $ry = $params['ry'];
+ $v1a = $params['v1'];
+ $v2a = $params['v2'];
+ $v1 = min($v1a, $v2a);
+ $v2 = max($v1a, $v2a);
+ $srx = (isset($params['srx']) ? $params['srx'] : 0);
+ $sry = (isset($params['sry']) ? $params['sry'] : 0);
+
+ $points =
+ round(($x + $srx * cos(deg2rad($v1 % 360)))) . ',' .
+ round(($y + $sry * sin(deg2rad($v1 % 360)))) . ',';
+
+ for ($v = $v1; $v < $v2; $v += 30) {
+ $points .=
+ round(($x + $rx * cos(deg2rad($v % 360)))) . ',' .
+ round(($y + $ry * sin(deg2rad($v % 360)))) . ',';
+ }
+
+ $points .=
+ round(($x + $rx * cos(deg2rad($v2 % 360)))) . ',' .
+ round(($y + $ry * sin(deg2rad($v2 % 360))));
+
+ if (($srx != 0) || ($sry != 0)) {
+ $points .= ',';
+ for ($v = $v2; $v > $v1; $v -= 30) {
+ $points .=
+ round(($x + $srx * cos(deg2rad($v % 360)))) . ',' .
+ round(($y + $sry * sin(deg2rad($v % 360)))) . ',';
+ }
+
+ }
+
+ $this->_addMapTag('polygon', $points, $params);
+ }
+ parent::pieslice($params);
+ }
+
+ /**
+ * Output the result of the canvas to the browser
+ *
+ * @param array $params Parameter array, the contents and meaning depends on the actual Canvas
+ * @abstract
+ */
+ function show($params = false)
+ {
+ parent::show($params);
+ if (count($this->_map) > 0) {
+ print $this->toHtml($params);
+ }
+ }
+
+ /**
+ * Save the result of the canvas to a file
+ *
+ * Parameter array:
+ * 'filename': string The file to output to
+ * @param array $params Parameter array, the contents and meaning depends on the actual Canvas
+ * @abstract
+ */
+ function save($params = false)
+ {
+ parent::save($params);
+ $file = fopen($param['filename'], 'w+');
+ fwrite($file, $this->toHtml($params));
+ fclose($file);
+ }
+
+ /**
+ * Get a canvas specific HTML tag.
+ *
+ * Parameter array:
+ * 'name': string The name of the image map
+ */
+ function toHtml($params)
+ {
+ if (count($this->_map) > 0) {
+ return '<map name="' . $params['name'] . '">' . "\n\t" . implode($this->_map, "\n\t") . "\n</map>";
+ }
+ return '';
+ }
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Canvas/PDF.php b/config/dspam/pear/Image/Canvas/PDF.php
new file mode 100644
index 00000000..180263cb
--- /dev/null
+++ b/config/dspam/pear/Image/Canvas/PDF.php
@@ -0,0 +1,1007 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Class for handling output in PDF format.
+ *
+ * Requires PHP extension PDFlib
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Canvas
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212
+ */
+
+/**
+ * Include file Image/Canvas.php
+ */
+require_once 'Image/Canvas.php';
+
+/**
+ * Include file Image/Canvas/Color.php
+ */
+require_once 'Image/Canvas/Color.php';
+
+/**
+ * PDF Canvas class.
+ *
+ * @category Images
+ * @package Image_Canvas
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212
+ */
+class Image_Canvas_PDF extends Image_Canvas
+{
+
+ /**
+ * The PDF document
+ * @var resource
+ * @access private
+ */
+ var $_pdf;
+
+ /**
+ * The major version of PDFlib
+ * @var int
+ * @access private
+ */
+ var $_pdflib;
+
+ /**
+ * The font
+ * @var mixed
+ * @access private
+ */
+ var $_pdfFont = false;
+
+ /**
+ * The width of the page
+ * @var int
+ * @access private
+ */
+ var $_pageWidth;
+
+ /**
+ * The height of the page
+ * @var int
+ * @access private
+ */
+ var $_pageHeight;
+
+ /**
+ * Create the PDF canvas.
+ *
+ * Parameters available:
+ *
+ * 'page' Specify the page/paper format for the graph's page, available
+ * formats are: A0, A1, A2, A3, A4, A5, A6, B5, letter, legal, ledger,
+ * 11x17, cd_front, inlay, inlay_nosides
+ *
+ * 'align' Alignment of the graph on the page, available options are:
+ * topleft, topcenter, topright, leftcenter, center, rightcenter,
+ * leftbottom, centerbottom, rightbottom
+ *
+ * 'orientation' Specifies the paper orientation, default is 'portrait' and
+ * 'landscape' is also supported.
+ *
+ * 'creator' The creator tag of the PDF/graph
+ *
+ * 'author' The author tag of the PDF/graph
+ *
+ * 'title' The title tag of the PDF/graph
+ *
+ * 'width' The width of the graph on the page
+ *
+ * 'height' The height of the graph on the page
+ *
+ * 'left' The left offset of the graph on the page
+ *
+ * 'top' The top offset of the graph on the page
+ *
+ * 'filename' The PDF file to open/add page to, using 'filename' requires
+ * the commercial version of PDFlib (http://www.pdflib.com/), this has for
+ * obvious ($ 450) reasons not been tested
+ *
+ * 'pdf' An existing PDFlib PDF document to add the page to
+ *
+ * 'add_page' (true/false) Used together with 'pdf', to specify whether the
+ * canvas should add a new graph page (true) or create the graph on the
+ * current page (false), default is 'true'
+ *
+ * The 'page' and 'width' & 'height' can be mutually omitted, if 'page' is
+ * omitted the page is created using dimensions of width x height, and if
+ * width and height are omitted the page dimensions are used for the graph.
+ *
+ * If 'pdf' is specified, 'filename', 'creator', 'author' and 'title' has no
+ * effect.
+ *
+ * 'left' and 'top' are overridden by 'align'
+ *
+ * It is required either to specify 'width' & 'height' or 'page'.
+ *
+ * The PDF format/PDFlib has some limitations on the capabilities, which
+ * means some functionality available using other canvass (fx. alpha
+ * blending and gradient fills) are not supported with PDF (see Canvas.txt
+ * in the docs/ folder for further details)
+ *
+ * @param array $param Parameter array
+ */
+ function Image_Canvas_PDF($param)
+ {
+ if (isset($param['page'])) {
+ switch (strtoupper($param['page'])) {
+ case 'A0':
+ $this->_pageWidth = 2380;
+ $this->_pageHeight = 3368;
+ break;
+
+ case 'A1':
+ $this->_pageWidth = 1684;
+ $this->_pageHeight = 2380;
+ break;
+
+ case 'A2':
+ $this->_pageWidth = 1190;
+ $this->_pageHeight = 1684;
+ break;
+
+ case 'A3':
+ $this->_pageWidth = 842;
+ $this->_pageHeight = 1190;
+ break;
+
+ case 'A4':
+ $this->_pageWidth = 595;
+ $this->_pageHeight = 842;
+ break;
+
+ case 'A5':
+ $this->_pageWidth = 421;
+ $this->_pageHeight = 595;
+ break;
+
+ case 'A6':
+ $this->_pageWidth = 297;
+ $this->_pageHeight = 421;
+ break;
+
+ case 'B5':
+ $this->_pageWidth = 501;
+ $this->_pageHeight = 709;
+ break;
+
+ case 'LETTER':
+ $this->_pageWidth = 612;
+ $this->_pageHeight = 792;
+ break;
+
+ case 'LEGAL':
+ $this->_pageWidth = 612;
+ $this->_pageHeight = 1008;
+ break;
+
+ case 'LEDGER':
+ $this->_pageWidth = 1224;
+ $this->_pageHeight = 792;
+ break;
+
+ case '11X17':
+ $this->_pageWidth = 792;
+ $this->_pageHeight = 1224;
+ break;
+
+ case 'CD_FRONT':
+ $this->_pageWidth = 337;
+ $this->_pageHeight = 337;
+ break;
+
+ case 'INLAY':
+ $this->_pageWidth = 425;
+ $this->_pageHeight = 332;
+ break;
+
+ case 'INLAY_NOSIDES':
+ $this->_pageWidth = 390;
+ $this->_pageHeight = 332;
+ break;
+ }
+ }
+
+ if ((isset($param['orientation'])) && (strtoupper($param['orientation']) == 'LANDSCAPE')) {
+ $w = $this->_pageWidth;
+ $this->_pageWidth = $this->_pageHeight;
+ $this->_pageHeight = $w;
+ }
+
+ parent::Image_Canvas($param);
+
+ if (!$this->_pageWidth) {
+ $this->_pageWidth = $this->_width;
+ } elseif (!$this->_width) {
+ $this->_width = $this->_pageWidth;
+ }
+
+ if (!$this->_pageHeight) {
+ $this->_pageHeight = $this->_height;
+ } elseif (!$this->_height) {
+ $this->_height = $this->_pageHeight;
+ }
+
+ $this->_width = min($this->_width, $this->_pageWidth);
+ $this->_height = min($this->_height, $this->_pageHeight);
+
+ if ((isset($param['align'])) &&
+ (($this->_width != $this->_pageWidth) || ($this->_height != $this->_pageHeight))
+ ) {
+ switch (strtoupper($param['align'])) {
+ case 'TOPLEFT':
+ $this->_top = 0;
+ $this->_left = 0;
+ break;
+
+ case 'TOPCENTER':
+ $this->_top = 0;
+ $this->_left = ($this->_pageWidth - $this->_width) / 2;
+ break;
+
+ case 'TOPRIGHT':
+ $this->_top = 0;
+ $this->_left = $this->_pageWidth - $this->_width;
+ break;
+
+ case 'LEFTCENTER':
+ $this->_top = ($this->_pageHeight - $this->_height) / 2;
+ $this->_left = 0;
+ break;
+
+ case 'CENTER':
+ $this->_top = ($this->_pageHeight - $this->_height) / 2;
+ $this->_left = ($this->_pageWidth - $this->_width) / 2;
+ break;
+
+ case 'RIGHTCENTER':
+ $this->_top = ($this->_pageHeight - $this->_height) / 2;
+ $this->_left = $this->_pageWidth - $this->_width;
+ break;
+
+ case 'LEFTBOTTOM':
+ $this->_top = $this->_pageHeight - $this->_height;
+ $this->_left = 0;
+ break;
+
+ case 'CENTERBOTTOM':
+ $this->_top = $this->_pageHeight - $this->_height;
+ $this->_left = ($this->_pageWidth - $this->_width) / 2;
+ break;
+
+ case 'RIGHTBOTTOM':
+ $this->_top = $this->_pageHeight - $this->_height;
+ $this->_left = $this->_pageWidth - $this->_width;
+ break;
+ }
+ }
+
+ $this->_pdflib = $this->_version();
+
+ $addPage = true;
+ if ((isset($param['pdf'])) && (is_resource($param['pdf']))) {
+ $this->_pdf =& $param['pdf'];
+ if ((isset($param['add_page'])) && ($param['add_page'] === false)) {
+ $addPage = false;
+ }
+ } else {
+ $this->_pdf = pdf_new();
+
+ if (isset($param['filename'])) {
+ pdf_open_file($this->_pdf, $param['filename']);
+ } else {
+ pdf_open_file($this->_pdf, '');
+ }
+
+ pdf_set_parameter($this->_pdf, 'warning', 'true');
+
+ pdf_set_info($this->_pdf, 'Creator', (isset($param['creator']) ? $param['creator'] : 'PEAR::Image_Canvas'));
+ pdf_set_info($this->_pdf, 'Author', (isset($param['author']) ? $param['author'] : 'Jesper Veggerby'));
+ pdf_set_info($this->_pdf, 'Title', (isset($param['title']) ? $param['title'] : 'Image_Canvas'));
+ }
+
+ if ($addPage) {
+ pdf_begin_page($this->_pdf, $this->_pageWidth, $this->_pageHeight);
+ }
+ $this->_reset();
+ }
+
+ /**
+ * Get the x-point from the relative to absolute coordinates
+ *
+ * @param float $x The relative x-coordinate (in percentage of total width)
+ * @return float The x-coordinate as applied to the canvas
+ * @access private
+ */
+ function _getX($x)
+ {
+ return $this->_left + $x;
+ }
+
+ /**
+ * Get the y-point from the relative to absolute coordinates
+ *
+ * @param float $y The relative y-coordinate (in percentage of total width)
+ * @return float The y-coordinate as applied to the canvas
+ * @access private
+ */
+ function _getY($y)
+ {
+ return $this->_pageHeight - ($this->_top + $y);
+ }
+
+ /**
+ * Get the color index for the RGB color
+ *
+ * @param int $color The color
+ * @return int The GD image index of the color
+ * @access private
+ */
+ function _color($color = false)
+ {
+ if (($color === false) || ($color === 'opague') || ($color === 'transparent')) {
+ return false;
+ } else {
+ $color = Image_Canvas_Color::color2RGB($color);
+ $color[0] = $color[0]/255;
+ $color[1] = $color[1]/255;
+ $color[2] = $color[2]/255;
+ return $color;
+ }
+ }
+
+ /**
+ * Get the PDF linestyle
+ *
+ * @param mixed $lineStyle The line style to return, false if the one
+ * explicitly set
+ * @return bool True if set (so that a line should be drawn)
+ * @access private
+ */
+ function _setLineStyle($lineStyle = false)
+ {
+ if ($lineStyle === false) {
+ $lineStyle = $this->_lineStyle;
+ }
+
+ if (($lineStyle == 'transparent') || ($lineStyle === false)) {
+ return false;
+ }
+
+ if (is_array($lineStyle)) {
+ // TODO Implement linestyles in PDFlib (using pdf_setcolor(.., 'pattern'...); ?
+ reset($lineStyle);
+ $lineStyle = current($lineStyle);
+ }
+
+ $color = $this->_color($lineStyle);
+
+ pdf_setlinewidth($this->_pdf, $this->_thickness);
+ if ($this->_pdflib < 4) {
+ pdf_setrgbcolor_stroke($this->_pdf, $color[0]/255, $color[1]/255, $color[2]/255);
+ } else {
+ pdf_setcolor($this->_pdf, 'stroke', 'rgb', $color[0], $color[1], $color[2], 0);
+ }
+ return true;
+ }
+
+ /**
+ * Set the PDF fill style
+ *
+ * @param mixed $fillStyle The fillstyle to return, false if the one
+ * explicitly set
+ * @return bool True if set (so that a line should be drawn)
+ * @access private
+ */
+ function _setFillStyle($fillStyle = false)
+ {
+ if ($fillStyle === false) {
+ $fillStyle = $this->_fillStyle;
+ }
+
+ if (($fillStyle == 'transparent') || ($fillStyle === false)) {
+ return false;
+ }
+
+ $color = $this->_color($fillStyle);
+
+ if ($this->_pdflib < 4) {
+ pdf_setrgbcolor_fill($this->_pdf, $color[0]/255, $color[1]/255, $color[2]/255);
+ } else {
+ pdf_setcolor($this->_pdf, 'fill', 'rgb', $color[0], $color[1], $color[2], 0);
+ }
+ return true;
+ }
+
+ /**
+ * Set the PDF font
+ *
+ * @access private
+ */
+ function _setFont()
+ {
+ $this->_pdfFont = false;
+ if (isset($this->_font['name'])) {
+ pdf_set_parameter($this->_pdf, 'FontOutline', $this->_font['name'] . '=' . $this->_font['file']);
+ $this->_pdfFont = pdf_findfont($this->_pdf, $this->_font['name'], $this->_font['encoding'], 1);
+
+ if ($this->_pdfFont) {
+ pdf_setfont($this->_pdf, $this->_pdfFont, $this->_font['size']);
+ $this->_setFillStyle($this->_font['color']);
+ }
+ } else {
+ $this->_setFillStyle('black');
+ }
+ }
+
+ /**
+ * Sets an image that should be used for filling.
+ *
+ * Image filling is not supported with PDF, filling 'transparent'
+ *
+ * @param string $filename The filename of the image to fill with
+ */
+ function setFillImage($filename)
+ {
+ $this->_fillStyle = 'transparent';
+ }
+
+ /**
+ * Sets a gradient fill
+ *
+ * Gradient filling is not supported with PDF, end color used as solid fill.
+ *
+ * @param array $gradient Gradient fill options
+ */
+ function setGradientFill($gradient)
+ {
+ $this->_fillStyle = $gradient['end'];
+ }
+
+ /**
+ * Sets the font options.
+ *
+ * The $font array may have the following entries:
+ *
+ * 'ttf' = the .ttf file (either the basename, filename or full path)
+ * If 'ttf' is specified, then the following can be specified
+ *
+ * 'size' = size in pixels
+ *
+ * 'angle' = the angle with which to write the text
+ *
+ * @param array $font The font options.
+ */
+ function setFont($fontOptions)
+ {
+ parent::setFont($fontOptions);
+
+ if (!isset($this->_font['size'])) {
+ $this->_font['size'] = 12;
+ }
+
+ if (!isset($this->_font['encoding'])) {
+ $this->_font['encoding'] = 'winansi';
+ }
+
+ if (!isset($this->_font['color'])) {
+ $this->_font['color'] = 'black';
+ }
+ }
+
+ /**
+ * Resets the canvas.
+ *
+ * Includes fillstyle, linestyle, thickness and polygon
+ *
+ * @access private
+ */
+ function _reset()
+ {
+ pdf_initgraphics($this->_pdf);
+ parent::_reset();
+ }
+
+ /**
+ * Draw a line
+ *
+ * Parameter array:
+ * 'x0': int X start point
+ * 'y0': int Y start point
+ * 'x1': int X end point
+ * 'y1': int Y end point
+ * 'color': mixed [optional] The line color
+ * @param array $params Parameter array
+ */
+ function line($params)
+ {
+ $color = (isset($params['color']) ? $params['color'] : false);
+ if ($this->_setLineStyle($color)) {
+ pdf_moveto($this->_pdf, $this->_getX($params['x0']), $this->_getY($params['y0']));
+ pdf_lineto($this->_pdf, $this->_getX($params['x1']), $this->_getY($params['x1']));
+ pdf_stroke($this->_pdf);
+ }
+ parent::line($params);
+ }
+
+ /**
+ * Parameter array:
+ * 'connect': bool [optional] Specifies whether the start point should be
+ * connected to the endpoint (closed polygon) or not (connected line)
+ * 'fill': mixed [optional] The fill color
+ * 'line': mixed [optional] The line color
+ * @param array $params Parameter array
+ */
+ function polygon($params = array())
+ {
+ $connectEnds = (isset($params['connect']) ? $params['connect'] : false);
+ $fillColor = (isset($params['fill']) ? $params['line'] : false);
+ $lineColor = (isset($params['line']) ? $params['line'] : false);
+
+ $line = $this->_setLineStyle($lineColor);
+ $fill = false;
+ if ($connectEnds) {
+ $fill = $this->_setFillStyle($fillColor);
+ }
+
+ $first = true;
+ foreach ($this->_polygon as $point) {
+ if ($first === true) {
+ pdf_moveto($this->_pdf, $point['X'], $point['Y']);
+ $first = $point;
+ } else {
+ if (isset($last['P1X'])) {
+ pdf_curveto($this->_pdf,
+ $last['P1X'],
+ $last['P1Y'],
+ $last['P2X'],
+ $last['P2Y'],
+ $point['X'],
+ $point['Y']
+ );
+ } else {
+ pdf_lineto($this->_pdf,
+ $point['X'],
+ $point['Y']
+ );
+ }
+ }
+ $last = $point;
+ }
+
+ if ($connectEnds) {
+ if (isset($last['P1X'])) {
+ pdf_curveto($this->_pdf,
+ $last['P1X'],
+ $last['P1Y'],
+ $last['P2X'],
+ $last['P2Y'],
+ $first['X'],
+ $first['Y']
+ );
+ } else {
+ pdf_lineto($this->_pdf,
+ $first['X'],
+ $first['Y']
+ );
+ }
+ }
+
+ if (($line) && ($fill)) {
+ pdf_fill_stroke($this->_pdf);
+ } elseif ($line) {
+ pdf_stroke($this->_pdf);
+ } elseif ($fill) {
+ pdf_fill($this->_pdf);
+ }
+ parent::polygon($params);
+ }
+
+ /**
+ * Draw a rectangle
+ *
+ * Parameter array:
+ * 'x0': int X start point
+ * 'y0': int Y start point
+ * 'x1': int X end point
+ * 'y1': int Y end point
+ * 'fill': mixed [optional] The fill color
+ * 'line': mixed [optional] The line color
+ * @param array $params Parameter array
+ */
+ function rectangle($params)
+ {
+ $x0 = $this->_getX($params['x0']);
+ $y0 = $this->_getY($params['y0']);
+ $x1 = $this->_getX($params['x1']);
+ $y1 = $this->_getY($params['y1']);
+ $fillColor = (isset($params['fill']) ? $params['line'] : false);
+ $lineColor = (isset($params['line']) ? $params['line'] : false);
+
+ $line = $this->_setLineStyle($lineColor);
+ $fill = $this->_setFillStyle($fillColor);
+ if (($line) || ($fill)) {
+ pdf_rect($this->_pdf, $this->_getX(min($x0, $x1)), $this->_getY(max($y0, $y1)), abs($x1 - $x0), abs($y1 - $y0));
+ if (($line) && ($fill)) {
+ pdf_fill_stroke($this->_pdf);
+ } elseif ($line) {
+ pdf_stroke($this->_pdf);
+ } elseif ($fill) {
+ pdf_fill($this->_pdf);
+ }
+ }
+ parent::rectangle($params);
+ }
+
+ /**
+ * Draw an ellipse
+ *
+ * Parameter array:
+ * 'x': int X center point
+ * 'y': int Y center point
+ * 'rx': int X radius
+ * 'ry': int Y radius
+ * 'fill': mixed [optional] The fill color
+ * 'line': mixed [optional] The line color
+ * @param array $params Parameter array
+ */
+ function ellipse($params)
+ {
+ $x = $this->_getX($params['x']);
+ $y = $this->_getY($params['y']);
+ $rx = $this->_getX($params['rx']);
+ $ry = $this->_getY($params['ry']);
+ $fillColor = (isset($params['fill']) ? $params['line'] : false);
+ $lineColor = (isset($params['line']) ? $params['line'] : false);
+
+ $line = $this->_setLineStyle($lineColor);
+ $fill = $this->_setFillStyle($fillColor);
+ if (($line) || ($fill)) {
+ if ($rx == $ry) {
+ pdf_circle($this->_pdf, $this->_getX($x), $this->_getY($y), $rx);
+ } else {
+ pdf_moveto($this->_pdf, $this->_getX($x - $rx), $this->_getY($y));
+ pdf_curveto($this->_pdf,
+ $this->_getX($x - $rx), $this->_getY($y),
+ $this->_getX($x - $rx), $this->_getY($y - $ry),
+ $this->_getX($x), $this->_getY($y - $ry)
+ );
+ pdf_curveto($this->_pdf,
+ $this->_getX($x), $this->_getY($y - $ry),
+ $this->_getX($x + $rx), $this->_getY($y - $ry),
+ $this->_getX($x + $rx), $this->_getY($y)
+ );
+ pdf_curveto($this->_pdf,
+ $this->_getX($x + $rx), $this->_getY($y),
+ $this->_getX($x + $rx), $this->_getY($y + $ry),
+ $this->_getX($x), $this->_getY($y + $ry)
+ );
+ pdf_curveto($this->_pdf,
+ $this->_getX($x), $this->_getY($y + $ry),
+ $this->_getX($x - $rx), $this->_getY($y + $ry),
+ $this->_getX($x - $rx), $this->_getY($y)
+ );
+ }
+
+ if (($line) && ($fill)) {
+ pdf_fill_stroke($this->_pdf);
+ } elseif ($line) {
+ pdf_stroke($this->_pdf);
+ } elseif ($fill) {
+ pdf_fill($this->_pdf);
+ }
+ }
+ parent::ellipse($params);
+ }
+
+ /**
+ * Draw a pie slice
+ *
+ * Parameter array:
+ * 'x': int X center point
+ * 'y': int Y center point
+ * 'rx': int X radius
+ * 'ry': int Y radius
+ * 'v1': int The starting angle (in degrees)
+ * 'v2': int The end angle (in degrees)
+ * 'srx': int [optional] Starting X-radius of the pie slice (i.e. for a doughnut)
+ * 'sry': int [optional] Starting Y-radius of the pie slice (i.e. for a doughnut)
+ * 'fill': mixed [optional] The fill color
+ * 'line': mixed [optional] The line color
+ * @param array $params Parameter array
+ */
+ function pieslice($params)
+ {
+ $x = $this->_getX($params['x']);
+ $y = $this->_getY($params['y']);
+ $rx = $this->_getX($params['rx']);
+ $ry = $this->_getY($params['ry']);
+ $v1 = $this->_getX($params['v1']);
+ $v2 = $this->_getY($params['v2']);
+ $srx = $this->_getX($params['srx']);
+ $sry = $this->_getY($params['sry']);
+ $fillColor = (isset($params['fill']) ? $params['line'] : false);
+ $lineColor = (isset($params['line']) ? $params['line'] : false);
+
+ // TODO Implement PDFLIB::pieSlice()
+ parent::pieslice($params);
+ }
+
+ /**
+ * Get the width of a text,
+ *
+ * @param string $text The text to get the width of
+ * @return int The width of the text
+ */
+ function textWidth($text)
+ {
+ if ($this->_pdfFont === false) {
+ return $this->_font['size'] * 0.7 * strlen($text);
+ } else {
+ return pdf_stringwidth($this->_pdf, $text, $this->_pdfFont, $this->_font['size']);
+ }
+ }
+
+ /**
+ * Get the height of a text,
+ *
+ * @param string $text The text to get the height of
+ * @return int The height of the text
+ */
+ function textHeight($text)
+ {
+ if (isset($this->_font['size'])) {
+ return $this->_font['size'];
+ } else {
+ return 12;
+ }
+ }
+
+ /**
+ * Writes text
+ *
+ * Parameter array:
+ * 'x': int X-point of text
+ * 'y': int Y-point of text
+ * 'text': string The text to add
+ * 'alignment': array [optional] Alignment
+ * 'color': mixed [optional] The color of the text
+ */
+ function addText($params)
+ {
+ $x = $this->_getX($params['x']);
+ $y = $this->_getY($params['y']);
+ $text = $params['text'];
+ $color = (isset($params['color']) ? $params['color'] : false);
+ $alignment = (isset($params['alignment']) ? $params['alignment'] : false);
+
+ $this->_setFont();
+
+ $textWidth = $this->textWidth($text);
+ $textHeight = $this->textHeight($text);
+
+ if (!is_array($alignment)) {
+ $alignment = array('vertical' => 'top', 'horizontal' => 'left');
+ }
+
+ if (!isset($alignment['vertical'])) {
+ $alignment['vertical'] = 'top';
+ }
+
+ if (!isset($alignment['horizontal'])) {
+ $alignment['horizontal'] = 'left';
+ }
+
+ if ($alignment['horizontal'] == 'right') {
+ $x = $x - $textWidth;
+ } elseif ($alignment['horizontal'] == 'center') {
+ $x = $x - ($textWidth / 2);
+ }
+
+ if ($alignment['vertical'] == 'top') {
+ $y = $y + $textHeight;
+ } elseif ($alignment['vertical'] == 'center') {
+ $y = $y + ($textHeight / 2);
+ }
+
+ if (($color === false) && (isset($this->_font['color']))) {
+ $color = $this->_font['color'];
+ }
+
+ pdf_show_xy($this->_pdf, $text, $this->_getX($x), $this->_getY($y));
+
+ parent::addText($params);
+ }
+
+ /**
+ * Overlay image
+ *
+ * Parameter array:
+ * 'x': int X-point of overlayed image
+ * 'y': int Y-point of overlayed image
+ * 'filename': string The filename of the image to overlay
+ * 'width': int [optional] The width of the overlayed image (resizing if possible)
+ * 'height': int [optional] The height of the overlayed image (resizing if possible)
+ * 'alignment': array [optional] Alignment
+ */
+ function image($params)
+ {
+ $x = $this->_getX($params['x']);
+ $y = $this->_getY($params['y']);
+ $filename = $params['filename'];
+ $width = (isset($params['width']) ? $params['width'] : false);
+ $height = (isset($params['height']) ? $params['height'] : false);
+ $alignment = (isset($params['alignment']) ? $params['alignment'] : false);
+
+ if (substr($filename, -4) == '.png') {
+ $type = 'png';
+ } elseif (substr($filename, -4) == '.jpg') {
+ $type = 'jpeg';
+ }
+
+ $image = pdf_load_image($this->_pdf, $type, realpath($filename), '');
+ $width_ = pdf_get_value($this->_pdf, 'imagewidth', $image);
+ $height_ = pdf_get_value($this->_pdf, 'imageheight', $image);
+
+ $outputWidth = ($width !== false ? $width : $width_);
+ $outputHeight = ($height !== false ? $height : $height_);
+
+ if (!is_array($alignment)) {
+ $alignment = array('vertical' => 'top', 'horizontal' => 'left');
+ }
+
+ if (!isset($alignment['vertical'])) {
+ $alignment['vertical'] = 'top';
+ }
+
+ if (!isset($alignment['horizontal'])) {
+ $alignment['horizontal'] = 'left';
+ }
+
+ if ($alignment['horizontal'] == 'right') {
+ $x -= $outputWidth;
+ } elseif ($alignment['horizontal'] == 'center') {
+ $x -= $outputWidth / 2;
+ }
+
+ if ($alignment['vertical'] == 'top') {
+ $y += $outputHeight;
+ } elseif ($alignment['vertical'] == 'center') {
+ $y += $outputHeight / 2;
+ }
+
+ if (($width === false) && ($height === false)) {
+ $scale = 1;
+ } else {
+ $scale = max(($height/$height_), ($width/$width_));
+ }
+
+ pdf_place_image($this->_pdf, $image, $this->_getX($x), $this->_getY($y), $scale);
+ pdf_close_image($this->_pdf, $image);
+
+ parent::image($params);
+ }
+
+ /**
+ * Output the result of the canvas
+ *
+ * @param array $param Parameter array
+ * @abstract
+ */
+ function show($param = false)
+ {
+ parent::show($param);
+ pdf_end_page($this->_pdf);
+ pdf_close($this->_pdf);
+
+ $buf = pdf_get_buffer($this->_pdf);
+ $len = strlen($buf);
+
+ header('Content-type: application/pdf');
+ header('Content-Length: ' . $len);
+ header('Content-Disposition: inline; filename=image_graph.pdf');
+ print $buf;
+
+ pdf_delete($this->_pdf);
+ }
+
+ /**
+ * Output the result of the canvas
+ *
+ * @param array $param Parameter array
+ * @abstract
+ */
+ function save($param = false)
+ {
+ parent::save($param);
+ pdf_end_page($this->_pdf);
+ pdf_close($this->_pdf);
+
+ $buf = pdf_get_buffer($this->_pdf);
+ $len = strlen($buf);
+
+ $fp = @fopen($param['filename'], 'wb');
+ if ($fp) {
+ fwrite($fp, $buf, strlen($buf));
+ fclose($fp);
+ }
+ pdf_delete($this->_pdf);
+ }
+
+ /**
+ * Get a canvas specific HTML tag.
+ *
+ * This method implicitly saves the canvas to the filename in the
+ * filesystem path specified and parses it as URL specified by URL path
+ *
+ * Parameter array:
+ * 'filename': string
+ * 'filepath': string Path to the file on the file system. Remember the final slash
+ * 'urlpath': string Path to the file available through an URL. Remember the final slash
+ * 'title': string The url title
+ */
+ function toHtml($params)
+ {
+ parent::toHtml($params);
+ return '<a href="' . $params['urlpath'] . $params['filename'] . '">' . $params['title'] . '</a>';
+ }
+
+ /**
+ * Check which major version of PDFlib is installed
+ *
+ * @return int The mahor version number of PDFlib
+ * @access private
+ */
+ function _version()
+ {
+ $result = false;
+ if (function_exists('pdf_get_majorversion')) {
+ $version = pdf_get_majorversion();
+ } else {
+ ob_start();
+ phpinfo(8);
+ $php_info = ob_get_contents();
+ ob_end_clean();
+
+ if (ereg("<td[^>]*>PDFlib GmbH Version *<\/td><td[^>]*>([^<]*)<\/td>",
+ $php_info, $result))
+ {
+ $version = $result[1];
+ }
+ }
+
+ if (ereg('([0-9]{1,2})\.[0-9]{1,2}(\.[0-9]{1,2})?', trim($version), $result)) {
+ return $result[1];
+ } else {
+ return 0;
+ }
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Canvas/SVG.php b/config/dspam/pear/Image/Canvas/SVG.php
new file mode 100644
index 00000000..3fed62ba
--- /dev/null
+++ b/config/dspam/pear/Image/Canvas/SVG.php
@@ -0,0 +1,918 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Class for handling output in SVG format.
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Canvas
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212
+ */
+
+/**
+ * Include file Image/Canvas.php
+ */
+require_once 'Image/Canvas.php';
+
+/**
+ * Include file Image/Canvas/Color.php
+ */
+require_once 'Image/Canvas/Color.php';
+
+/**
+ * SVG Canvas class.
+ *
+ * @category Images
+ * @package Image_Canvas
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212
+ */
+class Image_Canvas_SVG extends Image_Canvas
+{
+
+ /**
+ * The SVG elements
+ * @var string
+ * @access private
+ */
+ var $_elements = '';
+
+ /**
+ * The SVG defines
+ * @var string
+ * @access private
+ */
+ var $_defs = '';
+
+ /**
+ * The current indention level
+ * @var string
+ * @access private
+ */
+ var $_indent = ' ';
+
+ /**
+ * A unieuq id counter
+ * @var int
+ * @access private
+ */
+ var $_id = 1;
+
+ /**
+ * The current group ids
+ * @var array
+ * @access private
+ */
+ var $_groupIDs = array();
+
+ /**
+ * Create the SVG canvas.
+ *
+ * Parameters available:
+ *
+ * 'width' The width of the graph
+ *
+ * 'height' The height of the graph
+ *
+ * @param array $param Parameter array
+ */
+ function Image_Canvas_SVG($param)
+ {
+ parent::Image_Canvas($param);
+ $this->_reset();
+ }
+
+ /**
+ * Add a SVG "element" to the output
+ *
+ * @param string $element The element
+ * @access private
+ */
+ function _addElement($element, $params = array()) {
+ $elementdata = $this->_indent . $element . "\n";
+
+ if (isset($params['url'])) {
+ $url = $params['url'];
+ $target = (isset($params['target']) ? $params['target'] : false);
+ $alt = (isset($params['alt']) ? $params['alt'] : false);
+
+ $tags = '';
+ if (isset($params['htmltags'])) {
+ foreach ($params['htmltags'] as $key => $value) {
+ $tags .= ' ';
+ if (strpos($value, '"') >= 0) {
+ $tags .= $key . '=\'' . $value . '\'';
+ } else {
+ $tags .= $key . '="' . $value . '"';
+ }
+ }
+ }
+
+ $elementdata =
+ $this->_indent . '<a xlink:href="' . $url . '"' . ($target ? ' target="' . $target . '"' : '') . '>' . "\n" .
+ ' ' . $elementdata .
+ $this->_indent . '</a>' . "\n";
+ }
+
+
+ $this->_elements .= $elementdata;
+ }
+
+ /**
+ * Add a SVG "define" to the output
+ *
+ * @param string $def The define
+ * @access private
+ */
+ function _addDefine($def) {
+ $this->_defs .= ' ' . $def . "\n";
+ }
+
+ /**
+ * Get the color index for the RGB color
+ *
+ * @param int $color The color
+ * @return int A SVG compatible color
+ * @access private
+ */
+ function _color($color = false)
+ {
+ if ($color === false) {
+ return 'transparent';
+ } else {
+ $color = Image_Canvas_Color::color2RGB($color);
+ return 'rgb(' . $color[0] . ',' . $color[1] . ',' . $color[2] . ')';
+ }
+ }
+
+ /**
+ * Get the opacity for the RGB color
+ *
+ * @param int $color The color
+ * @return int A SVG compatible opacity value
+ * @access private
+ */
+ function _opacity($color = false)
+ {
+ if ($color === false) {
+ return false;
+ } else {
+ $color = Image_Canvas_Color::color2RGB($color);
+ if ($color[3] != 255) {
+ return sprintf('%0.1f', $color[3]/255);
+ } else {
+ return false;
+ }
+ }
+ }
+
+ /**
+ * Get the SVG applicable linestyle
+ *
+ * @param mixed $lineStyle The line style to return, false if the one
+ * explicitly set
+ * @return mixed A SVG compatible linestyle
+ * @access private
+ */
+ function _getLineStyle($lineStyle = false)
+ {
+ $result = '';
+ if ($lineStyle === false) {
+ $lineStyle = $this->_lineStyle;
+ }
+
+ // TODO Linestyles (i.e. fx. dotted) does not work
+
+ if (($lineStyle != 'transparent') && ($lineStyle !== false)) {
+ $result = 'stroke-width:' . $this->_thickness . ';';
+ $result .= 'stroke:' .$this->_color($lineStyle) . ';';
+ if ($opacity = $this->_opacity($lineStyle)) {
+ $result .= 'stroke-opacity:' . $opacity . ';';
+ }
+ }
+ return $result;
+ }
+
+ /**
+ * Get the SVG applicable fillstyle
+ *
+ * @param mixed $fillStyle The fillstyle to return, false if the one
+ * explicitly set
+ * @return mixed A SVG compatible fillstyle
+ * @access private
+ */
+ function _getFillStyle($fillStyle = false)
+ {
+ $result = '';
+ if ($fillStyle === false) {
+ $fillStyle = $this->_fillStyle;
+ }
+
+ if (is_array($fillStyle)) {
+ if ($fillStyle['type'] == 'gradient') {
+ $id = 'gradient_' . ($this->_id++);
+ $startColor = $this->_color($fillStyle['start']);
+ $endColor = $this->_color($fillStyle['end']);
+ $startOpacity = $this->_opacity($fillStyle['start']);
+ $endOpacity = $this->_opacity($fillStyle['end']);
+
+ switch ($fillStyle['direction']) {
+ case 'horizontal':
+ case 'horizontal_mirror':
+ $x1 = '0%';
+ $y1 = '0%';
+ $x2 = '100%';
+ $y2 = '0%';
+ break;
+
+ case 'vertical':
+ case 'vertical_mirror':
+ $x1 = '0%';
+ $y1 = '100%';
+ $x2 = '0%';
+ $y2 = '0%';
+ break;
+
+ case 'diagonal_tl_br':
+ $x1 = '0%';
+ $y1 = '0%';
+ $x2 = '100%';
+ $y2 = '100%';
+ break;
+
+ case 'diagonal_bl_tr':
+ $x1 = '0%';
+ $y1 = '100%';
+ $x2 = '100%';
+ $y2 = '0%';
+ break;
+
+ case 'radial':
+ $cx = '50%';
+ $cy = '50%';
+ $r = '100%';
+ $fx = '50%';
+ $fy = '50%';
+ break;
+
+ }
+
+ if ($fillStyle['direction'] == 'radial') {
+ $this->_addDefine(
+ '<radialGradient id="' . $id . '" cx="' .
+ $cx .'" cy="' . $cy .'" r="' . $r .'" fx="' .
+ $fx .'" fy="' . $fy .'">'
+ );
+ $this->_addDefine(
+ ' <stop offset="0%" style="stop-color:' .
+ $startColor. ';' . ($startOpacity ? 'stop-opacity:' .
+ $startOpacity . ';' : ''). '"/>'
+ );
+ $this->_addDefine(
+ ' <stop offset="100%" style="stop-color:' .
+ $endColor. ';' . ($endOpacity ? 'stop-opacity:' .
+ $endOpacity . ';' : ''). '"/>'
+ );
+ $this->_addDefine(
+ '</radialGradient>'
+ );
+ } elseif (($fillStyle['direction'] == 'vertical_mirror') ||
+ ($fillStyle['direction'] == 'horizontal_mirror'))
+ {
+ $this->_addDefine(
+ '<linearGradient id="' . $id . '" x1="' .
+ $x1 .'" y1="' . $y1 .'" x2="' . $x2 .'" y2="' .
+ $y2 .'">'
+ );
+ $this->_addDefine(
+ ' <stop offset="0%" style="stop-color:' .
+ $startColor. ';' . ($startOpacity ? 'stop-opacity:' .
+ $startOpacity . ';' : ''). '"/>'
+ );
+ $this->_addDefine(
+ ' <stop offset="50%" style="stop-color:' .
+ $endColor. ';' . ($endOpacity ? 'stop-opacity:' .
+ $endOpacity . ';' : ''). '"/>'
+ );
+ $this->_addDefine(
+ ' <stop offset="100%" style="stop-color:' .
+ $startColor. ';' . ($startOpacity ? 'stop-opacity:' .
+ $startOpacity . ';' : ''). '"/>'
+ );
+ $this->_addDefine(
+ '</linearGradient>'
+ );
+ } else {
+ $this->_addDefine(
+ '<linearGradient id="' . $id . '" x1="' .
+ $x1 .'" y1="' . $y1 .'" x2="' . $x2 .'" y2="' .
+ $y2 .'">'
+ );
+ $this->_addDefine(
+ ' <stop offset="0%" style="stop-color:' .
+ $startColor. ';' . ($startOpacity ? 'stop-opacity:' .
+ $startOpacity . ';' : ''). '"/>'
+ );
+ $this->_addDefine(
+ ' <stop offset="100%" style="stop-color:' .
+ $endColor. ';' . ($endOpacity ? 'stop-opacity:' .
+ $endOpacity . ';' : ''). '"/>'
+ );
+ $this->_addDefine(
+ '</linearGradient>'
+ );
+ }
+
+ return 'fill:url(#' . $id . ');';
+ }
+ } elseif (($fillStyle != 'transparent') && ($fillStyle !== false)) {
+ $result = 'fill:' . $this->_color($fillStyle) . ';';
+ if ($opacity = $this->_opacity($fillStyle)) {
+ $result .= 'fill-opacity:' . $opacity . ';';
+ }
+ return $result;
+ } else {
+ return 'fill:none;';
+ }
+ }
+
+ /**
+ * Sets an image that should be used for filling
+ *
+ * @param string $filename The filename of the image to fill with
+ */
+ function setFillImage($filename)
+ {
+ }
+
+ /**
+ * Sets a gradient fill
+ *
+ * @param array $gradient Gradient fill options
+ */
+ function setGradientFill($gradient)
+ {
+ $this->_fillStyle = $gradient;
+ $this->_fillStyle['type'] = 'gradient';
+ }
+
+ /**
+ * Sets the font options.
+ *
+ * The $font array may have the following entries:
+ * 'type' = 'ttf' (TrueType) or omitted for default<br>
+ * If 'type' = 'ttf' then the following can be specified<br>
+ * 'size' = size in pixels<br>
+ * 'angle' = the angle with which to write the text
+ * 'file' = the .ttf file (either the basename, filename or full path)
+ *
+ * @param array $font The font options.
+ */
+ function setFont($fontOptions)
+ {
+ parent::setFont($fontOptions);
+ if (!isset($this->_font['size'])) {
+ $this->_font['size'] = 10;
+ }
+ }
+
+ /**
+ * Parameter array:
+ * 'x0': int X start point
+ * 'y0': int Y start point
+ * 'x1': int X end point
+ * 'y1': int Y end point
+ * 'color': mixed [optional] The line color
+ * @param array $params Parameter array
+ */
+ function line($params)
+ {
+ $x0 = $this->_getX($params['x0']);
+ $y0 = $this->_getY($params['y0']);
+ $x1 = $this->_getX($params['x1']);
+ $y1 = $this->_getY($params['y1']);
+ $color = (isset($params['color']) ? $params['color'] : false);
+
+ $style = $this->_getLineStyle($color) . $this->_getFillStyle('transparent');
+ if ($style != '') {
+ $this->_addElement(
+ '<line ' .
+ 'x1="' . round($x0) . '" ' .
+ 'y1="' . round($y0) . '" ' .
+ 'x2="' . round($x1) . '" ' .
+ 'y2="' . round($y1) . '" ' .
+ 'style="' . $style . '"' .
+ '/>',
+ $params
+ );
+ }
+ parent::line($params);
+ }
+
+ /**
+ * Parameter array:
+ * 'connect': bool [optional] Specifies whether the start point should be
+ * connected to the endpoint (closed polygon) or not (connected line)
+ * 'fill': mixed [optional] The fill color
+ * 'line': mixed [optional] The line color
+ * @param array $params Parameter array
+ */
+ function polygon($params = array())
+ {
+ $connectEnds = (isset($params['connect']) ? $params['connect'] : false);
+ $fillColor = (isset($params['fill']) ? $params['line'] : false);
+ $lineColor = (isset($params['line']) ? $params['line'] : false);
+
+ if (!$connectEnds) {
+ $fillColor = 'transparent';
+ }
+ $style = $this->_getLineStyle($lineColor) . $this->_getFillStyle($fillColor);
+
+ $first = true;
+ $spline = false;
+ $lastpoint = false;
+ foreach($this->_polygon as $point) {
+ if ($first) {
+ $points = 'M';
+ } elseif (!$spline) {
+ $points .= ' L';
+ }
+
+ if (($spline) && ($lastpoint !== false)) {
+ $points .= ' ' .round($lastpoint['P1X']) . ',' . round($lastpoint['P1Y']) . ' ' .
+ round($lastpoint['P2X']) . ',' . round($lastpoint['P2Y']);
+ }
+
+ $points .= ' ' . round($point['X']) . ',' . round($point['Y']);
+
+ if ((isset($point['P1X'])) && (isset($point['P1Y'])) &&
+ (isset($point['P2X'])) && (isset($point['P2Y'])))
+ {
+ if (($first) || (!$spline)) {
+ $points .= ' C';
+ }
+ $lastpoint = $point;
+ $spline = true;
+ } else {
+ $spline = false;
+ }
+ $first = false;
+ }
+ if ($connectEnds) {
+ $point .= ' Z';
+ }
+ $this->_addElement(
+ '<path ' .
+ 'd="' . $points . '" ' .
+ 'style="' . $style . '"' .
+ '/>',
+ $params
+ );
+
+ parent::polygon($params);
+ }
+
+ /**
+ * Draw a rectangle
+ *
+ * Parameter array:
+ * 'x0': int X start point
+ * 'y0': int Y start point
+ * 'x1': int X end point
+ * 'y1': int Y end point
+ * 'fill': mixed [optional] The fill color
+ * 'line': mixed [optional] The line color
+ * @param array $params Parameter array
+ */
+ function rectangle($params)
+ {
+ $x0 = min($this->_getX($params['x0']), $this->_getX($params['x1']));
+ $y0 = min($this->_getY($params['y0']), $this->_getY($params['y1']));
+ $x1 = max($this->_getX($params['x0']), $this->_getX($params['x1']));
+ $y1 = max($this->_getY($params['y0']), $this->_getY($params['y1']));
+ $fillColor = (isset($params['fill']) ? $params['line'] : false);
+ $lineColor = (isset($params['line']) ? $params['line'] : false);
+
+ $style = $this->_getLineStyle($lineColor) . $this->_getFillStyle($fillColor);
+ if ($style != '') {
+ $this->_addElement(
+ '<rect ' .
+ 'x="' . round($x0) . '" ' .
+ 'y="' . round($y0) . '" ' .
+ 'width="' . round(abs($x1 - $x0)) . '" ' .
+ 'height="' . round(abs($y1 - $y0)) . '" ' .
+ 'style="' . $style . '"' .
+ '/>',
+ $params
+ );
+ }
+ parent::rectangle($params);
+ }
+
+ /**
+ * Draw an ellipse
+ *
+ * Parameter array:
+ * 'x': int X center point
+ * 'y': int Y center point
+ * 'rx': int X radius
+ * 'ry': int Y radius
+ * 'fill': mixed [optional] The fill color
+ * 'line': mixed [optional] The line color
+ * @param array $params Parameter array
+ */
+ function ellipse($params)
+ {
+ $x = $this->_getX($params['x']);
+ $y = $this->_getY($params['y']);
+ $rx = $this->_getX($params['rx']);
+ $ry = $this->_getY($params['ry']);
+ $fillColor = (isset($params['fill']) ? $params['line'] : false);
+ $lineColor = (isset($params['line']) ? $params['line'] : false);
+
+ $style = $this->_getLineStyle($lineColor) . $this->_getFillStyle($fillColor);
+ if ($style != '') {
+ $this->_addElement(
+ '<ellipse ' .
+ 'cx="' . round($x) . '" ' .
+ 'cy="' . round($y) . '" ' .
+ 'rx="' . round($rx) . '" ' .
+ 'ry="' . round($ry) . '" ' .
+ 'style="' . $style . '"' .
+ '/>',
+ $params
+ );
+ }
+ parent::ellipse($params);
+ }
+
+ /**
+ * Draw a pie slice
+ *
+ * Parameter array:
+ * 'x': int X center point
+ * 'y': int Y center point
+ * 'rx': int X radius
+ * 'ry': int Y radius
+ * 'v1': int The starting angle (in degrees)
+ * 'v2': int The end angle (in degrees)
+ * 'srx': int [optional] Starting X-radius of the pie slice (i.e. for a doughnut)
+ * 'sry': int [optional] Starting Y-radius of the pie slice (i.e. for a doughnut)
+ * 'fill': mixed [optional] The fill color
+ * 'line': mixed [optional] The line color
+ * @param array $params Parameter array
+ */
+ function pieslice($params)
+ {
+ $x = $this->_getX($params['x']);
+ $y = $this->_getY($params['y']);
+ $rx = $this->_getX($params['rx']);
+ $ry = $this->_getY($params['ry']);
+ $v1 = $this->_getX($params['v1']);
+ $v2 = $this->_getY($params['v2']);
+ $srx = (isset($params['srx']) ? $this->_getX($params['srx']) : false);
+ $sry = (isset($params['sry']) ? $this->_getX($params['sry']) : false);
+ $fillColor = (isset($params['fill']) ? $params['line'] : false);
+ $lineColor = (isset($params['line']) ? $params['line'] : false);
+
+ $dv = max($v2, $v1) - min($v2, $v1);
+ if ($dv >= 360) {
+ $this->ellipse($params);
+ }
+ else {
+ $style = $this->_getLineStyle($lineColor) . $this->_getFillStyle($fillColor);
+ if ($style != '') {
+ $x1 = ($x + $rx * cos(deg2rad(min($v1, $v2) % 360)));
+ $y1 = ($y + $ry * sin(deg2rad(min($v1, $v2) % 360)));
+ $x2 = ($x + $rx * cos(deg2rad(max($v1, $v2) % 360)));
+ $y2 = ($y + $ry * sin(deg2rad(max($v1, $v2) % 360)));
+ $this->_addElement(
+ '<path d="' .
+ 'M' . round($x) . ',' . round($y) . ' ' .
+ 'L' . round($x1) . ',' . round($y1) . ' ' .
+ 'A' . round($rx) . ',' . round($ry) . ($dv > 180 ? ' 0 1,1 ' : ' 0 0,1 ') .
+ round($x2) . ',' . round($y2) . ' ' .
+ 'Z" ' .
+ 'style="' . $style . '"' .
+ '/>',
+ $params
+ );
+ }
+
+ parent::pieslice($params);
+ }
+ }
+
+ /**
+ * Get the width of a text,
+ *
+ * @param string $text The text to get the width of
+ * @return int The width of the text
+ */
+ function textWidth($text)
+ {
+ if ((isset($this->_font['vertical'])) && ($this->_font['vertical'])) {
+ return $this->_font['size'];
+ } else {
+ return round($this->_font['size'] * 0.7 * strlen($text));
+ }
+ }
+
+ /**
+ * Get the height of a text,
+ *
+ * @param string $text The text to get the height of
+ * @return int The height of the text
+ */
+ function textHeight($text)
+ {
+ if ((isset($this->_font['vertical'])) && ($this->_font['vertical'])) {
+ return round($this->_font['size'] * 0.7 * strlen($text));
+ } else {
+ return $this->_font['size'];
+ }
+ }
+
+ /**
+ * Writes text
+ *
+ * Parameter array:
+ * 'x': int X-point of text
+ * 'y': int Y-point of text
+ * 'text': string The text to add
+ * 'alignment': array [optional] Alignment
+ * 'color': mixed [optional] The color of the text
+ */
+ function addText($params)
+ {
+ $x = $this->_getX($params['x']);
+ $y = $this->_getY($params['y']);
+ $text = $params['text'];
+ $color = (isset($params['color']) ? $params['color'] : false);
+ $alignment = (isset($params['alignment']) ? $params['alignment'] : false);
+
+ $textHeight = $this->textHeight($text);
+
+ if (!is_array($alignment)) {
+ $alignment = array('vertical' => 'top', 'horizontal' => 'left');
+ }
+
+ if (!isset($alignment['vertical'])) {
+ $alignment['vertical'] = 'top';
+ }
+
+ if (!isset($alignment['horizontal'])) {
+ $alignment['horizontal'] = 'left';
+ }
+
+ $align = '';
+
+ if ((isset($this->_font['vertical'])) && ($this->_font['vertical'])) {
+// $align .= 'writing-mode: tb-rl;';
+
+ if ($alignment['vertical'] == 'bottom') {
+ $align .= 'text-anchor:end;';
+ //$y = $y + $textHeight;
+ } elseif ($alignment['vertical'] == 'center') {
+ //$y = $y + ($textHeight / 2);
+ $align .= 'text-anchor:middle;';
+ }
+ } else {
+ if ($alignment['horizontal'] == 'right') {
+ $align .= 'text-anchor:end;';
+ } elseif ($alignment['horizontal'] == 'center') {
+ $align .= 'text-anchor:middle;';
+ }
+
+ if ($alignment['vertical'] == 'top') {
+ $y = $y + $textHeight;
+ } elseif ($alignment['vertical'] == 'center') {
+ $y = $y + ($textHeight / 2);
+ }
+ }
+
+ if (($color === false) && (isset($this->_font['color']))) {
+ $color = $this->_font['color'];
+ }
+
+ $textColor = $this->_color($color);
+ $textOpacity = $this->_opacity($color);
+
+ $this->_addElement(
+ '<g transform="translate(' . round($x) . ', ' . round($y) . ')">' . "\n" .
+ $this->_indent . ' <text ' .
+ 'x="0" ' .
+ 'y="0" ' .
+ (isset($this->_font['angle']) && ($this->_font['angle'] > 0) ?
+ 'transform="rotate(' . $this->_font['angle'] . ')" ' :
+ ''
+ ) .
+ 'style="' .
+ (isset($this->_font['name']) ?
+ 'font-family:' . $this->_font['name'] . ';' : '') .
+ 'font-size:' . $this->_font['size'] . 'px;fill:' .
+ $textColor . ($textOpacity ? ';fill-opacity:' .
+ $textOpacity :
+ ''
+ ) . ';' . $align . '">' .
+ htmlspecialchars($text) .
+ '</text>' . "\n" .
+ $this->_indent . '</g>',
+ $params
+ );
+ parent::addText($params);
+ }
+
+ /**
+ * Overlay image
+ *
+ * Parameter array:
+ * 'x': int X-point of overlayed image
+ * 'y': int Y-point of overlayed image
+ * 'filename': string The filename of the image to overlay
+ * 'width': int [optional] The width of the overlayed image (resizing if possible)
+ * 'height': int [optional] The height of the overlayed image (resizing if possible)
+ * 'alignment': array [optional] Alignment
+ */
+ function image($params)
+ {
+ $x = $this->_getX($params['x']);
+ $y = $this->_getY($params['y']);
+ $filename = $params['filename'];
+
+ list($width, $height, $type, $attr) = getimagesize($filename);
+ $width = (isset($params['width']) ? $params['width'] : $width);
+ $height = (isset($params['height']) ? $params['height'] : $height);
+ $alignment = (isset($params['alignment']) ? $params['alignment'] : false);
+
+ $file = fopen($filename, 'rb');
+ $filedata = fread($file, filesize($filename));
+ fclose($file);
+
+ $data = 'data:' . image_type_to_mime_type($type) . ';base64,' . base64_encode($filedata);
+ $this->_addElement(
+ '<image xlink:href="' . $data . '" x="' . $x . '" y="' . $y . '"' .
+ ($width ? ' width="' . $width . '"' : '') .
+ ($height ? ' height="' . $height . '"' : '') .
+ ' preserveAspectRatio="none"/>',
+ $params
+ );
+ parent::image($params);
+ }
+
+ /**
+ * Start a group.
+ *
+ * What this does, depends on the canvas/format.
+ *
+ * @param string $name The name of the group
+ */
+ function startGroup($name = false)
+ {
+ $name = strtolower(str_replace(' ', '_', $name));
+ if (in_array($name, $this->_groupIDs)) {
+ $name .= $this->_id;
+ $this->_id++;
+ }
+ $this->_groupIDs[] = $name;
+ $this->_addElement('<g id="' . htmlspecialchars($name) . '">');
+ $this->_indent .= ' ';
+ }
+
+ /**
+ * End the "current" group.
+ *
+ * What this does, depends on the canvas/format.
+ */
+ function endGroup()
+ {
+ $this->_indent = substr($this->_indent, 0, -4);
+ $this->_addElement('</g>');
+ }
+
+ /**
+ * Output the result of the canvas
+ *
+ * @param array $param Parameter array
+ */
+ function show($param = false)
+ {
+ parent::show($param);
+ $output = '<?xml version="1.0" encoding="iso-8859-1"?>' . "\n" .
+ '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN"' . "\n\t" .
+ ' "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">' . "\n" .
+ '<svg width="' . $this->_width . '" height="' . $this->_height .
+ '" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">' . "\n" .
+ ($this->_defs ?
+ ' <defs>' . "\n" .
+ $this->_defs .
+ ' </defs>' . "\n" :
+ ''
+ ) .
+ $this->_elements .
+ '</svg>';
+
+ header('Content-Type: image/svg+xml');
+ header('Content-Disposition: inline; filename = "' . basename($_SERVER['PHP_SELF'], '.php') . '.svg"');
+ print $output;
+ }
+
+ /**
+ * Output the result of the canvas
+ *
+ * @param array $param Parameter array
+ */
+ function save($param = false)
+ {
+ parent::save($param);
+ $output = '<?xml version="1.0" encoding="iso-8859-1"?>' . "\n" .
+ '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN"' . "\n\t" .
+ ' "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">' . "\n" .
+ '<svg width="' . $this->_width . '" height="' . $this->_height .
+ '" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">' . "\n" .
+ ($this->_defs ?
+ ' <defs>' . "\n" .
+ $this->_defs .
+ ' </defs>' . "\n" :
+ ''
+ ) .
+ $this->_elements .
+ '</svg>';
+
+ $file = fopen($param['filename'], 'w+');
+ fwrite($file, $output);
+ fclose($file);
+ }
+
+ /**
+ * Set clipping to occur
+ *
+ * Parameter array:
+ *
+ * 'x0': int X point of Upper-left corner
+ * 'y0': int X point of Upper-left corner
+ * 'x1': int X point of lower-right corner
+ * 'y1': int Y point of lower-right corner
+ */
+ function setClipping($params = false)
+ {
+ if ($params === false) {
+ $this->_addElement('</g>');
+ }
+ else {
+ $group = "clipping_" . $this->_id;
+ $this->_id++;
+ $this->_addElement('<g clip-path="url(#' . $group . ')">');
+
+ $this->_addDefine('<clipPath id="' . $group . '">');
+ $this->_addDefine(' <path d="' .
+ 'M' . $this->_getX($params['x0']) . ' ' . $this->_getY($params['y0']) .
+ ' H' . $this->_getX($params['x1']) .
+ ' V' . $this->_getY($params['y1']) .
+ ' H' . $this->_getX($params['x0']) .
+ ' Z"/>');
+ $this->_addDefine('</clipPath>');
+ }
+ }
+
+ /**
+ * Get a canvas specific HTML tag.
+ *
+ * This method implicitly saves the canvas to the filename in the
+ * filesystem path specified and parses it as URL specified by URL path
+ *
+ * Parameter array:
+ * 'filename': string
+ * 'filepath': string Path to the file on the file system. Remember the final slash
+ * 'urlpath': string Path to the file available through an URL. Remember the final slash
+ * 'width': int The width in pixels
+ * 'height': int The height in pixels
+ */
+ function toHtml($params)
+ {
+ parent::toHtml($params);
+ return '<embed src="' . $params['urlpath'] . $params['filename'] . '" width=' . $params['width'] . ' height=' . $params['height'] . ' type="image/svg+xml">';
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Canvas/Tool.php b/config/dspam/pear/Image/Canvas/Tool.php
new file mode 100644
index 00000000..3b87122c
--- /dev/null
+++ b/config/dspam/pear/Image/Canvas/Tool.php
@@ -0,0 +1,217 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Canvas
+ *
+ * Canvas based creation of images to facilitate different output formats
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Canvas
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212
+ */
+
+/**
+ * This class contains a set of tool-functions.
+ *
+ * These functions are all to be called statically
+ *
+ * @category Images
+ * @package Image_Canvas
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212
+ * @abstract
+ */
+class Image_Canvas_Tool
+{
+
+ /**
+ * Maps a font name to an actual font file (fx. a .ttf file)
+ *
+ * Used to translate names (i.e. 'Courier New' to 'cour.ttf' or
+ * '/Windows/Fonts/Cour.ttf')
+ *
+ * Font names are translated using the tab-separated file
+ * Image/Canvas/Tool/fontmap.txt.
+ *
+ * The translated font-name (or the original if no translation) exists is
+ * then returned if it is an existing file, otherwise the file is searched
+ * first in the path specified by IMAGE_CANVAS_SYSTEM_FONT_PATH defined in
+ * Image/Canvas.php, then in the Image/Canvas/Fonts folder. If a font is
+ * still not found and the name is not beginning with a '/' the search is
+ * left to the library, otherwise the font is deemed non-existing.
+ *
+ * @param string $name The name of the font
+ * @param string $type The needed file type of the font
+ * @return string The filename of the font
+ * @static
+ */
+ function fontMap($name, $type = '.ttf')
+ {
+ static $_fontMap;
+
+ if (!is_array($_fontMap)) {
+ if (file_exists($fontmap = (dirname(__FILE__) . '/Fonts/fontmap.txt'))) {
+ $file = file($fontmap);
+ foreach($file as $fontmapping) {
+ list($fontname, $filenames) = explode(',', $fontmapping, 2);
+ $fontname = trim($fontname);
+ $filenames = trim($filenames);
+ $filenames = explode(',', $filenames);
+ foreach ($filenames as $filename) {
+ $type_pos = strrpos($filename, '.');
+ $type = substr($filename, $type_pos);
+ $_fontMap[$fontname][$type] = $filename;
+ }
+ }
+ }
+ }
+
+ $type = strtolower($type);
+
+ if ((isset($_fontMap[$name])) && (isset($_fontMap[$name][$type]))) {
+ $filename = $_fontMap[$name][$type];
+ } else {
+ $filename = $name;
+ }
+
+ if (substr($filename, -strlen($type)) !== $type) {
+ $filename .= $type;
+ }
+
+ $result = false;
+ if (file_exists($filename)) {
+ $result = $filename;
+ } elseif (file_exists($file = (IMAGE_CANVAS_SYSTEM_FONT_PATH . $filename))) {
+ $result = $file;
+ } elseif (file_exists($file = (dirname(__FILE__) . '/Fonts/' . $filename))) {
+ $result = $file;
+ } elseif (substr($name, 0, 1) !== '/') {
+ // leave it to the library to find the font
+ $result = $name;
+ }
+
+ return str_replace('\\', '/', $result);
+ }
+
+ /**
+ * Return the average of 2 points
+ *
+ * @param double P1 1st point
+ * @param double P2 2nd point
+ * @return double The average of P1 and P2
+ * @static
+ */
+ function mid($p1, $p2)
+ {
+ return ($p1 + $p2) / 2;
+ }
+
+ /**
+ * Mirrors P1 in P2 by a amount of Factor
+ *
+ * @param double $p1 1st point, point to mirror
+ * @param double $o2 2nd point, mirror point
+ * @param double $factor Mirror factor, 0 returns $p2, 1 returns a pure
+ * mirror, ie $p1 on the exact other side of $p2
+ * @return double $p1 mirrored in $p2 by Factor
+ * @static
+ */
+ function mirror($p1, $p2, $factor = 1)
+ {
+ return $p2 + $factor * ($p2 - $p1);
+ }
+
+ /**
+ * Calculates a Bezier control point, this function must be called for BOTH
+ * X and Y coordinates (will it work for 3D coordinates!?)
+ *
+ * @param double $p1 1st point
+ * @param double $p2 Point to
+ * @param double $factor Mirror factor, 0 returns P2, 1 returns a pure
+ * mirror, i.e. P1 on the exact other side of P2
+ * @return double P1 mirrored in P2 by Factor
+ * @static
+ */
+ function controlPoint($p1, $p2, $factor, $smoothFactor = 0.75)
+ {
+ $sa = Image_Canvas_Tool::mirror($p1, $p2, $smoothFactor);
+ $sb = Image_Canvas_Tool::mid($p2, $sa);
+
+ $m = Image_Canvas_Tool::mid($p2, $factor);
+
+ $pC = Image_Canvas_Tool::mid($sb, $m);
+
+ return $pC;
+ }
+
+ /**
+ * Calculates a Bezier point, this function must be called for BOTH X and Y
+ * coordinates (will it work for 3D coordinates!?)
+ *
+ * @param double $t A position between $p2 and $p3, value between 0 and 1
+ * @param double $p1 Point to use for calculating control points
+ * @param double $p2 Point 1 to calculate bezier curve between
+ * @param double $p3 Point 2 to calculate bezier curve between
+ * @param double $p4 Point to use for calculating control points
+ * @return double The bezier value of the point t between $p2 and $p3 using
+ * $p1 and $p4 to calculate control points
+ * @static
+ */
+ function bezier($t, $p1, $p2, $p3, $p4)
+ {
+ // (1-t)^3*p1 + 3*(1-t)^2*t*p2 + 3*(1-t)*t^2*p3 + t^3*p4
+ return pow(1 - $t, 3) * $p1 +
+ 3 * pow(1 - $t, 2) * $t * $p2 +
+ 3 * (1 - $t) * pow($t, 2) * $p3 +
+ pow($t, 3) * $p4;
+ }
+
+ /**
+ * Gets the angle / slope of a line relative to horizontal (left -> right)
+ *
+ * @param double $x0 The starting x point
+ * @param double $y0 The starting y point
+ * @param double $x1 The ending x point
+ * @param double $y1 The ending y point
+ * @param double The angle in degrees of the line
+ * @static
+ */
+ function getAngle($x0, $y0, $x1, $y1)
+ {
+
+ $dx = ($x1 - $x0);
+ $dy = ($y1 - $y0);
+ $l = sqrt($dx * $dx + $dy * $dy);
+ $v = rad2deg(asin(($y0 - $y1) / $l));
+ if ($dx < 0) {
+ $v = 180 - $v;
+ }
+ return $v;
+
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Canvas/WithMap.php b/config/dspam/pear/Image/Canvas/WithMap.php
new file mode 100644
index 00000000..dc43ec4d
--- /dev/null
+++ b/config/dspam/pear/Image/Canvas/WithMap.php
@@ -0,0 +1,278 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Canvas
+ *
+ * Canvas based creation of images to facilitate different output formats
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Canvas
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212
+ */
+
+/**
+ * Class for handling different output formats including a HTML image map
+ *
+ * @category Images
+ * @package Image_Canvas
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212
+ * @since version 0.2.0
+ * @abstract
+ */
+class Image_Canvas_WithMap extends Image_Canvas
+{
+
+ /**
+ * The image map
+ * @var Image_Canvas_ImageMap
+ * @access private
+ */
+ var $_imageMap = null;
+
+ /**
+ * Create the canvas.
+ *
+ * Parameters available:
+ *
+ * 'width' The width of the graph on the canvas
+ *
+ * 'height' The height of the graph on the canvas
+ *
+ * 'left' The left offset of the graph on the canvas
+ *
+ * 'top' The top offset of the graph on the canvas
+ *
+ * 'usemap' Initialize an image map
+ *
+ * @param array $params Parameter array
+ * @abstract
+ */
+ function Image_Canvas_WithMap($params)
+ {
+ parent::Image_Canvas($params);
+
+ if ((isset($params['usemap'])) && ($params['usemap'] === true)) {
+ $this->_imageMap =& Image_Canvas::factory(
+ 'ImageMap',
+ array(
+ 'left' => $this->_left,
+ 'top' => $this->_top,
+ 'width' => $this->_width,
+ 'height' => $this->_height
+ )
+ );
+ }
+ }
+ /**
+ * Draw a line
+ *
+ * Parameter array:
+ * 'x0': int X start point
+ * 'y0': int Y start point
+ * 'x1': int X end point
+ * 'y1': int Y end point
+ * 'color': mixed [optional] The line color
+ * @param array $params Parameter array
+ */
+ function line($params)
+ {
+ if (isset($this->_imageMap)) {
+ $this->_imageMap->line($params);
+ }
+ parent::line($params);
+ }
+
+ /**
+ * Adds vertex to a polygon
+ *
+ * Parameter array:
+ * 'x': int X point
+ * 'y': int Y point
+ * @param array $params Parameter array
+ */
+ function addVertex($params)
+ {
+ if (isset($this->_imageMap)) {
+ $this->_imageMap->addVertex($params);
+ }
+ parent::addVertex($params);
+ }
+
+ /**
+ * Adds "splined" vertex to a polygon
+ *
+ * Parameter array:
+ * 'x': int X point
+ * 'y': int Y point
+ * 'p1x': X Control point 1
+ * 'p1y': Y Control point 1
+ * 'p2x': X Control point 2
+ * 'p2y': Y Control point 2
+ * @param array $params Parameter array
+ */
+ function addSpline($params)
+ {
+ if (isset($this->_imageMap)) {
+ $this->_imageMap->addSpline($params);
+ }
+ parent::addSpline($params);
+ }
+
+ /**
+ * Draws a polygon
+ *
+ * Parameter array:
+ * 'connect': bool [optional] Specifies whether the start point should be
+ * connected to the endpoint (closed polygon) or not (connected line)
+ * 'fill': mixed [optional] The fill color
+ * 'line': mixed [optional] The line color
+ * @param array $params Parameter array
+ */
+ function polygon($params)
+ {
+ if (isset($this->_imageMap)) {
+ $this->_imageMap->polygon($params);
+ }
+ parent::polygon($params);
+ }
+
+ /**
+ * Draw a rectangle
+ *
+ * Parameter array:
+ * 'x0': int X start point
+ * 'y0': int Y start point
+ * 'x1': int X end point
+ * 'y1': int Y end point
+ * 'fill': mixed [optional] The fill color
+ * 'line': mixed [optional] The line color
+ * @param array $params Parameter array
+ */
+ function rectangle($params)
+ {
+ if (isset($this->_imageMap)) {
+ $this->_imageMap->rectangle($params);
+ }
+ parent::rectangle($params);
+ }
+
+ /**
+ * Draw an ellipse
+ *
+ * Parameter array:
+ * 'x': int X center point
+ * 'y': int Y center point
+ * 'rx': int X radius
+ * 'ry': int Y radius
+ * 'fill': mixed [optional] The fill color
+ * 'line': mixed [optional] The line color
+ * @param array $params Parameter array
+ */
+ function ellipse($params)
+ {
+ if (isset($this->_imageMap)) {
+ $this->_imageMap->ellipse($params);
+ }
+ parent::ellipse($params);
+ }
+
+ /**
+ * Draw a pie slice
+ *
+ * Parameter array:
+ * 'x': int X center point
+ * 'y': int Y center point
+ * 'rx': int X radius
+ * 'ry': int Y radius
+ * 'v1': int The starting angle (in degrees)
+ * 'v2': int The end angle (in degrees)
+ * 'srx': int [optional] Starting X-radius of the pie slice (i.e. for a doughnut)
+ * 'sry': int [optional] Starting Y-radius of the pie slice (i.e. for a doughnut)
+ * 'fill': mixed [optional] The fill color
+ * 'line': mixed [optional] The line color
+ * @param array $params Parameter array
+ */
+ function pieslice($params)
+ {
+ if (isset($this->_imageMap)) {
+ $this->_imageMap->pieslice($params);
+ }
+ parent::pieslice($params);
+ }
+
+ /**
+ * Writes text
+ *
+ * Parameter array:
+ * 'x': int X-point of text
+ * 'y': int Y-point of text
+ * 'text': string The text to add
+ * 'alignment': array [optional] Alignment
+ * 'color': mixed [optional] The color of the text
+ */
+ function addText($params)
+ {
+ if (isset($this->_imageMap)) {
+ $this->_imageMap->addText($params);
+ }
+ parent::addText($params);
+ }
+
+ /**
+ * Overlay image
+ *
+ * Parameter array:
+ * 'x': int X-point of overlayed image
+ * 'y': int Y-point of overlayed image
+ * 'filename': string The filename of the image to overlay
+ * 'width': int [optional] The width of the overlayed image (resizing if possible)
+ * 'height': int [optional] The height of the overlayed image (resizing if possible)
+ * 'alignment': array [optional] Alignment
+ */
+ function image($params)
+ {
+ if (isset($this->_imageMap)) {
+ $this->_imageMap->image($params);
+ }
+ parent::image($params);
+ }
+
+ /**
+ * Get the imagemap
+ * @return Image_Graph_ImageMap The image map (or false if none)
+ */
+ function &getImageMap()
+ {
+ $result = null;
+ if (isset($this->_imageMap)) {
+ $result =& $this->_imageMap;
+ }
+ return $result;
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Color.php b/config/dspam/pear/Image/Color.php
new file mode 100644
index 00000000..1b20125d
--- /dev/null
+++ b/config/dspam/pear/Image/Color.php
@@ -0,0 +1,719 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Color.php is the implementation of Image_Color.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This source file is subject to version 3.0 of the PHP license
+ * that is available through the world-wide-web at the following URI:
+ * http://www.php.net/license/3_0.txt. If you did not receive a copy of
+ * the PHP License and are unable to obtain it through the web, please
+ * send a note to license@php.net so we can mail you a copy immediately.
+ *
+ * @category Image
+ * @package Image_Color
+ * @author Jason Lotito <jason@lehighweb.com>
+ * @author Andrew Morton <drewish@katherinehouse.com>
+ * @copyright 2003-2005 The PHP Group
+ * @license http://www.php.net/license/3_0.txt PHP License 3.0
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Color
+ */
+
+/**
+ * Image_Color handles color conversion and mixing.
+ *
+ * The class is quick, simple to use, and does its job fairly well but it's got
+ * some code smells:
+ * - Call setColors() for some functions but not others.
+ * - Different functions expect different color formats. setColors() only
+ * accepts hex while allocateColor() will accept named or hex (provided the
+ * hex ones start with the # character).
+ * - Some conversions go in only one direction, ie HSV->RGB but no RGB->HSV.
+ * I'm going to try to straighten out some of this but I'll be hard to do so
+ * without breaking backwards compatibility.
+ *
+ * @category Image
+ * @package Image_Color
+ * @author Jason Lotito <jason@lehighweb.com>
+ * @author Andrew Morton <drewish@katherinehouse.com>
+ * @copyright 2003-2005 The PHP Group
+ * @license http://www.php.net/license/3_0.txt PHP License 3.0
+ * @version Release: 0.1.2
+ * @link http://pear.php.net/package/Image_Color
+ */
+class Image_Color
+{
+ /**
+ * First color that the class handles for ranges and mixes.
+ * @var array
+ * @access public
+ * @see setColors()
+ */
+ var $color1 = array();
+
+ /**
+ * Second color that the class handles for ranges and mixes.
+ * @var array
+ * @access public
+ * @see setColors()
+ */
+ var $color2 = array();
+
+ /**
+ * Boolean value for determining whether colors outputted should be limited
+ * to the web safe pallet or not.
+ *
+ * @var boolean
+ * @access private
+ * @see setWebSafe()
+ */
+ var $_websafeb = false;
+
+ /**
+ * Mix two colors together by finding their average. If the colors are not
+ * passed as parameters, the class's colors will be mixed instead.
+ *
+ * @param string $col1 The first color you want to mix
+ * @param string $col2 The second color you want to mix
+ * @return string The mixed color.
+ * @access public
+ * @author Jason Lotito <jason@lehighweb.com>
+ * @uses _setColors() to assign the colors if any are passed to the
+ * class.
+ */
+ function mixColors($col1 = false, $col2 = false)
+ {
+ if ($col1) {
+ $this->_setColors($col1, $col2);
+ }
+
+ // after finding the average, it will be a float. add 0.5 and then
+ // cast to an integer to properly round it to an integer.
+ $color3[0] = (int) ((($this->color1[0] + $this->color2[0]) / 2) + 0.5);
+ $color3[1] = (int) ((($this->color1[1] + $this->color2[1]) / 2) + 0.5);
+ $color3[2] = (int) ((($this->color1[2] + $this->color2[2]) / 2) + 0.5);
+
+ if ($this->_websafeb) {
+ array_walk($color3, '_makeWebSafe');
+ }
+
+ return Image_Color::rgb2hex($color3);
+ }
+
+ /**
+ * Determines whether colors the returned by this class will be rounded to
+ * the nearest web safe value.
+ *
+ * @param boolean $bool Indicates if colors should be limited to the
+ * websafe pallet.
+ * @return void
+ * @access public
+ * @author Jason Lotito <jason@lehighweb.com>
+ */
+ function setWebSafe($bool = true)
+ {
+ $this->_websafeb = (boolean) $bool;
+ }
+
+ /**
+ * Set the two colors this class uses for mixing and ranges.
+ *
+ * @param string $col1 The first color in hex format
+ * @param string $col2 The second color in hex format
+ * @return void
+ * @access public
+ * @author Jason Lotito <jason@lehighweb.com>
+ */
+ function setColors($col1, $col2)
+ {
+ $this->_setColors($col1, $col2);
+ }
+
+ /**
+ * Get the range of colors between the class's two colors, given a degree.
+ *
+ * @param integer $degrees How large a 'step' we should take between the
+ * colors.
+ * @return array Returns an array of hex strings, one element for each
+ * color.
+ * @access public
+ * @author Jason Lotito <jason@lehighweb.com>
+ * @todo Allow for degrees for individual parts of the colors.
+ */
+ function getRange($degrees = 2)
+ {
+ if ($degrees == 0) {
+ $degrees = 1;
+ }
+
+ // The degrees give us how much we should advance each color at each
+ // phase of the loop. This way, the advance is equal throughout all
+ // the colors.
+
+ $red_steps = ($this->color2[0] - $this->color1[0]) / $degrees;
+ $green_steps = ($this->color2[1] - $this->color1[1]) / $degrees;
+ $blue_steps = ($this->color2[2] - $this->color1[2]) / $degrees;
+
+ $allcolors = array();
+
+ /**
+ * The loop stops once any color has gone beyond the end color.
+ */
+
+ // Loop through all the degrees between the colors
+ for ($x = 0; $x < $degrees; $x++) {
+ $col[0] = $red_steps * $x;
+ $col[1] = $green_steps * $x;
+ $col[2] = $blue_steps * $x;
+
+ // Loop through each R, G, and B
+ for ($i = 0; $i < 3; $i++) {
+ $partcolor = $this->color1[$i] + $col[$i];
+ // If the color is less than 256
+ if ($partcolor < 256) {
+ // Makes sure the colors is not less than 0
+ if ($partcolor > -1) {
+ $newcolor[$i] = $partcolor;
+ } else {
+ $newcolor[$i] = 0;
+ }
+ // Color was greater than 255
+ } else {
+ $newcolor[$i] = 255;
+ }
+ }
+
+ if ($this->_websafeb) {
+ array_walk($newcolor, '_makeWebSafe');
+ }
+
+ $allcolors[] = Image_Color::rgb2hex($newcolor);
+ }
+
+ return $allcolors;
+ }
+
+ /**
+ * Change the lightness of the class's two colors.
+ *
+ * @param integer $degree The degree of the change. Positive values
+ * lighten the color while negative values will darken it.
+ * @return void
+ * @access public
+ * @author Jason Lotito <jason@lehighweb.com>
+ * @uses Image_Color::$color1 as an input and return value.
+ * @uses Image_Color::$color2 as an input and return value.
+ */
+ function changeLightness($degree = 10)
+ {
+ $color1 =& $this->color1;
+ $color2 =& $this->color2;
+
+ for ($x = 0; $x < 3; $x++) {
+ if (($color1[$x] + $degree) < 256) {
+ if (($color1[$x] + $degree) > -1) {
+ $color1[$x] += $degree;
+ } else {
+ $color1[$x] = 0;
+ }
+ } else {
+ $color1[$x] = 255;
+ }
+
+ if (($color2[$x] + $degree) < 256) {
+ if (($color2[$x] + $degree) > -1) {
+ $color2[$x] += $degree;
+ } else {
+ $color2[$x] = 0;
+ }
+ } else {
+ $color2[$x] = 255;
+ }
+ }
+ }
+
+ /**
+ * Determine if a light or dark text color would be more readable on a
+ * background of a given color. This is determined by the G(reen) value of
+ * RGB. You can change the dark and the light colors from their default
+ * black and white.
+ *
+ * @param string $color The hex color to analyze
+ * @param string $light The light color value to return if we should
+ * have light text.
+ * @param string $dark The dark color value to return if we should have
+ * dark text.
+ * @return string The light or dark value which would make the text most
+ * readable.
+ * @access public
+ * @static
+ * @author Jason Lotito <jason@lehighweb.com>
+ */
+ function getTextColor($color, $light = '#FFFFFF', $dark = '#000000')
+ {
+ $color = Image_Color::_splitColor($color);
+ if ($color[1] > hexdec('66')) {
+ return $dark;
+ } else {
+ return $light;
+ }
+ }
+
+
+ /**
+ * Internal method to set the colors.
+ *
+ * @param string $col1 First color, either a name or hex value
+ * @param string $col2 Second color, either a name or hex value
+ * @return void
+ * @access private
+ * @author Jason Lotito <jason@lehighweb.com>
+ */
+ function _setColors($col1, $col2)
+ {
+ if ($col1) {
+ $this->color1 = Image_Color::_splitColor($col1);
+ }
+ if ($col2) {
+ $this->color2 = Image_Color::_splitColor($col2);
+ }
+ }
+
+ /**
+ * Given a color, properly split it up into a 3 element RGB array.
+ *
+ * @param string $color The color.
+ * @return array A three element RGB array.
+ * @access private
+ * @static
+ * @author Jason Lotito <jason@lehighweb.com>
+ */
+ function _splitColor($color)
+ {
+ $color = str_replace('#', '', $color);
+ $c[] = hexdec(substr($color, 0, 2));
+ $c[] = hexdec(substr($color, 2, 2));
+ $c[] = hexdec(substr($color, 4, 2));
+ return $c;
+ }
+
+ /**
+ * This is deprecated. Use rgb2hex() instead.
+ * @access private
+ * @deprecated Function deprecated after 1.0.1
+ * @see rgb2hex().
+ */
+ function _returnColor ( $color )
+ {
+ return Image_Color::rgb2hex($color);
+ }
+
+ /**
+ * Convert an RGB array to a hex string.
+ *
+ * @param array $color 3 element RGB array.
+ * @return string Hex color string.
+ * @access public
+ * @static
+ * @author Jason Lotito <jason@lehighweb.com>
+ * @see hex2rgb()
+ */
+ function rgb2hex($color)
+ {
+ return sprintf('%02X%02X%02X',$color[0],$color[1],$color[2]);
+ }
+
+ /**
+ * Convert a hex color string into an RGB array. An extra fourth element
+ * will be returned with the original hex value.
+ *
+ * @param string $hex Hex color string.
+ * @return array RGB color array with an extra 'hex' element containing
+ * the original hex string.
+ * @access public
+ * @static
+ * @author Jason Lotito <jason@lehighweb.com>
+ * @see rgb2hex()
+ */
+ function hex2rgb($hex)
+ {
+ $return = Image_Color::_splitColor($hex);
+ $return['hex'] = $hex;
+ return $return;
+ }
+
+ /**
+ * Convert an HSV (Hue, Saturation, Brightness) value to RGB.
+ *
+ * @param integer $h Hue
+ * @param integer $s Saturation
+ * @param integer $v Brightness
+ * @return array RGB array.
+ * @access public
+ * @static
+ * @author Jason Lotito <jason@lehighweb.com>
+ * @uses hsv2hex() to convert the HSV value to Hex.
+ * @uses hex2rgb() to convert the Hex value to RGB.
+ */
+ function hsv2rgb($h, $s, $v)
+ {
+ return Image_Color::hex2rgb(Image_Color::hsv2hex($h, $s, $v));
+ }
+
+ /**
+ * Convert HSV (Hue, Saturation, Brightness) to a hex color string.
+ *
+ * Originally written by Jurgen Schwietering. Integrated into the class by
+ * Jason Lotito.
+ *
+ * @param integer $h Hue
+ * @param integer $s Saturation
+ * @param integer $v Brightness
+ * @return string The hex string.
+ * @access public
+ * @static
+ * @author Jurgen Schwietering <jurgen@schwietering.com>
+ * @uses rgb2hex() to convert the return value to a hex string.
+ */
+ function hsv2hex($h, $s, $v)
+ {
+ $s /= 256.0;
+ $v /= 256.0;
+ if ($s == 0.0) {
+ $r = $g = $b = $v;
+ return '';
+ } else {
+ $h = $h / 256.0 * 6.0;
+ $i = floor($h);
+ $f = $h - $i;
+
+ $v *= 256.0;
+ $p = (integer)($v * (1.0 - $s));
+ $q = (integer)($v * (1.0 - $s * $f));
+ $t = (integer)($v * (1.0 - $s * (1.0 - $f)));
+ switch($i) {
+ case 0:
+ $r = $v;
+ $g = $t;
+ $b = $p;
+ break;
+
+ case 1:
+ $r = $q;
+ $g = $v;
+ $b = $p;
+ break;
+
+ case 2:
+ $r = $p;
+ $g = $v;
+ $b = $t;
+ break;
+
+ case 3:
+ $r = $p;
+ $g = $q;
+ $b = $v;
+ break;
+
+ case 4:
+ $r = $t;
+ $g = $p;
+ $b = $v;
+ break;
+
+ default:
+ $r = $v;
+ $g = $p;
+ $b = $q;
+ break;
+ }
+ }
+ return $this->rgb2hex(array($r, $g, $b));
+ }
+
+ /**
+ * Allocates a color in the given image.
+ *
+ * User defined color specifications get translated into an array of RGB
+ * values.
+ *
+ * @param resource $img Image handle
+ * @param string|array $color Name or hex string or an RGB array.
+ * @return resource Image color handle.
+ * @access public
+ * @static
+ * @uses ImageColorAllocate() to allocate the color.
+ * @uses color2RGB() to parse the color into RGB values.
+ */
+ function allocateColor(&$img, $color) {
+ $color = Image_Color::color2RGB($color);
+
+ return ImageColorAllocate($img, $color[0], $color[1], $color[2]);
+ }
+
+ /**
+ * Convert a named or hex color string to an RGB array. If the color begins
+ * with the # character it will be treated as a hex value. Everything else
+ * will be treated as a named color. If the named color is not known, black
+ * will be returned.
+ *
+ * @param string $color
+ * @return array RGB color
+ * @access public
+ * @static
+ * @author Laurent Laville <pear@laurent-laville.org>
+ * @uses hex2rgb() to convert colors begining with the # character.
+ * @uses namedColor2RGB() to convert everything not starting with a #.
+ */
+ function color2RGB($color)
+ {
+ $c = array();
+
+ if ($color{0} == '#') {
+ $c = Image_Color::hex2rgb($color);
+ } else {
+ $c = Image_Color::namedColor2RGB($color);
+ }
+
+ return $c;
+ }
+
+ /**
+ * Convert a named color to an RGB array. If the color is unknown black
+ * is returned.
+ *
+ * @param string $color Case insensitive color name.
+ * @return array RGB color array. If the color was unknown, the result
+ * will be black.
+ * @access public
+ * @static
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ */
+ function namedColor2RGB($color)
+ {
+ static $colornames;
+
+ if (!isset($colornames)) {
+ $colornames = array(
+ 'aliceblue' => array(240, 248, 255),
+ 'antiquewhite' => array(250, 235, 215),
+ 'aqua' => array( 0, 255, 255),
+ 'aquamarine' => array(127, 255, 212),
+ 'azure' => array(240, 255, 255),
+ 'beige' => array(245, 245, 220),
+ 'bisque' => array(255, 228, 196),
+ 'black' => array( 0, 0, 0),
+ 'blanchedalmond' => array(255, 235, 205),
+ 'blue' => array( 0, 0, 255),
+ 'blueviolet' => array(138, 43, 226),
+ 'brown' => array(165, 42, 42),
+ 'burlywood' => array(222, 184, 135),
+ 'cadetblue' => array( 95, 158, 160),
+ 'chartreuse' => array(127, 255, 0),
+ 'chocolate' => array(210, 105, 30),
+ 'coral' => array(255, 127, 80),
+ 'cornflowerblue' => array(100, 149, 237),
+ 'cornsilk' => array(255, 248, 220),
+ 'crimson' => array(220, 20, 60),
+ 'cyan' => array( 0, 255, 255),
+ 'darkblue' => array( 0, 0, 13),
+ 'darkcyan' => array( 0, 139, 139),
+ 'darkgoldenrod' => array(184, 134, 11),
+ 'darkgray' => array(169, 169, 169),
+ 'darkgreen' => array( 0, 100, 0),
+ 'darkkhaki' => array(189, 183, 107),
+ 'darkmagenta' => array(139, 0, 139),
+ 'darkolivegreen' => array( 85, 107, 47),
+ 'darkorange' => array(255, 140, 0),
+ 'darkorchid' => array(153, 50, 204),
+ 'darkred' => array(139, 0, 0),
+ 'darksalmon' => array(233, 150, 122),
+ 'darkseagreen' => array(143, 188, 143),
+ 'darkslateblue' => array( 72, 61, 139),
+ 'darkslategray' => array( 47, 79, 79),
+ 'darkturquoise' => array( 0, 206, 209),
+ 'darkviolet' => array(148, 0, 211),
+ 'deeppink' => array(255, 20, 147),
+ 'deepskyblue' => array( 0, 191, 255),
+ 'dimgray' => array(105, 105, 105),
+ 'dodgerblue' => array( 30, 144, 255),
+ 'firebrick' => array(178, 34, 34),
+ 'floralwhite' => array(255, 250, 240),
+ 'forestgreen' => array( 34, 139, 34),
+ 'fuchsia' => array(255, 0, 255),
+ 'gainsboro' => array(220, 220, 220),
+ 'ghostwhite' => array(248, 248, 255),
+ 'gold' => array(255, 215, 0),
+ 'goldenrod' => array(218, 165, 32),
+ 'gray' => array(128, 128, 128),
+ 'green' => array( 0, 128, 0),
+ 'greenyellow' => array(173, 255, 47),
+ 'honeydew' => array(240, 255, 240),
+ 'hotpink' => array(255, 105, 180),
+ 'indianred' => array(205, 92, 92),
+ 'indigo' => array(75, 0, 130),
+ 'ivory' => array(255, 255, 240),
+ 'khaki' => array(240, 230, 140),
+ 'lavender' => array(230, 230, 250),
+ 'lavenderblush' => array(255, 240, 245),
+ 'lawngreen' => array(124, 252, 0),
+ 'lemonchiffon' => array(255, 250, 205),
+ 'lightblue' => array(173, 216, 230),
+ 'lightcoral' => array(240, 128, 128),
+ 'lightcyan' => array(224, 255, 255),
+ 'lightgoldenrodyellow' => array(250, 250, 210),
+ 'lightgreen' => array(144, 238, 144),
+ 'lightgrey' => array(211, 211, 211),
+ 'lightpink' => array(255, 182, 193),
+ 'lightsalmon' => array(255, 160, 122),
+ 'lightseagreen' => array( 32, 178, 170),
+ 'lightskyblue' => array(135, 206, 250),
+ 'lightslategray' => array(119, 136, 153),
+ 'lightsteelblue' => array(176, 196, 222),
+ 'lightyellow' => array(255, 255, 224),
+ 'lime' => array( 0, 255, 0),
+ 'limegreen' => array( 50, 205, 50),
+ 'linen' => array(250, 240, 230),
+ 'magenta' => array(255, 0, 255),
+ 'maroon' => array(128, 0, 0),
+ 'mediumaquamarine' => array(102, 205, 170),
+ 'mediumblue' => array( 0, 0, 205),
+ 'mediumorchid' => array(186, 85, 211),
+ 'mediumpurple' => array(147, 112, 219),
+ 'mediumseagreen' => array( 60, 179, 113),
+ 'mediumslateblue' => array(123, 104, 238),
+ 'mediumspringgreen' => array( 0, 250, 154),
+ 'mediumturquoise' => array(72, 209, 204),
+ 'mediumvioletred' => array(199, 21, 133),
+ 'midnightblue' => array( 25, 25, 112),
+ 'mintcream' => array(245, 255, 250),
+ 'mistyrose' => array(255, 228, 225),
+ 'moccasin' => array(255, 228, 181),
+ 'navajowhite' => array(255, 222, 173),
+ 'navy' => array( 0, 0, 128),
+ 'oldlace' => array(253, 245, 230),
+ 'olive' => array(128, 128, 0),
+ 'olivedrab' => array(107, 142, 35),
+ 'orange' => array(255, 165, 0),
+ 'orangered' => array(255, 69, 0),
+ 'orchid' => array(218, 112, 214),
+ 'palegoldenrod' => array(238, 232, 170),
+ 'palegreen' => array(152, 251, 152),
+ 'paleturquoise' => array(175, 238, 238),
+ 'palevioletred' => array(219, 112, 147),
+ 'papayawhip' => array(255, 239, 213),
+ 'peachpuff' => array(255, 218, 185),
+ 'peru' => array(205, 133, 63),
+ 'pink' => array(255, 192, 203),
+ 'plum' => array(221, 160, 221),
+ 'powderblue' => array(176, 224, 230),
+ 'purple' => array(128, 0, 128),
+ 'red' => array(255, 0, 0),
+ 'rosybrown' => array(188, 143, 143),
+ 'royalblue' => array( 65, 105, 225),
+ 'saddlebrown' => array(139, 69, 19),
+ 'salmon' => array(250, 128, 114),
+ 'sandybrown' => array(244, 164, 96),
+ 'seagreen' => array( 46, 139, 87),
+ 'seashell' => array(255, 245, 238),
+ 'sienna' => array(160, 82, 45),
+ 'silver' => array(192, 192, 192),
+ 'skyblue' => array(135, 206, 235),
+ 'slateblue' => array(106, 90, 205),
+ 'slategray' => array(112, 128, 144),
+ 'snow' => array(255, 250, 250),
+ 'springgreen' => array( 0, 255, 127),
+ 'steelblue' => array( 70, 130, 180),
+ 'tan' => array(210, 180, 140),
+ 'teal' => array( 0, 128, 128),
+ 'thistle' => array(216, 191, 216),
+ 'tomato' => array(255, 99, 71),
+ 'turquoise' => array( 64, 224, 208),
+ 'violet' => array(238, 130, 238),
+ 'wheat' => array(245, 222, 179),
+ 'white' => array(255, 255, 255),
+ 'whitesmoke' => array(245, 245, 245),
+ 'yellow' => array(255, 255, 0),
+ 'yellowgreen' => array(154, 205, 50)
+ );
+ }
+
+ $color = strtolower($color);
+
+ if (isset($colornames[$color])) {
+ return $colornames[$color];
+ } else {
+ return array(0, 0, 0);
+ }
+ }
+
+ /**
+ * Convert an RGB percentage string into an RGB array.
+ *
+ * @param string $color Percentage color string like "50%,20%,100%".
+ * @return array RGB color array.
+ * @access public
+ * @static
+ */
+ function percentageColor2RGB($color)
+ {
+ // remove spaces
+ $color = str_replace(' ', '', $color);
+ // remove the percent signs
+ $color = str_replace('%', '', $color);
+ // split the string by commas
+ $color = explode(',', $color);
+
+ $ret = array();
+ foreach ($color as $k => $v) {
+ // range checks
+ if ($v <= 0) {
+ $ret[$k] = 0;
+ } else if ($v <= 100) {
+ // add 0.5 then cast to an integer to round the value.
+ $ret[$k] = (integer) ((2.55 * $v) + 0.5);
+ } else {
+ $ret[$k] = 255;
+ }
+ }
+
+ return $ret;
+ }
+}
+
+// For Array Walk
+// {{{
+/**
+ * Function for array_walk() to round colors to the closest web safe value.
+ *
+ * @param integer $color One channel of an RGB color.
+ * @return integer The websafe equivalent of the color channel.
+ * @author Jason Lotito <jason@lehighweb.com>
+ * @author Andrew Morton <drewish@katherinehouse.com>
+ * @access private
+ * @static
+ */
+function _makeWebSafe(&$color)
+{
+ if ($color < 0x1a) {
+ $color = 0x00;
+ } else if ($color < 0x4d) {
+ $color = 0x33;
+ } else if ($color < 0x80) {
+ $color = 0x66;
+ } else if ($color < 0xB3) {
+ $color = 0x99;
+ } else if ($color < 0xE6) {
+ $color = 0xCC;
+ } else {
+ $color = 0xFF;
+ }
+ return $color;
+}
+// }}}
+
+?>
diff --git a/config/dspam/pear/Image/Graph.php b/config/dspam/pear/Image/Graph.php
new file mode 100644
index 00000000..d2e2492b
--- /dev/null
+++ b/config/dspam/pear/Image/Graph.php
@@ -0,0 +1,851 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - Main class for the graph creation.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+
+/**
+ * Include PEAR.php
+ */
+require_once 'PEAR.inc';
+
+/**
+ * Include file Image/Graph/Element.php
+ */
+require_once 'Image/Graph/Element.php';
+
+/**
+ * Include file Image/Graph/Constants.php
+ */
+require_once 'Image/Graph/Constants.php';
+
+/**
+ * Main class for the graph creation.
+ *
+ * This is the main class, it manages the canvas and performs the final output
+ * by sequentialy making the elements output their results. The final output is
+ * handled using the {@link Image_Canvas} classes which makes it possible
+ * to use different engines (fx GD, PDFlib, libswf, etc) for output to several
+ * formats with a non-intersecting API.
+ *
+ * This class also handles coordinates and the correct managment of setting the
+ * correct coordinates on child elements.
+ *
+ * @category Images
+ * @package Image_Graph
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph extends Image_Graph_Element
+{
+
+ /**
+ * Show generation time on graph
+ * @var bool
+ * @access private
+ */
+ var $_showTime = false;
+
+ /**
+ * Display errors on the canvas
+ * @var boolean
+ * @access private
+ */
+ var $_displayErrors = false;
+
+ /**
+ * Image_Graph [Constructor].
+ *
+ * If passing the 3 parameters they are defined as follows:'
+ *
+ * Fx.:
+ *
+ * $Graph =& new Image_Graph(400, 300);
+ *
+ * or using the factory method:
+ *
+ * $Graph =& Image_Graph::factory('graph', array(400, 300));
+ *
+ * This causes a 'png' canvas to be created by default.
+ *
+ * Otherwise use a single parameter either as an associated array or passing
+ * the canvas along to the constructor:
+ *
+ * 1) Create a new canvas with the following parameters:
+ *
+ * 'canvas' - The canvas type, can be any of 'gd', 'jpg', 'png' or 'svg'
+ * (more to come) - if omitted the default is 'gd'
+ *
+ * 'width' - The width of the graph
+ *
+ * 'height' - The height of the graph
+ *
+ * An example of this usage:
+ *
+ * $Graph =& Image_Graph::factory('graph', array(array('width' => 400,
+ * 'height' => 300, 'canvas' => 'jpg')));
+ *
+ * NB! In thïs case remember the "double" array (see {@link Image_Graph::
+ * factory()})
+ *
+ * 2) Use the canvas specified, pass a valid Image_Canvas as
+ * parameter. Remember to pass by reference, i. e. &amp;$canvas, fx.:
+ *
+ * $Graph =& new Image_Graph($Canvas);
+ *
+ * or using the factory method:
+ *
+ * $Graph =& Image_Graph::factory('graph', $Canvas));
+ *
+ * @param mixed $params The width of the graph, an indexed array
+ * describing a new canvas or a valid {@link Image_Canvas} object
+ * @param int $height The height of the graph in pixels
+ * @param bool $createTransparent Specifies whether the graph should be
+ * created with a transparent background (fx for PNG's - note: transparent
+ * PNG's is not supported by Internet Explorer!)
+ */
+ function Image_Graph($params, $height = false, $createTransparent = false)
+ {
+ parent::Image_Graph_Element();
+
+ $this->setFont(Image_Graph::factory('Image_Graph_Font'));
+
+ if (defined('IMAGE_GRAPH_DEFAULT_CANVAS_TYPE')) {
+ $canvasType = IMAGE_GRAPH_DEFAULT_CANVAS_TYPE;
+ } else {
+ $canvasType = 'png'; // use GD as default, if nothing else is specified
+ }
+
+ if (is_array($params)) {
+ if (isset($params['canvas'])) {
+ $canvasType = $params['canvas'];
+ }
+
+ $width = 0;
+ $height = 0;
+
+ if (isset($params['width'])) {
+ $width = $params['width'];
+ }
+
+ if (isset($params['height'])) {
+ $height = $params['height'];
+ }
+ } elseif (is_a($params, 'Image_Canvas')) {
+ $this->_canvas =& $params;
+ $width = $this->_canvas->getWidth();
+ $height = $this->_canvas->getHeight();
+ } elseif (is_numeric($params)) {
+ $width = $params;
+ }
+
+ if ($this->_canvas == null) {
+ include_once 'Image/Canvas.php';
+ $this->_canvas =&
+ Image_Canvas::factory(
+ $canvasType,
+ array('width' => $width, 'height' => $height)
+ );
+ }
+
+ $this->_setCoords(0, 0, $width - 1, $height - 1);
+ }
+
+ /**
+ * Gets the canvas for this graph.
+ *
+ * The canvas is set by either passing it to the constructor {@link
+ * Image_Graph::ImageGraph()} or using the {@link Image_Graph::setCanvas()}
+ * method.
+ *
+ * @return Image_Canvas The canvas used by this graph
+ * @access private
+ * @since 0.3.0dev2
+ */
+ function &_getCanvas()
+ {
+ return $this->_canvas;
+ }
+
+ /**
+ * Sets the canvas for this graph.
+ *
+ * Calling this method makes this graph use the newly specified canvas for
+ * handling output. This method should be called whenever multiple
+ * 'outputs' are required. Invoke this method after calls to {@link
+ * Image_Graph:: done()} has been performed, to switch canvass.
+ *
+ * @param Image_Canvas $canvas The new canvas
+ * @return Image_Canvas The new canvas
+ * @since 0.3.0dev2
+ */
+ function &setCanvas(&$canvas)
+ {
+ if (!is_a($this->_canvas, 'Image_Canvas')) {
+ return $this->_error('The canvas introduced is not an Image_Canvas object');
+ }
+
+ $this->_canvas =& $canvas;
+ $this->_setCoords(
+ 0,
+ 0,
+ $this->_canvas->getWidth() - 1,
+ $this->_canvas->getHeight() - 1
+ );
+ return $this->_canvas;
+ }
+
+ /**
+ * Gets a very precise timestamp
+ *
+ * @return The number of seconds to a lot of decimals
+ * @access private
+ */
+ function _getMicroTime()
+ {
+ list($usec, $sec) = explode(' ', microtime());
+ return ((float)$usec + (float)$sec);
+ }
+
+ /**
+ * Gets the width of this graph.
+ *
+ * The width is returned as 'defined' by the canvas.
+ *
+ * @return int the width of this graph
+ */
+ function width()
+ {
+ return $this->_canvas->getWidth();
+ }
+
+ /**
+ * Gets the height of this graph.
+ *
+ * The height is returned as 'defined' by the canvas.
+ *
+ * @return int the height of this graph
+ */
+ function height()
+ {
+ return $this->_canvas->getHeight();
+ }
+
+ /**
+ * Enables displaying of errors on the output.
+ *
+ * Use this method to enforce errors to be displayed on the output. Calling
+ * this method makes PHP uses this graphs error handler as default {@link
+ * Image_Graph::_default_error_handler()}.
+ */
+ function displayErrors()
+ {
+ $this->_displayErrors = true;
+ set_error_handler(array(&$this, '_default_error_handler'));
+ }
+
+ /**
+ * Sets the log method for this graph.
+ *
+ * Use this method to enable logging. This causes any errors caught
+ * by either the error handler {@see Image_Graph::displayErrors()}
+ * or explicitly by calling {@link Image_Graph_Common::_error()} be
+ * logged using the specified logging method.
+ *
+ * If a filename is specified as log method, a Log object is created (using
+ * the 'file' handler), with a handle of 'Image_Graph Error Log'.
+ *
+ * Logging requires {@link Log}.
+ *
+ * @param mixed $log The log method, either a Log object or filename to log
+ * to
+ * @since 0.3.0dev2
+ */
+ function setLog($log)
+ {
+ }
+
+ /**
+ * Factory method to create Image_Graph objects.
+ *
+ * Used for 'lazy including', i.e. loading only what is necessary, when it
+ * is necessary. If only one parameter is required for the constructor of
+ * the class simply pass this parameter as the $params parameter, unless the
+ * parameter is an array or a reference to a value, in that case you must
+ * 'enclose' the parameter in an array. Similar if the constructor takes
+ * more than one parameter specify the parameters in an array, i.e
+ *
+ * Image_Graph::factory('MyClass', array($param1, $param2, &$param3));
+ *
+ * Variables that need to be passed by reference *must* have the &amp;
+ * before the variable, i.e:
+ *
+ * Image_Graph::factory('line', &$Dataset);
+ *
+ * or
+ *
+ * Image_graph::factory('bar', array(array(&$Dataset1, &$Dataset2),
+ * 'stacked'));
+ *
+ * Class name can be either of the following:
+ *
+ * 1 The 'real' Image_Graph class name, i.e. Image_Graph_Plotarea or
+ * Image_Graph_Plot_Line
+ *
+ * 2 Short class name (leave out Image_Graph) and retain case, i.e.
+ * Plotarea, Plot_Line *not* plot_line
+ *
+ * 3 Class name 'alias', the following are supported:
+ *
+ * 'graph' = Image_Graph
+ *
+ * 'plotarea' = Image_Graph_Plotarea
+ *
+ * 'line' = Image_Graph_Plot_Line
+ *
+ * 'area' = Image_Graph_Plot_Area
+ *
+ * 'bar' = Image_Graph_Plot_Bar
+ *
+ * 'pie' = Image_Graph_Plot_Pie
+ *
+ * 'radar' = Image_Graph_Plot_Radar
+ *
+ * 'step' = Image_Graph_Plot_Step
+ *
+ * 'impulse' = Image_Graph_Plot_Impulse
+ *
+ * 'dot' or 'scatter' = Image_Graph_Plot_Dot
+ *
+ * 'smooth_line' = Image_Graph_Plot_Smoothed_Line
+ *
+ * 'smooth_area' = Image_Graph_Plot_Smoothed_Area
+
+ * 'dataset' = Image_Graph_Dataset_Trivial
+ *
+ * 'random' = Image_Graph_Dataset_Random
+ *
+ * 'function' = Image_Graph_Dataset_Function
+ *
+ * 'vector' = Image_Graph_Dataset_VectorFunction
+ *
+ * 'category' = Image_Graph_Axis_Category
+ *
+ * 'axis' = Image_Graph_Axis
+ *
+ * 'axis_log' = Image_Graph_Axis_Logarithmic
+ *
+ * 'title' = Image_Graph_Title
+ *
+ * 'line_grid' = Image_Graph_Grid_Lines
+ *
+ * 'bar_grid' = Image_Graph_Grid_Bars
+ *
+ * 'polar_grid' = Image_Graph_Grid_Polar
+ *
+ * 'legend' = Image_Graph_Legend
+ *
+ * 'font' = Image_Graph_Font
+ *
+ * 'ttf_font' = Image_Graph_Font
+ *
+ * 'Image_Graph_Font_TTF' = Image_Graph_Font (to maintain BC with Image_Graph_Font_TTF)
+ *
+ * 'gradient' = Image_Graph_Fill_Gradient
+ *
+ * 'icon_marker' = Image_Graph_Marker_Icon
+ *
+ * 'value_marker' = Image_Graph_Marker_Value
+ *
+ * @param string $class The class for the new object
+ * @param mixed $params The paramaters to pass to the constructor
+ * @return object A new object for the class
+ * @static
+ */
+ function &factory($class, $params = null)
+ {
+ static $Image_Graph_classAliases = array(
+ 'graph' => 'Image_Graph',
+ 'plotarea' => 'Image_Graph_Plotarea',
+
+ 'line' => 'Image_Graph_Plot_Line',
+ 'area' => 'Image_Graph_Plot_Area',
+ 'bar' => 'Image_Graph_Plot_Bar',
+ 'smooth_line' => 'Image_Graph_Plot_Smoothed_Line',
+ 'smooth_area' => 'Image_Graph_Plot_Smoothed_Area',
+ 'pie' => 'Image_Graph_Plot_Pie',
+ 'radar' => 'Image_Graph_Plot_Radar',
+ 'step' => 'Image_Graph_Plot_Step',
+ 'impulse' => 'Image_Graph_Plot_Impulse',
+ 'dot' => 'Image_Graph_Plot_Dot',
+ 'scatter' => 'Image_Graph_Plot_Dot',
+
+ 'dataset' => 'Image_Graph_Dataset_Trivial',
+ 'random' => 'Image_Graph_Dataset_Random',
+ 'function' => 'Image_Graph_Dataset_Function',
+ 'vector' => 'Image_Graph_Dataset_VectorFunction',
+
+ 'category' => 'Image_Graph_Axis_Category',
+ 'axis' => 'Image_Graph_Axis',
+ 'axis_log' => 'Image_Graph_Axis_Logarithmic',
+
+ 'title' => 'Image_Graph_Title',
+
+ 'line_grid' => 'Image_Graph_Grid_Lines',
+ 'bar_grid' => 'Image_Graph_Grid_Bars',
+ 'polar_grid' => 'Image_Graph_Grid_Polar',
+
+ 'legend' => 'Image_Graph_Legend',
+ 'font' => 'Image_Graph_Font',
+ 'ttf_font' => 'Image_Graph_Font',
+ 'Image_Graph_Font_TTF' => 'Image_Graph_Font', // BC with Image_Graph_Font_TTF
+ 'gradient' => 'Image_Graph_Fill_Gradient',
+
+ 'icon_marker' => 'Image_Graph_Marker_Icon',
+ 'value_marker' => 'Image_Graph_Marker_Value'
+ );
+
+ if (substr($class, 0, 11) != 'Image_Graph') {
+ if (isset($Image_Graph_classAliases[$class])) {
+ $class = $Image_Graph_classAliases[$class];
+ } else {
+ $class = 'Image_Graph_' . $class;
+ }
+ }
+
+ include_once str_replace('_', '/', $class) . '.php';
+
+ $obj = null;
+
+ if (is_array($params)) {
+ switch (count($params)) {
+ case 1:
+ $obj =& new $class(
+ $params[0]
+ );
+ break;
+
+ case 2:
+ $obj =& new $class(
+ $params[0],
+ $params[1]
+ );
+ break;
+
+ case 3:
+ $obj =& new $class(
+ $params[0],
+ $params[1],
+ $params[2]
+ );
+ break;
+
+ case 4:
+ $obj =& new $class(
+ $params[0],
+ $params[1],
+ $params[2],
+ $params[3]
+ );
+ break;
+
+ case 5:
+ $obj =& new $class(
+ $params[0],
+ $params[1],
+ $params[2],
+ $params[3],
+ $params[4]
+ );
+ break;
+
+ case 6:
+ $obj =& new $class(
+ $params[0],
+ $params[1],
+ $params[2],
+ $params[3],
+ $params[4],
+ $params[5]
+ );
+ break;
+
+ case 7:
+ $obj =& new $class(
+ $params[0],
+ $params[1],
+ $params[2],
+ $params[3],
+ $params[4],
+ $params[5],
+ $params[6]
+ );
+ break;
+
+ case 8:
+ $obj =& new $class(
+ $params[0],
+ $params[1],
+ $params[2],
+ $params[3],
+ $params[4],
+ $params[5],
+ $params[6],
+ $params[7]
+ );
+ break;
+
+ case 9:
+ $obj =& new $class(
+ $params[0],
+ $params[1],
+ $params[2],
+ $params[3],
+ $params[4],
+ $params[5],
+ $params[6],
+ $params[7],
+ $params[8]
+ );
+ break;
+
+ case 10:
+ $obj =& new $class(
+ $params[0],
+ $params[1],
+ $params[2],
+ $params[3],
+ $params[4],
+ $params[5],
+ $params[6],
+ $params[7],
+ $params[8],
+ $params[9]
+ );
+ break;
+
+ default:
+ $obj =& new $class();
+ break;
+
+ }
+ } else {
+ if ($params == null) {
+ $obj =& new $class();
+ } else {
+ $obj =& new $class($params);
+ }
+ }
+ return $obj;
+ }
+
+ /**
+ * Factory method to create layouts.
+ *
+ * This method is used for easy creation, since using {@link Image_Graph::
+ * factory()} does not work with passing newly created objects from
+ * Image_Graph::factory() as reference, this is something that is
+ * fortunately fixed in PHP5. Also used for 'lazy including', i.e. loading
+ * only what is necessary, when it is necessary.
+ *
+ * Use {@link Image_Graph::horizontal()} or {@link Image_Graph::vertical()}
+ * instead for easier access.
+ *
+ * @param mixed $layout The type of layout, can be either 'Vertical'
+ * or 'Horizontal' (case sensitive)
+ * @param Image_Graph_Element $part1 The 1st part of the layout
+ * @param Image_Graph_Element $part2 The 2nd part of the layout
+ * @param int $percentage The percentage of the layout to split at
+ * @return Image_Graph_Layout The newly created layout object
+ * @static
+ */
+ function &layoutFactory($layout, &$part1, &$part2, $percentage = 50)
+ {
+ if (($layout != 'Vertical') && ($layout != 'Horizontal')) {
+ return $this->_error('Layouts must be either \'Horizontal\' or \'Vertical\'');
+ }
+
+ if (!(is_a($part1, 'Image_Graph_Element'))) {
+ return $this->_error('Part 1 is not a valid Image_Graph element');
+ }
+
+ if (!(is_a($part2, 'Image_Graph_Element'))) {
+ return $this->_error('Part 2 is not a valid Image_Graph element');
+ }
+
+ if ((!is_numeric($percentage)) || ($percentage < 0) || ($percentage > 100)) {
+ return $this->_error('Percentage has to be a number between 0 and 100');
+ }
+
+ include_once "Image/Graph/Layout/$layout.php";
+ $class = "Image_Graph_Layout_$layout";
+ $obj =& new $class($part1, $part2, $percentage);
+ return $obj;
+ }
+
+ /**
+ * Factory method to create horizontal layout.
+ *
+ * See {@link Image_Graph::layoutFactory()}
+ *
+ * @param Image_Graph_Element $part1 The 1st (left) part of the layout
+ * @param Image_Graph_Element $part2 The 2nd (right) part of the layout
+ * @param int $percentage The percentage of the layout to split at
+ * (percentage of total height from the left side)
+ * @return Image_Graph_Layout The newly created layout object
+ * @static
+ */
+ function &horizontal(&$part1, &$part2, $percentage = 50)
+ {
+ $obj =& Image_Graph::layoutFactory('Horizontal', $part1, $part2, $percentage);
+ return $obj;
+ }
+
+ /**
+ * Factory method to create vertical layout.
+ *
+ * See {@link Image_Graph::layoutFactory()}
+ *
+ * @param Image_Graph_Element $part1 The 1st (top) part of the layout
+ * @param Image_Graph_Element $part2 The 2nd (bottom) part of the layout
+ * @param int $percentage The percentage of the layout to split at
+ * (percentage of total width from the top edge)
+ * @return Image_Graph_Layout The newly created layout object
+ * @static
+ */
+ function &vertical(&$part1, &$part2, $percentage = 50)
+ {
+ $obj =& Image_Graph::layoutFactory('Vertical', $part1, $part2, $percentage);
+ return $obj;
+ }
+
+ /**
+ * The error handling routine set by set_error_handler().
+ *
+ * This method is used internaly by Image_Graph and PHP as a proxy for {@link
+ * Image_Graph::_error()}.
+ *
+ * @param string $error_type The type of error being handled.
+ * @param string $error_msg The error message being handled.
+ * @param string $error_file The file in which the error occurred.
+ * @param integer $error_line The line in which the error occurred.
+ * @param string $error_context The context in which the error occurred.
+ * @access private
+ */
+ function _default_error_handler($error_type, $error_msg, $error_file, $error_line, $error_context)
+ {
+ switch( $error_type ) {
+ case E_ERROR:
+ $level = 'error';
+ break;
+
+ case E_USER_ERROR:
+ $level = 'user error';
+ break;
+
+ case E_WARNING:
+ $level = 'warning';
+ break;
+
+ case E_USER_WARNING:
+ $level = 'user warning';
+ break;
+
+ case E_NOTICE:
+ $level = 'notice';
+ break;
+
+ case E_USER_NOTICE:
+ $level = 'user notice';
+ break;
+
+ default:
+ $level = '(unknown)';
+ break;
+
+ }
+
+ $this->_error("PHP $level: $error_msg",
+ array(
+ 'type' => $error_type,
+ 'file' => $error_file,
+ 'line' => $error_line,
+ 'context' => $error_context
+ )
+ );
+ }
+
+ /**
+ * Displays the errors on the error stack.
+ *
+ * Invoking this method cause all errors on the error stack to be displayed
+ * on the graph-output, by calling the {@link Image_Graph::_displayError()}
+ * method.
+ *
+ * @access private
+ */
+ function _displayErrors()
+ {
+ return true;
+ }
+
+ /**
+ * Display an error from the error stack.
+ *
+ * This method writes error messages caught from the {@link Image_Graph::
+ * _default_error_handler()} if {@Image_Graph::displayErrors()} was invoked,
+ * and the error explicitly set by the system using {@link
+ * Image_Graph_Common::_error()}.
+ *
+ * @param int $x The horizontal position of the error message
+ * @param int $y The vertical position of the error message
+ * @param array $error The error context
+ *
+ * @access private
+ */
+ function _displayError($x, $y, $error)
+ {
+ }
+
+ /**
+ * Outputs this graph using the canvas.
+ *
+ * This causes the graph to make all elements perform their output. Their
+ * result is 'written' to the output using the canvas, which also performs
+ * the actual output, fx. it being to a file or directly to the browser
+ * (in the latter case, the canvas will also make sure the correct HTTP
+ * headers are sent, making the browser handle the output correctly, if
+ * supported by it).
+ *
+ * Parameters are the ones supported by the canvas, common ones are:
+ *
+ * 'filename' To output to a file instead of browser
+ *
+ * 'tohtml' Return a HTML string that encompasses the current graph/canvas - this
+ * implies an implicit save using the following parameters: 'filename' The "temporary"
+ * filename of the graph, 'filepath' A path in the file system where Image_Graph can
+ * store the output (this file must be in DOCUMENT_ROOT scope), 'urlpath' The URL that the
+ * 'filepath' corresponds to (i.e. filepath + filename must be reachable from a browser using
+ * urlpath + filename)
+ *
+ * @param mixed $param The output parameters to pass to the canvas
+ * @return bool Was the output 'good' (true) or 'bad' (false).
+ */
+ function done($param = false)
+ {
+ $result = $this->_reset();
+ if (PEAR::isError($result)) {
+ return $result;
+ }
+ return $this->_done($param);
+ }
+
+ /**
+ * Outputs this graph using the canvas.
+ *
+ * This causes the graph to make all elements perform their output. Their
+ * result is 'written' to the output using the canvas, which also performs
+ * the actual output, fx. it being to a file or directly to the browser
+ * (in the latter case, the canvas will also make sure the correct HTTP
+ * headers are sent, making the browser handle the output correctly, if
+ * supported by it).
+ *
+ * @param mixed $param The output parameters to pass to the canvas
+ * @return bool Was the output 'good' (true) or 'bad' (false).
+ * @access private
+ */
+ function _done($param = false)
+ {
+ $timeStart = $this->_getMicroTime();
+
+ if ($this->_shadow) {
+ $this->setPadding(20);
+ $this->_setCoords(
+ $this->_left,
+ $this->_top,
+ $this->_right - 10,
+ $this->_bottom - 10);
+ }
+
+ $result = $this->_updateCoords();
+ if (PEAR::isError($result)) {
+ return $result;
+ }
+
+ if ($this->_getBackground()) {
+ $this->_canvas->rectangle(
+ array(
+ 'x0' => $this->_left,
+ 'y0' => $this->_top,
+ 'x1' => $this->_right,
+ 'y1' => $this->_bottom
+ )
+ );
+ }
+
+ $result = parent::_done();
+ if (PEAR::isError($result)) {
+ return $result;
+ }
+
+ if ($this->_displayErrors) {
+ $this->_displayErrors();
+ }
+
+ $timeEnd = $this->_getMicroTime();
+
+ if (($this->_showTime) ||
+ ((isset($param['showtime'])) && ($param['showtime'] === true))
+ ) {
+ $text = 'Generated in ' .
+ sprintf('%0.3f', $timeEnd - $timeStart) . ' sec';
+ $this->write(
+ $this->_right,
+ $this->_bottom,
+ $text,
+ IMAGE_GRAPH_ALIGN_RIGHT + IMAGE_GRAPH_ALIGN_BOTTOM,
+ array('color' => 'red')
+ );
+ }
+
+ if (isset($param['filename'])) {
+ if ((isset($param['tohtml'])) && ($param['tohtml'])) {
+ return $this->_canvas->toHtml($param);
+ }
+ else {
+ return $this->_canvas->save($param);
+ }
+ } else {
+ return $this->_canvas->show($param);
+ }
+ }
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Axis.php b/config/dspam/pear/Image/Graph/Axis.php
new file mode 100644
index 00000000..99da305f
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Axis.php
@@ -0,0 +1,1690 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Class for axis handling.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Axis
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Plotarea/Element.php
+ */
+require_once 'Image/Graph/Plotarea/Element.php';
+
+/**
+ * Diplays a normal linear axis (either X- or Y-axis).
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Axis
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+ class Image_Graph_Axis extends Image_Graph_Plotarea_Element
+{
+
+ /**
+ * The type of the axis, possible values are:
+ * <ul>
+ * <li>IMAGE_GRAPH_AXIS_X / IMAGE_GRAPH_AXIS_HORIZONTAL
+ * <li>IMAGE_GRAPH_AXIS_Y / IMAGE_GRAPH_AXIS_VERTICAL /
+ * IMAGE_GRAPH_AXIS_Y_SECONDARY
+ * </ul>
+ * @var int
+ * @access private
+ */
+ var $_type;
+
+ /**
+ * The minimum value the axis displays
+ * @var int
+ * @access private
+ */
+ var $_minimum = false;
+
+ /**
+ * The minimum value the axis has been explicitly set by the user
+ * @var bool
+ * @access private
+ */
+ var $_minimumSet = false;
+
+ /**
+ * The maximum value the axis displays
+ * @var int
+ * @access private
+ */
+ var $_maximum = false;
+
+ /**
+ * The maximum value the axis has been explicitly set by the user
+ * @var bool
+ * @access private
+ */
+ var $_maximumSet = false;
+
+ /**
+ * The value span of the axis.
+ * This is primarily included for performance reasons
+ * @var double
+ * @access private
+ */
+ var $_axisSpan = false;
+
+ /**
+ * The value span of the axis.
+ * This is primarily included for performance reasons
+ * @var double
+ * @access private
+ */
+ var $_axisValueSpan = false;
+
+ /**
+ * The axis padding.
+ * The index 'low' specifies the padding for the low axis values (when not
+ * inverted), i.e. to the left on an x-axis and on the bottom of an y-axis,
+ * vice versa for 'high'.
+ *
+ * Axis padding does not make sense on a normal linear y-axis with a 'y-min'
+ * of 0 since this corresponds to displaying a small part of the y-axis
+ * below 0!
+ *
+ * @var array
+ * @access private
+ */
+ var $_axisPadding = array('low' => 0, 'high' => 0);
+
+ /**
+ * The number of "pixels" representing 1 unit on the axis
+ *
+ * This is primarily included for performance reasons
+ * @var double
+ * @access private
+ */
+ var $_delta = false;
+
+ /**
+ * Specify if the axis should label the minimum value
+ * @var bool
+ * @access private
+ */
+ var $_showLabelMinimum = true;
+
+ /**
+ * Specify if the axis should label 0 (zero)
+ * @var bool
+ * @access private
+ */
+ var $_showLabelZero = false;
+
+ /**
+ * Specify if the axis should label the maximum value
+ * @var bool
+ * @access private
+ */
+ var $_showLabelMaximum = true;
+
+ /**
+ * Show arrow heads at the 'end' of the axis, default: false
+ * @var bool
+ * @access private
+ */
+ var $_showArrow = false;
+
+ /**
+ * Intersection data of axis
+ * @var array
+ * @access private
+ */
+ var $_intersect = array('value' => 'default', 'axis' => 'default');
+
+ /**
+ * The fixed size of the axis (i.e. width for y-axis, height for x-axis)
+ * @var mixed
+ * @access private
+ */
+ var $_fixedSize = false;
+
+ /**
+ * The label options
+ *
+ * Should text be shows, preferences for ticks. The indexes start at level
+ * 1, which is chosen for readability
+ * @var array
+ * @access private
+ */
+ var $_labelOptions = array(
+ 1 => array(
+ 'interval' => 1,
+ 'type' => 'auto',
+ 'tick' => array(
+ 'start' => -2,
+ 'end' => 2,
+ 'color' => false // default color
+ ),
+ 'showtext' => true,
+ 'showoffset' => false,
+ 'font' => array(),
+ 'offset' => 0,
+ 'position' => 'outside',
+ )
+ );
+
+ /**
+ * The labels that are shown.
+ *
+ * This is used to make values show only once...
+ * @access private
+ */
+ var $_labelText = array();
+
+ /**
+ * A data preprocessor for formatting labels, fx showing dates as a standard
+ * date instead of Unix time stamp
+ * @var Image_Graph_DatePreProcessor
+ * @access private
+ * @see Image_Graph_DataPreProcessor
+ */
+ var $_dataPreProcessor = null;
+
+ /**
+ * Point marked in the axis
+ * @var array
+ * @access private
+ */
+ var $_marks = array();
+
+ /**
+ * Specifies whether the values should be 'pushed' by 0.5
+ * @var bool
+ * @access private
+ */
+ var $_pushValues = false;
+
+ /**
+ * The title of this axis
+ * @var string
+ * @access private
+ */
+ var $_title = '';
+
+ /**
+ * The font used for the title of this axis
+ * @var Image_Graph_Font
+ * @access private
+ */
+ var $_titleFont = false;
+
+ /**
+ * Invert the axis (i.e. if an y-axis normally displays minimum values at
+ * the bottom, they are not displayed at the top
+ * @var bool
+ * @access private
+ * @since 0.3.0dev3
+ */
+ var $_invert = false;
+
+ /**
+ * Transpose the axis (i.e. is a normal y-axis transposed, so thats it's not show
+ * vertically as normally expected, but instead horizontally)
+ * @var bool
+ * @access private
+ */
+ var $_transpose = false;
+
+ /**
+ * Image_Graph_Axis [Constructor].
+ * Normally a manual creation should not be necessary, axis are created
+ * automatically by the {@link Image_Graph_Plotarea} constructor unless
+ * explicitly defined otherwise
+ *
+ * @param int $type The type (direction) of the Axis, use IMAGE_GRAPH_AXIS_X
+ * for an X-axis (default, may be omitted) and IMAGE_GRAPH_AXIS_Y for Y-
+ * axis)
+ */
+ function Image_Graph_Axis($type = IMAGE_GRAPH_AXIS_X)
+ {
+ parent::Image_Graph_Element();
+ $this->_type = $type;
+ $this->_fillStyle = 'black';
+ }
+
+ /**
+ * Push the values by 0.5 (for bar and step chart)
+ *
+ * @access private
+ */
+ function _pushValues()
+ {
+ $this->_pushValues = true;
+ }
+
+ /**
+ * Sets the axis padding for a given position ('low' or 'high')
+ * @param string $where The position
+ * @param int $value The number of pixels to "pad"
+ * @access private
+ */
+ function _setAxisPadding($where, $value)
+ {
+ $this->_axisPadding[$where] = $value;
+ }
+
+ /**
+ * Gets the font of the title.
+ *
+ * If not font has been set, the parent font is propagated through it's
+ * children.
+ *
+ * @return array An associated array used for canvas
+ * @access private
+ */
+ function _getTitleFont()
+ {
+ if ($this->_titleFont === false) {
+ if ($this->_defaultFontOptions !== false) {
+ return $this->_defaultFontOptions;
+ } else {
+ return $this->_getFont();
+ }
+ } else {
+ if (is_object($this->_titleFont)) {
+ return $this->_titleFont->_getFont();
+ } elseif (is_array($this->_titleFont)) {
+ return $this->_getFont($this->_titleFont);
+ } elseif (is_int($this->_titleFont)) {
+ return $this->_getFont(array('size' => $this->_titleFont));
+ }
+ }
+ return array();
+ }
+
+ /**
+ * Shows a label for the the specified values.
+ *
+ * Allowed values are combinations of:
+ * <ul>
+ * <li>IMAGE_GRAPH_LABEL_MINIMUM
+ * <li>IMAGE_GRAPH_LABEL_ZERO
+ * <li>IMAGE_GRAPH_LABEL_MAXIMUM
+ * </ul>
+ * By default none of these are shows on the axis
+ *
+ * @param int $value The values to show labels for
+ */
+ function showLabel($value)
+ {
+ $this->_showLabelMinimum = ($value & IMAGE_GRAPH_LABEL_MINIMUM);
+ $this->_showLabelZero = ($value & IMAGE_GRAPH_LABEL_ZERO);
+ $this->_showLabelMaximum = ($value & IMAGE_GRAPH_LABEL_MAXIMUM);
+ }
+
+ /**
+ * Sets a data preprocessor for formatting the axis labels
+ *
+ * @param Image_Graph_DataPreprocessor $dataPreProcessor The data preprocessor
+ * @see Image_Graph_DataPreprocessor
+ */
+ function setDataPreProcessor(& $dataPreProcessor)
+ {
+ $this->_dataPreProcessor =& $dataPreProcessor;
+ }
+
+ /**
+ * Gets the minimum value the axis will show
+ *
+ * @return double The minumum value
+ * @access private
+ */
+ function _getMinimum()
+ {
+ return $this->_minimum;
+ }
+
+ /**
+ * Gets the maximum value the axis will show
+ *
+ * @return double The maximum value
+ * @access private
+ */
+ function _getMaximum()
+ {
+ return $this->_maximum;
+ }
+
+ /**
+ * Sets the minimum value the axis will show
+ *
+ * @param double $minimum The minumum value to use on the axis
+ * @access private
+ */
+ function _setMinimum($minimum)
+ {
+ if ($this->_minimum === false) {
+ $this->forceMinimum($minimum, false);
+ } else {
+ $this->forceMinimum(min($this->_minimum, $minimum), false);
+ }
+ }
+
+ /**
+ * Sets the maximum value the axis will show
+ *
+ * @param double $maximum The maximum value to use on the axis
+ * @access private
+ */
+ function _setMaximum($maximum)
+ {
+ if ($this->_maximum === false) {
+ $this->forceMaximum($maximum, false);
+ } else {
+ $this->forceMaximum(max($this->_maximum, $maximum), false);
+ }
+ }
+
+ /**
+ * Forces the minimum value of the axis
+ *
+ * @param double $minimum The minumum value to use on the axis
+ * @param bool $userEnforce This value should not be set, used internally
+ */
+ function forceMinimum($minimum, $userEnforce = true)
+ {
+ if (($userEnforce) || (!$this->_minimumSet)) {
+ $this->_minimum = $minimum;
+ $this->_minimumSet = $userEnforce;
+ }
+ $this->_calcLabelInterval();
+ }
+
+ /**
+ * Forces the maximum value of the axis
+ *
+ * @param double $maximum The maximum value to use on the axis
+ * @param bool $userEnforce This value should not be set, used internally
+ */
+ function forceMaximum($maximum, $userEnforce = true)
+ {
+ if (($userEnforce) || (!$this->_maximumSet)) {
+ $this->_maximum = $maximum;
+ $this->_maximumSet = $userEnforce;
+ }
+ $this->_calcLabelInterval();
+ }
+
+ /**
+ * Show an arrow head on the 'end' of the axis
+ */
+ function showArrow()
+ {
+ $this->_showArrow = true;
+ }
+
+ /**
+ * Do not show an arrow head on the 'end' of the axis (default)
+ */
+ function hideArrow()
+ {
+ $this->_showArrow = false;
+ }
+
+ /**
+ * Return the label distance.
+ *
+ * @param int $level The label level to return the distance of
+ * @return int The distance between 2 adjacent labels
+ * @access private
+ */
+ function _labelDistance($level = 1)
+ {
+ $l1 = $this->_getNextLabel(false, $level);
+ $l2 = $this->_getNextLabel($l1, $level);;
+ return abs($this->_point($l2) - $this->_point($l1));
+ }
+
+ /**
+ * Sets an interval for when labels are shown on the axis.
+ *
+ * By default 'auto' is used, forcing the axis to calculate a approximate
+ * best label interval to be used. Specify an array to use user-defined
+ * values for labels.
+ *
+ * @param mixed $labelInterval The interval with which labels are shown
+ * @param int $level The label level to set the interval on
+ */
+ function setLabelInterval($labelInterval = 'auto', $level = 1)
+ {
+ if (!isset($this->_labelOptions[$level])) {
+ $this->_labelOptions[$level] = array();
+ }
+
+ if ($labelInterval === 'auto') {
+ $this->_labelOptions[$level]['type'] = 'auto';
+ $this->_calcLabelInterval();
+ } else {
+ $this->_labelOptions[$level]['type'] = 'manual';
+ $this->_labelOptions[$level]['interval'] = $labelInterval;
+ }
+ }
+
+ /**
+ * Sets options for the label at a specific level.
+ *
+ * Possible options are:
+ *
+ * 'showtext' true or false whether label text should be shown or not
+ *
+ * 'showoffset' should the label be shown at an offset, i.e. should the
+ * label be shown at a position so that it does not overlap with prior
+ * levels. Only applies to multilevel labels with text
+ *
+ * 'font' The font options as an associated array
+ *
+ * 'position' The position at which the labels are written ('inside' or
+ * 'outside' the axis). NB! This relative position only applies to the
+ * default location of the axis, i.e. if an x-axis is inverted then
+ * 'outside' still refers to the "left" side of a normal y-axis (since this
+ * is normally 'outside') but the actual output will be labels on the
+ * "inside"!
+ *
+ * 'format' To format the label text according to a sprintf statement
+ *
+ * 'dateformat' To format the label as a date, fx. j. M Y = 29. Jun 2005
+ *
+ * @param string $option The label option name (see detailed description
+ * for possible values)
+ * @param mixed $value The value for the option
+ * @param int $level The label level to set the interval on
+ */
+ function setLabelOption($option, $value, $level = 1)
+ {
+ if (!isset($this->_labelOptions[$level])) {
+ $this->_labelOptions[$level] = array('type' => 'auto');
+ }
+
+ $this->_labelOptions[$level][$option] = $value;
+ }
+
+ /**
+ * Sets options for the label at a specific level.
+ *
+ * The possible options are specified in {@link Image_Graph_Axis::
+ * setLabelOption()}.
+ *
+ * @param array $options An assciated array with label options
+ * @param int $level The label level to set the interval on
+ */
+ function setLabelOptions($options, $level = 1)
+ {
+ if (is_array($options)) {
+ if (isset($this->_labelOptions[$level])) {
+ $this->_labelOptions[$level] = array_merge($this->_labelOptions[$level], $options);
+ } else {
+ $this->_labelOptions[$level] = $options;
+ }
+
+ }
+ }
+
+ /**
+ * Sets the title of this axis.
+ *
+ * This is used as an alternative (maybe better) method, than using layout's
+ * for axis-title generation.
+ *
+ * To use the current propagated font, but just set it vertically, simply
+ * pass 'vertical' as second parameter for vertical alignment down-to-up or
+ * 'vertical2' for up-to-down alignment.
+ *
+ * @param string $title The title of this axis
+ * @param Image_Graph_Font $font The font used for the title
+ * @since 0.3.0dev2
+ */
+ function setTitle($title, $font = false)
+ {
+ $this->_title = $title;
+ if ($font === 'vertical') {
+ $this->_titleFont = array('vertical' => true, 'angle' => 90);
+ } elseif ($font === 'vertical2') {
+ $this->_titleFont = array('vertical' => true, 'angle' => 270);
+ } else {
+ $this->_titleFont =& $font;
+ }
+ }
+
+ /**
+ * Sets a fixed "size" for the axis.
+ *
+ * If the axis is any type of y-axis the size relates to the width of the
+ * axis, if an x-axis is concerned the size is the height.
+ *
+ * @param int $size The fixed size of the axis
+ * @since 0.3.0dev5
+ */
+ function setFixedSize($size)
+ {
+ $this->_fixedSize = $size;
+ }
+
+ /**
+ * Preprocessor for values, ie for using logarithmic axis
+ *
+ * @param double $value The value to preprocess
+ * @return double The preprocessed value
+ * @access private
+ */
+ function _value($value)
+ {
+ return $value - $this->_getMinimum() + ($this->_pushValues ? 0.5 : 0);
+ }
+
+ /**
+ * Apply the dataset to the axis
+ *
+ * @param Image_Graph_Dataset $dataset The dataset
+ * @access private
+ */
+ function _applyDataset(&$dataset)
+ {
+ if ($this->_type == IMAGE_GRAPH_AXIS_X) {
+ $this->_setMinimum($dataset->minimumX());
+ $this->_setMaximum($dataset->maximumX());
+ } else {
+ $this->_setMinimum($dataset->minimumY());
+ $this->_setMaximum($dataset->maximumY());
+ }
+ }
+
+ /**
+ * Get the pixel position represented by a value on the canvas
+ *
+ * @param double $value the value to get the pixel-point for
+ * @return double The pixel position along the axis
+ * @access private
+ */
+ function _point($value)
+ {
+ if ((($this->_type == IMAGE_GRAPH_AXIS_X) && (!$this->_transpose)) ||
+ (($this->_type != IMAGE_GRAPH_AXIS_X) && ($this->_transpose)))
+ {
+ if ($this->_invert) {
+ return max($this->_left, $this->_right - $this->_axisPadding['high'] - $this->_delta * $this->_value($value));
+ } else {
+ return min($this->_right, $this->_left + $this->_axisPadding['low'] + $this->_delta * $this->_value($value));
+ }
+ } else {
+ if ($this->_invert) {
+ return min($this->_bottom, $this->_top + $this->_axisPadding['high'] + $this->_delta * $this->_value($value));
+ } else {
+ return max($this->_top, $this->_bottom - $this->_axisPadding['low'] - $this->_delta * $this->_value($value));
+ }
+ }
+ }
+
+
+ /**
+ * Get the axis intersection pixel position
+ *
+ * This is only to be called prior to output! I.e. between the user
+ * invokation of Image_Graph::done() and any actual output is performed.
+ * This is because it can change the axis range.
+ *
+ * @param double $value the intersection value to get the pixel-point for
+ * @return double The pixel position along the axis
+ * @access private
+ */
+ function _intersectPoint($value)
+ {
+
+ if (($value === 'min') || ($value < $this->_getMinimum())) {
+ if ($this->_type == IMAGE_GRAPH_AXIS_X) {
+ if ($this->_invert) {
+ return ($this->_transpose ? $this->_top : $this->_right);
+ } else {
+ return ($this->_transpose ? $this->_bottom : $this->_left);
+ }
+ } else {
+ if ($this->_invert) {
+ return ($this->_transpose ? $this->_right : $this->_top);
+ } else {
+ return ($this->_transpose ? $this->_left : $this->_bottom);
+ }
+ }
+ } elseif (($value === 'max') || ($value > $this->_getMaximum())) {
+ if ($this->_type == IMAGE_GRAPH_AXIS_X) {
+ if ($this->_invert) {
+ return ($this->_transpose ? $this->_bottom : $this->_left);
+ } else {
+ return ($this->_transpose ? $this->_top : $this->_right);
+ }
+ } else {
+ if ($this->_invert) {
+ return ($this->_transpose ? $this->_left : $this->_bottom);
+ } else {
+ return ($this->_transpose ? $this->_right : $this->_top);
+ }
+ }
+ }
+
+ return $this->_point($value);
+ }
+
+ /**
+ * Calculate the delta value (the number of pixels representing one unit
+ * on the axis)
+ *
+ * @return double The label interval
+ * @access private
+ */
+ function _calcDelta()
+ {
+ if ($this->_axisValueSpan == 0) {
+ $this->_delta = false;
+ } elseif ($this->_type == IMAGE_GRAPH_AXIS_X) {
+ $this->_delta = (($this->_transpose ? $this->height() : $this->width()) - ($this->_axisPadding['low'] + $this->_axisPadding['high'])) / ($this->_axisValueSpan + ($this->_pushValues ? 1 : 0));
+ } else {
+ $this->_delta = (($this->_transpose ? $this->width() : $this->height()) - ($this->_axisPadding['low'] + $this->_axisPadding['high'])) / ($this->_axisValueSpan + ($this->_pushValues ? 1 : 0));
+ }
+ }
+
+ /**
+ * Calculate the label interval
+ *
+ * If explicitly defined this will be calucated to an approximate best.
+ *
+ * @return double The label interval
+ * @access private
+ */
+ function _calcLabelInterval()
+ {
+ $min = $this->_getMinimum();
+ $max = $this->_getMaximum();
+
+ $this->_axisValueSpan = $this->_axisSpan = abs($max - $min);
+
+ if ((!empty($min)) && (!empty($max)) && ($min > $max)) {
+ $this->_labelOptions[1]['interval'] = 1;
+ return true;
+ }
+
+ $span = 0;
+ foreach($this->_labelOptions as $level => $labelOptions) {
+ if ((!isset($labelOptions['type'])) || ($labelOptions['type'] !== 'auto')) {
+ $span = false;
+ } elseif ($level == 1) {
+ $span = $this->_axisValueSpan;
+ } else {
+ $l1 = $this->_getNextLabel(false, $level - 1);
+ $l2 = $this->_getNextLabel($l1, $level - 1);
+ if ((!is_numeric($l1)) || (!is_numeric($l2))) {
+ $span == false;
+ } else {
+ $span = $l2 - $l1;
+ }
+ }
+
+ if ($span !== false) {
+ $interval = pow(10, floor(log10($span)));
+
+ if ($interval == 0) {
+ $interval = 1;
+ }
+
+ if ((($span) / $interval) < 3) {
+ $interval = $interval / 4;
+ } elseif ((($span) / $interval) < 5) {
+ $interval = $interval / 2;
+ } elseif ((($span) / $interval) > 10) {
+ $interval = $interval * 2;
+ }
+
+ if (($interval -floor($interval) == 0.5) && ($interval != 0.5)) {
+ $interval = floor($interval);
+ }
+
+ // just to be 100% sure that an interval of 0 is not returned some
+ // additional checks are performed
+ if ($interval == 0) {
+ $interval = ($span) / 5;
+ }
+
+ if ($interval == 0) {
+ $interval = 1;
+ }
+
+ $this->_labelOptions[$level]['interval'] = $interval;
+ }
+ }
+ }
+
+ /**
+ * Get next label point
+ *
+ * @param doubt $currentLabel The current label, if omitted or false, the
+ * first is returned
+ * @param int $level The label level to get the next label from
+ * @return double The next label point
+ * @access private
+ */
+ function _getNextLabel($currentLabel = false, $level = 1)
+ {
+ if (!isset($this->_labelOptions[$level])) {
+ return false;
+ }
+
+ if (is_array($this->_labelOptions[$level]['interval'])) {
+ if ($currentLabel === false) {
+ reset($this->_labelOptions[$level]['interval']);
+ }
+
+ if (list(, $label) = each($this->_labelOptions[$level]['interval'])) {
+ return $label;
+ } else {
+ return false;
+ }
+ } else {
+ $li = $this->_labelInterval($level);
+ if (($this->_axisSpan == 0) || ($this->_axisValueSpan == 0) ||
+ ($li == 0)
+ ) {
+ return false;
+ }
+
+ $labelInterval = $this->_axisSpan / ($this->_axisValueSpan / $li);
+
+ if ($labelInterval == 0) {
+ return false;
+ }
+
+ if ($currentLabel === false) {
+ $label = ((int) ($this->_getMinimum() / $labelInterval)) *
+ $labelInterval - $labelInterval;
+ while ($label < $this->_getMinimum()) {
+ $label += $labelInterval;
+ }
+ return $label;
+ } else {
+ if ($currentLabel + $labelInterval > $this->_getMaximum()) {
+ return false;
+ } else {
+ return $currentLabel + $labelInterval;
+ }
+ }
+ }
+ }
+
+ /**
+ * Get the interval with which labels are shown on the axis.
+ *
+ * If explicitly defined this will be calucated to an approximate best.
+ *
+ * @param int $level The label level to get the label interval for
+ * @return double The label interval
+ * @access private
+ */
+ function _labelInterval($level = 1)
+ {
+ if ((!isset($this->_labelOptions[$level])) ||
+ (!isset($this->_labelOptions[$level]['interval']))
+ ) {
+ return 1;
+ }
+
+ return (is_array($this->_labelOptions[$level]['interval'])
+ ? 1
+ : $this->_labelOptions[$level]['interval']
+ );
+ }
+
+ /**
+ * Get the size in pixels of the axis.
+ *
+ * For an x-axis this is the width of the axis including labels, and for an
+ * y-axis it is the corrresponding height
+ *
+ * @return int The size of the axis
+ * @access private
+ */
+ function _size()
+ {
+ if (!$this->_visible) {
+ return 0;
+ }
+
+ if ($this->_fixedSize !== false) {
+ return $this->_fixedSize;
+ }
+
+ krsort($this->_labelOptions);
+
+ $totalMaxSize = 0;
+
+ foreach ($this->_labelOptions as $level => $labelOptions) {
+ if ((isset($labelOptions['showoffset'])) && ($labelOptions['showoffset'] === true)) {
+ $this->_labelOptions[$level]['offset'] += $totalMaxSize;
+ } elseif (!isset($this->_labelOptions[$level]['offset'])) {
+ $this->_labelOptions[$level]['offset'] = 0;
+ }
+ if (
+ (isset($labelOptions['showtext'])) &&
+ ($labelOptions['showtext'] === true) &&
+ (
+ (!isset($labelOptions['position'])) ||
+ ($labelOptions['position'] == 'outside')
+ )
+ ) {
+ if (isset($labelOptions['font'])) {
+ $font = $this->_getFont($labelOptions['font']);
+ } else {
+ if ($this->_defaultFontOptions !== false) {
+ $font = $this->_defaultFontOptions;
+ } else {
+ $font = $this->_getFont();
+ }
+ }
+ $this->_canvas->setFont($font);
+
+ $value = false;
+ $maxSize = 0;
+ while (($value = $this->_getNextLabel($value, $level)) !== false) {
+ if ((abs($value) > 0.0001) && ($value > $this->_getMinimum()) &&
+ ($value < $this->_getMaximum()))
+ {
+ if (is_object($this->_dataPreProcessor)) {
+ $labelText = $this->_dataPreProcessor->_process($value);
+ } elseif (isset($labelOptions['format'])) {
+ $labelText = sprintf($labelOptions['format'], $value);
+ } elseif (isset($labelOptions['dateformat'])) {
+ $labelText = date($labelOptions['dateformat'], $value);
+ } else {
+ $labelText = $value;
+ }
+
+ if ((($this->_type == IMAGE_GRAPH_AXIS_X) && (!$this->_transpose)) ||
+ (($this->_type != IMAGE_GRAPH_AXIS_X) && ($this->_transpose)))
+ {
+ $maxSize = max($maxSize, $this->_canvas->textHeight($labelText));
+ } else {
+ $maxSize = max($maxSize, $this->_canvas->textWidth($labelText));
+ }
+ }
+ }
+ if ((isset($labelOptions['showoffset'])) && ($labelOptions['showoffset'] === true)) {
+ $totalMaxSize += $maxSize;
+ } else {
+ $totalMaxSize = max($totalMaxSize, $maxSize);
+ }
+ }
+ }
+
+ if ($this->_title) {
+ $this->_canvas->setFont($this->_getTitleFont());
+
+ if ((($this->_type == IMAGE_GRAPH_AXIS_X) && (!$this->_transpose)) ||
+ (($this->_type != IMAGE_GRAPH_AXIS_X) && ($this->_transpose)))
+ {
+ $totalMaxSize += $this->_canvas->textHeight($this->_title);
+ } else {
+ $totalMaxSize += $this->_canvas->textWidth($this->_title);
+ }
+ $totalMaxSize += 10;
+ }
+
+ return $totalMaxSize + 3;
+ }
+
+ /**
+ * Adds a mark to the axis at the specified value
+ *
+ * @param double $value The value
+ * @param double $value2 The second value (for a ranged mark)
+ */
+ function addMark($value, $value2 = false, $text = false)
+ {
+ if ($value2 === false) {
+ $this->_marks[] = $value;
+ } else {
+ $this->_marks[] = array($value, $value2);
+ }
+ }
+
+ /**
+ * Is the axis numeric or not?
+ *
+ * @return bool True if numeric, false if not
+ * @access private
+ */
+ function _isNumeric()
+ {
+ return true;
+ }
+
+ /**
+ * Set the major tick appearance.
+ *
+ * The positions are specified in pixels relative to the axis, meaning that
+ * a value of -1 for start will draw the major tick 'line' starting at 1
+ * pixel outside (negative) value the axis (i.e. below an x-axis and to the
+ * left of a normal y-axis).
+ *
+ * @param int $start The start position relative to the axis
+ * @param int $end The end position relative to the axis
+ * @param int $level The label level to set the tick options for
+ * @since 0.3.0dev2
+ */
+ function setTickOptions($start, $end, $level = 1)
+ {
+ if (!isset($this->_labelOptions[$level])) {
+ $this->_labelOptions[$level] = array();
+ }
+
+ $this->_labelOptions[$level]['tick'] = array(
+ 'start' => $start,
+ 'end' => $end
+ );
+ }
+
+ /**
+ * Invert the axis direction
+ *
+ * If the minimum values are normally displayed fx. at the bottom setting
+ * axis inversion to true, will cause the minimum values to be displayed at
+ * the top and maximum at the bottom.
+ *
+ * @param bool $invert True if the axis is to be inverted, false if not
+ * @since 0.3.0dev3
+ */
+ function setInverted($invert)
+ {
+ $this->_invert = $invert;
+ }
+
+ /**
+ * Set axis intersection.
+ *
+ * Sets the value at which the axis intersects other axis, fx. at which Y-
+ * value the x-axis intersects the y-axis (normally at 0).
+ *
+ * Possible values are 'default', 'min', 'max' or a number between axis min
+ * and max (the value will automatically be limited to this range).
+ *
+ * For a coordinate system with 2 y-axis, the x-axis can either intersect
+ * the primary or the secondary y-axis. To make the x-axis intersect the
+ * secondary y-axis at a given value pass IMAGE_GRAPH_AXIS_Y_SECONDARY as
+ * second parameter.
+ *
+ * @param mixed $intersection The value at which the axis intersect the
+ * 'other' axis
+ * @param mixed $axis The axis to intersect. Only applies to x-axis with
+ * both a primary and secondary y-axis available.
+ * @since 0.3.0dev2
+ */
+ function setAxisIntersection($intersection, $axis = 'default')
+ {
+ if ($axis == 'x') {
+ $axis = IMAGE_GRAPH_AXIS_X;
+ } elseif ($axis == 'y') {
+ $axis = IMAGE_GRAPH_AXIS_Y;
+ } elseif ($axis == 'ysec') {
+ $axis = IMAGE_GRAPH_AXIS_Y_SECONDARY;
+ }
+ $this->_intersect = array(
+ 'value' => $intersection,
+ 'axis' => $axis
+ );
+ }
+
+ /**
+ * Get axis intersection data.
+ *
+ * @return array An array with the axis intersection data.
+ * @since 0.3.0dev2
+ * @access private
+ */
+ function _getAxisIntersection()
+ {
+ $value = $this->_intersect['value'];
+ $axis = $this->_intersect['axis'];
+ if (($this->_type == IMAGE_GRAPH_AXIS_Y)
+ || ($this->_type == IMAGE_GRAPH_AXIS_Y_SECONDARY)
+ ) {
+ $axis = IMAGE_GRAPH_AXIS_X;
+ } elseif ($axis == 'default') {
+ $axis = IMAGE_GRAPH_AXIS_Y;
+ }
+
+ if ($value === 'default') {
+ switch ($this->_type) {
+ case IMAGE_GRAPH_AXIS_Y:
+ $value = 'min';
+ break;
+ case IMAGE_GRAPH_AXIS_Y_SECONDARY:
+ $value = 'max';
+ break;
+ case IMAGE_GRAPH_AXIS_X:
+ $value = 0;
+ break;
+ }
+ }
+
+ return array('value' => $value, 'axis' => $axis);
+ }
+
+ /**
+ * Resets the elements
+ *
+ * @access private
+ */
+ function _reset()
+ {
+ parent::_reset();
+ $this->_labelText = array();
+ }
+
+ /**
+ * Output an axis tick mark.
+ *
+ * @param int $value The value to output
+ * @param int $level The label level to draw the tick for
+ * @access private
+ */
+ function _drawTick($value, $level = 1)
+ {
+ if (isset($this->_labelOptions[$level])) {
+ $labelOptions = $this->_labelOptions[$level];
+ $labelPosition = $this->_point($value);
+
+ if (isset($labelOptions['offset'])) {
+ $offset = $labelOptions['offset'];
+ } else {
+ $offset = 0;
+ }
+
+ if ((isset($labelOptions['showtext'])) && ($labelOptions['showtext'] === true)) {
+ if (is_object($this->_dataPreProcessor)) {
+ $labelText = $this->_dataPreProcessor->_process($value);
+ } elseif (isset($labelOptions['format'])) {
+ $labelText = sprintf($labelOptions['format'], $value);
+ } elseif (isset($labelOptions['dateformat'])) {
+ $labelText = date($labelOptions['dateformat'], $value);
+ } else {
+ $labelText = $value;
+ }
+
+ if (!in_array($labelText, $this->_labelText)) {
+ $this->_labelText[] = $labelText;
+
+ if (isset($labelOptions['font'])) {
+ $font = $this->_getFont($labelOptions['font']);
+ } else {
+ if ($this->_defaultFontOptions !== false) {
+ $font = $this->_defaultFontOptions;
+ } else {
+ $font = $this->_getFont();
+ }
+ }
+ $this->_canvas->setFont($font);
+
+ if (
+ (isset($labelOptions['position'])) &&
+ ($labelOptions['position'] == 'inside')
+ ) {
+ $labelInside = true;
+ } else {
+ $labelInside = false;
+ }
+
+ if ($this->_type == IMAGE_GRAPH_AXIS_Y) {
+ if ($this->_transpose) {
+ if ($labelInside) {
+ $this->write(
+ $labelPosition,
+ $this->_top - 3 - $offset,
+ $labelText,
+ IMAGE_GRAPH_ALIGN_BOTTOM | IMAGE_GRAPH_ALIGN_CENTER_X,
+ $font
+ );
+ } else {
+ $this->write(
+ $labelPosition,
+ $this->_top + 6 + $offset + $font['size'] * (substr_count($labelText, "\n") + 1),
+ $labelText,
+ IMAGE_GRAPH_ALIGN_BOTTOM | IMAGE_GRAPH_ALIGN_CENTER_X,
+ $font
+ );
+ }
+ }
+ else {
+ if ($labelInside) {
+ $this->write(
+ $this->_right + 3 + $offset,
+ $labelPosition,
+ $labelText,
+ IMAGE_GRAPH_ALIGN_CENTER_Y | IMAGE_GRAPH_ALIGN_LEFT,
+ $font
+ );
+ } else {
+ $this->write(
+ $this->_right - 3 - $offset,
+ $labelPosition,
+ $labelText,
+ IMAGE_GRAPH_ALIGN_CENTER_Y | IMAGE_GRAPH_ALIGN_RIGHT,
+ $font
+ );
+ }
+ }
+ } elseif ($this->_type == IMAGE_GRAPH_AXIS_Y_SECONDARY) {
+ if ($this->_transpose) {
+ if ($labelInside) {
+ $this->write(
+ $labelPosition,
+ $this->_bottom + 6 + $offset + $font['size'] * (substr_count($labelText, "\n") + 1),
+ $labelText,
+ IMAGE_GRAPH_ALIGN_BOTTOM | IMAGE_GRAPH_ALIGN_CENTER_X,
+ $font
+ );
+ } else {
+ $this->write(
+ $labelPosition,
+ $this->_bottom - 3 - $offset,
+ $labelText,
+ IMAGE_GRAPH_ALIGN_BOTTOM | IMAGE_GRAPH_ALIGN_CENTER_X,
+ $font
+ );
+ }
+ }
+ else {
+ if ($labelInside) {
+ $this->write(
+ $this->_left - 3 - $offset,
+ $labelPosition,
+ $labelText,
+ IMAGE_GRAPH_ALIGN_CENTER_Y | IMAGE_GRAPH_ALIGN_RIGHT,
+ $font
+ );
+ } else {
+ $this->write(
+ $this->_left + 3 + $offset,
+ $labelPosition,
+ $labelText,
+ IMAGE_GRAPH_ALIGN_CENTER_Y | IMAGE_GRAPH_ALIGN_LEFT,
+ $font
+ );
+ }
+ }
+ } else {
+ if ($this->_transpose) {
+ if ($labelInside) {
+ $this->write(
+ $this->_right + 3 + $offset,
+ $labelPosition,
+ $labelText,
+ IMAGE_GRAPH_ALIGN_CENTER_Y | IMAGE_GRAPH_ALIGN_LEFT,
+ $font
+ );
+ } else {
+ $this->write(
+ $this->_right - 3 - $offset,
+ $labelPosition,
+ $labelText,
+ IMAGE_GRAPH_ALIGN_CENTER_Y | IMAGE_GRAPH_ALIGN_RIGHT,
+ $font
+ );
+ }
+ }
+ else {
+ if ($labelInside === true) {
+ $this->write(
+ $labelPosition,
+ $this->_top - 3 - $offset,
+ $labelText,
+ IMAGE_GRAPH_ALIGN_CENTER_X | IMAGE_GRAPH_ALIGN_BOTTOM,
+ $font
+ );
+ } else {
+ $this->write(
+ $labelPosition,
+ $this->_top + 6 + $offset + $font['size'] * (substr_count($labelText, "\n") + 1),
+ $labelText,
+ IMAGE_GRAPH_ALIGN_CENTER_X | IMAGE_GRAPH_ALIGN_BOTTOM,
+ $font
+ );
+ }
+ }
+ }
+ }
+ }
+
+ $tickColor = false;
+ if (isset($this->_labelOptions[$level]['tick'])) {
+ if (isset($this->_labelOptions[$level]['tick']['start'])) {
+ $tickStart = $this->_labelOptions[$level]['tick']['start'];
+ } else {
+ $tickStart = false;
+ }
+
+ if (isset($this->_labelOptions[$level]['tick']['end'])) {
+ $tickEnd = $this->_labelOptions[$level]['tick']['end'];
+ } else {
+ $tickEnd = false;
+ }
+
+ if ((isset($this->_labelOptions[$level]['tick']['color'])) && ($this->_labelOptions[$level]['tick']['color'] !== false)) {
+ $tickColor = $this->_labelOptions[$level]['tick']['color'];
+ }
+ }
+
+ if ($tickStart === false) {
+ $tickStart = -2;
+ }
+
+ if ($tickEnd === false) {
+ $tickEnd = 2;
+ }
+
+ if ($tickColor !== false) {
+ $this->_canvas->setLineColor($tickColor);
+ }
+ else {
+ $this->_getLineStyle();
+ }
+
+ if ($this->_type == IMAGE_GRAPH_AXIS_Y) {
+ if ($tickStart === 'auto') {
+ $tickStart = -$offset;
+ }
+ if ($this->_transpose) {
+ $this->_canvas->line(
+ array(
+ 'x0' => $labelPosition,
+ 'y0' => $this->_top + $tickStart,
+ 'x1' => $labelPosition,
+ 'y1' => $this->_top + $tickEnd
+ )
+ );
+ }
+ else {
+ $this->_canvas->line(
+ array(
+ 'x0' => $this->_right + $tickStart,
+ 'y0' => $labelPosition,
+ 'x1' => $this->_right + $tickEnd,
+ 'y1' => $labelPosition
+ )
+ );
+ }
+ } elseif ($this->_type == IMAGE_GRAPH_AXIS_Y_SECONDARY) {
+ if ($tickStart === 'auto') {
+ $tickStart = $offset;
+ }
+ if ($this->_transpose) {
+ $this->_canvas->line(
+ array(
+ 'x0' => $labelPosition,
+ 'y0' => $this->_bottom - $tickStart,
+ 'x1' => $labelPosition,
+ 'y1' => $this->_bottom - $tickEnd
+ )
+ );
+ }
+ else {
+ $this->_canvas->line(
+ array(
+ 'x0' => $this->_left - $tickStart,
+ 'y0' => $labelPosition,
+ 'x1' => $this->_left - $tickEnd,
+ 'y1' => $labelPosition
+ )
+ );
+ }
+ } else {
+ if ($tickStart === 'auto') {
+ $tickStart = $offset;
+ }
+ if ($this->_transpose) {
+ $this->_canvas->line(
+ array(
+ 'x0' => $this->_right + $tickStart,
+ 'y0' => $labelPosition,
+ 'x1' => $this->_right + $tickEnd,
+ 'y1' => $labelPosition
+ )
+ );
+ }
+ else {
+ $this->_canvas->line(
+ array(
+ 'x0' => $labelPosition,
+ 'y0' => $this->_top - $tickStart,
+ 'x1' => $labelPosition,
+ 'y1' => $this->_top - $tickEnd
+ )
+ );
+ }
+ }
+ }
+ }
+
+ /**
+ * Draws axis lines.
+ *
+ * @access private
+ */
+ function _drawAxisLines()
+ {
+ if ($this->_type == IMAGE_GRAPH_AXIS_X) {
+ $this->_getLineStyle();
+ $this->_getFillStyle();
+
+ if ($this->_transpose) {
+ $data = array(
+ 'x0' => $this->_right,
+ 'y0' => $this->_top,
+ 'x1' => $this->_right,
+ 'y1' => $this->_bottom
+ );
+ } else {
+ $data = array(
+ 'x0' => $this->_left,
+ 'y0' => $this->_top,
+ 'x1' => $this->_right,
+ 'y1' => $this->_top
+ );
+ }
+
+ if ($this->_showArrow) {
+ if ($this->_getMaximum() <= 0) {
+ $data['end0'] = 'arrow2';
+ $data['size0'] = 7;
+ }
+ else {
+ $data['end1'] = 'arrow2';
+ $data['size1'] = 7;
+ }
+ }
+
+ $this->_canvas->line($data);
+
+ if ($this->_title) {
+ if (!$this->_transpose) {
+ $y = $this->_bottom;
+ $x = $this->_left + $this->width() / 2;
+ $this->write($x, $y, $this->_title, IMAGE_GRAPH_ALIGN_CENTER_X + IMAGE_GRAPH_ALIGN_BOTTOM, $this->_getTitleFont());
+ }
+ else {
+ $y = $this->_top + $this->height() / 2;
+ $x = $this->_left;
+ $this->write($x, $y, $this->_title, IMAGE_GRAPH_ALIGN_LEFT + IMAGE_GRAPH_ALIGN_CENTER_Y, $this->_getTitleFont());
+ }
+ }
+ } elseif ($this->_type == IMAGE_GRAPH_AXIS_Y_SECONDARY) {
+ $this->_getLineStyle();
+ $this->_getFillStyle();
+
+ if ($this->_transpose) {
+ $data = array(
+ 'x0' => $this->_left,
+ 'y0' => $this->_bottom,
+ 'x1' => $this->_right,
+ 'y1' => $this->_bottom
+ );
+ } else {
+ $data = array(
+ 'x0' => $this->_left,
+ 'y0' => $this->_bottom,
+ 'x1' => $this->_left,
+ 'y1' => $this->_top
+ );
+ }
+ if ($this->_showArrow) {
+ if ($this->_getMaximum() <= 0) {
+ $data['end0'] = 'arrow2';
+ $data['size0'] = 7;
+ }
+ else {
+ $data['end1'] = 'arrow2';
+ $data['size1'] = 7;
+ }
+ }
+ $this->_canvas->line($data);
+
+ if ($this->_title) {
+ if ($this->_transpose) {
+ $y = $this->_top;
+ $x = $this->_left + $this->width() / 2;
+ $this->write($x, $y, $this->_title, IMAGE_GRAPH_ALIGN_CENTER_X + IMAGE_GRAPH_ALIGN_TOP, $this->_getTitleFont());
+ }
+ else {
+ $y = $this->_top + $this->height() / 2;
+ $x = $this->_right;
+ $this->write($x, $y, $this->_title, IMAGE_GRAPH_ALIGN_RIGHT + IMAGE_GRAPH_ALIGN_CENTER_Y, $this->_getTitleFont());
+ }
+ }
+ } else {
+ $this->_getLineStyle();
+ $this->_getFillStyle();
+
+ if ($this->_transpose) {
+ $data = array(
+ 'x0' => $this->_left,
+ 'y0' => $this->_top,
+ 'x1' => $this->_right,
+ 'y1' => $this->_top
+ );
+ } else {
+ $data = array(
+ 'x0' => $this->_right,
+ 'y0' => $this->_bottom,
+ 'x1' => $this->_right,
+ 'y1' => $this->_top
+ );
+ }
+ if ($this->_showArrow) {
+ if ($this->_getMaximum() <= 0) {
+ $data['end0'] = 'arrow2';
+ $data['size0'] = 7;
+ }
+ else {
+ $data['end1'] = 'arrow2';
+ $data['size1'] = 7;
+ }
+ }
+ $this->_canvas->line($data);
+
+ if ($this->_title) {
+ if ($this->_transpose) {
+ $y = $this->_bottom;
+ $x = $this->_left + $this->width() / 2;
+ $this->write($x, $y, $this->_title, IMAGE_GRAPH_ALIGN_CENTER_X + IMAGE_GRAPH_ALIGN_BOTTOM, $this->_getTitleFont());
+ }
+ else {
+ $y = $this->_top + $this->height() / 2;
+ $x = $this->_left;
+ $this->write($x, $y, $this->_title, IMAGE_GRAPH_ALIGN_LEFT + IMAGE_GRAPH_ALIGN_CENTER_Y, $this->_getTitleFont());
+ }
+ }
+ }
+ }
+
+ /**
+ * Causes the object to update all sub elements coordinates
+ *
+ * (Image_Graph_Common, does not itself have coordinates, this is basically
+ * an abstract method)
+ *
+ * @access private
+ */
+ function _updateCoords()
+ {
+ parent::_updateCoords();
+ $this->_calcDelta();
+ }
+
+ /**
+ * Output the axis
+ *
+ * @return bool Was the output 'good' (true) or 'bad' (false).
+ * @access private
+ */
+ function _done()
+ {
+ $this->_canvas->startGroup(get_class($this));
+
+ if (parent::_done() === false) {
+ return false;
+ }
+
+ $this->_drawAxisLines();
+
+ $this->_canvas->startGroup(get_class($this) . '_ticks');
+ ksort($this->_labelOptions);
+ foreach ($this->_labelOptions as $level => $labelOption) {
+ $value = false;
+ while (($value = $this->_getNextLabel($value, $level)) !== false) {
+ if ((((abs($value) > 0.0001) || ($this->_showLabelZero)) &&
+ (($value > $this->_getMinimum()) || ($this->_showLabelMinimum)) &&
+ (($value < $this->_getMaximum()) || ($this->_showLabelMaximum))) &&
+ ($value >= $this->_getMinimum()) && ($value <= $this->_getMaximum())
+ ) {
+ $this->_drawTick($value, $level);
+ }
+ }
+ }
+ $this->_canvas->endGroup();
+
+ $tickStart = -3;
+ $tickEnd = 2;
+
+ foreach ($this->_marks as $mark) {
+ if (is_array($mark)) {
+ if ($this->_type == IMAGE_GRAPH_AXIS_X) {
+ if ($this->_transpose) {
+ $x0 = $this->_right + $tickStart;
+ $y0 = $this->_point($mark[1]);
+ $x1 = $this->_right + $tickEnd;
+ $y1 = $this->_point($mark[0]);
+ }
+ else {
+ $x0 = $this->_point($mark[0]);
+ $y0 = $this->_top + $tickStart;
+ $x1 = $this->_point($mark[1]);
+ $y1 = $this->_top + $tickEnd;
+ }
+ } elseif ($this->_type == IMAGE_GRAPH_AXIS_Y) {
+ if ($this->_transpose) {
+ $x0 = $this->_point($mark[0]);
+ $y0 = $this->_top + $tickStart;
+ $x1 = $this->_point($mark[1]);
+ $y1 = $this->_top + $tickEnd;
+ }
+ else {
+ $x0 = $this->_right + $tickStart;
+ $y0 = $this->_point($mark[1]);
+ $x1 = $this->_right + $tickEnd;
+ $y1 = $this->_point($mark[0]);
+ }
+ } elseif ($this->_type == IMAGE_GRAPH_AXIS_Y_SECONDARY) {
+ if ($this->_transpose) {
+ $x0 = $this->_point($mark[0]);
+ $y0 = $this->_bottom + $tickStart;
+ $x1 = $this->_point($mark[1]);
+ $y1 = $this->_bottom + $tickEnd;
+ }
+ else {
+ $x0 = $this->_left + $tickStart;
+ $y0 = $this->_point($mark[1]);
+ $x1 = $this->_left + $tickEnd;
+ $y1 = $this->_point($mark[0]);
+ }
+ }
+ $this->_getFillStyle();
+ $this->_getLineStyle();
+ $this->_canvas->rectangle(array('x0' => $x0, 'y0' => $y0, 'x1' => $x1, 'y1' => $y1));
+ } else {
+ if ($this->_type == IMAGE_GRAPH_AXIS_X) {
+ if ($this->_transpose) {
+ $x0 = $this->_right + 5;
+ $y0 = $this->_point($mark);
+ $x1 = $this->_right + 15;
+ $y1 = $y0;
+ }
+ else {
+ $x0 = $this->_point($mark);
+ $y0 = $this->_top - 5;
+ $x1 = $x0;
+ $y1 = $this->_top - 15;
+ }
+ } elseif ($this->_type == IMAGE_GRAPH_AXIS_Y) {
+ if ($this->_transpose) {
+ $x0 = $this->_point($mark);
+ $y0 = $this->_top - 5;
+ $x1 = $x0;
+ $y1 = $this->_top - 15;
+ }
+ else {
+ $x0 = $this->_right + 5;
+ $y0 = $this->_point($mark);
+ $x1 = $this->_right + 15;
+ $y1 = $y0;
+ }
+ } elseif ($this->_type == IMAGE_GRAPH_AXIS_Y_SECONDARY) {
+ if ($this->_transpose) {
+ $x0 = $this->_point($mark);
+ $y0 = $this->_bottom + 5;
+ $x1 = $x0;
+ $y1 = $this->_bottom + 15;
+ }
+ else {
+ $x0 = $this->_left - 5;
+ $y0 = $this->_point($mark);
+ $x1 = $this->_left - 15;
+ $y1 = $y0;
+ }
+ }
+ $this->_getFillStyle();
+ $this->_getLineStyle();
+ $this->_canvas->line(
+ array(
+ 'x0' => $x0,
+ 'y0' => $y0,
+ 'x1' => $x1,
+ 'y1' => $y1,
+ 'end0' => 'arrow2',
+ 'size0' => 5
+ )
+ );
+ }
+ }
+ $this->_canvas->endGroup();
+
+ return true;
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Axis/Category.php b/config/dspam/pear/Image/Graph/Axis/Category.php
new file mode 100644
index 00000000..b6451496
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Axis/Category.php
@@ -0,0 +1,437 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Class for axis handling.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Axis
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Axis.php
+ */
+require_once 'Image/Graph/Axis.php';
+
+/**
+ * A normal axis thats displays labels with a 'interval' of 1.
+ * This is basically a normal axis where the range is
+ * the number of labels defined, that is the range is explicitly defined
+ * when constructing the axis.
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Axis
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Axis_Category extends Image_Graph_Axis
+{
+
+ /**
+ * The labels shown on the axis
+ * @var array
+ * @access private
+ */
+ var $_labels = false;
+
+ /**
+ * Image_Graph_Axis_Category [Constructor].
+ *
+ * @param int $type The type (direction) of the Axis
+ */
+ function Image_Graph_Axis_Category($type = IMAGE_GRAPH_AXIS_X)
+ {
+ parent::Image_Graph_Axis($type);
+ $this->_labels = array();
+ $this->setlabelInterval(1);
+ }
+
+ /**
+ * Gets the minimum value the axis will show.
+ *
+ * This is always 0
+ *
+ * @return double The minumum value
+ * @access private
+ */
+ function _getMinimum()
+ {
+ return 0;
+ }
+
+ /**
+ * Gets the maximum value the axis will show.
+ *
+ * This is always the number of labels passed to the constructor.
+ *
+ * @return double The maximum value
+ * @access private
+ */
+ function _getMaximum()
+ {
+ return count($this->_labels) - 1;
+ }
+
+ /**
+ * Sets the minimum value the axis will show.
+ *
+ * A minimum cannot be set on a SequentialAxis, it is always 0.
+ *
+ * @param double Minimum The minumum value to use on the axis
+ * @access private
+ */
+ function _setMinimum($minimum)
+ {
+ }
+
+ /**
+ * Sets the maximum value the axis will show
+ *
+ * A maximum cannot be set on a SequentialAxis, it is always the number
+ * of labels passed to the constructor.
+ *
+ * @param double Maximum The maximum value to use on the axis
+ * @access private
+ */
+ function _setMaximum($maximum)
+ {
+ }
+
+ /**
+ * Forces the minimum value of the axis
+ *
+ * <b>A minimum cannot be set on this type of axis</b>
+ *
+ * To modify the labels which are displayed on the axis, instead use
+ * setLabelInterval($labels) where $labels is an array containing the
+ * values/labels the axis should display. <b>Note!</b> Only values in
+ * this array will then be displayed on the graph!
+ *
+ * @param double $minimum A minimum cannot be set on this type of axis
+ */
+ function forceMinimum($minimum, $userEnforce = true)
+ {
+ }
+
+ /**
+ * Forces the maximum value of the axis
+ *
+ * <b>A maximum cannot be set on this type of axis</b>
+ *
+ * To modify the labels which are displayed on the axis, instead use
+ * setLabelInterval($labels) where $labels is an array containing the
+ * values/labels the axis should display. <b>Note!</b> Only values in
+ * this array will then be displayed on the graph!
+ *
+ * @param double $maximum A maximum cannot be set on this type of axis
+ */
+ function forceMaximum($maximum, $userEnforce = true)
+ {
+ }
+
+ /**
+ * Sets an interval for where labels are shown on the axis.
+ *
+ * The label interval is rounded to nearest integer value.
+ *
+ * @param double $labelInterval The interval with which labels are shown
+ */
+ function setLabelInterval($labelInterval = 'auto', $level = 1)
+ {
+ if (is_array($labelInterval)) {
+ parent::setLabelInterval($labelInterval);
+ } elseif ($labelInterval == 'auto') {
+ parent::setLabelInterval(1);
+ } else {
+ parent::setLabelInterval(round($labelInterval));
+ }
+ }
+
+ /**
+ * Preprocessor for values, ie for using logarithmic axis
+ *
+ * @param double $value The value to preprocess
+ * @return double The preprocessed value
+ * @access private
+ */
+ function _value($value)
+ {
+// $the_value = array_search($value, $this->_labels);
+ if (isset($this->_labels[$value])) {
+ $the_value = $this->_labels[$value];
+ if ($the_value !== false) {
+ return $the_value + ($this->_pushValues ? 0.5 : 0);
+ } else {
+ return 0;
+ }
+ }
+ }
+
+
+ /**
+ * Get the minor label interval with which axis label ticks are drawn.
+ *
+ * For a sequential axis this is always disabled (i.e false)
+ *
+ * @return double The minor label interval, always false
+ * @access private
+ */
+ function _minorLabelInterval()
+ {
+ return false;
+ }
+
+ /**
+ * Get the size in pixels of the axis.
+ *
+ * For an x-axis this is the width of the axis including labels, and for an
+ * y-axis it is the corrresponding height
+ *
+ * @return int The size of the axis
+ * @access private
+ */
+ function _size()
+ {
+ if (!$this->_visible) {
+ return 0;
+ }
+
+ $this->_canvas->setFont($this->_getFont());
+
+ $maxSize = 0;
+ foreach($this->_labels as $label => $id) {
+ $labelPosition = $this->_point($label);
+
+ if (is_object($this->_dataPreProcessor)) {
+ $labelText = $this->_dataPreProcessor->_process($label);
+ } else {
+ $labelText = $label;
+ }
+
+ if ((($this->_type == IMAGE_GRAPH_AXIS_X) && (!$this->_transpose)) ||
+ (($this->_type != IMAGE_GRAPH_AXIS_X) && ($this->_transpose)))
+ {
+ $maxSize = max($maxSize, $this->_canvas->textHeight($labelText));
+ } else {
+ $maxSize = max($maxSize, $this->_canvas->textWidth($labelText));
+ }
+ }
+
+ if ($this->_title) {
+ $this->_canvas->setFont($this->_getTitleFont());
+
+ if ((($this->_type == IMAGE_GRAPH_AXIS_X) && (!$this->_transpose)) ||
+ (($this->_type != IMAGE_GRAPH_AXIS_X) && ($this->_transpose)))
+ {
+ $maxSize += $this->_canvas->textHeight($this->_title);
+ } else {
+ $maxSize += $this->_canvas->textWidth($this->_title);
+ }
+ $maxSize += 10;
+ }
+ return $maxSize +3;
+ }
+
+ /**
+ * Apply the dataset to the axis.
+ *
+ * This calculates the order of the categories, which is very important
+ * for fx. line plots, so that the line does not "go backwards", consider
+ * these X-sets:<p>
+ * 1: (1, 2, 3, 4, 5, 6)<br>
+ * 2: (0, 1, 2, 3, 4, 5, 6, 7)<p>
+ * If they are not ordered, but simply appended, the categories on the axis
+ * would be:<p>
+ * X: (1, 2, 3, 4, 5, 6, 0, 7)<p>
+ * Which would render the a line for the second plot to show incorrectly.
+ * Instead this algorithm, uses and 'value- is- before' method to see that
+ * the 0 is before a 1 in the second set, and that it should also be before
+ * a 1 in the X set. Hence:<p>
+ * X: (0, 1, 2, 3, 4, 5, 6, 7)
+ *
+ * @param Image_Graph_Dataset $dataset The dataset
+ * @access private
+ */
+ function _applyDataset(&$dataset)
+ {
+ $newLabels = array();
+ $allLabels = array();
+
+ $dataset->_reset();
+ $count = 0;
+ $count_new = 0;
+ while ($point = $dataset->_next()) {
+ if ($this->_type == IMAGE_GRAPH_AXIS_X) {
+ $data = $point['X'];
+ } else {
+ $data = $point['Y'];
+ }
+ if (!isset($this->_labels[$data])) {
+ $newLabels[$data] = $count_new++;
+ //$this->_labels[] = $data;
+ }
+ $allLabels[$data] = $count++;
+ }
+
+ if (count($this->_labels) == 0) {
+ $this->_labels = $newLabels;
+ } elseif ((is_array($newLabels)) && (count($newLabels) > 0)) {
+ // get all intersecting labels
+ $intersect = array_intersect(array_keys($allLabels), array_keys($this->_labels));
+ // traverse all new and find their relative position withing the
+ // intersec, fx value X0 is before X1 in the intersection, which
+ // means that X0 should be placed before X1 in the label array
+ foreach($newLabels as $newLabel => $id) {
+ $key = $allLabels[$newLabel];
+ reset($intersect);
+ $this_value = false;
+ // intersect indexes are the same as in allLabels!
+ $first = true;
+ while ((list($id, $value) = each($intersect)) &&
+ ($this_value === false))
+ {
+ if (($first) && ($id > $key)) {
+ $this_value = $value;
+ } elseif ($id >= $key) {
+ $this_value = $value;
+ }
+ $first = false;
+ }
+
+ if ($this_value === false) {
+ // the new label was not found before anything in the
+ // intersection -> append it
+ $this->_labels[$newLabel] = count($this->_labels);
+ } else {
+ // the new label was found before $this_value in the
+ // intersection, insert the label before this position in
+ // the label array
+// $key = $this->_labels[$this_value];
+ $keys = array_keys($this->_labels);
+ $key = array_search($this_value, $keys);
+ $pre = array_slice($keys, 0, $key);
+ $pre[] = $newLabel;
+ $post = array_slice($keys, $key);
+ $this->_labels = array_flip(array_merge($pre, $post));
+ }
+ }
+ unset($keys);
+ }
+
+ $labels = array_keys($this->_labels);
+ $i = 0;
+ foreach ($labels as $label) {
+ $this->_labels[$label] = $i++;
+ }
+
+// $this->_labels = array_values(array_unique($this->_labels));
+ $this->_calcLabelInterval();
+ }
+
+ /**
+ * Return the label distance.
+ *
+ * @return int The distance between 2 adjacent labels
+ * @access private
+ */
+ function _labelDistance($level = 1)
+ {
+ reset($this->_labels);
+ list($l1) = each($this->_labels);
+ list($l2) = each($this->_labels);
+ return abs($this->_point($l2) - $this->_point($l1));
+ }
+
+ /**
+ * Get next label point
+ *
+ * @param doubt $point The current point, if omitted or false, the first is
+ * returned
+ * @return double The next label point
+ * @access private
+ */
+ function _getNextLabel($currentLabel = false, $level = 1)
+ {
+ if ($currentLabel === false) {
+ reset($this->_labels);
+ }
+ $result = false;
+ $count = ($currentLabel === false ? $this->_labelInterval() - 1 : 0);
+ while ($count < $this->_labelInterval()) {
+ $result = (list($label) = each($this->_labels));
+ $count++;
+ }
+ if ($result) {
+ return $label;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Is the axis numeric or not?
+ *
+ * @return bool True if numeric, false if not
+ * @access private
+ */
+ function _isNumeric()
+ {
+ return false;
+ }
+
+ /**
+ * Output the axis
+ *
+ * @return bool Was the output 'good' (true) or 'bad' (false).
+ * @access private
+ */
+ function _done()
+ {
+ $result = true;
+ if (Image_Graph_Element::_done() === false) {
+ $result = false;
+ }
+
+ $this->_canvas->startGroup(get_class($this));
+
+ $this->_drawAxisLines();
+
+ $this->_canvas->startGroup(get_class($this) . '_ticks');
+ $label = false;
+ while (($label = $this->_getNextLabel($label)) !== false) {
+ $this->_drawTick($label);
+ }
+ $this->_canvas->endGroup();
+
+ $this->_canvas->endGroup();
+
+ return $result;
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Axis/Logarithmic.php b/config/dspam/pear/Image/Graph/Axis/Logarithmic.php
new file mode 100644
index 00000000..2675ee4c
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Axis/Logarithmic.php
@@ -0,0 +1,152 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Class for axis handling.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Axis
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Axis.php
+ */
+require_once 'Image/Graph/Axis.php';
+
+/**
+ * Diplays a logarithmic axis (either X- or Y-axis).
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Axis
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Axis_Logarithmic extends Image_Graph_Axis
+{
+
+ /**
+ * Image_Graph_AxisLogarithmic [Constructor].
+ *
+ * Normally a manual creation should not be necessary, axis are
+ * created automatically by the {@link Image_Graph_Plotarea} constructor
+ * unless explicitly defined otherwise
+ *
+ * @param int $type The type (direction) of the Axis, use IMAGE_GRAPH_AXIS_X
+ * for an X-axis (default, may be omitted) and IMAGE_GRAPH_AXIS_Y for Y-
+ * axis)
+ */
+ function Image_Graph_Axis_Logarithmic($type = IMAGE_GRAPH_AXIS_X)
+ {
+ parent::Image_Graph_Axis($type);
+ $this->showLabel(IMAGE_GRAPH_LABEL_MINIMUM + IMAGE_GRAPH_LABEL_MAXIMUM);
+ $this->_minimum = 1;
+ $this->_minimumSet = true;
+ }
+
+ /**
+ * Calculate the label interval
+ *
+ * If explicitly defined this will be calucated to an approximate best.
+ *
+ * @return double The label interval
+ * @access private
+ */
+ function _calcLabelInterval()
+ {
+ $result = parent::_calcLabelInterval();
+ $this->_axisValueSpan = $this->_value($this->_axisSpan);
+ return $result;
+ }
+
+ /**
+ * Preprocessor for values, ie for using logarithmic axis
+ *
+ * @param double $value The value to preprocess
+ * @return double The preprocessed value
+ * @access private
+ */
+ function _value($value)
+ {
+ return log10($value) - log10($this->_minimum);
+ }
+
+ /**
+ * Get next label point
+ *
+ * @param doubt $point The current point, if omitted or false, the first is
+ * returned
+ * @return double The next label point
+ * @access private
+ */
+ function _getNextLabel($currentLabel = false, $level = 1)
+ {
+ if (is_array($this->_labelOptions[$level]['interval'])) {
+ return parent::_getNextLabel($currentLabel, $level);
+ }
+
+ if ($currentLabel !== false) {
+ $value = log10($currentLabel);
+ $base = floor($value);
+ $frac = $value - $base;
+ for ($i = 2; $i < 10; $i++) {
+ if ($frac <= (log10($i)-0.01)) {
+ $label = pow(10, $base)*$i;
+ if ($label > $this->_getMaximum()) {
+ return false;
+ } else {
+ return $label;
+ }
+ }
+ }
+ return pow(10, $base+1);
+ }
+
+ return max(1, $this->_minimum);
+ }
+
+ /**
+ * Get the axis intersection pixel position
+ *
+ * This is only to be called prior to output! I.e. between the user
+ * invokation of Image_Graph::done() and any actual output is performed.
+ * This is because it can change the axis range.
+ *
+ * @param double $value the intersection value to get the pixel-point for
+ * @return double The pixel position along the axis
+ * @access private
+ */
+ function _intersectPoint($value)
+ {
+ if (($value <= 0) && ($value !== 'max') && ($value !== 'min')) {
+ $value = 1;
+ }
+ return parent::_intersectPoint($value);
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Axis/Marker/Area.php b/config/dspam/pear/Image/Graph/Axis/Marker/Area.php
new file mode 100644
index 00000000..1931ab48
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Axis/Marker/Area.php
@@ -0,0 +1,156 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Class file containing a axis marker used for explicitly highlighting a area
+ * on the graph, based on an interval specified on an axis.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Grid
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Grid.php
+ */
+require_once 'Image/Graph/Grid.php';
+
+/**
+ * Display a grid
+ *
+ * {@link Image_Graph_Grid}
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Grid
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Axis_Marker_Area extends Image_Graph_Grid
+{
+
+ /**
+ * The lower bound
+ * @var double
+ * @access private
+ */
+ var $_lower = false;
+
+ /**
+ * The upper bound
+ * @var double
+ * @access private
+ */
+ var $_upper = false;
+
+ /**
+ * [Constructor]
+ */
+ function Image_Graph_Axis_Marker_Area()
+ {
+ parent::Image_Graph_Grid();
+ $this->_lineStyle = false;
+ }
+
+ /**
+ * Sets the lower bound of the area (value on the axis)
+ *
+ * @param double $lower the lower bound
+ */
+ function setLowerBound($lower)
+ {
+ $this->_lower = $lower;
+ }
+
+ /**
+ * Sets the upper bound of the area (value on the axis)
+ *
+ * @param double $upper the upper bound
+ */
+ function setUpperBound($upper)
+ {
+ $this->_upper = $upper;
+ }
+
+ /**
+ * Output the grid
+ *
+ * @return bool Was the output 'good' (true) or 'bad' (false).
+ * @access private
+ */
+ function _done()
+ {
+ if (parent::_done() === false) {
+ return false;
+ }
+
+ if (!$this->_primaryAxis) {
+ return false;
+ }
+
+ $this->_canvas->startGroup(get_class($this));
+
+ $i = 0;
+
+ $this->_lower = max($this->_primaryAxis->_getMinimum(), $this->_lower);
+ $this->_upper = min($this->_primaryAxis->_getMaximum(), $this->_upper);
+
+ $secondaryPoints = $this->_getSecondaryAxisPoints();
+
+ reset($secondaryPoints);
+ list ($id, $previousSecondaryValue) = each($secondaryPoints);
+ while (list ($id, $secondaryValue) = each($secondaryPoints)) {
+ if ($this->_primaryAxis->_type == IMAGE_GRAPH_AXIS_X) {
+ $p1 = array ('Y' => $secondaryValue, 'X' => $this->_lower);
+ $p2 = array ('Y' => $previousSecondaryValue, 'X' => $this->_lower);
+ $p3 = array ('Y' => $previousSecondaryValue, 'X' => $this->_upper);
+ $p4 = array ('Y' => $secondaryValue, 'X' => $this->_upper);
+ } else {
+ $p1 = array ('X' => $secondaryValue, 'Y' => $this->_lower);
+ $p2 = array ('X' => $previousSecondaryValue, 'Y' => $this->_lower);
+ $p3 = array ('X' => $previousSecondaryValue, 'Y' => $this->_upper);
+ $p4 = array ('X' => $secondaryValue, 'Y' => $this->_upper);
+ }
+
+ $this->_canvas->addVertex(array('x' => $this->_pointX($p1), 'y' => $this->_pointY($p1)));
+ $this->_canvas->addVertex(array('x' => $this->_pointX($p2), 'y' => $this->_pointY($p2)));
+ $this->_canvas->addVertex(array('x' => $this->_pointX($p3), 'y' => $this->_pointY($p3)));
+ $this->_canvas->addVertex(array('x' => $this->_pointX($p4), 'y' => $this->_pointY($p4)));
+
+ $previousSecondaryValue = $secondaryValue;
+
+ $this->_getLineStyle();
+ $this->_getFillStyle();
+ $this->_canvas->polygon(array('connect' => true));
+ }
+
+ $this->_canvas->endGroup();
+
+ return true;
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Axis/Marker/Line.php b/config/dspam/pear/Image/Graph/Axis/Marker/Line.php
new file mode 100644
index 00000000..0c46c144
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Axis/Marker/Line.php
@@ -0,0 +1,124 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Class file containing a axis marker used for explicitly highlighting a point
+ * (line) on the graph, based on an value specified on an axis.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Grid
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Grid.php
+ */
+require_once 'Image/Graph/Grid.php';
+
+/**
+ * Display a grid
+ *
+ * {@link Image_Graph_Grid}
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Grid
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Axis_Marker_Line extends Image_Graph_Grid
+{
+
+ /**
+ * The value
+ * @var double
+ * @access private
+ */
+ var $_value = false;
+
+ /**
+ * Sets the value of the line marker (value on the axis)
+ *
+ * @param double $value the value
+ */
+ function setValue($value)
+ {
+ $this->_value = $value;
+ }
+
+ /**
+ * Output the grid
+ *
+ * @return bool Was the output 'good' (true) or 'bad' (false).
+ * @access private
+ */
+ function _done()
+ {
+ if (parent::_done() === false) {
+ return false;
+ }
+
+ if (!$this->_primaryAxis) {
+ return false;
+ }
+
+ $this->_canvas->startGroup(get_class($this));
+
+ $i = 0;
+
+ $this->_value = min($this->_primaryAxis->_getMaximum(), max($this->_primaryAxis->_getMinimum(), $this->_value));
+
+ $secondaryPoints = $this->_getSecondaryAxisPoints();
+
+ reset($secondaryPoints);
+ list ($id, $previousSecondaryValue) = each($secondaryPoints);
+ while (list ($id, $secondaryValue) = each($secondaryPoints)) {
+ if ($this->_primaryAxis->_type == IMAGE_GRAPH_AXIS_X) {
+ $p1 = array ('X' => $this->_value, 'Y' => $secondaryValue);
+ $p2 = array ('X' => $this->_value, 'Y' => $previousSecondaryValue);
+ } else {
+ $p1 = array ('X' => $secondaryValue, 'Y' => $this->_value);
+ $p2 = array ('X' => $previousSecondaryValue, 'Y' => $this->_value);
+ }
+
+ $x1 = $this->_pointX($p1);
+ $y1 = $this->_pointY($p1);
+ $x2 = $this->_pointX($p2);
+ $y2 = $this->_pointY($p2);
+
+ $previousSecondaryValue = $secondaryValue;
+
+ $this->_getLineStyle();
+ $this->_canvas->line(array('x0' => $x1, 'y0' => $y1, 'x1' => $x2, 'y1' => $y2));
+ }
+
+ $this->_canvas->endGroup();
+
+ return true;
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Axis/Radar.php b/config/dspam/pear/Image/Graph/Axis/Radar.php
new file mode 100644
index 00000000..7348254c
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Axis/Radar.php
@@ -0,0 +1,204 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Class for axis handling.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Axis
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Axis/Category.php
+ */
+require_once 'Image/Graph/Axis/Category.php';
+
+/**
+ * Displays an 'X'-axis in a radar plot chart.
+ *
+ * This axis maps the number of elements in the dataset to a angle (from 0-
+ * 360 degrees). Displaying the axis consist of drawing a number of lines from
+ * center to the edge of the 'circle' than encloses the radar plot. The labels
+ * are drawn on the 'ends' of these radial lines.
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Axis
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Axis_Radar extends Image_Graph_Axis_Category
+{
+
+ /**
+ * Specifies the number of pixels, the labels is offsetted from the end of
+ * the axis
+ *
+ * @var int
+ * @access private
+ */
+ var $_distanceFromEnd = 5;
+
+ /**
+ * Gets the minimum value the axis will show.
+ *
+ * This is always 0
+ *
+ * @return double The minumum value
+ * @access private
+ */
+ function _getMinimum()
+ {
+ return 0;
+ }
+
+ /**
+ * Gets the maximum value the axis will show.
+ *
+ * This is always the number of labels passed to the constructor.
+ *
+ * @return double The maximum value
+ * @access private
+ */
+ function _getMaximum()
+ {
+ return count($this->_labels);
+ }
+
+ /**
+ * Calculate the delta value (the number of pixels representing one unit
+ * on the axis)
+ *
+ * @return double The label interval
+ * @access private
+ */
+ function _calcDelta()
+ {
+ if (abs($this->_getMaximum() - $this->_getMinimum()) == 0) {
+ $this->_delta = false;
+ } else {
+ $this->_delta = 360 / ($this->_getMaximum() - $this->_getMinimum());
+ }
+ }
+
+ /**
+ * Get the pixel position represented by a value on the canvas
+ *
+ * @param double $value the value to get the pixel-point for
+ * @return double The pixel position along the axis
+ * @access private
+ */
+ function _point($value)
+ {
+ return (90 + (int) ($this->_value($value) * $this->_delta)) % 360;
+ }
+
+ /**
+ * Get the size in pixels of the axis.
+ *
+ * For a radar plot this is always 0
+ *
+ * @return int The size of the axis
+ * @access private
+ */
+ function _size()
+ {
+ return 0;
+ }
+
+ /**
+ * Sets the distance from the end of the category lines to the label.
+ *
+ * @param int $distance The distance in pixels
+ */
+ function setDistanceFromEnd($distance = 5)
+ {
+ $this->_distanceFromEnd = $distance;
+ }
+
+ /**
+ * Draws axis lines.
+ *
+ * @access private
+ */
+ function _drawAxisLines()
+ {
+ }
+
+ /**
+ * Output an axis tick mark.
+ *
+ * @param int $value The value to output
+ * @access private
+ */
+ function _drawTick($value, $level = 1)
+ {
+ $centerX = (int) (($this->_left + $this->_right) / 2);
+ $centerY = (int) (($this->_top + $this->_bottom) / 2);
+
+ $radius = min($this->height(), $this->width()) / 2;
+
+ $endPoint = array ('X' => $value, 'Y' => '#max#');
+ $dX = $this->_pointX($endPoint);
+ $dY = $this->_pointY($endPoint);
+
+ $offX = ($dX - $centerX);
+ $offY = ($dY - $centerY);
+
+ $hyp = sqrt($offX*$offX + $offY*$offY);
+ if ($hyp != 0) {
+ $scale = $this->_distanceFromEnd / $hyp;
+ } else {
+ $scale = 1;
+ }
+
+ $adX = $dX + $offX * $scale;
+ $adY = $dY + $offY * $scale;
+
+ if (is_object($this->_dataPreProcessor)) {
+ $labelText = $this->_dataPreProcessor->_process($value);
+ } else {
+ $labelText = $value;
+ }
+
+ if ((abs($dX - $centerX) < 1.5) && ($dY < $centerY)) {
+ $align = IMAGE_GRAPH_ALIGN_BOTTOM + IMAGE_GRAPH_ALIGN_CENTER_X;
+ } elseif ((abs($dX - $centerX) < 1.5) && ($dY > $centerY)) {
+ $align = IMAGE_GRAPH_ALIGN_TOP + IMAGE_GRAPH_ALIGN_CENTER_X;
+ } elseif ($dX < $centerX) {
+ $align = IMAGE_GRAPH_ALIGN_RIGHT + IMAGE_GRAPH_ALIGN_CENTER_Y;
+ } else {
+ $align = IMAGE_GRAPH_ALIGN_LEFT + IMAGE_GRAPH_ALIGN_CENTER_Y;
+ }
+ $this->write($adX, $adY, $labelText, $align);
+
+ $this->_getLineStyle();
+ $this->_canvas->line(array('x0' => $centerX, 'y0' => $centerY, 'x1' => $dX, 'y1' => $dY));
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Common.php b/config/dspam/pear/Image/Graph/Common.php
new file mode 100644
index 00000000..f695cb58
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Common.php
@@ -0,0 +1,313 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - Main class for the graph creation.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+if (!function_exists('is_a')) {
+
+ /**
+ * Check if an object is of a given class, this function is available as of PHP 4.2.0, so if it exist it will not be declared
+ *
+ * @link http://www.php.net/manual/en/function.is-a.php PHP.net Online Manual for function is_a()
+ * @param object $object The object to check class for
+ * @param string $class_name The name of the class to check the object for
+ * @return bool Returns TRUE if the object is of this class or has this class as one of its parents
+ */
+ function is_a($object, $class_name)
+ {
+ if (empty ($object)) {
+ return false;
+ }
+ $object = is_object($object) ? get_class($object) : $object;
+ if (strtolower($object) == strtolower($class_name)) {
+ return true;
+ }
+ return is_a(get_parent_class($object), $class_name);
+ }
+}
+
+/**
+ * Include file Image/Canvas.php
+ */
+require_once 'Image/Canvas.php';
+
+/**
+ * The ultimate ancestor of all Image_Graph classes.
+ *
+ * This class contains common functionality needed by all Image_Graph classes.
+ *
+ * @category Images
+ * @package Image_Graph
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ * @abstract
+ */
+class Image_Graph_Common
+{
+
+ /**
+ * The parent container of the current Image_Graph object
+ *
+ * @var Image_Graph_Common
+ * @access private
+ */
+ var $_parent = null;
+
+ /**
+ * The sub-elements of the current Image_Graph container object
+ *
+ * @var array
+ * @access private
+ */
+ var $_elements;
+
+ /**
+ * The canvas for output.
+ *
+ * Enables support for multiple output formats.
+ *
+ * @var Image_Canvas
+ * @access private
+ */
+ var $_canvas = null;
+
+ /**
+ * Is the object visible?
+ *
+ * @var bool
+ * @access private
+ */
+ var $_visible = true;
+
+ /**
+ * Constructor [Image_Graph_Common]
+ */
+ function Image_Graph_Common()
+ {
+ }
+
+ /**
+ * Resets the elements
+ *
+ * @access private
+ */
+ function _reset()
+ {
+ if (is_array($this->_elements)) {
+ $keys = array_keys($this->_elements);
+ foreach ($keys as $key) {
+ if (is_object($this->_elements[$key])) {
+ $this->_elements[$key]->_setParent($this);
+ $result =& $this->_elements[$key]->_reset();
+ if (PEAR::isError($result)) {
+ return $result;
+ }
+ }
+ }
+ unset($keys);
+ }
+ return true;
+ }
+
+ /**
+ * Sets the parent. The parent chain should ultimately be a GraPHP object
+ *
+ * @see Image_Graph_Common
+ * @param Image_Graph_Common $parent The parent
+ * @access private
+ */
+ function _setParent(& $parent)
+ {
+ $this->_parent =& $parent;
+ $this->_canvas =& $this->_parent->_getCanvas();
+
+ if (is_array($this->_elements)) {
+ $keys = array_keys($this->_elements);
+ foreach ($keys as $key) {
+ if (is_object($this->_elements[$key])) {
+ $this->_elements[$key]->_setParent($this);
+ }
+ }
+ unset($keys);
+ }
+ }
+
+ /**
+ * Hide the element
+ */
+ function hide()
+ {
+ $this->_visible = false;
+ }
+
+ /**
+ * Get the canvas
+ *
+ * @return Image_Canvas The canvas
+ * @access private
+ */
+ function &_getCanvas()
+ {
+ if (($this->_canvas !== null) || ($this->_canvas !== false)) {
+ return $this->_canvas;
+ } elseif (is_a($this->_parent, 'Image_Graph_Common')) {
+ $this->_canvas =& $this->_parent->_getCanvas();
+ return $this->_canvas;
+ } else {
+ $this->_error('Invalid canvas');
+ $result = null;
+ return $result;
+ }
+ }
+
+ /**
+ * Adds an element to the objects element list.
+ *
+ * The new Image_Graph_elements parent is automatically set.
+ *
+ * @param Image_Graph_Common $element The new Image_Graph_element
+ * @return Image_Graph_Common The new Image_Graph_element
+ */
+ function &add(& $element)
+ {
+ if (!is_a($element, 'Image_Graph_Font')) {
+ $this->_elements[] = &$element;
+ }
+ $element->_setParent($this);
+ return $element;
+ }
+
+ /**
+ * Creates an object from the class and adds it to the objects element list.
+ *
+ * Creates an object from the class specified and adds it to the objects
+ * element list. If only one parameter is required for the constructor of
+ * the class simply pass this parameter as the $params parameter, unless the
+ * parameter is an array or a reference to a value, in that case you must
+ * 'enclose' the parameter in an array. Similar if the constructor takes
+ * more than one parameter specify the parameters in an array.
+ *
+ * @see Image_Graph::factory()
+ * @param string $class The class for the object
+ * @param mixed $params The paramaters to pass to the constructor
+ * @return Image_Graph_Common The new Image_Graph_element
+ */
+ function &addNew($class, $params = null, $additional = false)
+ {
+ include_once 'Image/Graph.php';
+ $element =& Image_Graph::factory($class, $params);
+ if ($additional === false) {
+ $obj =& $this->add($element);
+ } else {
+ $obj =& $this->add($element, $additional);
+ }
+ return $obj;
+ }
+
+ /**
+ * Shows an error message box on the canvas
+ *
+ * @param string $text The error text
+ * @param array $params An array containing error specific details
+ * @param int $error_code Error code
+ * @access private
+ */
+ function _error($text, $params = false, $error_code = IMAGE_GRAPH_ERROR_GENERIC)
+ {
+ if ((is_array($params)) && (count($params) > 0)) {
+ foreach ($params as $name => $key) {
+ if (isset($parameters)) {
+ $parameters .= ' ';
+ }
+ else {
+ $parameters = '';
+ }
+ $parameters .= $name . '=' . $key;
+ }
+ }
+ $error =& PEAR::raiseError(
+ $text .
+ ($error_code != IMAGE_GRAPH_ERROR_GENERIC ? ' error:' . IMAGE_GRAPH_ERROR_GENERIC : '') .
+ (isset($parameters) ? ' parameters:[' . $parameters . ']' : '')
+ );
+ }
+
+ /**
+ * Causes the object to update all sub elements coordinates
+ *
+ * (Image_Graph_Common, does not itself have coordinates, this is basically
+ * an abstract method)
+ *
+ * @access private
+ */
+ function _updateCoords()
+ {
+ if (is_array($this->_elements)) {
+ $keys = array_keys($this->_elements);
+ foreach ($keys as $key) {
+ if (is_object($this->_elements[$key])) {
+ $this->_elements[$key]->_updateCoords();
+ }
+ }
+ unset($keys);
+ }
+ return true;
+ }
+
+ /**
+ * Causes output to canvas
+ *
+ * The last method to call. Calling Done causes output to the canvas. All
+ * sub elements done() method will be invoked
+ *
+ * @return bool Was the output 'good' (true) or 'bad' (false).
+ * @access private
+ */
+ function _done()
+ {
+ if (($this->_canvas == null) || (!is_a($this->_canvas, 'Image_Canvas'))) {
+ return false;
+ }
+
+ if (is_array($this->_elements)) {
+ $keys = array_keys($this->_elements);
+ foreach ($keys as $key) {
+ if (($this->_elements[$key]->_visible) && ($this->_elements[$key]->_done() === false)) {
+ return false;
+ }
+ }
+ unset($keys);
+ }
+ return true;
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Config.php b/config/dspam/pear/Image/Graph/Config.php
new file mode 100644
index 00000000..ece8a91b
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Config.php
@@ -0,0 +1,30 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - Main class for the graph creation.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Constants.php b/config/dspam/pear/Image/Graph/Constants.php
new file mode 100644
index 00000000..f03674ba
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Constants.php
@@ -0,0 +1,225 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - Main class for the graph creation.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Font.php
+ */
+require_once 'Image/Graph/Font.php';
+
+// Constant declarations
+
+/**
+ * Defines an X (horizontal) axis
+ */
+define('IMAGE_GRAPH_AXIS_X', 1);
+
+/**
+ * Defines an Y (vertical) axis
+ */
+define('IMAGE_GRAPH_AXIS_Y', 2);
+
+/**
+ * Defines an Y (vertical) axis
+ */
+define('IMAGE_GRAPH_AXIS_Y_SECONDARY', 3);
+
+/**
+ * Defines an horizontal (X) axis
+ */
+define('IMAGE_GRAPH_AXIS_HORIZONTAL', 1);
+
+/**
+ * Defines an vertical (Y) axis
+ */
+define('IMAGE_GRAPH_AXIS_VERTICAL', 2);
+
+/**
+ * Define if label should be shown for axis minimum value
+ */
+define('IMAGE_GRAPH_LABEL_MINIMUM', 1);
+
+/**
+ * Define if label should be shown for axis 0 (zero) value
+ */
+define('IMAGE_GRAPH_LABEL_ZERO', 2);
+
+/**
+ * Define if label should be shown for axis maximum value
+ */
+define('IMAGE_GRAPH_LABEL_MAXIMUM', 4);
+
+/**
+ * Defines a horizontal gradient fill
+ */
+define('IMAGE_GRAPH_GRAD_HORIZONTAL', 1);
+
+/**
+ * Defines a vertical gradient fill
+ */
+define('IMAGE_GRAPH_GRAD_VERTICAL', 2);
+
+/**
+ * Defines a horizontally mirrored gradient fill
+ */
+define('IMAGE_GRAPH_GRAD_HORIZONTAL_MIRRORED', 3);
+
+/**
+ * Defines a vertically mirrored gradient fill
+ */
+define('IMAGE_GRAPH_GRAD_VERTICAL_MIRRORED', 4);
+
+/**
+ * Defines a diagonal gradient fill from top-left to bottom-right
+ */
+define('IMAGE_GRAPH_GRAD_DIAGONALLY_TL_BR', 5);
+
+/**
+ * Defines a diagonal gradient fill from bottom-left to top-right
+ */
+define('IMAGE_GRAPH_GRAD_DIAGONALLY_BL_TR', 6);
+
+/**
+ * Defines a radial gradient fill
+ */
+define('IMAGE_GRAPH_GRAD_RADIAL', 7);
+
+/**
+ * Defines the default builtin font
+ */
+define('IMAGE_GRAPH_FONT', 1);
+
+/**
+ * Defines a X value should be used
+ */
+define('IMAGE_GRAPH_VALUE_X', 0);
+
+/**
+ * Defines a Y value should be used
+ */
+define('IMAGE_GRAPH_VALUE_Y', 1);
+
+/**
+ * Defines a min X% value should be used
+ */
+define('IMAGE_GRAPH_PCT_X_MIN', 2);
+
+/**
+ * Defines a max X% value should be used
+ */
+define('IMAGE_GRAPH_PCT_X_MAX', 3);
+
+/**
+ * Defines a min Y% value should be used
+ */
+define('IMAGE_GRAPH_PCT_Y_MIN', 4);
+
+/**
+ * Defines a max Y% value should be used
+ */
+define('IMAGE_GRAPH_PCT_Y_MAX', 5);
+
+/**
+ * Defines a total Y% value should be used
+ */
+define('IMAGE_GRAPH_PCT_Y_TOTAL', 6);
+
+/**
+ * Defines a ID value should be used
+ */
+define('IMAGE_GRAPH_POINT_ID', 7);
+
+/**
+ * Align text left
+ */
+define('IMAGE_GRAPH_ALIGN_LEFT', 0x1);
+
+/**
+ * Align text right
+ */
+define('IMAGE_GRAPH_ALIGN_RIGHT', 0x2);
+
+/**
+ * Align text center x (horizontal)
+ */
+define('IMAGE_GRAPH_ALIGN_CENTER_X', 0x4);
+
+/**
+ * Align text top
+ */
+define('IMAGE_GRAPH_ALIGN_TOP', 0x8);
+
+/**
+ * Align text bottom
+ */
+define('IMAGE_GRAPH_ALIGN_BOTTOM', 0x10);
+
+/**
+ * Align text center y (vertical)
+ */
+define('IMAGE_GRAPH_ALIGN_CENTER_Y', 0x20);
+
+/**
+ * Align text center (both x and y)
+ */
+define('IMAGE_GRAPH_ALIGN_CENTER', IMAGE_GRAPH_ALIGN_CENTER_X + IMAGE_GRAPH_ALIGN_CENTER_Y);
+
+/**
+ * Align text top left
+ */
+define('IMAGE_GRAPH_ALIGN_TOP_LEFT', IMAGE_GRAPH_ALIGN_TOP + IMAGE_GRAPH_ALIGN_LEFT);
+
+/**
+ * Align text top right
+ */
+define('IMAGE_GRAPH_ALIGN_TOP_RIGHT', IMAGE_GRAPH_ALIGN_TOP + IMAGE_GRAPH_ALIGN_RIGHT);
+
+/**
+ * Align text bottom left
+ */
+define('IMAGE_GRAPH_ALIGN_BOTTOM_LEFT', IMAGE_GRAPH_ALIGN_BOTTOM + IMAGE_GRAPH_ALIGN_LEFT);
+
+/**
+ * Align text bottom right
+ */
+define('IMAGE_GRAPH_ALIGN_BOTTOM_RIGHT', IMAGE_GRAPH_ALIGN_BOTTOM + IMAGE_GRAPH_ALIGN_RIGHT);
+
+/**
+ * Align vertical
+ */
+define('IMAGE_GRAPH_ALIGN_VERTICAL', IMAGE_GRAPH_ALIGN_TOP);
+
+/**
+ * Align horizontal
+ */
+define('IMAGE_GRAPH_ALIGN_HORIZONTAL', IMAGE_GRAPH_ALIGN_LEFT);
+
+// Error codes
+define('IMAGE_GRAPH_ERROR_GENERIC', 0);
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/DataPreprocessor.php b/config/dspam/pear/Image/Graph/DataPreprocessor.php
new file mode 100644
index 00000000..f135d539
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/DataPreprocessor.php
@@ -0,0 +1,74 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage DataPreprocessor
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Data preprocessor used for preformatting a data.
+ *
+ * A data preprocessor is used in cases where a value from a dataset or label must be
+ * displayed in another format or way than entered. This could for example be the need
+ * to display X-values as a date instead of 1, 2, 3, .. or even worse unix-timestamps.
+ * It could also be when a {@link Image_Graph_Marker_Value} needs to display values as percentages
+ * with 1 decimal digit instead of the default formatting (fx. 12.01271 -> 12.0%).
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage DataPreprocessor
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ * @abstract
+ */
+class Image_Graph_DataPreprocessor
+{
+
+ /**
+ * Image_Graph_DataPreprocessor [Constructor].
+ */
+ function Image_Graph_DataPreprocessor()
+ {
+ }
+
+ /**
+ * Process the value
+ *
+ * @param var $value The value to process/format
+ * @return string The processed value
+ * @access private
+ */
+ function _process($value)
+ {
+ return $value;
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/DataPreprocessor/Array.php b/config/dspam/pear/Image/Graph/DataPreprocessor/Array.php
new file mode 100644
index 00000000..08e62378
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/DataPreprocessor/Array.php
@@ -0,0 +1,103 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage DataPreprocessor
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/DataPreprocessor.php
+ */
+require_once 'Image/Graph/DataPreprocessor.php';
+
+/**
+ * Format data as looked up in an array.
+ *
+ * ArrayData is useful when a numercal value is to be translated to
+ * something thats cannot directly be calculated from this value, this could for
+ * example be a dataset meant to plot population of various countries. Since x-
+ * values are numerical and they should really be country names, but there is no
+ * linear correlation between the number and the name, we use an array to 'map'
+ * the numbers to the name, i.e. $array[0] = 'Denmark'; $array[1] = 'Sweden';
+ * ..., where the indexes are the numerical values from the dataset. This is NOT
+ * usefull when the x-values are a large domain, i.e. to map unix timestamps to
+ * date-strings for an x-axis. This is because the x-axis will selecte arbitrary
+ * values for labels, which would in principle require the ArrayData to hold
+ * values for every unix timestamp. However ArrayData can still be used to solve
+ * such a situation, since one can use another value for X-data in the dataset
+ * and then map this (smaller domain) value to a date. That is we for example
+ * instead of using the unix-timestamp we use value 0 to represent the 1st date,
+ * 1 to represent the next date, etc.
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage DataPreprocessor
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_DataPreprocessor_Array extends Image_Graph_DataPreprocessor
+{
+
+ /**
+ * The data label array
+ * @var array
+ * @access private
+ */
+ var $_dataArray;
+
+ /**
+ * Image_Graph_ArrayData [Constructor].
+ *
+ * @param array $array The array to use as a lookup table
+ */
+ function Image_Graph_DataPreprocessor_Array($array)
+ {
+ parent::Image_Graph_DataPreprocessor();
+ $this->_dataArray = $array;
+ }
+
+ /**
+ * Process the value
+ *
+ * @param var $value The value to process/format
+ * @return string The processed value
+ * @access private
+ */
+ function _process($value)
+ {
+ if ((is_array($this->_dataArray)) && (isset ($this->_dataArray[$value]))) {
+ return $this->_dataArray[$value];
+ } else {
+ return $value;
+ }
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/DataPreprocessor/Currency.php b/config/dspam/pear/Image/Graph/DataPreprocessor/Currency.php
new file mode 100644
index 00000000..2d3b5e2f
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/DataPreprocessor/Currency.php
@@ -0,0 +1,66 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage DataPreprocessor
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/DataPreprocessor/Formatted.php
+ */
+require_once 'Image/Graph/DataPreprocessor/Formatted.php';
+
+/**
+ * Format data as a currency.
+ *
+ * Uses the {@link Image_Graph_DataPreprocessor_Formatted} to represent the
+ * values as a currency, i.e. 10 => € 10.00
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage DataPreprocessor
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_DataPreprocessor_Currency extends Image_Graph_DataPreprocessor_Formatted
+{
+
+ /**
+ * Image_Graph_CurrencyData [Constructor].
+ *
+ * @param string $currencySymbol The symbol representing the currency
+ */
+ function Image_Graph_DataPreprocessor_Currency($currencySymbol)
+ {
+ parent::Image_Graph_DataPreprocessor_Formatted("$currencySymbol %0.2f");
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/DataPreprocessor/Date.php b/config/dspam/pear/Image/Graph/DataPreprocessor/Date.php
new file mode 100644
index 00000000..74695264
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/DataPreprocessor/Date.php
@@ -0,0 +1,90 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage DataPreprocessor
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/DataPreprocessor.php
+ */
+require_once 'Image/Graph/DataPreprocessor.php';
+
+/**
+ * Formats Unix timestamp as a date using specified format.
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage DataPreprocessor
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_DataPreprocessor_Date extends Image_Graph_DataPreprocessor
+{
+
+ /**
+ * The format of the Unix time stamp.
+ * See <a href = 'http://www.php.net/manual/en/function.date.php'>PHP
+ * Manual</a> for a description
+ * @var string
+ * @access private
+ */
+ var $_format;
+
+ /**
+ * Create a DateData preprocessor [Constructor]
+ *
+ * @param string $format See {@link http://www.php.net/manual/en/function.date.php
+ * PHP Manual} for a description
+ */
+ function Image_Graph_DataPreprocessor_Date($format)
+ {
+ parent::Image_Graph_DataPreprocessor();
+ $this->_format = $format;
+ }
+
+ /**
+ * Process the value
+ *
+ * @param var $value The value to process/format
+ * @return string The processed value
+ * @access private
+ */
+ function _process($value)
+ {
+ if (!$value) {
+ return false;
+ } else {
+ return date($this->_format, $value);
+ }
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/DataPreprocessor/Formatted.php b/config/dspam/pear/Image/Graph/DataPreprocessor/Formatted.php
new file mode 100644
index 00000000..ff7335a0
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/DataPreprocessor/Formatted.php
@@ -0,0 +1,90 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage DataPreprocessor
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/DataPreprocessor.php
+ */
+require_once 'Image/Graph/DataPreprocessor.php';
+
+/**
+ * Format data using a (s)printf pattern.
+ *
+ * This method is useful when data must displayed using a simple (s) printf
+ * pattern as described in the {@link http://www.php. net/manual/en/function.
+ * sprintf.php PHP manual}
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage DataPreprocessor
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_DataPreprocessor_Formatted extends Image_Graph_DataPreprocessor
+{
+
+ /**
+ * A (s)printf format string.
+ * See {@link http://www.php.net/manual/en/function.sprintf.php PHP Manual}
+ * for a description
+ * @var string
+ * @access private
+ */
+ var $_format;
+
+ /**
+ * Create a (s)printf format data preprocessor
+ *
+ * @param string $format See {@link http://www.php.net/manual/en/function.sprintf.php
+ * PHP Manual} for a description
+ */
+ function Image_Graph_DataPreprocessor_Formatted($format)
+ {
+ parent::Image_Graph_DataPreprocessor();
+ $this->_format = $format;
+ }
+
+ /**
+ * Process the value
+ *
+ * @param var $value The value to process/format
+ * @return string The processed value
+ * @access private
+ */
+ function _process($value)
+ {
+ return sprintf($this->_format, $value);
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/DataPreprocessor/Function.php b/config/dspam/pear/Image/Graph/DataPreprocessor/Function.php
new file mode 100644
index 00000000..b23a718d
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/DataPreprocessor/Function.php
@@ -0,0 +1,92 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage DataPreprocessor
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/DataPreprocessor.php
+ */
+require_once 'Image/Graph/DataPreprocessor.php';
+
+/**
+ * Formatting a value using a userdefined function.
+ *
+ * Use this method to convert/format a value to a 'displayable' lable using a (perhaps)
+ * more complex function. An example could be (not very applicable though) if one would
+ * need for values to be displayed on the reverse order, i.e. 1234 would be displayed as
+ * 4321, then this method can solve this by creating the function that converts the value
+ * and use the FunctionData datapreprocessor to make Image_Graph use this function.
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage DataPreprocessor
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_DataPreprocessor_Function extends Image_Graph_DataPreprocessor
+{
+
+ /**
+ * The name of the PHP function
+ * @var string
+ * @access private
+ */
+ var $_dataFunction;
+
+ /**
+ * Create a FunctionData preprocessor
+ *
+ * @param string $function The name of the PHP function to use as
+ * a preprocessor, this function must take a single parameter and return a
+ * formatted version of this parameter
+ */
+ function Image_Graph_DataPreprocessor_Function($function)
+ {
+ parent::Image_Graph_DataPreprocessor();
+ $this->_dataFunction = $function;
+ }
+
+ /**
+ * Process the value
+ *
+ * @param var $value The value to process/format
+ * @return string The processed value
+ * @access private
+ */
+ function _process($value)
+ {
+ $function = $this->_dataFunction;
+ return call_user_func($function, $value);
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/DataPreprocessor/NumberText.php b/config/dspam/pear/Image/Graph/DataPreprocessor/NumberText.php
new file mode 100644
index 00000000..a7d6874e
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/DataPreprocessor/NumberText.php
@@ -0,0 +1,89 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage DataPreprocessor
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/DataPreprocessor.php
+ */
+require_once 'Image/Graph/DataPreprocessor.php';
+
+/**
+ * Formatting a number as its written in languages supported by Numbers_Words.
+ *
+ * Used to display values as text, i.e. 123 is displayed as one hundred and twenty three.
+ * Requires Numbers_Words
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage DataPreprocessor
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_DataPreprocessor_NumberText extends Image_Graph_DataPreprocessor
+{
+
+ /**
+ * The language identifier
+ * @var string
+ * @access private
+ */
+ var $_language;
+
+ /**
+ * Image_Graph_NumberText [Constructor].
+ *
+ * Supported languages see {@link http://pear.php.net/package/Numbers_Words Numbers_Words}
+ *
+ * @param string $langugage The language identifier for the language.
+ */
+ function Image_Graph_DataPreprocessor_NumberText($language = 'en_US')
+ {
+ parent::Image_Graph_DataPreprocessor();
+ $this->_language = $language;
+ require_once 'Numbers/Words.php';
+ }
+
+ /**
+ * Process the value
+ *
+ * @param var $value The value to process/format
+ * @return string The processed value
+ * @access private
+ */
+ function _process($value)
+ {
+ return Numbers_Words::toWords($value, $this->_language);
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/DataPreprocessor/RomanNumerals.php b/config/dspam/pear/Image/Graph/DataPreprocessor/RomanNumerals.php
new file mode 100644
index 00000000..0bfcdb62
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/DataPreprocessor/RomanNumerals.php
@@ -0,0 +1,79 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage DataPreprocessor
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/DataPreprocessor.php
+ */
+require_once 'Image/Graph/DataPreprocessor.php';
+
+/**
+ * Formatting a value as a roman numerals.
+ *
+ * Values are formatted as roman numeral, i.e. 1 = I, 2 = II, 9 = IX, 2004 = MMIV.
+ * Requires Numbers_Roman
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage DataPreprocessor
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_DataPreprocessor_RomanNumerals extends Image_Graph_DataPreprocessor
+{
+
+ /**
+ * Create a RomanNumerals preprocessor
+ *
+ * See {@link http://pear.php.net/package/Numbers_Roman Numbers_Roman}
+ */
+ function Image_Graph_DataPreprocessor_RomanNumerals()
+ {
+ parent::Image_Graph_DataPreprocessor();
+ include_once 'Numbers/Roman.php';
+ }
+
+ /**
+ * Process the value
+ *
+ * @param var $value The value to process/format
+ * @return string The processed value
+ * @access private
+ */
+ function _process($value)
+ {
+ return Numbers_Roman::toNumeral($value);
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/DataPreprocessor/Sequential.php b/config/dspam/pear/Image/Graph/DataPreprocessor/Sequential.php
new file mode 100644
index 00000000..248f0be9
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/DataPreprocessor/Sequential.php
@@ -0,0 +1,67 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage DataPreprocessor
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/DataPreprocessor/Array.php
+ */
+require_once 'Image/Graph/DataPreprocessor/Array.php';
+
+/**
+ * Formatting values using a sequential data label array, ie. returning the
+ * 'next label' when asked for any label.
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage DataPreprocessor
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_DataPreprocessor_Sequential extends Image_Graph_DataPreprocessor_Array
+{
+
+ /**
+ * Process the value
+ *
+ * @param var $value The value to process/format
+ * @return string The processed value
+ * @access private
+ */
+ function _process($value)
+ {
+ list ($id, $value) = each($this->_dataArray);
+ return $value;
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/DataSelector.php b/config/dspam/pear/Image/Graph/DataSelector.php
new file mode 100644
index 00000000..0a81716c
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/DataSelector.php
@@ -0,0 +1,67 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage DataSelector
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Filter used for selecting which data to show as markers
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage DataSelector
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_DataSelector
+{
+
+ /**
+ * Image_Graph_DataSelector [Constructor]
+ */
+ function Image_Graph_DataSelector()
+ {
+ }
+
+ /**
+ * Check if a specified value should be 'selected', ie shown as a marker
+ *
+ * @param array $values The values to check
+ * @return bool True if the Values should cause a marker to be shown, false if not
+ * @access private
+ */
+ function _select($values)
+ {
+ return true;
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/DataSelector/EveryNthPoint.php b/config/dspam/pear/Image/Graph/DataSelector/EveryNthPoint.php
new file mode 100644
index 00000000..62581222
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/DataSelector/EveryNthPoint.php
@@ -0,0 +1,97 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage DataSelector
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/DataSelector.php
+ */
+require_once 'Image/Graph/DataSelector.php';
+
+/**
+ * Filter out all points except every Nth point.
+ *
+ * Use this dataselector if you have a large number of datapoints, but only want to
+ * show markers for a small number of them, say every 10th.
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage DataSelector
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_DataSelector_EveryNthPoint extends Image_Graph_DataSelector
+{
+
+ /**
+ * The number of points checked
+ * @var int
+ * @access private
+ */
+ var $_pointNum = 0;
+
+ /**
+ * The number of points between every 'show', default: 10
+ * @var int
+ * @access private
+ */
+ var $_pointInterval = 10;
+
+ /**
+ * EvertNthPoint [Constructor]
+ *
+ * @param int $pointInterval The number of points between every 'show',
+ * default: 10
+ */
+ function Image_Graph_DataSelector_EveryNthpoint($pointInterval = 10)
+ {
+ parent::Image_Graph_DataSelector();
+ $this->_pointInterval = $pointInterval;
+ }
+
+ /**
+ * Check if a specified value should be 'selected', ie shown as a marker
+ *
+ * @param array $values The values to check
+ * @return bool True if the Values should cause a marker to be shown,
+ * false if not
+ * @access private
+ */
+ function _select($values)
+ {
+ $oldPointNum = $this->_pointNum;
+ $this->_pointNum++;
+ return (($oldPointNum % $this->_pointInterval) == 0);
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/DataSelector/NoZeros.php b/config/dspam/pear/Image/Graph/DataSelector/NoZeros.php
new file mode 100644
index 00000000..f32b918e
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/DataSelector/NoZeros.php
@@ -0,0 +1,68 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage DataSelector
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/DataSelector.php
+ */
+require_once 'Image/Graph/DataSelector.php';
+
+/**
+ * Filter out all zero's.
+ *
+ * Display all Y-values as markers, except those with Y = 0
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage DataSelector
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_DataSelector_NoZeros extends Image_Graph_DataSelector
+{
+
+ /**
+ * Check if a specified value should be 'selected', ie shown as a marker
+ *
+ * @param array $values The values to check
+ * @return bool True if the Values should cause a marker to be shown, false
+ * if not
+ * @access private
+ */
+ function _select($values)
+ {
+ return ($values['Y'] != 0);
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/DataSelector/Values.php b/config/dspam/pear/Image/Graph/DataSelector/Values.php
new file mode 100644
index 00000000..412e6ea9
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/DataSelector/Values.php
@@ -0,0 +1,90 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage DataSelector
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/DataSelector.php
+ */
+require_once 'Image/Graph/DataSelector.php';
+
+/**
+ * Filter out all but the specified values.
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage DataSelector
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_DataSelector_Values extends Image_Graph_DataSelector {
+
+ /**
+ * The array with values that should be included
+ * @var array
+ * @access private
+ */
+ var $_values;
+
+ /**
+ * ValueArray [Constructor]
+ *
+ * @param array $valueArray The array to use as filter (default empty)
+ */
+ function &Image_Graph_DataSelector_Values($values)
+ {
+ parent::Image_Graph_DataSelector();
+ $this->_values = $values;
+ }
+
+ /**
+ * Sets the array to use
+ */
+ function setValueArray($values)
+ {
+ $this->_values = $values;
+ }
+
+ /**
+ * Check if a specified value should be 'selected', ie shown as a marker
+ *
+ * @param array $values The values to check
+ * @return bool True if the Values should cause a marker to be shown, false
+ * if not
+ * @access private
+ */
+ function _select($values)
+ {
+ return ( in_array($values['Y'], $this->_values) );
+ }
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Dataset.php b/config/dspam/pear/Image/Graph/Dataset.php
new file mode 100644
index 00000000..4c349980
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Dataset.php
@@ -0,0 +1,483 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Dataset
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+
+/**
+ * Data set used to represent a data collection to plot in a chart
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Dataset
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ * @abstract
+ */
+class Image_Graph_Dataset
+{
+
+ /**
+ * The pointer of the data set
+ * @var int
+ * @access private
+ */
+ var $_posX = 0;
+
+ /**
+ * The minimum X value of the dataset
+ * @var int
+ * @access private
+ */
+ var $_minimumX = 0;
+
+ /**
+ * The maximum X value of the dataset
+ * @var int
+ * @access private
+ */
+ var $_maximumX = 0;
+
+ /**
+ * The minimum Y value of the dataset
+ * @var int
+ * @access private
+ */
+ var $_minimumY = 0;
+
+ /**
+ * The maximum Y value of the dataset
+ * @var int
+ * @access private
+ */
+ var $_maximumY = 0;
+
+ /**
+ * The number of points in the dataset
+ * @var int
+ * @access private
+ */
+ var $_count = 0;
+
+ /**
+ * The name of the dataset, used for legending
+ * @var string
+ * @access private
+ */
+ var $_name = '';
+
+ /**
+ * Image_Graph_Dataset [Constructor]
+ */
+ function Image_Graph_Dataset()
+ {
+ }
+
+ /**
+ * Sets the name of the data set, used for legending
+ *
+ * @param string $name The name of the dataset
+ */
+ function setName($name)
+ {
+ $this->_name = $name;
+ }
+
+ /**
+ * Add a point to the dataset
+ *
+ * $ID can contain either the ID of the point, i.e. 'DK', 123, 'George', etc. or it can contain
+ * values used for creation of the HTML image map. This is achieved using is an an associated array
+ * with the following values:
+ *
+ * 'url' The URL to create the link to
+ *
+ * 'alt' [optional] The alt text on the link
+ *
+ * 'target' [optional] The target of the link
+ *
+ * 'htmltags' [optional] An associated array with html tags (tag as key), fx. 'onMouseOver' => 'history.go(-1);', 'id' => 'thelink'
+ *
+ * @param int $x The X value to add
+ * @param int $y The Y value to add, can be omited
+ * @param var $ID The ID of the point
+ */
+ function addPoint($x, $y = false, $ID = false)
+ {
+ if ($y !== null) {
+ if (is_array($y)) {
+ $maxY = max($y);
+ $minY = min($y);
+ } else {
+ $maxY = $y;
+ $minY = $y;
+ }
+ }
+
+ if ($this->_count) {
+ $this->_minimumX = min($x, $this->_minimumX);
+ $this->_maximumX = max($x, $this->_maximumX);
+ if ($y !== null) {
+ $this->_minimumY = min($minY, $this->_minimumY);
+ $this->_maximumY = max($maxY, $this->_maximumY);
+ }
+ } else {
+ $this->_minimumX = $x;
+ $this->_maximumX = $x;
+ if ($y !== null) {
+ $this->_minimumY = $minY;
+ $this->_maximumY = $maxY;
+ }
+ }
+
+ $this->_count++;
+ }
+
+ /**
+ * The number of values in the dataset
+ *
+ * @return int The number of values in the dataset
+ */
+ function count()
+ {
+ return $this->_count;
+ }
+
+ /**
+ * Gets a X point from the dataset
+ *
+ * @param var $x The variable to return an X value from, fx in a vector
+ * function data set
+ * @return var The X value of the variable
+ * @access private
+ */
+ function _getPointX($x)
+ {
+ return $x;
+ }
+
+ /**
+ * Gets a Y point from the dataset
+ *
+ * @param var $x The variable to return an Y value from, fx in a vector
+ * function data set
+ * @return var The Y value of the variable
+ * @access private
+ */
+ function _getPointY($x)
+ {
+ return $x;
+ }
+
+ /**
+ * Gets a ID from the dataset
+ *
+ * @param var $x The variable to return an Y value from, fx in a vector
+ * function data set
+ * @return var The ID value of the variable
+ * @access private
+ */
+ function _getPointID($x)
+ {
+ return false;
+ }
+
+ /**
+ * Gets point data from the dataset
+ *
+ * @param var $x The variable to return an Y value from, fx in a vector
+ * function data set
+ * @return array The data for the point
+ * @access private
+ */
+ function _getPointData($x)
+ {
+ return false;
+ }
+
+ /**
+ * The minimum X value
+ *
+ * @return var The minimum X value
+ */
+ function minimumX()
+ {
+ return $this->_minimumX;
+ }
+
+ /**
+ * The maximum X value
+ *
+ * @return var The maximum X value
+ */
+ function maximumX()
+ {
+ return $this->_maximumX;
+ }
+
+ /**
+ * The minimum Y value
+ *
+ * @return var The minimum Y value
+ */
+ function minimumY()
+ {
+ return $this->_minimumY;
+ }
+
+ /**
+ * The maximum Y value
+ *
+ * @return var The maximum Y value
+ */
+ function maximumY()
+ {
+ return $this->_maximumY;
+ }
+
+ /**
+ * The first point
+ *
+ * @return array The last point
+ */
+ function first()
+ {
+ return array('X' => $this->minimumX(), 'Y' => $this->minimumY());
+ }
+
+ /**
+ * The last point
+ *
+ * @return array The first point
+ */
+ function last()
+ {
+ return array('X' => $this->maximumX(), 'Y' => $this->maximumY());
+ }
+
+ /**
+ * The minimum X value
+ *
+ * @param var $value The minimum X value
+ * @access private
+ */
+ function _setMinimumX($value)
+ {
+ $this->_minimumX = $value;
+ }
+
+ /**
+ * The maximum X value
+ *
+ * @param var $value The maximum X value
+ * @access private
+ */
+ function _setMaximumX($value)
+ {
+ $this->_maximumX = $value;
+ }
+
+ /**
+ * The minimum Y value
+ *
+ * @param var $value The minimum X value
+ * @access private
+ */
+ function _setMinimumY($value)
+ {
+ $this->_minimumY = $value;
+ }
+
+ /**
+ * The maximum Y value
+ *
+ * @param var $value The maximum X value
+ * @access private
+ */
+ function _setMaximumY($value)
+ {
+ $this->_maximumY = $value;
+ }
+
+ /**
+ * The interval between 2 adjacent X values
+ *
+ * @return var The interval
+ * @access private
+ */
+ function _stepX()
+ {
+ return 1;
+ }
+
+ /**
+ * The interval between 2 adjacent Y values
+ *
+ * @return var The interval
+ * @access private
+ */
+ function _stepY()
+ {
+ return 1;
+ }
+
+ /**
+ * Reset the intertal dataset pointer
+ *
+ * @return var The first X value
+ * @access private
+ */
+ function _reset()
+ {
+ $this->_posX = $this->_minimumX;
+ return $this->_posX;
+ }
+
+ /**
+ * Get a point close to the internal pointer
+ *
+ * @param int Step Number of points next to the internal pointer, negative
+ * Step is towards lower X values, positive towards higher X values
+ * @return array The point
+ * @access private
+ */
+ function _nearby($step = 0)
+ {
+ $x = $this->_getPointX($this->_posX + $this->_stepX() * $step);
+ $y = $this->_getPointY($this->_posX + $this->_stepX() * $step);
+ $ID = $this->_getPointID($this->_posX + $this->_stepX() * $step);
+ $data = $this->_getPointData($this->_posX + $this->_stepX() * $step);
+ if (($x === false) || ($y === false)) {
+ return false;
+ } else {
+ return array ('X' => $x, 'Y' => $y, 'ID' => $ID, 'data' => $data);
+ }
+ }
+
+ /**
+ * Get the next point the internal pointer refers to and advance the pointer
+ *
+ * @return array The next point
+ * @access private
+ */
+ function _next()
+ {
+ if ($this->_posX > $this->_maximumX) {
+ return false;
+ }
+
+ $x = $this->_getPointX($this->_posX);
+ $y = $this->_getPointY($this->_posX);
+ $ID = $this->_getPointID($this->_posX);
+ $data = $this->_getPointData($this->_posX);
+ $this->_posX += $this->_stepX();
+
+ return array ('X' => $x, 'Y' => $y, 'ID' => $ID, 'data' => $data);
+ }
+
+ /**
+ * Get the average of the dataset's Y points
+ *
+ * @return var The Y-average across the dataset
+ * @access private
+ */
+ function _averageY()
+ {
+ $posX = $this->_minimumX;
+ $count = 0;
+ $total = 0;
+ while ($posX < $this->_maximumX) {
+ $count ++;
+ $total += $this->_getPointY($posX);
+ $posX += $this->_stepX();
+ }
+
+ if ($count != 0) {
+ return $total / $count;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Get the median of the array passed Y points
+ *
+ * @param array $data The data-array to get the median from
+ * @param int $quartile The quartile to return the median from
+ * @return var The Y-median across the dataset from the specified quartile
+ * @access private
+ */
+ function _median($data, $quartile = 'second')
+ {
+ sort($data);
+ $point = (count($data) - 1) / 2;
+
+ if ($quartile == 'first') {
+ $lowPoint = 0;
+ $highPoint = floor($point);
+ } elseif ($quartile == 'third') {
+ $lowPoint = round($point);
+ $highPoint = count($data) - 1;
+ } else {
+ $lowPoint = 0;
+ $highPoint = count($data) - 1;
+ }
+
+ $point = ($lowPoint + $highPoint) / 2;
+
+ if (floor($point) != $point) {
+ $point = floor($point);
+ return ($data[$point] + $data[($point + 1)]) / 2;
+ } else {
+ return $data[$point];
+ }
+ }
+
+ /**
+ * Get the median of the datasets Y points
+ *
+ * @param int $quartile The quartile to return the median from
+ * @return var The Y-median across the dataset from the specified quartile
+ * @access private
+ */
+ function _medianY($quartile = 'second')
+ {
+ $pointsY = array();
+ $posX = $this->_minimumX;
+ while ($posX <= $this->_maximumX) {
+ $pointsY[] = $this->_getPointY($posX);
+ $posX += $this->_stepX();
+ }
+ return $this->_median($pointsY, $quartile);
+ }
+
+}
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Dataset/Function.php b/config/dspam/pear/Image/Graph/Dataset/Function.php
new file mode 100644
index 00000000..08174b1d
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Dataset/Function.php
@@ -0,0 +1,147 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Dataset
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Dataset.php
+ */
+require_once 'Image/Graph/Dataset.php';
+
+/**
+ * Function data set, points are generated by calling an external function.
+ *
+ * The function must be a single variable function and return a the result,
+ * builtin functions that are fx sin() or cos(). User defined function can be
+ * used if they are such, i.e: function myFunction($variable)
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Dataset
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Dataset_Function extends Image_Graph_Dataset
+{
+
+ /**
+ * The name of the function
+ * @var string
+ * @access private
+ */
+ var $_dataFunction;
+
+ /**
+ * Image_Graph_FunctionDataset [Constructor]
+ *
+ * @param double $minimumX The minimum X value
+ * @param double $maximumX The maximum X value
+ * @param string $function The name of the function, if must be a single
+ * parameter function like fx sin(x) or cos(x)
+ * @param int $points The number of points to create
+ */
+ function Image_Graph_Dataset_Function($minimumX, $maximumX, $function, $points)
+ {
+ parent::Image_Graph_Dataset();
+ $this->_minimumX = $minimumX;
+ $this->_maximumX = $maximumX;
+ $this->_dataFunction = $function;
+ $this->_count = $points;
+ $this->_calculateMaxima();
+ }
+
+ /**
+ * Add a point to the dataset.
+ *
+ * You can't add points to a function dataset
+ *
+ * @param int $x The X value to add
+ * @param int $y The Y value to add, can be omited
+ * @param var $ID The ID of the point
+ */
+ function addPoint($x, $y = false, $ID = false)
+ {
+ }
+
+ /**
+ * Gets a Y point from the dataset
+ *
+ * @param var $x The variable to apply the function to
+ * @return var The function applied to the X value
+ * @access private
+ */
+ function _getPointY($x)
+ {
+ $function = $this->_dataFunction;
+ return $function ($x);
+ }
+
+ /**
+ * The number of values in the dataset
+ *
+ * @return int The number of values in the dataset
+ * @access private
+ */
+ function _count()
+ {
+ return $this->_count;
+ }
+
+ /**
+ * The interval between 2 adjacent Y values
+ *
+ * @return var The interval
+ * @access private
+ */
+ function _stepX()
+ {
+ return ($this->_maximumX - $this->_minimumX) / $this->_count();
+ }
+
+ /**
+ * Calculates the Y extrema of the function
+ *
+ * @access private
+ */
+ function _calculateMaxima()
+ {
+ $x = $this->_minimumX;
+ while ($x <= $this->_maximumX) {
+ $y = $this->_getPointY($x);
+ $this->_minimumY = min($y, $this->_minimumY);
+ $this->_maximumY = max($y, $this->_maximumY);
+ $x += $this->_stepX();
+ }
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Dataset/Random.php b/config/dspam/pear/Image/Graph/Dataset/Random.php
new file mode 100644
index 00000000..0b2d7c68
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Dataset/Random.php
@@ -0,0 +1,77 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Dataset
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Dataset/Trivial.php
+ */
+require_once 'Image/Graph/Dataset/Trivial.php';
+
+/**
+ * Random data set, points are generated by random.
+ *
+ * This dataset is mostly (if not solely) used for demo-purposes.
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Dataset
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Dataset_Random extends Image_Graph_Dataset_Trivial
+{
+
+ /**
+ * RandomDataset [Constructor]
+ *
+ * @param int $count The number of points to create
+ * @param double $minimum The minimum value the random set can be
+ * @param double $maximum The maximum value the random set can be
+ * @param bool $includeZero Whether 0 should be included or not as an X
+ * value, may be omitted, default: false</false>
+ */
+ function Image_Graph_Dataset_Random($count, $minimum, $maximum, $includeZero = false)
+ {
+ parent::Image_Graph_Dataset_Trivial();
+ $i = 0;
+ while ($i < $count) {
+ $this->addPoint(
+ $ixc = ($includeZero ? $i : $i +1),
+ rand($minimum, $maximum)
+ );
+ $i ++;
+ }
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Dataset/Sequential.php b/config/dspam/pear/Image/Graph/Dataset/Sequential.php
new file mode 100644
index 00000000..2605c409
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Dataset/Sequential.php
@@ -0,0 +1,114 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Dataset
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Dataset/Trivial.php
+ */
+require_once 'Image/Graph/Dataset/Trivial.php';
+
+/**
+ * Sequential data set, simply add points (y) 1 by 1.
+ *
+ * This is a single point (1D) dataset, all points are of the type (0, y1), (1,
+ * y2), (2, y3)... Where the X-value is implicitly incremented. This is useful
+ * for example for barcharts, where you could fx. use an {@link
+ * Image_Graph_Dataset_Array} datapreprocessor to make sence of the x-values.
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Dataset
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Dataset_Sequential extends Image_Graph_Dataset_Trivial
+{
+
+ /**
+ * Image_Graph_SequentialDataset [Constructor]
+ */
+ function Image_Graph_Dataset_Sequential($dataArray = false)
+ {
+ parent::Image_Graph_Dataset_Trivial();
+ if (is_array($dataArray)) {
+ reset($dataArray);
+ foreach ($dataArray as $value) {
+ $this->addPoint($value);
+ }
+ }
+ }
+
+ /**
+ * Add a point to the dataset
+ *
+ * @param int $y The Y value to add, can be omited
+ * @param var $ID The ID of the point
+ */
+ function addPoint($y, $ID = false)
+ {
+ parent::addPoint($this->count(), $y);
+ }
+
+ /**
+ * Gets a X point from the dataset
+ *
+ * @param var $x The variable to return an X value from, fx in a
+ * vector function data set
+ * @return var The X value of the variable
+ * @access private
+ */
+ function _getPointX($x)
+ {
+ return ((int) $x);
+ }
+
+ /**
+ * The minimum X value
+ * @return var The minimum X value
+ */
+ function minimumX()
+ {
+ return 0;
+ }
+
+ /**
+ * The maximum X value
+ * @return var The maximum X value
+ */
+ function maximumX()
+ {
+ return $this->count();
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Dataset/Trivial.php b/config/dspam/pear/Image/Graph/Dataset/Trivial.php
new file mode 100644
index 00000000..84af1c4b
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Dataset/Trivial.php
@@ -0,0 +1,260 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Dataset
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Dataset.php
+ */
+require_once 'Image/Graph/Dataset.php';
+
+/**
+ * Trivial data set, simply add points (x, y) 1 by 1
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Dataset
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Dataset_Trivial extends Image_Graph_Dataset
+{
+
+ /**
+ * Data storage
+ * @var array
+ * @access private
+ */
+ var $_data;
+
+ /**
+ * Image_Graph_Dataset_Trivial [Constructor]
+ *
+ * Pass an associated array ($data[$x] = $y) to the constructor for easy
+ * data addition. Alternatively (if multiple entries with same x value is
+ * required) pass an array with (x, y) values: $data[$id] = array('x' => $x,
+ * 'y' => $y);
+ *
+ * NB! If passing the 1st type array at this point, the x-values will also
+ * be used for ID tags, i.e. when using {@link Image_Graph_Fill_Array}. In
+ * the 2nd type the key/index of the "outermost" array will be the id tag
+ * (i.e. $id in the example)
+ *
+ * @param array $dataArray An associated array with values to the dataset
+ */
+ function Image_Graph_Dataset_Trivial($dataArray = false)
+ {
+ parent::Image_Graph_Dataset();
+ $this->_data = array ();
+ if (is_array($dataArray)) {
+ reset($dataArray);
+ $keys = array_keys($dataArray);
+ foreach ($keys as $x) {
+ $y =& $dataArray[$x];
+ if ((is_array($y)) && (isset($y['x'])) && (isset($y['y']))) {
+ $this->addPoint($y['x'], $y['y'], (isset($y['id']) ? $y['id'] : $x));
+ } else {
+ $this->addPoint($x, $y, $x);
+ }
+ }
+ }
+ }
+
+ /**
+ * Add a point to the dataset
+ *
+ * $ID can contain either the ID of the point, i.e. 'DK', 123, 'George', etc. or it can contain
+ * values used for creation of the HTML image map. This is achieved using is an an associated array
+ * with the following values:
+ *
+ * 'url' The URL to create the link to
+ *
+ * 'alt' [optional] The alt text on the link
+ *
+ * 'target' [optional] The target of the link
+ *
+ * 'htmltags' [optional] An associated array with html tags (tag as key), fx. 'onMouseOver' => 'history.go(-1);', 'id' => 'thelink'
+ *
+ * @param int $x The X value to add
+ * @param int $y The Y value to add, can be omited
+ * @param var $ID The ID of the point
+ */
+ function addPoint($x, $y = false, $ID = false)
+ {
+ parent::addPoint($x, $y, $ID);
+
+ if (is_array($ID)) {
+ $data = $ID;
+ $ID = (isset($data['id']) ? $data['id'] : false);
+ } else {
+ $data = false;
+ }
+
+ $this->_data[] = array ('X' => $x, 'Y' => $y, 'ID' => $ID, 'data' => $data);
+ if (!is_numeric($x)) {
+ $this->_maximumX = count($this->_data);
+ }
+ }
+
+ /**
+ * The first point
+ *
+ * @return array The last point
+ */
+ function first()
+ {
+ reset($this->_data);
+ return current($this->_data);
+ }
+
+ /**
+ * The last point
+ *
+ * @return array The first point
+ */
+ function last()
+ {
+ return end($this->_data);
+ }
+
+ /**
+ * Gets a X point from the dataset
+ *
+ * @param var $x The variable to return an X value from, fx in a
+ * vector function data set
+ * @return var The X value of the variable
+ * @access private
+ */
+ function _getPointX($x)
+ {
+ if (isset($this->_data[$x])) {
+ return $this->_data[$x]['X'];
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Gets a Y point from the dataset
+ *
+ * @param var $x The variable to return an Y value from, fx in a
+ * vector function data set
+ * @return var The Y value of the variable
+ * @access private
+ */
+ function _getPointY($x)
+ {
+ if (isset($this->_data[$x])) {
+ return $this->_data[$x]['Y'];
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Gets a ID from the dataset
+ *
+ * @param var $x The variable to return an Y value from, fx in a
+ * vector function data set
+ * @return var The ID value of the variable
+ * @access private
+ */
+ function _getPointID($x)
+ {
+ if (isset($this->_data[$x])) {
+ return $this->_data[$x]['ID'];
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Gets point data from the dataset
+ *
+ * @param var $x The variable to return an Y value from, fx in a vector
+ * function data set
+ * @return array The data for the point
+ * @access private
+ */
+ function _getPointData($x)
+ {
+ if (isset($this->_data[$x])) {
+ return $this->_data[$x]['data'];
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * The number of values in the dataset
+ *
+ * @return int The number of values in the dataset
+ */
+ function count()
+ {
+ return count($this->_data);
+ }
+
+ /**
+ * Reset the intertal dataset pointer
+ *
+ * @return var The first X value
+ * @access private
+ */
+ function _reset()
+ {
+ $this->_posX = 0;
+ return $this->_posX;
+ }
+
+ /**
+ * Get the next point the internal pointer refers to and advance the pointer
+ *
+ * @return array The next point
+ * @access private
+ */
+ function _next()
+ {
+ if ($this->_posX >= $this->count()) {
+ return false;
+ }
+ $x = $this->_getPointX($this->_posX);
+ $y = $this->_getPointY($this->_posX);
+ $ID = $this->_getPointID($this->_posX);
+ $data = $this->_getPointData($this->_posX);
+ $this->_posX += $this->_stepX();
+
+ return array('X' => $x, 'Y' => $y, 'ID' => $ID, 'data' => $data);
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Dataset/VectorFunction.php b/config/dspam/pear/Image/Graph/Dataset/VectorFunction.php
new file mode 100644
index 00000000..4250bbc0
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Dataset/VectorFunction.php
@@ -0,0 +1,185 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Dataset
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Dataset.php
+ */
+require_once 'Image/Graph/Dataset.php';
+
+/**
+ * Vector Function data set.
+ *
+ * Points are generated by calling 2 external functions, fx. x = sin(t) and y =
+ * cos(t)
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Dataset
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Dataset_VectorFunction extends Image_Graph_Dataset
+{
+
+ /**
+ * The name of the X function
+ * @var string
+ * @access private
+ */
+ var $_functionX;
+
+ /**
+ * The name of the Y function
+ * @var string
+ * @access private
+ */
+ var $_functionY;
+
+ /**
+ * The minimum of the vector function variable
+ * @var double
+ * @access private
+ */
+ var $_minimumT;
+
+ /**
+ * The maximum of the vector function variable
+ * @var double
+ * @access private
+ */
+ var $_maximumT;
+
+ /**
+ * Image_Graph_VectorFunctionDataset [Constructor]
+ *
+ * @param double $minimumT The minimum value of the vector function variable
+ * @param double $maximumT The maximum value of the vector function variable
+ * @param string $functionX The name of the X function, if must be a single
+ * parameter function like fx sin(x) or cos(x)
+ * @param string $functionY The name of the Y function, if must be a single
+ * parameter function like fx sin(x) or cos(x)
+ * @param int $points The number of points to create
+ */
+ function Image_Graph_Dataset_VectorFunction($minimumT, $maximumT, $functionX, $functionY, $points)
+ {
+ parent::Image_Graph_Dataset();
+ $this->_minimumT = $minimumT;
+ $this->_maximumT = $maximumT;
+ $this->_functionX = $functionX;
+ $this->_functionY = $functionY;
+ $this->_count = $points;
+ $this->_calculateMaxima();
+ }
+
+ /**
+ * Add a point to the dataset
+ *
+ * @param int $x The X value to add
+ * @param int $y The Y value to add, can be omited
+ * @param var $ID The ID of the point
+ */
+ function addPoint($x, $y = false, $ID = false)
+ {
+ }
+
+ /**
+ * Gets a X point from the dataset
+ *
+ * @param var $x The variable to apply the X function to
+ * @return var The X function applied to the X value
+ * @access private
+ */
+ function _getPointX($x)
+ {
+ $functionX = $this->_functionX;
+ return $functionX ($x);
+ }
+
+ /**
+ * Gets a Y point from the dataset
+ *
+ * @param var $x The variable to apply the Y function to
+ * @return var The Y function applied to the X value
+ * @access private
+ */
+ function _getPointY($x)
+ {
+ $functionY = $this->_functionY;
+ return $functionY ($x);
+ }
+
+ /**
+ * Reset the intertal dataset pointer
+ *
+ * @return var The first T value
+ * @access private
+ */
+ function _reset()
+ {
+ $this->_posX = $this->_minimumT;
+ return $this->_posX;
+ }
+
+ /**
+ * The interval between 2 adjacent T values
+ *
+ * @return var The interval
+ * @access private
+ */
+ function _stepX()
+ {
+ return ($this->_maximumT - $this->_minimumT) / $this->count();
+ }
+
+ /**
+ * Calculates the X and Y extrema of the functions
+ *
+ * @access private
+ */
+ function _calculateMaxima()
+ {
+ $t = $this->_minimumT;
+ while ($t <= $this->_maximumT) {
+ $x = $this->_getPointX($t);
+ $y = $this->_getPointY($t);
+ $this->_minimumX = min($x, $this->_minimumX);
+ $this->_maximumX = max($x, $this->_maximumX);
+ $this->_minimumY = min($y, $this->_minimumY);
+ $this->_maximumY = max($y, $this->_maximumY);
+ $t += $this->_stepX();
+ }
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Element.php b/config/dspam/pear/Image/Graph/Element.php
new file mode 100644
index 00000000..7c352ee5
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Element.php
@@ -0,0 +1,763 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - Main class for the graph creation.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Common.php
+ */
+require_once 'Image/Graph/Common.php';
+
+/**
+ * Representation of a element.
+ *
+ * The Image_Graph_Element can be drawn on the canvas, ie it has coordinates,
+ * {@link Image_Graph_Line}, {@link Image_Graph_Fill}, border and background -
+ * although not all of these may apply to all children.
+ *
+ * @category Images
+ * @package Image_Graph
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ * @abstract
+ */
+class Image_Graph_Element extends Image_Graph_Common
+{
+
+ /**
+ * The leftmost pixel of the element on the canvas
+ * @var int
+ * @access private
+ */
+ var $_left = 0;
+
+ /**
+ * The topmost pixel of the element on the canvas
+ * @var int
+ * @access private
+ */
+ var $_top = 0;
+
+ /**
+ * The rightmost pixel of the element on the canvas
+ * @var int
+ * @access private
+ */
+ var $_right = 0;
+
+ /**
+ * The bottommost pixel of the element on the canvas
+ * @var int
+ * @access private
+ */
+ var $_bottom = 0;
+
+ /**
+ * Background of the element. Default: None
+ * @var FillStyle
+ * @access private
+ */
+ var $_background = null;
+
+ /**
+ * Borderstyle of the element. Default: None
+ * @var LineStyle
+ * @access private
+ */
+ var $_borderStyle = null;
+
+ /**
+ * Line style of the element. Default: None
+ * @var LineStyle
+ * @access private
+ */
+ var $_lineStyle = 'black';
+
+ /**
+ * Fill style of the element. Default: None
+ * @var FillStyle
+ * @access private
+ */
+ var $_fillStyle = 'white';
+
+ /**
+ * Font of the element. Default: Standard font - FONT
+ * @var Font
+ * @access private
+ * @see $IMAGE_GRAPH_FONT
+ */
+ var $_font = null;
+
+ /**
+ * Font options
+ * @var array
+ * @access private
+ */
+ var $_fontOptions = array();
+
+ /**
+ * Default font options
+ *
+ * This option is included for performance reasons. The value is calculated
+ * before output and reused in default cases to avoid unnecessary recursive
+ * calls.
+ *
+ * @var array
+ * @access private
+ */
+ var $_defaultFontOptions = false;
+
+ /**
+ * Shadows options of the element
+ * @var mixed
+ * @access private
+ */
+ var $_shadow = false;
+
+ /**
+ * The padding displayed on the element
+ * @var int
+ * @access private
+ */
+ var $_padding = array('left' => 0, 'top' => 0, 'right' => 0, 'bottom' => 0);
+
+ /**
+ * Sets the background fill style of the element
+ *
+ * @param Image_Graph_Fill $background The background
+ * @see Image_Graph_Fill
+ */
+ function setBackground(& $background)
+ {
+ if (!is_a($background, 'Image_Graph_Fill')) {
+ $this->_error(
+ 'Could not set background for ' . get_class($this) . ': ' .
+ get_class($background), array('background' => &$background)
+ );
+ } else {
+ $this->_background =& $background;
+ $this->add($background);
+ }
+ }
+
+ /**
+ * Shows shadow on the element
+ */
+ function showShadow($color = 'black@0.2', $size = 5)
+ {
+ $this->_shadow = array(
+ 'color' => $color,
+ 'size' => $size
+ );
+ }
+
+ /**
+ * Sets the background color of the element.
+ *
+ * See colors.txt in the docs/ folder for a list of available named colors.
+ *
+ * @param mixed $color The color
+ */
+ function setBackgroundColor($color)
+ {
+ $this->_background = $color;
+ }
+
+ /**
+ * Gets the background fill style of the element
+ *
+ * @return int A GD fillstyle representing the background style
+ * @see Image_Graph_Fill
+ * @access private
+ */
+ function _getBackground()
+ {
+ if (is_object($this->_background)) {
+ $this->_canvas->setFill($this->_background->_getFillStyle());
+ } elseif ($this->_background != null) {
+ $this->_canvas->setFill($this->_background);
+ } else {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Sets the border line style of the element
+ *
+ * @param Image_Graph_Line $borderStyle The line style of the border
+ * @see Image_Graph_Line
+ */
+ function setBorderStyle(& $borderStyle)
+ {
+ if (!is_a($borderStyle, 'Image_Graph_Line')) {
+ $this->_error(
+ 'Could not set border style for ' . get_class($this) . ': ' .
+ get_class($borderStyle), array('borderstyle' => &$borderStyle)
+ );
+ } else {
+ $this->_borderStyle =& $borderStyle;
+ $this->add($borderStyle);
+ }
+ }
+
+ /**
+ * Sets the border color of the element.
+ *
+ * See colors.txt in the docs/ folder for a list of available named colors.
+ * @param mixed $color The color
+ */
+ function setBorderColor($color)
+ {
+ $this->_borderStyle = $color;
+ }
+
+ /**
+ * Gets the border line style of the element
+ *
+ * @return int A GD linestyle representing the borders line style
+ * @see Image_Graph_Line
+ * @access private
+ */
+ function _getBorderStyle()
+ {
+ if (is_object($this->_borderStyle)) {
+ $result = $this->_borderStyle->_getLineStyle();
+ $this->_canvas->setLineThickness($result['thickness']);
+ $this->_canvas->setLineColor($result['color']);
+ } elseif ($this->_borderStyle != null) {
+ $this->_canvas->setLineThickness(1);
+ $this->_canvas->setLineColor($this->_borderStyle);
+ } else {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Sets the line style of the element
+ *
+ * @param Image_Graph_Line $lineStyle The line style of the element
+ * @see Image_Graph_Line
+ */
+ function setLineStyle(& $lineStyle)
+ {
+ if (!is_object($lineStyle)) {
+ $this->_error(
+ 'Could not set line style for ' . get_class($this) . ': ' .
+ get_class($lineStyle), array('linestyle' => &$lineStyle)
+ );
+ } else {
+ $this->_lineStyle =& $lineStyle;
+ $this->add($lineStyle);
+ }
+ }
+
+ /**
+ * Sets the line color of the element.
+ *
+ * See colors.txt in the docs/ folder for a list of available named colors.
+ *
+ * @param mixed $color The color
+ */
+ function setLineColor($color)
+ {
+ $this->_lineStyle = $color;
+ }
+
+ /**
+ * Gets the line style of the element
+ *
+ * @return int A GD linestyle representing the line style
+ * @see Image_Graph_Line
+ * @access private
+ */
+ function _getLineStyle($ID = false)
+ {
+ if (is_object($this->_lineStyle)) {
+ $result = $this->_lineStyle->_getLineStyle($ID);
+ if (is_array($result)) {
+ $this->_canvas->setLineThickness($result['thickness']);
+ $this->_canvas->setLineColor($result['color']);
+ } else {
+ $this->_canvas->setLineThickness(1);
+ $this->_canvas->setLineColor($result);
+ }
+ } elseif ($this->_lineStyle != null) {
+ $this->_canvas->setLineThickness(1);
+ $this->_canvas->setLineColor($this->_lineStyle);
+ } else {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Sets the fill style of the element
+ *
+ * @param Image_Graph_Fill $fillStyle The fill style of the element
+ * @see Image_Graph_Fill
+ */
+ function setFillStyle(& $fillStyle)
+ {
+ if (!is_a($fillStyle, 'Image_Graph_Fill')) {
+ $this->_error(
+ 'Could not set fill style for ' . get_class($this) . ': ' .
+ get_class($fillStyle), array('fillstyle' => &$fillStyle)
+ );
+ } else {
+ $this->_fillStyle =& $fillStyle;
+ $this->add($fillStyle);
+ }
+ }
+
+ /**
+ * Sets the fill color of the element.
+ *
+ * See colors.txt in the docs/ folder for a list of available named colors.
+ *
+ * @param mixed $color The color
+ */
+ function setFillColor($color)
+ {
+ $this->_fillStyle = $color;
+ }
+
+
+ /**
+ * Gets the fill style of the element
+ *
+ * @return int A GD filestyle representing the fill style
+ * @see Image_Graph_Fill
+ * @access private
+ */
+ function _getFillStyle($ID = false)
+ {
+ if (is_object($this->_fillStyle)) {
+ $this->_canvas->setFill($this->_fillStyle->_getFillStyle($ID));
+ } elseif ($this->_fillStyle != null) {
+ $this->_canvas->setFill($this->_fillStyle);
+ } else {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Gets the font of the element.
+ *
+ * If not font has been set, the parent font is propagated through it's
+ * children.
+ *
+ * @return array An associated array used for canvas
+ * @access private
+ */
+ function _getFont($options = false)
+ {
+ if (($options === false) && ($this->_defaultFontOptions !== false)) {
+ return $this->_defaultFontOptions;
+ }
+
+ if ($options === false) {
+ $saveDefault = true;
+ } else {
+ $saveDefault = false;
+ }
+
+ if ($options === false) {
+ $options = $this->_fontOptions;
+ } else {
+ $options = array_merge($this->_fontOptions, $options);
+ }
+
+ if ($this->_font == null) {
+ $result = $this->_parent->_getFont($options);
+ } else {
+ $result = $this->_font->_getFont($options);
+ }
+
+ if ((isset($result['size'])) && (isset($result['size_rel']))) {
+ $result['size'] += $result['size_rel'];
+ unset($result['size_rel']);
+ }
+
+ if ($saveDefault) {
+ $this->_defaultFontOptions = $result;
+ }
+
+ return $result;
+ }
+
+ /**
+ * Sets the font of the element
+ *
+ * @param Image_Graph_Font $font The font of the element
+ * @see Image_Graph_Font
+ */
+ function setFont(& $font)
+ {
+ if (!is_a($font, 'Image_Graph_Font')) {
+ $this->_error('Invalid font set on ' . get_class($this));
+ } else {
+ $this->_font =& $font;
+ $this->add($font);
+ }
+ }
+
+ /**
+ * Sets the font size
+ *
+ * @param int $size The size of the font
+ */
+ function setFontSize($size)
+ {
+ $this->_fontOptions['size'] = $size;
+ }
+
+ /**
+ * Sets the font angle
+ *
+ * @param int $angle The angle of the font
+ */
+ function setFontAngle($angle)
+ {
+ if ($angle == 'vertical') {
+ $this->_fontOptions['vertical'] = true;
+ $this->_fontOptions['angle'] = 90;
+ } else {
+ $this->_fontOptions['angle'] = $angle;
+ }
+ }
+
+ /**
+ * Sets the font color
+ *
+ * @param mixed $color The color of the font
+ */
+ function setFontColor($color)
+ {
+ $this->_fontOptions['color'] = $color;
+ }
+
+ /**
+ * Clip the canvas to the coordinates of the element
+ *
+ * @param $enable bool Whether clipping should be enabled or disabled
+ * @access protected
+ */
+ function _clip($enable)
+ {
+ $this->_canvas->setClipping(
+ ($enable ?
+ array(
+ 'x0' => min($this->_left, $this->_right),
+ 'y0' => min($this->_top, $this->_bottom),
+ 'x1' => max($this->_left, $this->_right),
+ 'y1' => max($this->_top, $this->_bottom)
+ )
+ : false
+ )
+ );
+ }
+
+ /**
+ * Sets the coordinates of the element
+ *
+ * @param int $left The leftmost pixel of the element on the canvas
+ * @param int $top The topmost pixel of the element on the canvas
+ * @param int $right The rightmost pixel of the element on the canvas
+ * @param int $bottom The bottommost pixel of the element on the canvas
+ * @access private
+ */
+ function _setCoords($left, $top, $right, $bottom)
+ {
+ if ($left === false) {
+ $left = $this->_left;
+ }
+
+ if ($top === false) {
+ $top = $this->_top;
+ }
+
+ if ($right === false) {
+ $right = $this->_right;
+ }
+
+ if ($bottom === false) {
+ $bottom = $this->_bottom;
+ }
+
+ $this->_left = min($left, $right);
+ $this->_top = min($top, $bottom);
+ $this->_right = max($left, $right);
+ $this->_bottom = max($top, $bottom);
+ }
+
+ /**
+ * Moves the element
+ *
+ * @param int $deltaX Number of pixels to move the element to the right
+ * (negative values move to the left)
+ * @param int $deltaY Number of pixels to move the element downwards
+ * (negative values move upwards)
+ * @access private
+ */
+ function _move($deltaX, $deltaY)
+ {
+ $this->_left += $deltaX;
+ $this->_right += $deltaX;
+ $this->_top += $deltaY;
+ $this->_bottom += $deltaY;
+ }
+
+ /**
+ * Sets the width of the element relative to the left side
+ *
+ * @param int $width Number of pixels the element should be in width
+ * @access private
+ */
+ function _setWidth($width)
+ {
+ $this->_right = $this->_left + $width;
+ }
+
+ /**
+ * Sets the height of the element relative to the top
+ *
+ * @param int $width Number of pixels the element should be in height
+ * @access private
+ */
+ function _setHeight($height)
+ {
+ $this->_bottom = $this->_top + $height;
+ }
+
+ /**
+ * Sets padding of the element
+ *
+ * @param mixed $padding Number of pixels the element should be padded with
+ * or an array of paddings (left, top, right and bottom as index)
+ */
+ function setPadding($padding)
+ {
+ if (is_array($padding)) {
+ $this->_padding = array();
+ $this->_padding['left'] = (isset($padding['left']) ? $padding['left'] : 0);
+ $this->_padding['top'] = (isset($padding['top']) ? $padding['top'] : 0);
+ $this->_padding['right'] = (isset($padding['right']) ? $padding['right'] : 0);
+ $this->_padding['bottom'] = (isset($padding['bottom']) ? $padding['bottom'] : 0);
+ }
+ else {
+ $this->_padding = array(
+ 'left' => $padding,
+ 'top' => $padding,
+ 'right' => $padding,
+ 'bottom' => $padding
+ );
+ }
+ }
+
+ /**
+ * The width of the element on the canvas
+ *
+ * @return int Number of pixels representing the width of the element
+ */
+ function width()
+ {
+ return abs($this->_right - $this->_left) + 1;
+ }
+
+ /**
+ * The height of the element on the canvas
+ *
+ * @return int Number of pixels representing the height of the element
+ */
+ function height()
+ {
+ return abs($this->_bottom - $this->_top) + 1;
+ }
+
+ /**
+ * Left boundary of the background fill area
+ *
+ * @return int Leftmost position on the canvas
+ * @access private
+ */
+ function _fillLeft()
+ {
+ return $this->_left + $this->_padding['left'];
+ }
+
+ /**
+ * Top boundary of the background fill area
+ *
+ * @return int Topmost position on the canvas
+ * @access private
+ */
+ function _fillTop()
+ {
+ return $this->_top + $this->_padding['top'];
+ }
+
+ /**
+ * Right boundary of the background fill area
+ *
+ * @return int Rightmost position on the canvas
+ * @access private
+ */
+ function _fillRight()
+ {
+ return $this->_right - $this->_padding['right'];
+ }
+
+ /**
+ * Bottom boundary of the background fill area
+ *
+ * @return int Bottommost position on the canvas
+ * @access private
+ */
+ function _fillBottom()
+ {
+ return $this->_bottom - $this->_padding['bottom'];
+ }
+
+ /**
+ * Returns the filling width of the element on the canvas
+ *
+ * @return int Filling width
+ * @access private
+ */
+ function _fillWidth()
+ {
+ return $this->_fillRight() - $this->_fillLeft() + 1;
+ }
+
+ /**
+ * Returns the filling height of the element on the canvas
+ *
+ * @return int Filling height
+ * @access private
+ */
+ function _fillHeight()
+ {
+ return $this->_fillBottom() - $this->_fillTop() + 1;
+ }
+
+ /**
+ * Draws a shadow 'around' the element
+ *
+ * Not implemented yet.
+ *
+ * @access private
+ */
+ function _displayShadow()
+ {
+ if (is_array($this->_shadow)) {
+ $this->_canvas->startGroup(get_class($this) . '_shadow');
+ $this->_canvas->setFillColor($this->_shadow['color']);
+ $this->_canvas->addVertex(array('x' => $this->_right + 1, 'y' => $this->_top + $this->_shadow['size']));
+ $this->_canvas->addVertex(array('x' => $this->_right + $this->_shadow['size'], 'y' => $this->_top + $this->_shadow['size']));
+ $this->_canvas->addVertex(array('x' => $this->_right + $this->_shadow['size'], 'y' => $this->_bottom + $this->_shadow['size']));
+ $this->_canvas->addVertex(array('x' => $this->_left + $this->_shadow['size'], 'y' => $this->_bottom + $this->_shadow['size']));
+ $this->_canvas->addVertex(array('x' => $this->_left + $this->_shadow['size'], 'y' => $this->_bottom + 1));
+ $this->_canvas->addVertex(array('x' => $this->_right + 1, 'y' => $this->_bottom + 1));
+ $this->_canvas->polygon(array('connect' => true));
+ $this->_canvas->endGroup();
+ }
+ }
+
+ /**
+ * Writes text to the canvas.
+ *
+ * @param int $x The x position relative to alignment
+ * @param int $y The y position relative to alignment
+ * @param string $text The text
+ * @param int $alignmen The text alignment (both vertically and horizontally)
+ */
+ function write($x, $y, $text, $alignment = false, $font = false)
+ {
+ if (($font === false) && ($this->_defaultFontOptions !== false)) {
+ $font = $this->_defaultFontOptions;
+ } else {
+ $font = $this->_getFont($font);
+ }
+
+ if ($alignment === false) {
+ $alignment = IMAGE_GRAPH_ALIGN_LEFT + IMAGE_GRAPH_ALIGN_TOP;
+ }
+
+ $align = array();
+
+ if (($alignment & IMAGE_GRAPH_ALIGN_TOP) != 0) {
+ $align['vertical'] = 'top';
+ } else if (($alignment & IMAGE_GRAPH_ALIGN_BOTTOM) != 0) {
+ $align['vertical'] = 'bottom';
+ } else {
+ $align['vertical'] = 'center';
+ }
+
+ if (($alignment & IMAGE_GRAPH_ALIGN_LEFT) != 0) {
+ $align['horizontal'] = 'left';
+ } else if (($alignment & IMAGE_GRAPH_ALIGN_RIGHT) != 0) {
+ $align['horizontal'] = 'right';
+ } else {
+ $align['horizontal'] = 'center';
+ }
+
+ $this->_canvas->setFont($font);
+ $this->_canvas->addText(array('x' => $x, 'y' => $y, 'text' => $text, 'alignment' => $align));
+ }
+
+ /**
+ * Output the element to the canvas
+ *
+ * @return bool Was the output 'good' (true) or 'bad' (false).
+ * @see Image_Graph_Common
+ * @access private
+ */
+ function _done()
+ {
+ $background = $this->_getBackground();
+ $border = $this->_getBorderStyle();
+ if (($background) || ($border)) {
+ $this->_canvas->rectangle(array('x0' => $this->_left, 'y0' => $this->_top, 'x1' => $this->_right, 'y1' => $this->_bottom));
+ }
+
+ $result = parent::_done();
+
+ if ($this->_shadow !== false) {
+ $this->_displayShadow();
+ }
+
+ return $result;
+ }
+
+}
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Figure/Circle.php b/config/dspam/pear/Image/Graph/Figure/Circle.php
new file mode 100644
index 00000000..a3f1652e
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Figure/Circle.php
@@ -0,0 +1,64 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Figure
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Figure/Ellipse.php
+ */
+require_once 'Image/Graph/Figure/Ellipse.php';
+
+/**
+ * Circle to draw on the canvas
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Figure
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Figure_Circle extends Image_Graph_Figure_Ellipse
+{
+
+ /**
+ * Image_Graph_Circle [Constructor]
+ *
+ * @param int $x The center pixel of the circle on the canvas
+ * @param int $y The center pixel of the circle on the canvas
+ * @param int $radius The radius in pixels of the circle
+ */
+ function Image_Graph_Figure_Circle($x, $y, $radius)
+ {
+ parent::Image_Graph_Ellipse($x, $y, $radius, $radius);
+ }
+
+}
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Figure/Ellipse.php b/config/dspam/pear/Image/Graph/Figure/Ellipse.php
new file mode 100644
index 00000000..8e42f2b1
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Figure/Ellipse.php
@@ -0,0 +1,97 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Figure
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Element.php
+ */
+require_once 'Image/Graph/Element.php';
+
+/**
+ * Ellipse to draw on the canvas
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Figure
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Figure_Ellipse extends Image_Graph_Element
+{
+
+ /**
+ * Ellipse [Constructor]
+ *
+ * @param int $x The center pixel of the ellipse on the canvas
+ * @param int $y The center pixel of the ellipse on the canvas
+ * @param int $radiusX The width in pixels of the box on the canvas
+ * @param int $radiusY The height in pixels of the box on the canvas
+ */
+ function Image_Graph_Figure_Ellipse($x, $y, $radiusX, $radiusY)
+ {
+ parent::Image_Graph_Element();
+ $this->_setCoords($x - $radiusX, $y - $radiusY, $x + $radiusX, $y + $radiusY);
+ }
+
+ /**
+ * Output the ellipse
+ *
+ * @return bool Was the output 'good' (true) or 'bad' (false).
+ * @access private
+ */
+ function _done()
+ {
+ if (parent::_done() === false) {
+ return false;
+ }
+
+ $this->_canvas->startGroup(get_class($this));
+
+ $this->_getFillStyle();
+ $this->_getLineStyle();
+ $this->_canvas->ellipse(
+ array(
+ 'x' => ($this->_left + $this->_right) / 2,
+ 'y' => ($this->_top + $this->_bottom) / 2,
+ 'rx' => $this->width(),
+ 'ry' => $this->height()
+ )
+ );
+
+ $this->_canvas->endGroup();
+
+ return true;
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Figure/Polygon.php b/config/dspam/pear/Image/Graph/Figure/Polygon.php
new file mode 100644
index 00000000..5b78f635
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Figure/Polygon.php
@@ -0,0 +1,94 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Figure
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Element.php
+ */
+require_once 'Image/Graph/Element.php';
+
+/**
+ * Polygon to draw on the canvas
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Figure
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Figure_Polygon extends Image_Graph_Element
+{
+
+ /**
+ * Polygon vertices
+ *
+ * @var array
+ * @access private
+ */
+ var $_polygon = array ();
+
+ /**
+ * Add a vertex to the polygon
+ *
+ * @param int $x X-coordinate
+ * @param int $y Y-coordinate
+ */
+ function addVertex($x, $y)
+ {
+ $this->_canvas->addVertex(array('x' => $x, 'y' => $y));
+ }
+
+ /**
+ * Output the polygon
+ *
+ * @return bool Was the output 'good' (true) or 'bad' (false).
+ * @access private
+ */
+ function _done()
+ {
+ if (parent::_done() === false) {
+ return false;
+ }
+
+ $this->_canvas->startGroup(get_class($this));
+
+ $this->_getFillStyle();
+ $this->_getLineStyle();
+ $this->_canvas->polygon(array('connect' => true));
+
+ $this->_canvas->endGroup();
+ return true;
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Figure/Rectangle.php b/config/dspam/pear/Image/Graph/Figure/Rectangle.php
new file mode 100644
index 00000000..dbca58e0
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Figure/Rectangle.php
@@ -0,0 +1,96 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Figure
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Element.php
+ */
+require_once 'Image/Graph/Element.php';
+
+/**
+ * Rectangle to draw on the canvas
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Figure
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Figure_Rectangle extends Image_Graph_Element
+{
+
+ /**
+ * Rectangle [Construcor]
+ *
+ * @param int $x The leftmost pixel of the box on the canvas
+ * @param int $y The topmost pixel of the box on the canvas
+ * @param int $width The width in pixels of the box on the canvas
+ * @param int $height The height in pixels of the box on the canvas
+ */
+ function Image_Graph_Figure_Rectangle($x, $y, $width, $height)
+ {
+ parent::Image_Graph_Element();
+ $this->_setCoords($x, $y, $x + $width, $y + $height);
+ }
+
+ /**
+ * Output the box
+ *
+ * @return bool Was the output 'good' (true) or 'bad' (false).
+ * @access private
+ */
+ function _done()
+ {
+ if (parent::_done() === false) {
+ return false;
+ }
+
+ $this->_canvas->startGroup(get_class($this));
+
+ $this->_getFillStyle();
+ $this->_getLineStyle();
+ $this->_canvas->rectangle(
+ array(
+ 'x0' => $this->_left,
+ 'y0' => $this->_top,
+ 'x1' => $this->_right,
+ 'y1' => $this->_bottom
+ )
+ );
+
+ $this->_canvas->endGroup();
+
+ return true;
+ }
+
+}
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Fill.php b/config/dspam/pear/Image/Graph/Fill.php
new file mode 100644
index 00000000..f1cd36d7
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Fill.php
@@ -0,0 +1,63 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Fill
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Element.php
+ */
+require_once 'Image/Graph/Element.php';
+
+/**
+ * Style used for filling elements.
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Fill
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ * @abstract
+ */
+class Image_Graph_Fill extends Image_Graph_Common
+{
+
+ /**
+ * Resets the fillstyle
+ *
+ * @access private
+ */
+ function _reset()
+ {
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Fill/Array.php b/config/dspam/pear/Image/Graph/Fill/Array.php
new file mode 100644
index 00000000..8d0b2dfa
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Fill/Array.php
@@ -0,0 +1,137 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Fill
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Fill.php
+ */
+require_once 'Image/Graph/Fill.php';
+
+/**
+ * A sequential array of fillstyles.
+ *
+ * This is used for filling multiple objects within the same element with
+ * different styles. This is done by adding multiple fillstyles to a FillArrray
+ * structure. The fillarray will then when requested return the 'next' fillstyle
+ * in sequential order. It is possible to specify ID tags to each fillstyle,
+ * which is used to make sure some data uses a specific fillstyle (i.e. in a
+ * multiple-/stackedbarchart you name the {@link Image_Graph_Dataset}s and uses
+ * this name as ID tag when adding the dataset's associated fillstyle to the
+ * fillarray.
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Fill
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Fill_Array extends Image_Graph_Fill
+{
+
+ /**
+ * The fill array
+ * @var array
+ * @access private
+ */
+ var $_fillStyles = array ();
+
+ /**
+ * Resets the fillstyle
+ *
+ * @access private
+ */
+ function _reset()
+ {
+ reset($this->_fillStyles);
+ }
+
+ /**
+ * Add a fill style to the array
+ *
+ * @param Image_Graph_Fill $style The style to add
+ * @param string $id The id or name of the style
+ */
+ function &add(& $style, $id = '')
+ {
+ if ($id == '') {
+ $this->_fillStyles[] =& $style;
+ } else {
+ $this->_fillStyles[$id] =& $style;
+ }
+ reset($this->_fillStyles);
+ return $style;
+ }
+
+ /**
+ * Add a color to the array
+ *
+ * @param int $color The color
+ * @param string $id The id or name of the color
+ */
+ function addColor($color, $id = false)
+ {
+ if ($id !== false) {
+ $this->_fillStyles[$id] = $color;
+ } else {
+ $this->_fillStyles[] = $color;
+ }
+ reset($this->_fillStyles);
+ }
+
+ /**
+ * Return the fillstyle
+ *
+ * @return int A GD fillstyle
+ * @access private
+ */
+ function _getFillStyle($ID = false)
+ {
+ if (($ID === false) || (!isset($this->_fillStyles[$ID]))) {
+ $ID = key($this->_fillStyles);
+ if (!next($this->_fillStyles)) {
+ reset($this->_fillStyles);
+ }
+ }
+ $fillStyle =& $this->_fillStyles[$ID];
+
+ if (is_object($fillStyle)) {
+ return $fillStyle->_getFillStyle($ID);
+ } elseif ($fillStyle !== null) {
+ return $fillStyle;
+ } else {
+ return parent::_getFillStyle($ID);
+ }
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Fill/Gradient.php b/config/dspam/pear/Image/Graph/Fill/Gradient.php
new file mode 100644
index 00000000..9cf23a6b
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Fill/Gradient.php
@@ -0,0 +1,149 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Fill
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Fill/Image.php
+ */
+require_once 'Image/Graph/Fill/Image.php';
+
+/**
+ * Fill using a gradient color.
+ * This creates a scaled fillstyle with colors flowing gradiently between 2
+ * specified RGB values. Several directions are supported:
+ *
+ * 1 Vertically (IMAGE_GRAPH_GRAD_VERTICAL)
+ *
+ * 2 Horizontally (IMAGE_GRAPH_GRAD_HORIZONTAL)
+ *
+ * 3 Mirrored vertically (the color grades from a- b-a vertically)
+ * (IMAGE_GRAPH_GRAD_VERTICAL_MIRRORED)
+ *
+ * 4 Mirrored horizontally (the color grades from a-b-a horizontally)
+ * IMAGE_GRAPH_GRAD_HORIZONTAL_MIRRORED
+ *
+ * 5 Diagonally from top-left to right-bottom
+ * (IMAGE_GRAPH_GRAD_DIAGONALLY_TL_BR)
+ *
+ * 6 Diagonally from bottom-left to top-right
+ * (IMAGE_GRAPH_GRAD_DIAGONALLY_BL_TR)
+ *
+ * 7 Radially (concentric circles in the center) (IMAGE_GRAPH_GRAD_RADIAL)
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Fill
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Fill_Gradient extends Image_Graph_Fill //Image_Graph_Fill_Image
+{
+
+ /**
+ * The direction of the gradient
+ * @var int
+ * @access private
+ */
+ var $_direction;
+
+ /**
+ * The first color to gradient
+ * @var mixed
+ * @access private
+ */
+ var $_startColor;
+
+ /**
+ * The last color to gradient
+ * @var mixed
+ * @access private
+ */
+ var $_endColor;
+
+ /**
+ * Image_Graph_GradientFill [Constructor]
+ *
+ * @param int $direction The direction of the gradient
+ * @param mixed $startColor The value of the starting color
+ * @param mixed $endColor The value of the ending color
+ */
+ function Image_Graph_Fill_Gradient($direction, $startColor, $endColor)
+ {
+ parent::Image_Graph_Fill();
+ $this->_direction = $direction;
+ $this->_startColor = $startColor;
+ $this->_endColor = $endColor;
+ }
+
+ /**
+ * Return the fillstyle
+ *
+ * @return int A GD fillstyle
+ * @access private
+ */
+ function _getFillStyle($ID = false)
+ {
+ switch ($this->_direction) {
+ case IMAGE_GRAPH_GRAD_HORIZONTAL:
+ $direction = 'horizontal';
+ break;
+ case IMAGE_GRAPH_GRAD_VERTICAL:
+ $direction = 'vertical';
+ break;
+ case IMAGE_GRAPH_GRAD_HORIZONTAL_MIRRORED:
+ $direction = 'horizontal_mirror';
+ break;
+ case IMAGE_GRAPH_GRAD_VERTICAL_MIRRORED:
+ $direction = 'vertical_mirror';
+ break;
+ case IMAGE_GRAPH_GRAD_DIAGONALLY_TL_BR:
+ $direction = 'diagonal_tl_br';
+ break;
+ case IMAGE_GRAPH_GRAD_DIAGONALLY_BL_TR:
+ $direction = 'diagonal_bl_tr';
+ break;
+ case IMAGE_GRAPH_GRAD_RADIAL:
+ $direction = 'radial';
+ break;
+ }
+
+ return array(
+ 'type' => 'gradient',
+ 'start' => $this->_startColor,
+ 'end' => $this->_endColor,
+ 'direction' => $direction
+ );
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Fill/Image.php b/config/dspam/pear/Image/Graph/Fill/Image.php
new file mode 100644
index 00000000..9b1fb142
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Fill/Image.php
@@ -0,0 +1,97 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Fill
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Fill.php
+ */
+require_once 'Image/Graph/Fill.php';
+
+/**
+ * Fill using an image.
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Fill
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Fill_Image extends Image_Graph_Fill
+{
+
+ /**
+ * The file name
+ * @var stirng
+ * @access private
+ */
+ var $_filename;
+
+ /**
+ * The GD Image resource
+ * @var resource
+ * @access private
+ */
+ var $_image;
+
+ /**
+ * Resize the image to the bounding box of the area to fill
+ * @var bool
+ * @access private
+ */
+ var $_resize = true;
+
+ /**
+ * Image_Graph_ImageFill [Constructor]
+ *
+ * @param string $filename The filename and path of the image to use for filling
+ */
+ function Image_Graph_Fill_Image($filename)
+ {
+ parent::Image_Graph_Fill();
+ $this->_filename = $filename;
+ }
+
+ /**
+ * Return the fillstyle
+ *
+ * @param (something) $ID (Add description)
+ * @return int A GD fillstyle
+ * @access private
+ */
+ function _getFillStyle($ID = false)
+ {
+ return $this->_filename;
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Font.php b/config/dspam/pear/Image/Graph/Font.php
new file mode 100644
index 00000000..ad018a27
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Font.php
@@ -0,0 +1,158 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Text
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Common.php
+ */
+require_once 'Image/Graph/Common.php';
+
+/**
+ * A font.
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Text
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ * @abstract
+ */
+class Image_Graph_Font extends Image_Graph_Common
+{
+
+ /**
+ * The name of the font
+ * @var string
+ * @access private
+ */
+ var $_name = false;
+
+ /**
+ * The angle of the output
+ * @var int
+ * @access private
+ */
+ var $_angle = false;
+
+ /**
+ * The size of the font
+ * @var int
+ * @access private
+ */
+ var $_size = 11;
+
+ /**
+ * The color of the font
+ * @var Color
+ * @access private
+ */
+ var $_color = 'black';
+
+ /**
+ * Image_Graph_Font [Constructor]
+ */
+ function Image_Graph_Font($name = false, $size = false)
+ {
+ parent::Image_Graph_Common();
+ if ($name !== false) {
+ $this->_name = $name;
+ }
+ if ($size !== false) {
+ $this->_size = $size;
+ }
+ }
+
+ /**
+ * Set the color of the font
+ *
+ * @param mixed $color The color object of the Font
+ */
+ function setColor($color)
+ {
+ $this->_color = $color;
+ }
+
+ /**
+ * Set the angle slope of the output font.
+ *
+ * 0 = normal, 90 = bottom and up, 180 = upside down, 270 = top and down
+ *
+ * @param int $angle The angle in degrees to slope the text
+ */
+ function setAngle($angle)
+ {
+ $this->_angle = $angle;
+ }
+
+ /**
+ * Set the size of the font
+ *
+ * @param int $size The size in pixels of the font
+ */
+ function setSize($size)
+ {
+ $this->_size = $size;
+ }
+
+ /**
+ * Get the font 'array'
+ *
+ * @return array The font 'summary' to pass to the canvas
+ * @access private
+ */
+ function _getFont($options = false)
+ {
+ if ($options === false) {
+ $options = array();
+ }
+
+ if ($this->_name !== false) {
+ $options['name'] = $this->_name;
+ }
+
+ if (!isset($options['color'])) {
+ $options['color'] = $this->_color;
+ }
+
+ if (!isset($options['size'])) {
+ $options['size'] = $this->_size;
+ }
+
+ if ((!isset($options['angle'])) && ($this->_angle !== false)) {
+ $options['angle'] = $this->_angle;
+ }
+ return $options;
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Grid.php b/config/dspam/pear/Image/Graph/Grid.php
new file mode 100644
index 00000000..4406dbdd
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Grid.php
@@ -0,0 +1,175 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Grid
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Element.php
+ */
+require_once 'Image/Graph/Element.php';
+
+/**
+ * A grid displayed on the plotarea.
+ *
+ * A grid is associated with a primary and a secondary axis. The grid is
+ * displayed in context of the primary axis' label interval - meaning that a
+ * grid for an Y-axis displays a grid for every label on the y-axis (fx. a {@link
+ * Image_Graph_Grid_Lines}, which displays horizontal lines for every label on
+ * the y-axis from the x-axis minimum to the x-axis maximum). You should always
+ * add the grid as one of the first elements to the plotarea. This is due to the
+ * fact that elements are 'outputted' in the order they are added, i.e. if an
+ * grid is added *after* a chart, the grid will be displayed on top of the chart
+ * which is (probably) not desired.
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Grid
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ * @abstract
+ */
+class Image_Graph_Grid extends Image_Graph_Plotarea_Element
+{
+
+ /**
+ * The primary axis: the grid 'refers' to
+ * @var Axis
+ * @access private
+ */
+ var $_primaryAxis = null;
+
+ /**
+ * The secondary axis
+ * @var Axis
+ * @access private
+ */
+ var $_secondaryAxis = null;
+
+ /**
+ * Set the primary axis: the grid should 'refer' to
+ *
+ * @param Image_Graph_Axis $axis The axis
+ * @access private
+ */
+ function _setPrimaryAxis(& $axis)
+ {
+ $this->_primaryAxis =& $axis;
+ }
+
+ /**
+ * Set the secondary axis
+ *
+ * @param Image_Graph_Axis $axis The axis
+ * @access private
+ */
+ function _setSecondaryAxis(& $axis)
+ {
+ $this->_secondaryAxis =& $axis;
+ }
+
+ /**
+ * Get the points on the secondary axis that the grid should 'connect'
+ *
+ * @return array The secondary data values that should mark the grid 'end points'
+ * @access private
+ */
+ function _getSecondaryAxisPoints()
+ {
+ if (is_a($this->_secondaryAxis, 'Image_Graph_Axis_Radar')) {
+ $secondaryValue = false;
+ $firstValue = $secondaryValue;
+ while (($secondaryValue = $this->_secondaryAxis->_getNextLabel($secondaryValue)) !== false) {
+ $secondaryAxisPoints[] = $secondaryValue;
+ }
+ $secondaryAxisPoints[] = $firstValue;
+ } else {
+ $secondaryAxisPoints = array ('#min#', '#max#');
+ }
+ return $secondaryAxisPoints;
+ }
+
+ /**
+ * Get the X pixel position represented by a value
+ *
+ * @param double $point the value to get the pixel-point for
+ * @return double The pixel position along the axis
+ * @access private
+ */
+ function _pointX($point)
+ {
+ if (($this->_primaryAxis->_type == IMAGE_GRAPH_AXIS_Y) ||
+ ($this->_primaryAxis->_type == IMAGE_GRAPH_AXIS_Y_SECONDARY))
+ {
+ $point['AXIS_Y'] = $this->_primaryAxis->_type;
+ } else {
+ $point['AXIS_Y'] = $this->_secondaryAxis->_type;
+ }
+ return parent::_pointX($point);
+ }
+
+ /**
+ * Get the Y pixel position represented by a value
+ *
+ * @param double $point the value to get the pixel-point for
+ * @return double The pixel position along the axis
+ * @access private
+ */
+ function _pointY($point)
+ {
+ if (($this->_primaryAxis->_type == IMAGE_GRAPH_AXIS_Y) ||
+ ($this->_primaryAxis->_type == IMAGE_GRAPH_AXIS_Y_SECONDARY))
+ {
+ $point['AXIS_Y'] = $this->_primaryAxis->_type;
+ } else {
+ $point['AXIS_Y'] = $this->_secondaryAxis->_type;
+ }
+ return parent::_pointY($point);
+ }
+
+ /**
+ * Causes the object to update all sub elements coordinates.
+ *
+ * @access private
+ */
+ function _updateCoords()
+ {
+ $this->_setCoords(
+ $this->_parent->_plotLeft,
+ $this->_parent->_plotTop,
+ $this->_parent->_plotRight,
+ $this->_parent->_plotBottom
+ );
+ parent::_updateCoords();
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Grid/Bars.php b/config/dspam/pear/Image/Graph/Grid/Bars.php
new file mode 100644
index 00000000..a75782f2
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Grid/Bars.php
@@ -0,0 +1,117 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Grid
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Grid.php
+ */
+require_once 'Image/Graph/Grid.php';
+
+/**
+ * Display alternating bars on the plotarea.
+ *
+ * {@link Image_Graph_Grid}
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Grid
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Grid_Bars extends Image_Graph_Grid
+{
+
+ /**
+ * Output the grid
+ *
+ * @return bool Was the output 'good' (true) or 'bad' (false).
+ * @access private
+ */
+ function _done()
+ {
+ if (parent::_done() === false) {
+ return false;
+ }
+
+ if (!$this->_primaryAxis) {
+ return false;
+ }
+
+ $this->_canvas->startGroup(get_class($this));
+
+ $i = 0;
+ $value = false;
+
+ $previousValue = 0;
+
+ $secondaryPoints = $this->_getSecondaryAxisPoints();
+
+ while (($value = $this->_primaryAxis->_getNextLabel($value)) !== false) {
+ if ($i == 1) {
+ reset($secondaryPoints);
+ list ($id, $previousSecondaryValue) = each($secondaryPoints);
+ while (list ($id, $secondaryValue) = each($secondaryPoints)) {
+ if ($this->_primaryAxis->_type == IMAGE_GRAPH_AXIS_X) {
+ $p1 = array ('Y' => $secondaryValue, 'X' => $value);
+ $p2 = array ('Y' => $previousSecondaryValue, 'X' => $value);
+ $p3 = array ('Y' => $previousSecondaryValue, 'X' => $previousValue);
+ $p4 = array ('Y' => $secondaryValue, 'X' => $previousValue);
+ } else {
+ $p1 = array ('X' => $secondaryValue, 'Y' => $value);
+ $p2 = array ('X' => $previousSecondaryValue, 'Y' => $value);
+ $p3 = array ('X' => $previousSecondaryValue, 'Y' => $previousValue);
+ $p4 = array ('X' => $secondaryValue, 'Y' => $previousValue);
+ }
+
+ $this->_canvas->addVertex(array('x' => $this->_pointX($p1), 'y' => $this->_pointY($p1)));
+ $this->_canvas->addVertex(array('x' => $this->_pointX($p2), 'y' => $this->_pointY($p2)));
+ $this->_canvas->addVertex(array('x' => $this->_pointX($p3), 'y' => $this->_pointY($p3)));
+ $this->_canvas->addVertex(array('x' => $this->_pointX($p4), 'y' => $this->_pointY($p4)));
+
+ $this->_getFillStyle();
+ $this->_canvas->polygon(array('connect' => true));
+
+ $previousSecondaryValue = $secondaryValue;
+ }
+ }
+ $i = 1 - $i;
+ $previousValue = $value;
+ }
+
+ $this->_canvas->endGroup();
+
+ return true;
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Grid/Lines.php b/config/dspam/pear/Image/Graph/Grid/Lines.php
new file mode 100644
index 00000000..805778ee
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Grid/Lines.php
@@ -0,0 +1,114 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Grid
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Grid.php
+ */
+require_once 'Image/Graph/Grid.php';
+
+/**
+ * Display a line grid on the plotarea.
+ *
+ * {@link Image_Graph_Grid}
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Grid
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Grid_Lines extends Image_Graph_Grid
+{
+
+ /**
+ * GridLines [Constructor]
+ */
+ function Image_Graph_Grid_Lines()
+ {
+ parent::Image_Graph_Grid();
+ $this->_lineStyle = 'lightgrey';
+ }
+
+ /**
+ * Output the grid
+ *
+ * @return bool Was the output 'good' (true) or 'bad' (false).
+ * @access private
+ */
+ function _done()
+ {
+ if (parent::_done() === false) {
+ return false;
+ }
+
+ if (!$this->_primaryAxis) {
+ return false;
+ }
+
+ $this->_canvas->startGroup(get_class($this));
+
+ $value = false;
+
+ $secondaryPoints = $this->_getSecondaryAxisPoints();
+
+ while (($value = $this->_primaryAxis->_getNextLabel($value)) !== false) {
+ reset($secondaryPoints);
+ list ($id, $previousSecondaryValue) = each($secondaryPoints);
+ while (list ($id, $secondaryValue) = each($secondaryPoints)) {
+ if ($this->_primaryAxis->_type == IMAGE_GRAPH_AXIS_Y) {
+ $p1 = array ('X' => $secondaryValue, 'Y' => $value);
+ $p2 = array ('X' => $previousSecondaryValue, 'Y' => $value);
+ } else {
+ $p1 = array ('X' => $value, 'Y' => $secondaryValue);
+ $p2 = array ('X' => $value, 'Y' => $previousSecondaryValue);
+ }
+
+ $x1 = $this->_pointX($p1);
+ $y1 = $this->_pointY($p1);
+ $x2 = $this->_pointX($p2);
+ $y2 = $this->_pointY($p2);
+
+ $previousSecondaryValue = $secondaryValue;
+
+ $this->_getLineStyle();
+ $this->_canvas->line(array('x0' => $x1, 'y0' => $y1, 'x1' => $x2, 'y1' => $y2));
+ }
+ }
+
+ $this->_canvas->endGroup();
+
+ return true;
+ }
+
+}
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Grid/Polar.php b/config/dspam/pear/Image/Graph/Grid/Polar.php
new file mode 100644
index 00000000..03b1b916
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Grid/Polar.php
@@ -0,0 +1,111 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Grid
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ * @since File available since Release 0.3.0dev2
+ */
+
+/**
+ * Include file Image/Graph/Grid.php
+ */
+require_once 'Image/Graph/Grid.php';
+
+/**
+ * Display a line grid on the plotarea.
+ *
+ * {@link Image_Graph_Grid}
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Grid
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ * @since Class available since Release 0.3.0dev2
+ */
+class Image_Graph_Grid_Polar extends Image_Graph_Grid
+{
+
+ /**
+ * GridLines [Constructor]
+ */
+ function Image_Graph_Grid_Polar()
+ {
+ parent::Image_Graph_Grid();
+ $this->_lineStyle = 'lightgrey';
+ }
+
+ /**
+ * Output the grid
+ *
+ * @return bool Was the output 'good' (true) or 'bad' (false).
+ * @access private
+ */
+ function _done()
+ {
+ if (parent::_done() === false) {
+ return false;
+ }
+
+ if (!$this->_primaryAxis) {
+ return false;
+ }
+
+ $this->_canvas->startGroup(get_class($this));
+
+ $value = false;
+
+ $p0 = array ('X' => '#min#', 'Y' => '#min#');
+ if ($this->_primaryAxis->_type == IMAGE_GRAPH_AXIS_Y) {
+ $p1 = array ('X' => '#min#', 'Y' => '#max#');
+ $r0 = abs($this->_pointY($p1) - $this->_pointY($p0));
+ } else {
+ $p1 = array ('X' => '#max#', 'Y' => '#min#');
+ $r0 = abs($this->_pointX($p1) - $this->_pointX($p0));
+ }
+
+ $cx = $this->_pointX($p0);
+ $cy = $this->_pointY($p0);
+
+ $span = $this->_primaryAxis->_axisSpan;
+
+ while (($value = $this->_primaryAxis->_getNextLabel($value)) !== false) {
+ $r = $r0 * ($value - $this->_primaryAxis->_getMinimum()) / $span;
+
+ $this->_getLineStyle();
+ $this->_canvas->ellipse(array('x' => $cx, 'y' => $cy, 'rx' => $r, 'ry' => $r));
+ }
+
+ $this->_canvas->endGroup();
+
+ return true;
+ }
+
+}
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Images/Icons/pinpoint.png b/config/dspam/pear/Image/Graph/Images/Icons/pinpoint.png
new file mode 100644
index 00000000..d23f0b7d
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Images/Icons/pinpoint.png
Binary files differ
diff --git a/config/dspam/pear/Image/Graph/Images/Icons/pinpointr.png b/config/dspam/pear/Image/Graph/Images/Icons/pinpointr.png
new file mode 100644
index 00000000..2455e09b
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Images/Icons/pinpointr.png
Binary files differ
diff --git a/config/dspam/pear/Image/Graph/Images/Maps/README b/config/dspam/pear/Image/Graph/Images/Maps/README
new file mode 100644
index 00000000..1b984bbb
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Images/Maps/README
@@ -0,0 +1,17 @@
+In this folder the files for the Image_Graph_Plot_Map are located. They should be the
+following format:
+
+[map name].png
+[map name].txt
+
+The [map name].png (fx. europe.png) is the actual image presenting the map. The
+[map name].txt file is the location -> (x,y) conversion table. In this file the
+named locations is written on every line with the x and y coordinates after the
+name (with a TAB), i.e.:
+
+Denmark 10 30
+England 4 30
+
+Where Denmark will be 'located' on (10, 30) on the map, and England at (4, 30).
+
+No maps are released by default due to we want to avoid possible copyright issues. \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Layout.php b/config/dspam/pear/Image/Graph/Layout.php
new file mode 100644
index 00000000..1561aafa
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Layout.php
@@ -0,0 +1,219 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Layout
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Plotarea/Element.php
+ */
+require_once 'Image/Graph/Plotarea/Element.php';
+
+/**
+ * Defines an area of the graph that can be layout'ed.
+ *
+ * Any class that extends this abstract class can be used within a layout on the canvas.
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Layout
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ * @abstract
+ */
+class Image_Graph_Layout extends Image_Graph_Plotarea_Element
+{
+
+ /**
+ * Has the coordinates already been updated?
+ * @var bool
+ * @access private
+ */
+ var $_updated = false;
+
+ /**
+ * Alignment of the area for each vertice (left, top, right, bottom)
+ * @var array
+ * @access private
+ */
+ var $_alignSize = array ('left' => 0, 'top' => 0, 'right' => 0, 'bottom' => 0);
+
+ /**
+ * Image_Graph_Layout [Constructor]
+ */
+ function Image_Graph_Layout()
+ {
+ parent::Image_Graph_Element();
+ $this->_padding = array('left' => 2, 'top' => 2, 'right' => 2, 'bottom' => 2);
+ }
+
+ /**
+ * Resets the elements
+ *
+ * @access private
+ */
+ function _reset()
+ {
+ parent::_reset();
+ $this->_updated = false;
+ }
+
+ /**
+ * Calculate the edge offset for a specific edge
+ * @param array $alignSize The alignment of the edge
+ * @param int $offset The offset/posision of the at 0% edge
+ * @param int $total The total size (width or height) of the element
+ * @param int $multiplier +/- 1 if the edge should pushed either toward more
+ * negative or positive values
+ * @since 0.3.0dev2
+ * @access private
+ */
+ function _calcEdgeOffset($alignSize, $offset, $total, $multiplier)
+ {
+ if ($alignSize['unit'] == 'percentage') {
+ return $offset + $multiplier * ($total * $alignSize['value'] / 100);
+ } elseif ($alignSize['unit'] == 'pixels') {
+ if (($alignSize['value'] == 'auto_part1') || ($alignSize['value'] == 'auto_part2')) {
+ $alignSize['value'] = $multiplier * $this->_parent->_getAbsolute($alignSize['value']);
+ }
+ if ($alignSize['value'] < 0) {
+ return $offset + $multiplier * ($total + $alignSize['value']);
+ } else {
+ return $offset + $multiplier * $alignSize['value'];
+ }
+ }
+ return $offset;
+ }
+
+ /**
+ * Calculate the edges
+ *
+ * @access private
+ */
+ function _calcEdges()
+ {
+ if ((is_array($this->_alignSize)) && (!$this->_updated)) {
+ $left = $this->_calcEdgeOffset(
+ $this->_alignSize['left'],
+ $this->_parent->_fillLeft(),
+ $this->_parent->_fillWidth(),
+ +1
+ );
+ $top = $this->_calcEdgeOffset(
+ $this->_alignSize['top'],
+ $this->_parent->_fillTop(),
+ $this->_parent->_fillHeight(),
+ +1
+ );
+ $right = $this->_calcEdgeOffset(
+ $this->_alignSize['right'],
+ $this->_parent->_fillRight(),
+ $this->_parent->_fillWidth(),
+ -1
+ );
+ $bottom = $this->_calcEdgeOffset(
+ $this->_alignSize['bottom'],
+ $this->_parent->_fillBottom(),
+ $this->_parent->_fillHeight(),
+ -1
+ );
+
+ $this->_setCoords(
+ $left + $this->_padding['left'],
+ $top + $this->_padding['top'],
+ $right - $this->_padding['right'],
+ $bottom - $this->_padding['bottom']
+ );
+ }
+ }
+
+ /**
+ * Update coordinates
+ *
+ * @access private
+ */
+ function _updateCoords()
+ {
+ $this->_calcEdges();
+ parent::_updateCoords();
+ }
+
+ /**
+ * Pushes an edge of area a specific distance 'into' the canvas
+ *
+ * @param int $edge The edge of the canvas to align relative to
+ * @param int $size The number of pixels or the percentage of the canvas total size to occupy relative to the selected alignment edge
+ * @access private
+ */
+ function _push($edge, $size = '100%')
+ {
+ $result = array();
+ if (ereg("([0-9]*)\%", $size, $result)) {
+ $this->_alignSize[$edge] = array(
+ 'value' => min(100, max(0, $result[1])),
+ 'unit' => 'percentage'
+ );
+ } else {
+ $this->_alignSize[$edge] = array(
+ 'value' => $size,
+ 'unit' => 'pixels'
+ );
+ }
+ }
+
+ /**
+ * Sets the coordinates of the element
+ *
+ * @param int $left The leftmost pixel of the element on the canvas
+ * @param int $top The topmost pixel of the element on the canvas
+ * @param int $right The rightmost pixel of the element on the canvas
+ * @param int $bottom The bottommost pixel of the element on the canvas
+ * @access private
+ */
+ function _setCoords($left, $top, $right, $bottom)
+ {
+ parent::_setCoords($left, $top, $right, $bottom);
+ $this->_updated = true;
+ }
+
+ /**
+ * Returns the calculated "auto" size
+ *
+ * @return int The calculated auto size
+ * @access private
+ */
+ function _getAutoSize()
+ {
+ return false;
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Layout/Horizontal.php b/config/dspam/pear/Image/Graph/Layout/Horizontal.php
new file mode 100644
index 00000000..414a168c
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Layout/Horizontal.php
@@ -0,0 +1,186 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Layout
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Layout.php
+ */
+require_once 'Image/Graph/Layout.php';
+
+/**
+ * Layout for displaying two elements side by side.
+ *
+ * This splits the area contained by this element in two, side by side by
+ * a specified percentage (relative to the left side). A layout can be nested.
+ * Fx. a HorizontalLayout can layout two {@link Image_Graph_Layout_Vertical}s to
+ * make a 2 by 2 matrix of 'element-areas'.
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Layout
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Layout_Horizontal extends Image_Graph_Layout
+{
+
+ /**
+ * Part1 of the layout
+ * @var GraPHPElemnt
+ * @access private
+ */
+ var $_part1 = false;
+
+ /**
+ * Part2 of the layout
+ * @var GraPHPElemnt
+ * @access private
+ */
+ var $_part2 = false;
+
+ /**
+ * The percentage of the graph where the split occurs
+ * @var int
+ * @access private
+ */
+ var $_percentage;
+
+ /**
+ * An absolute position where the split occurs
+ * @var int
+ * @access private
+ */
+ var $_absolute;
+
+ /**
+ * HorizontalLayout [Constructor]
+ *
+ * @param Image_Graph_Element $part1 The 1st part of the layout
+ * @param Image_Graph_Element $part2 The 2nd part of the layout
+ * @param int $percentage The percentage of the layout to split at
+ */
+ function Image_Graph_Layout_Horizontal(& $part1, & $part2, $percentage = 50)
+ {
+ parent::Image_Graph_Layout();
+ if (!is_a($part1, 'Image_Graph_Layout')) {
+ $this->_error(
+ 'Cannot create layout on non-layouable parts: ' . get_class($part1),
+ array('part1' => &$part1, 'part2' => &$part2)
+ );
+ } elseif (!is_a($part2, 'Image_Graph_Layout')) {
+ $this->_error(
+ 'Cannot create layout on non-layouable parts: ' . get_class($part2),
+ array('part1' => &$part1, 'part2' => &$part2)
+ );
+ } else {
+ $this->_part1 =& $part1;
+ $this->_part2 =& $part2;
+ $this->add($this->_part1);
+ $this->add($this->_part2);
+ };
+ if ($percentage === 'auto') {
+ $this->_percentage = false;
+ $this->_absolute = 'runtime';
+ } else {
+ $this->_absolute = false;
+ $this->_percentage = max(0, min(100, $percentage));
+ }
+ $this->_split();
+ $this->_padding = array('left' => 0, 'top' => 0, 'right' => 0, 'bottom' => 0);
+ }
+
+ /**
+ * Gets the absolute size of one of the parts.
+ *
+ * @param string $part The name of the part - auto_part(1|2)
+ * @return int The number of pixels the edge should be pushed
+ * @since 0.3.0dev2
+ * @access private
+ */
+ function _getAbsolute(&$part)
+ {
+ $part1Size = $this->_part1->_getAutoSize();
+ $part2Size = $this->_part2->_getAutoSize();
+ $this->_percentage = false;
+ if (($part1Size !== false) and ($part2Size !== false)) {
+ $width = $this->_fillWidth() * $part1Size / ($part1Size + $part2Size);
+ } elseif ($part1Size !== false) {
+ $width = $part1Size;
+ } elseif ($part2Size !== false) {
+ $width = -$part2Size;
+ } else {
+ $width = $this->_fillWidth() / 2;
+ }
+ if ($part == 'auto_part2') {
+ $width = -$width;
+ }
+
+ return $width;
+ }
+
+ /**
+ * Splits the layout between the parts, by the specified percentage
+ *
+ * @access private
+ */
+ function _split()
+ {
+ if (($this->_part1) && ($this->_part2)) {
+ if ($this->_percentage !== false) {
+ $split1 = 100 - $this->_percentage;
+ $split2 = $this->_percentage;
+ $this->_part1->_push('right', "$split1%");
+ $this->_part2->_push('left', "$split2%");
+ } else {
+ $this->_part1->_push('right', 'auto_part1');
+ $this->_part2->_push('left', 'auto_part2');
+ }
+ }
+ }
+
+ /**
+ * Output the layout to the canvas
+ *
+ * @return bool Was the output 'good' (true) or 'bad' (false).
+ * @access private
+ */
+ function _done()
+ {
+ if (($this->_part1) && ($this->_part2)) {
+ return (($this->_part1->_done()) && ($this->_part2->_done()));
+ }
+ return true;
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Layout/Matrix.php b/config/dspam/pear/Image/Graph/Layout/Matrix.php
new file mode 100644
index 00000000..8acec871
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Layout/Matrix.php
@@ -0,0 +1,201 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Layout
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Layout.php
+ */
+require_once 'Image/Graph/Layout.php';
+
+/**
+ * Layout for displaying elements in a matix.
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Layout
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Layout_Matrix extends Image_Graph_Layout
+{
+
+ /**
+ * Layout matrix
+ * @var array
+ * @access private
+ */
+ var $_matrix = false;
+
+ /**
+ * The number of rows
+ * @var int
+ * @access private
+ */
+ var $_rows = false;
+
+ /**
+ * The number of columns
+ * @var int
+ * @access private
+ */
+ var $_cols = false;
+
+ /**
+ * Image_Graph_Layout_Matrix [Constructor]
+ *
+ * @param int $rows The number of rows
+ * @param int $cols The number of cols
+ * @param bool $autoCreate Specifies whether the matrix should automatically
+ * be filled with newly created Image_Graph_Plotares objects, or they will
+ * be added manually
+ */
+ function Image_Graph_Layout_Matrix($rows, $cols, $autoCreate = true)
+ {
+ parent::Image_Graph_Layout();
+
+ $this->_rows = $rows;
+ $this->_cols = $cols;
+ if (($this->_rows > 0) && ($this->_cols > 0)) {
+ $this->_matrix = array(array());
+ for ($i = 0; $i < $this->_rows; $i++) {
+ for ($j = 0; $j < $this->_cols; $j++) {
+ if ($autoCreate) {
+ $this->_matrix[$i][$j] =& $this->addNew('plotarea');
+ $this->_pushEdges($i, $j);
+ } else {
+ $this->_matrix[$i][$j] = false;
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Pushes the edges on the specified position in the matrix
+ *
+ * @param int $row The row
+ * @param int $col The column
+ * @access private
+ */
+ function _pushEdges($row, $col)
+ {
+ if ((isset($this->_matrix[$row])) && (isset($this->_matrix[$row][$col]))) {
+ $height = 100/$this->_rows;
+ $width = 100/$this->_cols;
+ if ($col > 0) {
+ $this->_matrix[$row][$col]->_push('left', round($col*$width) . '%');
+ }
+ if ($col+1 < $this->_cols) {
+ $this->_matrix[$row][$col]->_push('right', round(100-($col+1)*$width) . '%');
+ }
+ if ($row > 0) {
+ $this->_matrix[$row][$col]->_push('top', round($row*$height) . '%');
+ }
+ if ($row+1 < $this->_rows) {
+ $this->_matrix[$row][$col]->_push('bottom', round(100-($row+1)*$height) . '%');
+ }
+ }
+ }
+
+ /**
+ * Get the area on the specified position in the matrix
+ *
+ * @param int $row The row
+ * @param int $col The column
+ * @return Image_Graph_Layout The element of position ($row, $col) in the
+ * matrix
+ */
+ function &getEntry($row, $col)
+ {
+ if ((isset($this->_matrix[$row])) && (isset($this->_matrix[$row][$col]))) {
+ return $this->_matrix[$row][$col];
+ } else {
+ $result = null;
+ return $result;
+ }
+ }
+
+ /**
+ * Get the area on the specified position in the matrix
+ *
+ * @param int $row The row
+ * @param int $col The column
+ * @param Image_Graph_Layout $element The element to set in the position
+ * ($row, $col) in the matrix
+ */
+ function setEntry($row, $col, &$element)
+ {
+ $this->_matrix[$row][$col] =& $element;
+ $this->_pushEdges($row, $col);
+ }
+
+ /**
+ * Update coordinates
+ *
+ * @access private
+ */
+ function _updateCoords()
+ {
+ for ($i = 0; $i < $this->_rows; $i++) {
+ for ($j = 0; $j < $this->_cols; $j++) {
+ $element =& $this->getEntry($i, $j);
+ $this->add($element);
+ }
+ }
+ parent::_updateCoords();
+ }
+
+ /**
+ * Output the layout to the canvas
+ *
+ * @return bool Was the output 'good' (true) or 'bad' (false).
+ * @access private
+ */
+ function _done()
+ {
+ $result = true;
+ for ($i = 0; $i < $this->_rows; $i++) {
+ for ($j = 0; $j < $this->_cols; $j++) {
+ $element =& $this->getEntry($i, $j);
+ if ($element) {
+ if (!$element->_done()) {
+ $result = false;
+ }
+ }
+ }
+ }
+ return $result;
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Layout/Vertical.php b/config/dspam/pear/Image/Graph/Layout/Vertical.php
new file mode 100644
index 00000000..2dc6f945
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Layout/Vertical.php
@@ -0,0 +1,108 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Layout
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Layout/Horizontal.php
+ */
+require_once 'Image/Graph/Layout/Horizontal.php';
+
+/**
+ * Layout for displaying two elements on top of each other.
+ *
+ * This splits the area contained by this element in two on top of each other
+ * by a specified percentage (relative to the top). A layout can be nested.
+ * Fx. a {@link Image_Graph_Layout_Horizontal} can layout two VerticalLayout's to
+ * make a 2 by 2 matrix of 'element-areas'.
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Layout
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Layout_Vertical extends Image_Graph_Layout_Horizontal
+{
+
+ /**
+ * Gets the absolute size of one of the parts.
+ *
+ * @param string $part The name of the part - auto_part(1|2)
+ * @return int The number of pixels the edge should be pushed
+ * @since 0.3.0dev2
+ * @access private
+ */
+ function _getAbsolute(&$part)
+ {
+ $part1Size = $this->_part1->_getAutoSize();
+ $part2Size = $this->_part2->_getAutoSize();
+ $this->_percentage = false;
+ if (($part1Size !== false) and ($part2Size !== false)) {
+ $height = $this->_fillHeight() * $part1Size / ($part1Size + $part2Size);
+ } elseif ($part1Size !== false) {
+ $height = $part1Size;
+ } elseif ($part2Size !== false) {
+ $height = -$part2Size;
+ } else {
+ $height = $this->_fillHeight() / 2;
+ }
+
+ if ($part == 'auto_part2') {
+// $height = $this->_fillHeight() - $height;
+ }
+
+ return $height;
+ }
+
+ /**
+ * Splits the layout between the parts, by the specified percentage
+ *
+ * @access private
+ */
+ function _split()
+ {
+ if (($this->_part1) && ($this->_part2)) {
+ if ($this->_percentage !== false) {
+ $split1 = 100 - $this->_percentage;
+ $split2 = $this->_percentage;
+ $this->_part1->_push('bottom', "$split1%");
+ $this->_part2->_push('top', "$split2%");
+ } else {
+ $this->_part1->_push('bottom', 'auto_part1');
+ $this->_part2->_push('top', 'auto_part2');
+ }
+ }
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Legend.php b/config/dspam/pear/Image/Graph/Legend.php
new file mode 100644
index 00000000..d853dad5
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Legend.php
@@ -0,0 +1,385 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - Main class for the graph creation.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Legend
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Layout.php
+ */
+require_once 'Image/Graph/Layout.php';
+
+/**
+ * Displays a legend for a plotarea.
+ *
+ * A legend can be displayed in two ways:
+ *
+ * 1 As an overlayed box within the plotarea
+ *
+ * 2 Layout'ed on the canvas smewhere next to the plotarea.
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Legend
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Legend extends Image_Graph_Layout
+{
+
+ /**
+ * Alignment of the text
+ * @var int
+ * @access private
+ */
+ var $_alignment = false;
+
+ /**
+ * The plotarea(s) to show the legend for
+ * @var array
+ * @access private
+ */
+ var $_plotareas = array();
+
+ /**
+ * Should markers be shown or not on this legend
+ * @var bool
+ * @access private
+ */
+ var $_showMarker = false;
+
+ /**
+ * Image_Graph_Legend [Constructor]
+ */
+ function Image_Graph_Legend()
+ {
+ parent::Image_Graph_Layout();
+ $this->_padding = array('left' => 5, 'top' => 5, 'right' => 5, 'bottom' => 5);
+ }
+
+ /**
+ * The number of actual plots in the plot area
+ *
+ * @return int The number of plotes
+ * @access private
+ */
+ function _plotCount()
+ {
+ $count = 0;
+ $keys = array_keys($this->_plotareas);
+ foreach($keys as $key) {
+ $plotarea =& $this->_plotareas[$key];
+ if (is_a($plotarea, 'Image_Graph_Plotarea')) {
+ $keys2 = array_keys($plotarea->_elements);
+ foreach ($keys2 as $key) {
+ $element =& $plotarea->_elements[$key];
+ if (is_a($element, 'Image_Graph_Plot')) {
+ $count ++;
+ }
+ }
+ unset($keys2);
+ }
+ }
+ unset($keys);
+ return $count;
+ }
+
+ /**
+ * Get a default parameter array for legendSamples
+ * @param bool $simulate Whether the array should be used for simulation or
+ * not
+ * @return array Default parameter array
+ * @access private
+ */
+ function _parameterArray($simulate = false)
+ {
+ $param['left'] = $this->_left + $this->_padding['left'];
+ $param['top'] = $this->_top + $this->_padding['top'];
+ $param['right'] = $this->_right - $this->_padding['right'];
+ $param['bottom'] = $this->_bottom - $this->_padding['bottom'];
+ $param['align'] = $this->_alignment;
+ $param['x'] = $this->_left + $this->_padding['left'];
+ $param['y'] = $this->_top + $this->_padding['top'];
+ $param['width'] = 16;
+ $param['height'] = 16;
+ $param['show_marker'] = $this->_showMarker;
+ $param['maxwidth'] = 0;
+ $param['font'] = $this->_getFont();
+ if ($simulate) {
+ $param['simulate'] = true;
+ }
+
+ return $param;
+ }
+
+ /**
+ * The height of the element on the canvas
+ *
+ * @return int Number of pixels representing the height of the element
+ * @access private
+ */
+ function _height()
+ {
+ $parent = (is_object($this->_parent) ? get_class($this->_parent) : $this->_parent);
+
+ if (strtolower($parent) == 'image_graph_plotarea') {
+ $param = $this->_parameterArray(true);
+ $param['align'] = IMAGE_GRAPH_ALIGN_VERTICAL;
+ $param0 = $param;
+ $keys = array_keys($this->_plotareas);
+ foreach($keys as $key) {
+ $plotarea =& $this->_plotareas[$key];
+ $keys2 = array_keys($plotarea->_elements);
+ foreach($keys2 as $key) {
+ $element =& $plotarea->_elements[$key];
+ if (is_a($element, 'Image_Graph_Plot')) {
+ $element->_legendSample($param);
+ }
+ }
+ unset($keys2);
+ }
+ unset($keys);
+ return abs($param['y'] - $param0['y']) + $this->_padding['top'] + $this->_padding['bottom'];
+ } else {
+ return parent::height();
+ }
+ }
+
+ /**
+ * The width of the element on the canvas
+ *
+ * @return int Number of pixels representing the width of the element
+ * @access private
+ */
+ function _width()
+ {
+ $parent = (is_object($this->_parent) ? get_class($this->_parent) : $this->_parent);
+
+ if (strtolower($parent) == 'image_graph_plotarea') {
+ $param = $this->_parameterArray(true);
+ $param['align'] = IMAGE_GRAPH_ALIGN_VERTICAL;
+ $keys = array_keys($this->_plotareas);
+ foreach($keys as $key) {
+ $plotarea =& $this->_plotareas[$key];
+ $keys2 = array_keys($plotarea->_elements);
+ foreach($keys2 as $key) {
+ $element =& $plotarea->_elements[$key];
+ if (is_a($element, 'Image_Graph_Plot')) {
+ $element->_legendSample($param);
+ }
+ }
+ unset($keys2);
+ }
+ unset($keys);
+ return $param['maxwidth'];
+ } else {
+ return parent::width();
+ }
+ }
+
+ /**
+ * Set the alignment of the legend
+ *
+ * @param int $alignment The alignment
+ */
+ function setAlignment($alignment)
+ {
+ $this->_alignment = $alignment;
+ }
+
+ /**
+ * Update coordinates
+ *
+ * @access private
+ */
+ function _updateCoords()
+ {
+ parent::_updateCoords();
+
+ $parent = (is_object($this->_parent) ? get_class($this->_parent) : $this->_parent);
+
+ if (strtolower($parent) == 'image_graph_plotarea') {
+ $w = $this->_width();
+ $h = $this->_height();
+
+ if ($this->_alignment === false) {
+ $this->_alignment = IMAGE_GRAPH_ALIGN_TOP + IMAGE_GRAPH_ALIGN_RIGHT;
+ }
+
+ if (($this->_alignment & IMAGE_GRAPH_ALIGN_BOTTOM) != 0) {
+ $y = $this->_parent->_fillBottom() - $h - $this->_padding['bottom'];
+ } else {
+ $y = $this->_parent->_fillTop() + $this->_padding['top'];
+ }
+
+ if (($this->_alignment & IMAGE_GRAPH_ALIGN_LEFT) != 0) {
+ $x = $this->_parent->_fillLeft() + $this->_padding['left'];
+ } else {
+ $x = $this->_parent->_fillRight() - $w - $this->_padding['right'];
+ }
+
+ $this->_setCoords($x, $y, $x + $w, $y + $h);
+ }
+ }
+
+ /**
+ * Sets Plotarea
+ *
+ * @param Image_Graph_Plotarea $plotarea The plotarea
+ */
+ function setPlotarea(& $plotarea)
+ {
+ if (is_a($plotarea, 'Image_Graph_Plotarea')) {
+ $this->_plotareas[] =& $plotarea;
+ }
+ }
+
+ /**
+ * Sets the parent. The parent chain should ultimately be a GraPHP object
+ *
+ * @see Image_Graph
+ * @param Image_Graph_Common $parent The parent
+ * @access private
+ */
+ function _setParent(& $parent)
+ {
+ parent::_setParent($parent);
+ if (count($this->_plotareas) == 0) {
+ $this->setPlotarea($parent);
+ }
+ }
+
+ /**
+ * Set if this legends should show markers
+ *
+ * @param bool $showMarker True if markers are to be shown, false is not
+ */
+ function setShowMarker($showMarker)
+ {
+ $this->_showMarker = $showMarker;
+ }
+
+
+ /**
+ * Output the plot
+ *
+ * @return bool Was the output 'good' (true) or 'bad' (false).
+ * @access private
+ */
+ function _done()
+ {
+
+ if (Image_Graph_Element::_done() === false) {
+ return false;
+ }
+
+ $this->_canvas->startGroup(get_class($this));
+
+ $param = $this->_parameterArray();
+
+ $parent = (is_object($this->_parent) ?
+ get_class($this->_parent) :
+ $this->_parent
+ );
+
+ if (strtolower($parent) == 'image_graph_plotarea') {
+ $this->_getFillStyle();
+ $this->_getLineStyle();
+ $this->_canvas->rectangle(
+ array(
+ 'x0' => $this->_left,
+ 'y0' => $this->_top,
+ 'x1' => $this->_right,
+ 'y1' => $this->_bottom
+ )
+ );
+
+ $param = $this->_parameterArray();
+
+ $keys = array_keys($this->_plotareas);
+ foreach($keys as $key) {
+ $plotarea =& $this->_plotareas[$key];
+ $keys2 = array_keys($plotarea->_elements);
+ foreach($keys2 as $key) {
+ $element =& $plotarea->_elements[$key];
+ if (is_a($element, 'Image_Graph_Plot')) {
+ $element->_legendSample($param);
+ }
+ }
+ unset($keys2);
+ }
+ unset($keys);
+ } else {
+ $param0 = $param;
+ $param0['simulate'] = true;
+ $keys = array_keys($this->_plotareas);
+ foreach($keys as $key) {
+ $plotarea =& $this->_plotareas[$key];
+ $keys2 = array_keys($plotarea->_elements);
+ foreach($keys2 as $key) {
+ $element =& $plotarea->_elements[$key];
+ if (is_a($element, 'Image_Graph_Plot')) {
+ $element->_legendSample($param0);
+ }
+ }
+ unset($keys2);
+ }
+ unset($keys);
+ if (($this->_alignment & IMAGE_GRAPH_ALIGN_VERTICAL) != 0) {
+ if ($param0['x'] == $param['x']) {
+ $param['y'] = $param['y'] + ($this->_height() - ($param0['y'] - $param['y']))/2;
+ }
+ } else {
+ if ($param0['y'] == $param['y']) {
+ $param['x'] = $param['x'] + ($this->_width() - ($param0['x'] - $param['x']))/2;
+ }
+ }
+
+ $keys = array_keys($this->_plotareas);
+ foreach($keys as $key) {
+ $plotarea =& $this->_plotareas[$key];
+ $keys2 = array_keys($plotarea->_elements);
+ foreach($keys2 as $key) {
+ $element =& $plotarea->_elements[$key];
+ if (is_a($element, 'Image_Graph_Plot')) {
+ $element->_legendSample($param);
+ }
+ }
+ unset($keys2);
+ }
+ unset($keys);
+ }
+
+ $this->_canvas->endGroup();
+
+ return true;
+ }
+}
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Line/Array.php b/config/dspam/pear/Image/Graph/Line/Array.php
new file mode 100644
index 00000000..5d542141
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Line/Array.php
@@ -0,0 +1,129 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Line
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Common.php
+ */
+require_once 'Image/Graph/Common.php';
+
+/**
+ * A sequential array of linestyles.
+ *
+ * This is used for multiple objects within the same element with different line
+ * styles. This is done by adding multiple line styles to a LineArrray
+ * structure. The linearray will then when requested return the 'next' linestyle
+ * in sequential order. It is possible to specify ID tags to each linestyle,
+ * which is used to make sure some data uses a specific linestyle (i.e. in a
+ * multiple-/stackedbarchart you name the {@link Image_Graph_Dataset}s and uses
+ * this name as ID tag when adding the dataset's associated linestyle to the
+ * linearray.
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Line
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Line_Array extends Image_Graph_Common
+{
+
+ /**
+ * The fill array
+ * @var array
+ * @access private
+ */
+ var $_lineStyles = array ();
+
+ /**
+ * Add a line style to the array
+ *
+ * @param Image_Graph_Line $style The style to add
+ */
+ function add(& $style, $id = false)
+ {
+ if (is_a($style, 'Image_Graph_Element')) {
+ parent::add($style);
+ }
+ if ($id === false) {
+ $this->_lineStyles[] =& $style;
+ } else {
+ $this->_lineStyles[$id] =& $style;
+ }
+ reset($this->_lineStyles);
+
+ }
+
+ /**
+ * Add a color to the array
+ *
+ * @param int $color The color
+ * @param string $id The id or name of the color
+ */
+ function addColor($color, $id = false)
+ {
+ if ($id !== false) {
+ $this->_lineStyles[$id] = $color;
+ } else {
+ $this->_lineStyles[] = $color;
+ }
+ reset($this->_lineStyles);
+ }
+
+ /**
+ * Return the linestyle
+ *
+ * @return int A GD Linestyle
+ * @access private
+ */
+ function _getLineStyle($ID = false)
+ {
+ if (($ID === false) || (!isset($this->_lineStyles[$ID]))) {
+ $ID = key($this->_lineStyles);
+ if (!next($this->_lineStyles)) {
+ reset($this->_lineStyles);
+ }
+ }
+ $lineStyle =& $this->_lineStyles[$ID];
+
+ if (is_object($lineStyle)) {
+ return $lineStyle->_getLineStyle($ID);
+ } elseif ($lineStyle !== null) {
+ return $lineStyle;
+ } else {
+ return parent::_getLineStyle($ID);
+ }
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Line/Dashed.php b/config/dspam/pear/Image/Graph/Line/Dashed.php
new file mode 100644
index 00000000..448fb218
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Line/Dashed.php
@@ -0,0 +1,76 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Line
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Line/Formatted.php
+ */
+require_once 'Image/Graph/Line/Formatted.php';
+
+/**
+ * Dashed line style.
+ *
+ * This style displays as a short line with a shorter space afterwards, i.e
+ * 4px color1, 2px color2, 4px color1, etc.
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Line
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Line_Dashed extends Image_Graph_Line_Formatted
+{
+
+ /**
+ * Image_Graph_DashedLine [Constructor]
+ *
+ * @param mixed $color1 The color for the 'dashes'
+ * @param mixed $color2 The color for the 'spaces'
+ */
+ function Image_Graph_Line_Dashed($color1, $color2)
+ {
+ parent::Image_Graph_Line_Formatted(
+ array(
+ $color1,
+ $color1,
+ $color1,
+ $color1,
+ $color2,
+ $color2
+ )
+ );
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Line/Dotted.php b/config/dspam/pear/Image/Graph/Line/Dotted.php
new file mode 100644
index 00000000..8574f8da
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Line/Dotted.php
@@ -0,0 +1,67 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Line
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Line/Formatted.php
+ */
+require_once 'Image/Graph/Line/Formatted.php';
+
+/**
+ * Dotted line style.
+ *
+ * This style displays as a short line with a shorter space afterwards, i.e
+ * 1px color1, 1px color2, 1px color1, etc.
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Line
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Line_Dotted extends Image_Graph_Line_Formatted
+{
+
+ /**
+ * DottedLine [Constructor]
+ *
+ * @param mixed $color1 The color representing the dots
+ * @param mixed $color2 The color representing the spaces
+ */
+ function Image_Graph_Line_Dotted($color1, $color2)
+ {
+ parent::Image_Graph_Line_Formatted(array ($color1, $color2));
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Line/Formatted.php b/config/dspam/pear/Image/Graph/Line/Formatted.php
new file mode 100644
index 00000000..e6d0181b
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Line/Formatted.php
@@ -0,0 +1,90 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Line
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Line/Solid.php
+ */
+require_once 'Image/Graph/Line/Solid.php';
+
+/**
+ * Formatted user defined line style.
+ *
+ * Use this to create a user defined line style. Specify an array of colors that are to
+ * be used for displaying the line.
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Line
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Line_Formatted extends Image_Graph_Line_Solid
+{
+
+ /**
+ * The style of the line
+ *
+ * @var array
+ * @access private
+ */
+ var $_style;
+
+ /**
+ * Image_Graph_FormattedLine [Constructor]
+ *
+ * @param array $style The style of the line
+ */
+ function Image_Graph_Line_Formatted($style)
+ {
+ parent::Image_Graph_Line_Solid(reset($style));
+ $this->_style = $style;
+ }
+
+ /**
+ * Gets the line style of the element
+ *
+ * @return int A GD linestyle representing the line style
+ * @see Image_Graph_Line
+ * @access private
+ */
+ function _getLineStyle()
+ {
+ return array(
+ 'color' => $this->_style,
+ 'thickness' => $this->_thickness
+ );
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Line/Solid.php b/config/dspam/pear/Image/Graph/Line/Solid.php
new file mode 100644
index 00000000..e77e62f1
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Line/Solid.php
@@ -0,0 +1,105 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Line
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Common.php
+ */
+require_once 'Image/Graph/Common.php';
+
+/**
+ * Simple colored line style.
+ *
+ * Use a color for line style.
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Line
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Line_Solid extends Image_Graph_Common
+{
+
+ /**
+ * The thickness of the line (requires GD 2)
+ * @var int
+ * @access private
+ */
+ var $_thickness = 1;
+
+ /**
+ * The color of the line
+ * @var mixed
+ * @access private
+ */
+ var $_color;
+
+ /**
+ * Image_Graph_SolidLine [Constructor]
+ *
+ * @param mixed $color The color of the line
+ */
+ function Image_Graph_Line_Solid($color)
+ {
+ parent::Image_Graph_Common();
+ $this->_color = $color;
+ }
+
+ /**
+ * Set the thickness of the linestyle
+ *
+ * @param int $thickness The line width in pixels
+ */
+ function setThickness($thickness)
+ {
+ $this->_thickness = $thickness;
+ }
+
+ /**
+ * Gets the line style of the element
+ *
+ * @return int A GD linestyle representing the line style
+ * @see Image_Graph_Line
+ * @access private
+ */
+ function _getLineStyle()
+ {
+ return array(
+ 'color' => $this->_color,
+ 'thickness' => $this->_thickness
+ );
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Logo.php b/config/dspam/pear/Image/Graph/Logo.php
new file mode 100644
index 00000000..df5fe7e4
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Logo.php
@@ -0,0 +1,153 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - Main class for the graph creation.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Logo
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Element.php
+ */
+require_once 'Image/Graph/Element.php';
+
+/**
+ * Displays a logo on the canvas.
+ *
+ * By default the logo is displayed in the top-right corner of the canvas.
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Logo
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Logo extends Image_Graph_Element
+{
+
+ /**
+ * The file name
+ * @var stirng
+ * @access private
+ */
+ var $_filename;
+
+ /**
+ * The GD Image resource
+ * @var resource
+ * @access private
+ */
+ var $_image;
+
+ /**
+ * Alignment of the logo
+ * @var int
+ * @access private
+ */
+ var $_alignment;
+
+ /**
+ * Logo [Constructor]
+ *
+ * @param string $filename The filename and path of the image to use for logo
+ */
+ function Image_Graph_Logo($filename, $alignment = IMAGE_GRAPH_ALIGN_TOP_RIGHT)
+ {
+ parent::Image_Graph_Element();
+ $this->_filename = $filename;
+ $this->_alignment = $alignment;
+ }
+
+ /**
+ * Sets the parent. The parent chain should ultimately be a GraPHP object
+ *
+ * @see Image_Graph
+ * @param Image_Graph_Common $parent The parent
+ * @access private
+ */
+ function _setParent(& $parent)
+ {
+ parent::_setParent($parent);
+ $this->_setCoords(
+ $this->_parent->_left,
+ $this->_parent->_top,
+ $this->_parent->_right,
+ $this->_parent->_bottom
+ );
+ }
+
+ /**
+ * Output the logo
+ *
+ * @return bool Was the output 'good' (true) or 'bad' (false).
+ * @access private
+ */
+ function _done()
+ {
+ if (parent::_done() === false) {
+ return false;
+ }
+
+ $align = array();
+
+ if ($this->_alignment & IMAGE_GRAPH_ALIGN_LEFT) {
+ $x = $this->_parent->_left + 2;
+ $align['horizontal'] = 'left';
+ } elseif ($this->_alignment & IMAGE_GRAPH_ALIGN_RIGHT) {
+ $x = $this->_parent->_right - 2;
+ $align['horizontal'] = 'right';
+ } else {
+ $x = ($this->_parent->_left + $this->_parent->_right) / 2;
+ $align['horizontal'] = 'center';
+ }
+
+ if ($this->_alignment & IMAGE_GRAPH_ALIGN_TOP) {
+ $y = $this->_parent->_top + 2;
+ $align['vertical'] = 'top';
+ } elseif ($this->_alignment & IMAGE_GRAPH_ALIGN_BOTTOM) {
+ $y = $this->_parent->_bottom - 2;
+ $align['vertical'] = 'bottom';
+ } else {
+ $y = ($this->_parent->_top + $this->_parent->_bottom) / 2;
+ $align['vertical'] = 'center';
+ }
+
+ $this->_canvas->image(
+ array(
+ 'x' => $x,
+ 'y' => $y,
+ 'filename' => $this->_filename,
+ 'alignment' => $align
+ )
+ );
+ return true;
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Marker.php b/config/dspam/pear/Image/Graph/Marker.php
new file mode 100644
index 00000000..1c1926fe
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Marker.php
@@ -0,0 +1,123 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Marker
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Plotarea/Element.php
+ */
+require_once 'Image/Graph/Plotarea/Element.php';
+
+/**
+ * Data point marker.
+ *
+ * The data point marker is used for marking the datapoints on a graph with some
+ * visual label, fx. a cross, a text box with the value or an icon.
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Marker
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ * @abstract
+ */
+class Image_Graph_Marker extends Image_Graph_Plotarea_Element
+{
+
+ /**
+ * Secondary marker
+ * @var Marker
+ * @access private
+ */
+ var $_secondaryMarker = false;
+
+ /**
+ * The 'size' of the marker, the meaning depends on the specific Marker
+ * implementation
+ * @var int
+ * @access private
+ */
+ var $_size = 6;
+
+ /**
+ * Set the 'size' of the marker
+ *
+ * @param int $size The 'size' of the marker, the meaning depends on the
+ * specific Marker implementation
+ */
+ function setSize($size)
+ {
+ $this->_size = $size;
+ }
+
+ /**
+ * Set the secondary marker
+ *
+ * @param Marker $secondaryMarker The secondary marker
+ */
+ function setSecondaryMarker(& $secondaryMarker)
+ {
+ $this->_secondaryMarker =& $secondaryMarker;
+ $this->_secondaryMarker->_setParent($this);
+ }
+
+ /**
+ * Draw the marker on the canvas
+ *
+ * @param int $x The X (horizontal) position (in pixels) of the marker on
+ * the canvas
+ * @param int $y The Y (vertical) position (in pixels) of the marker on the
+ * canvas
+ * @param array $values The values representing the data the marker 'points'
+ * to
+ * @access private
+ */
+ function _drawMarker($x, $y, $values = false)
+ {
+ if (is_a($this->_secondaryMarker, 'Image_Graph_Marker')) {
+ $this->_secondaryMarker->_drawMarker($x, $y, $values);
+ }
+ }
+
+ /**
+ * Output to the canvas
+ *
+ * @return bool Was the output 'good' (true) or 'bad' (false).
+ * @access private
+ */
+ function _done()
+ {
+ return true;
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Marker/Array.php b/config/dspam/pear/Image/Graph/Marker/Array.php
new file mode 100644
index 00000000..12fed66c
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Marker/Array.php
@@ -0,0 +1,105 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Marker
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Marker.php
+ */
+require_once 'Image/Graph/Marker.php';
+
+/**
+ * A sequential array of markers.
+ *
+ * This is used for displaying different markers for datapoints on a chart.
+ * This is done by adding multiple markers to a MarkerArrray structure.
+ * The marker array will then when requested return the 'next' marker in
+ * sequential order. It is possible to specify ID tags to each marker, which is
+ * used to make sure some data uses a specific marker.
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Marker
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Marker_Array extends Image_Graph_Marker
+{
+
+ /**
+ * The marker array
+ * @var array
+ * @access private
+ */
+ var $_markers = array ();
+
+ /**
+ * Add a marker style to the array
+ *
+ * @param Marker $marker The marker to add
+ */
+ function add(& $marker)
+ {
+ if (is_a($marker, 'Image_Graph_Element')) {
+ parent::add($marker);
+ }
+ $this->_markers[] =& $marker;
+ reset($this->_markers);
+ }
+
+ /**
+ * Draw the marker on the canvas
+ *
+ * @param int $x The X (horizontal) position (in pixels) of the marker on
+ * the canvas
+ * @param int $y The Y (vertical) position (in pixels) of the marker on the
+ * canvas
+ * @param array $values The values representing the data the marker 'points'
+ * to
+ * @access private
+ */
+ function _drawMarker($x, $y, $values = false)
+ {
+ $ID = key($this->_markers);
+ if (!next($this->_markers)) {
+ reset($this->_markers);
+ }
+ $marker =& $this->_markers[$ID];
+
+ if ($marker != null) {
+ $marker->_drawMarker($x, $y, $values);
+ }
+ parent::_drawMarker($x, $y, $values);
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Marker/Asterisk.php b/config/dspam/pear/Image/Graph/Marker/Asterisk.php
new file mode 100644
index 00000000..effde5a5
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Marker/Asterisk.php
@@ -0,0 +1,109 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Marker
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Marker.php
+ */
+require_once 'Image/Graph/Marker.php';
+
+/**
+ * Data marker as an asterisk (*)
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Marker
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Marker_Asterisk extends Image_Graph_Marker
+{
+
+ /**
+ * Draw the marker on the canvas
+ *
+ * @param int $x The X (horizontal) position (in pixels) of the marker on
+ * the canvas
+ * @param int $y The Y (vertical) position (in pixels) of the marker on the
+ * canvas
+ * @param array $values The values representing the data the marker 'points'
+ * to
+ * @access private
+ */
+ function _drawMarker($x, $y, $values = false)
+ {
+ $this->_getLineStyle();
+ $this->_canvas->line(
+ array(
+ 'x0' => $x - $this->_size,
+ 'y0' => $y - $this->_size,
+ 'x1' => $x + $this->_size,
+ 'y1' => $y + $this->_size
+ )
+ );
+
+ $this->_getLineStyle();
+ $this->_canvas->line(
+ array(
+ 'x0' => $x + $this->_size,
+ 'y0' => $y - $this->_size,
+ 'x1' => $x - $this->_size,
+ 'y1' => $y + $this->_size
+ )
+ );
+
+ $this->_getLineStyle();
+ $this->_canvas->line(
+ array(
+ 'x0' => $x - $this->_size,
+ 'y0' => $y,
+ 'x1' => $x + $this->_size,
+ 'y1' => $y
+ )
+ );
+
+ $this->_getLineStyle();
+ $this->_canvas->line(
+ array(
+ 'x0' => $x,
+ 'y0' => $y - $this->_size,
+ 'x1' => $x,
+ 'y1' => $y + $this->_size
+ )
+ );
+
+ parent::_drawMarker($x, $y, $values);
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Marker/Average.php b/config/dspam/pear/Image/Graph/Marker/Average.php
new file mode 100644
index 00000000..c4e3e7a4
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Marker/Average.php
@@ -0,0 +1,91 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Marker
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Marker.php
+ */
+require_once 'Image/Graph/Marker.php';
+
+/**
+ * A marker displaying the 'distance' to the datasets average value.
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Marker
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Marker_Average extends Image_Graph_Marker
+{
+
+ /**
+ * Draw the marker on the canvas
+ *
+ * @param int $x The X (horizontal) position (in pixels) of the marker on
+ * the canvas
+ * @param int $y The Y (vertical) position (in pixels) of the marker on the
+ * canvas
+ * @param array $values The values representing the data the marker 'points'
+ * to
+ * @access private
+ */
+ function _drawMarker($x, $y, $values = false)
+ {
+ if ((isset($values['AVERAGE_Y'])) &&
+ (is_a($this->_parent, 'Image_Graph_Plot')))
+ {
+ $point = $this->_pointXY(
+ array(
+ 'X' => $values['APX'],
+ 'Y' => $values['AVERAGE_Y']
+ )
+ );
+ $this->_getLineStyle();
+ $this->_canvas->line(array('x0' => $x, 'y0' => $y, 'x1' => $point['X'], 'y1' => $point['Y']));
+
+ $this->_getLineStyle();
+ $this->_canvas->line(
+ array(
+ 'x0' => $point['X'] - 2,
+ 'y0' => $point['Y'],
+ 'x1' => $point['X'] + 2,
+ 'y1' => $point['Y']
+ )
+ );
+ }
+ parent::_drawMarker($x, $y, $values);
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Marker/Box.php b/config/dspam/pear/Image/Graph/Marker/Box.php
new file mode 100644
index 00000000..5602c33d
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Marker/Box.php
@@ -0,0 +1,76 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Marker
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Marker.php
+ */
+require_once 'Image/Graph/Marker.php';
+
+/**
+ * Data marker as a box
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Marker
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Marker_Box extends Image_Graph_Marker
+{
+
+ /**
+ * Draw the marker on the canvas
+ *
+ * @param int $x The X (horizontal) position (in pixels) of the marker on the canvas
+ * @param int $y The Y (vertical) position (in pixels) of the marker on the canvas
+ * @param array $values The values representing the data the marker 'points' to
+ * @access private
+ */
+ function _drawMarker($x, $y, $values = false)
+ {
+ $this->_getFillStyle();
+ $this->_getLineStyle();
+ $this->_canvas->rectangle(
+ array(
+ 'x0' => $x - $this->_size,
+ 'y0' => $y - $this->_size,
+ 'x1' => $x + $this->_size,
+ 'y1' => $y + $this->_size
+ )
+ );
+ parent::_drawMarker($x, $y, $values);
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Marker/Bubble.php b/config/dspam/pear/Image/Graph/Marker/Bubble.php
new file mode 100644
index 00000000..180ab4e3
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Marker/Bubble.php
@@ -0,0 +1,91 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Marker
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Marker/Circle.php
+ */
+require_once 'Image/Graph/Marker/Circle.php';
+
+/**
+ * Display a circle with y-value percentage as radius (require GD2).
+ *
+ * This will display a circle centered on the datapoint with a radius calculated
+ * as a percentage of the maximum value. I.e. the radius depends on the y-value
+ * of the datapoint
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Marker
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Marker_Bubble extends Image_Graph_Marker_Circle
+{
+
+ /**
+ * The radius of the marker when 100%
+ * @var int
+ * @access private
+ */
+ var $_size100Pct = 40;
+
+ /**
+ * Sets the maximum radius the marker can occupy
+ *
+ * @param int $radius The new Image_Graph_max radius
+ */
+ function setMaxRadius($radius)
+ {
+ $this->_size100Pct = $radius;
+ }
+
+ /**
+ * Draw the marker on the canvas
+ *
+ * @param int $x The X (horizontal) position (in pixels) of the marker on
+ * the canvas
+ * @param int $y The Y (vertical) position (in pixels) of the marker on the
+ * canvas
+ * @param array $values The values representing the data the marker 'points'
+ * to
+ * @access private
+ */
+ function _drawMarker($x, $y, $values = false)
+ {
+ $this->_size = $this->_size100Pct*$values['PCT_MAX_Y']/100;
+ parent::_drawMarker($x, $y, $values);
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Marker/Circle.php b/config/dspam/pear/Image/Graph/Marker/Circle.php
new file mode 100644
index 00000000..7eeb5cb6
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Marker/Circle.php
@@ -0,0 +1,96 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Marker
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Marker.php
+ */
+require_once 'Image/Graph/Marker.php';
+
+/**
+ * Data marker as circle (require GD2)
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Marker
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Marker_Circle extends Image_Graph_Marker
+{
+
+ /**
+ * The 'size' of the marker, the meaning depends on the specific Marker
+ * implementation
+ * @var int
+ * @access private
+ */
+ var $_size = 10;
+
+ /**
+ * Draw the marker on the canvas
+ *
+ * @param int $x The X (horizontal) position (in pixels) of the marker on
+ * the canvas
+ * @param int $y The Y (vertical) position (in pixels) of the marker on the
+ * canvas
+ * @param array $values The values representing the data the marker 'points' to
+ * @access private
+ */
+ function _drawMarker($x, $y, $values = false)
+ {
+ $this->_getFillStyle();
+ $this->_getLineStyle();
+
+ $dA = 2*pi()/($this->_size*2);
+ $angle = 0;
+ while ($angle < 2*pi()) {
+ $this->_canvas->addVertex(array('x' =>
+ $x + $this->_size*cos($angle), 'y' =>
+ $y - $this->_size*sin($angle)
+ ));
+ $angle += $dA;
+ }
+
+ $this->_canvas->addVertex(array('x' =>
+ $x + $this->_size*cos(0), 'y' =>
+ $y - $this->_size*sin(0)
+ ));
+
+ $this->_canvas->polygon(array('connect' => true));
+
+ parent::_drawMarker($x, $y, $values);
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Marker/Cross.php b/config/dspam/pear/Image/Graph/Marker/Cross.php
new file mode 100644
index 00000000..720f3bb4
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Marker/Cross.php
@@ -0,0 +1,114 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Marker
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Marker.php
+ */
+require_once 'Image/Graph/Marker.php';
+
+/**
+ * Data marker as a cross.
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Marker
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Marker_Cross extends Image_Graph_Marker
+{
+
+ /**
+ * The thickness of the plus in pixels (thickness is actually double this)
+ * @var int
+ * @access private
+ */
+ var $_thickness = 2;
+
+ /**
+ * Draw the marker on the canvas
+ *
+ * @param int $x The X (horizontal) position (in pixels) of the marker on the canvas
+ * @param int $y The Y (vertical) position (in pixels) of the marker on the canvas
+ * @param array $values The values representing the data the marker 'points' to
+ * @access private
+ */
+ function _drawMarker($x, $y, $values = false)
+ {
+ if ($this->_thickness > 0) {
+ $this->_getLineStyle();
+ $this->_getFillStyle();
+
+ $d1 = round(0.7071067 * $this->_size); // cos/sin(45 de>)
+ $d2 = round(0.7071067 * $this->_thickness); // cos/sin(45 deg)
+
+ $this->_canvas->addVertex(array('x' => $x - $d1 - $d2, 'y' => $y - $d1 + $d2));
+ $this->_canvas->addVertex(array('x' => $x - $d1 + $d2, 'y' => $y - $d1 - $d2));
+ $this->_canvas->addVertex(array('x' => $x, 'y' => $y - 2 * $d2));
+ $this->_canvas->addVertex(array('x' => $x + $d1 - $d2, 'y' => $y - $d1 - $d2));
+ $this->_canvas->addVertex(array('x' => $x + $d1 + $d2, 'y' => $y - $d1 + $d2));
+ $this->_canvas->addVertex(array('x' => $x + 2 * $d2, 'y' => $y));
+ $this->_canvas->addVertex(array('x' => $x + $d1 + $d2, 'y' => $y + $d1 - $d2));
+ $this->_canvas->addVertex(array('x' => $x + $d1 - $d2, 'y' => $y + $d1 + $d2));
+ $this->_canvas->addVertex(array('x' => $x, 'y' => $y + 2 * $d2));
+ $this->_canvas->addVertex(array('x' => $x - $d1 + $d2, 'y' => $y + $d1 + $d2));
+ $this->_canvas->addVertex(array('x' => $x - $d1 - $d2, 'y' => $y + $d1 - $d2));
+ $this->_canvas->addVertex(array('x' => $x - 2 * $d2, 'y' => $y));
+ $this->_canvas->polygon(array('connect' => true));
+ } else {
+ $this->_getLineStyle();
+ $this->_canvas->line(
+ array(
+ 'x0' => $x - $this->_size,
+ 'y0' => $y - $this->_size,
+ 'x1' => $x + $this->_size,
+ 'y1' => $y + $this->_size
+ )
+ );
+
+ $this->_getLineStyle();
+ $this->_canvas->line(
+ array(
+ 'x0' => $x + $this->_size,
+ 'y0' => $y - $this->_size,
+ 'x1' => $x - $this->_size,
+ 'y1' => $y + $this->_size
+ )
+ );
+ }
+ parent::_drawMarker($x, $y, $values);
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Marker/Diamond.php b/config/dspam/pear/Image/Graph/Marker/Diamond.php
new file mode 100644
index 00000000..2a3d68c8
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Marker/Diamond.php
@@ -0,0 +1,73 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Marker
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Marker.php
+ */
+require_once 'Image/Graph/Marker.php';
+
+/**
+ * Data marker as a diamond.
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Marker
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Marker_Diamond extends Image_Graph_Marker
+{
+
+ /**
+ * Draw the marker on the canvas
+ *
+ * @param int $x The X (horizontal) position (in pixels) of the marker on the canvas
+ * @param int $y The Y (vertical) position (in pixels) of the marker on the canvas
+ * @param array $values The values representing the data the marker 'points' to
+ * @access private
+ */
+ function _drawMarker($x, $y, $values = false)
+ {
+ $this->_getFillStyle();
+ $this->_getLineStyle();
+ $this->_canvas->addVertex(array('x' => $x - $this->_size, 'y' => $y));
+ $this->_canvas->addVertex(array('x' => $x, 'y' => $y - $this->_size));
+ $this->_canvas->addVertex(array('x' => $x + $this->_size, 'y' => $y));
+ $this->_canvas->addVertex(array('x' => $x, 'y' => $y + $this->_size));
+ $this->_canvas->polygon(array('connect' => true));
+ parent::_drawMarker($x, $y, $values);
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Marker/Icon.php b/config/dspam/pear/Image/Graph/Marker/Icon.php
new file mode 100644
index 00000000..d9b9456f
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Marker/Icon.php
@@ -0,0 +1,133 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Marker
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Marker.php
+ */
+require_once 'Image/Graph/Marker.php';
+
+/**
+ * Data marker using an image as icon.
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Marker
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Marker_Icon extends Image_Graph_Marker
+{
+
+ /**
+ * Filename of the image icon
+ * @var string
+ * @access private
+ */
+ var $_filename;
+
+ /**
+ * X Point of the icon to use as data 'center'
+ * @var int
+ * @access private
+ */
+ var $_pointX = 0;
+
+ /**
+ * Y Point of the icon to use as data 'center'
+ * @var int
+ * @access private
+ */
+ var $_pointY = 0;
+
+ /**
+ * Create an icon marker
+ *
+ * @param string $filename The filename of the icon
+ * @param int $width The 'new' width of the icon if it is to be resized
+ * @param int $height The 'new' height of the icon if it is to be resized
+ */
+ function Image_Graph_Marker_Icon($filename, $width = 0, $height = 0)
+ {
+ parent::Image_Graph_Marker();
+ $this->_filename = $filename;
+ }
+
+ /**
+ * Set the X 'center' point of the marker
+ *
+ * @param int $x The X 'center' point of the marker
+ */
+ function setPointX($x)
+ {
+ $this->_pointX = $x;
+ }
+
+ /**
+ * Set the Y 'center' point of the marker
+ *
+ * @param int $y The Y 'center' point of the marker
+ */
+ function setPointY($y)
+ {
+ $this->_pointY = $y;
+ }
+
+ /**
+ * Draw the marker on the canvas
+ *
+ * @param int $x The X (horizontal) position (in pixels) of the marker on
+ * the canvas
+ * @param int $y The Y (vertical) position (in pixels) of the marker on the
+ * canvas
+ * @param array $values The values representing the data the marker 'points'
+ * to
+ * @access private
+ */
+ function _drawMarker($x, $y, $values = false)
+ {
+ parent::_drawMarker($x, $y, $values);
+ if ($this->_filename) {
+ $this->_canvas->image(
+ array(
+ 'x' => $x,
+ 'y' => $y,
+ 'filename' => $this->_filename,
+ 'alignment' => array('horizontal' => 'center', 'vertical' => 'center')
+ )
+ );
+ }
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Marker/Pinpoint.php b/config/dspam/pear/Image/Graph/Marker/Pinpoint.php
new file mode 100644
index 00000000..7b87f153
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Marker/Pinpoint.php
@@ -0,0 +1,65 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Marker
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Marker/Icon.php
+ */
+require_once 'Image/Graph/Marker/Icon.php';
+
+/**
+ * Data marker using a pinpoint as marker.
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Marker
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Marker_Pinpoint extends Image_Graph_Marker_Icon
+{
+
+ /**
+ * Create the marker as a pin point
+ */
+ function Image_Graph_Marker_Pinpoint()
+ {
+ parent::Image_Graph_Marker_Icon(
+ dirname(__FILE__).'/../Images/Icons/pinpoint.png'
+ );
+ $this->setPointX(0);
+ $this->setPointY(13);
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Marker/Plus.php b/config/dspam/pear/Image/Graph/Marker/Plus.php
new file mode 100644
index 00000000..0a817cfc
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Marker/Plus.php
@@ -0,0 +1,98 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Marker
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Marker.php
+ */
+require_once 'Image/Graph/Marker.php';
+
+/**
+ * Data marker as a plus.
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Marker
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Marker_Plus extends Image_Graph_Marker
+{
+
+ /**
+ * The thickness of the plus in pixels (thickness is actually double this)
+ * @var int
+ * @access private
+ */
+ var $_thickness = 2;
+
+ /**
+ * Draw the marker on the canvas
+ *
+ * @param int $x The X (horizontal) position (in pixels) of the marker on
+ * the canvas
+ * @param int $y The Y (vertical) position (in pixels) of the marker on the
+ * canvas
+ * @param array $values The values representing the data the marker 'points'
+ * to
+ * @access private
+ */
+ function _drawMarker($x, $y, $values = false)
+ {
+ if ($this->_thickness > 0) {
+ $this->_getLineStyle();
+ $this->_getFillStyle();
+ $this->_canvas->addVertex(array('x' => $x - $this->_size, 'y' => $y - $this->_thickness));
+ $this->_canvas->addVertex(array('x' => $x - $this->_thickness, 'y' => $y - $this->_thickness));
+ $this->_canvas->addVertex(array('x' => $x - $this->_thickness, 'y' => $y - $this->_size));
+ $this->_canvas->addVertex(array('x' => $x + $this->_thickness, 'y' => $y - $this->_size));
+ $this->_canvas->addVertex(array('x' => $x + $this->_thickness, 'y' => $y - $this->_thickness));
+ $this->_canvas->addVertex(array('x' => $x + $this->_size, 'y' => $y - $this->_thickness));
+ $this->_canvas->addVertex(array('x' => $x + $this->_size, 'y' => $y + $this->_thickness));
+ $this->_canvas->addVertex(array('x' => $x + $this->_thickness, 'y' => $y + $this->_thickness));
+ $this->_canvas->addVertex(array('x' => $x + $this->_thickness, 'y' => $y + $this->_size));
+ $this->_canvas->addVertex(array('x' => $x - $this->_thickness, 'y' => $y + $this->_size));
+ $this->_canvas->addVertex(array('x' => $x - $this->_thickness, 'y' => $y + $this->_thickness));
+ $this->_canvas->addVertex(array('x' => $x - $this->_size, 'y' => $y + $this->_thickness));
+ $this->_canvas->polygon(array('connect' => true));
+ } else {
+ $this->_getLineStyle();
+ $this->_canvas->line(array('x0' => $x - $this->_size, 'y0' => $y, 'x1' => $x + $this->_size, 'y1' => $y));
+ $this->_getLineStyle();
+ $this->_canvas->line(array('x0' => $x, 'y0' => $y - $this->_size, 'x1' => $x, 'y1' => $y + $this->_size));
+ }
+ parent::_drawMarker($x, $y, $values);
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Marker/Pointing.php b/config/dspam/pear/Image/Graph/Marker/Pointing.php
new file mode 100644
index 00000000..05ab94e4
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Marker/Pointing.php
@@ -0,0 +1,140 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Marker
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Marker.php
+ */
+require_once 'Image/Graph/Marker.php';
+
+/**
+ * Data marker as a 'pointing marker'.
+ *
+ * Points to the data using another marker (as start and/or end)
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Marker
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Marker_Pointing extends Image_Graph_Marker
+{
+
+ /**
+ * The starting marker
+ * @var Marker
+ * @access private
+ */
+ var $_markerStart;
+
+ /**
+ * The ending marker
+ * @var Marker
+ * @access private
+ */
+ var $_markerEnd;
+
+ /**
+ * The X offset from the 'data'
+ * @var int
+ * @access private
+ */
+ var $_deltaX = -1;
+
+ /**
+ * The Y offset from the 'data'
+ * @var int
+ * @access private
+ */
+ var $_deltaY = -1;
+
+ /**
+ * Create an pointing marker, ie a pin on a board
+ *
+ * @param int $deltaX The the X offset from the real 'data' point
+ * @param int $deltaY The the Y offset from the real 'data' point
+ * @param Marker $markerEnd The ending marker that represents 'the head of
+ * the pin'
+ */
+ function Image_Graph_Marker_Pointing($deltaX, $deltaY, & $markerEnd)
+ {
+ parent::Image_Graph_Marker();
+ $this->_deltaX = $deltaX;
+ $this->_deltaY = $deltaY;
+ $this->_markerStart = null;
+ $this->_markerEnd =& $markerEnd;
+ }
+
+ /**
+ * Sets the starting marker, ie the tip of the pin on a board
+ *
+ * @param Marker $markerStart The starting marker that represents 'the tip
+ * of the pin'
+ */
+ function setMarkerStart(& $markerStart)
+ {
+ $this->_markerStart =& $markerStart;
+ $this->_markerStart->_setParent($this);
+ }
+
+ /**
+ * Draw the marker on the canvas
+ *
+ * @param int $x The X (horizontal) position (in pixels) of the marker on
+ * the canvas
+ * @param int $y The Y (vertical) position (in pixels) of the marker on the
+ * canvas
+ * @param array $values The values representing the data the marker 'points'
+ * to
+ * @access private
+ */
+ function _drawMarker($x, $y, $values = false)
+ {
+ parent::_drawMarker($x, $y, $values);
+ if ($this->_markerStart) {
+ $this->_markerStart->_setParent($this);
+ $this->_markerStart->_drawMarker($x, $y, $values);
+ }
+ $this->_getLineStyle();
+ $this->_canvas->line(array('x0' => $x, 'y0' => $y, 'x1' => $x + $this->_deltaX, 'y1' => $y + $this->_deltaY));
+ $this->_markerEnd->_setParent($this);
+ $this->_markerEnd->_drawMarker(
+ $x + $this->_deltaX,
+ $y + $this->_deltaY,
+ $values
+ );
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Marker/Pointing/Angular.php b/config/dspam/pear/Image/Graph/Marker/Pointing/Angular.php
new file mode 100644
index 00000000..93b8b7cf
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Marker/Pointing/Angular.php
@@ -0,0 +1,105 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Marker
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Marker/Pointing.php
+ */
+require_once 'Image/Graph/Marker/Pointing.php';
+
+/**
+ * Marker that points 'away' from the graph.
+ *
+ * Use this as a marker for displaying another marker pointing to the original
+ * point on the graph - where the 'pointer' is calculated as line orthogonal to
+ * a line drawn between the points neighbours to both sides (an approximate
+ * tangent). This should make an the pointer appear to point 'straight' out from
+ * the graph. The 'head' of the pointer is then another marker of any choice.
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Marker
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Marker_Pointing_Angular extends Image_Graph_Marker_Pointing
+{
+
+ /**
+ * The length of the angular marker
+ * @var int
+ * @access private
+ */
+ var $_radius;
+
+ /**
+ * Image_Graph_AngularPointingMarker [Constructor]
+ * @param int $radius The 'length' of the pointer
+ * @param Marker $markerEnd The ending marker that represents 'the head of
+ * the pin'
+ */
+ function Image_Graph_Marker_Pointing_Angular($radius, & $markerEnd)
+ {
+ parent::Image_Graph_Marker_Pointing(0, 0, $markerEnd);
+ $this->_radius = $radius;
+ }
+
+ /**
+ * Draw the marker on the canvas
+ * @param int $x The X (horizontal) position (in pixels) of the marker on
+ * the canvas
+ * @param int $y The Y (vertical) position (in pixels) of the marker on the
+ * canvas
+ * @param array $values The values representing the data the marker 'points'
+ * to
+ * @access private
+ */
+ function _drawMarker($x, $y, $values = false)
+ {
+ if ((isset($values['LENGTH'])) && ($values['LENGTH'] != 0)) {
+ $this->_deltaX = - $values['AX'] * $this->_radius / $values['LENGTH'];
+ $this->_deltaY = - $values['AY'] * $this->_radius / $values['LENGTH'];
+ }
+
+ if ((isset($values['NPY'])) && (isset($values['APY'])) &&
+ (isset($values['PPY'])) && ($values['NPY'] > $values['APY']) &&
+ ($values['PPY'] > $values['APY']))
+ {
+ $this->_deltaX = - $this->_deltaX;
+ $this->_deltaY = - $this->_deltaY;
+ }
+ parent::_drawMarker($x, $y, $values);
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Marker/Pointing/Radial.php b/config/dspam/pear/Image/Graph/Marker/Pointing/Radial.php
new file mode 100644
index 00000000..ce1a0aac
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Marker/Pointing/Radial.php
@@ -0,0 +1,91 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Marker
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Marker/Pointing.php
+ */
+require_once 'Image/Graph/Marker/Pointing.php';
+
+/**
+ * A pointing marker in a random angle from the data
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Marker
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Marker_Pointing_Radial extends Image_Graph_Marker_Pointing
+{
+
+ /**
+ * The radius of the radial marker
+ * @var int
+ * @access private
+ */
+ var $_radius;
+
+ /**
+ * Create an radial pointing marker, ie a marker on a defined distance from
+ * the data
+ * @param int $radius The 'length' of the pointer
+ * @param Marker $markerEnd The ending marker that represents 'the head of
+ * the pin'
+ */
+ function Image_Graph_Marker_Pointing_Radial($radius, & $markerEnd)
+ {
+ parent::Image_Graph_Marker_Pointing(0, 0, $markerEnd);
+ $this->_radius = $radius;
+ }
+
+ /**
+ * Draw the marker on the canvas
+ * @param int $x The X (horizontal) position (in pixels) of the marker on
+ * the canvas
+ * @param int $y The Y (vertical) position (in pixels) of the marker on the
+ * canvas
+ * @param array $values The values representing the data the marker 'points'
+ * to
+ * @access private
+ */
+ function _drawMarker($x, $y, $values = false)
+ {
+ $angle = pi() * rand(0, 360) / 180;
+ $this->_deltaX = $this->_radius * cos($angle);
+ $this->_deltaY = $this->_radius * sin($angle);
+ parent::_drawMarker($x, $y, $values);
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Marker/ReversePinpoint.php b/config/dspam/pear/Image/Graph/Marker/ReversePinpoint.php
new file mode 100644
index 00000000..57e945ab
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Marker/ReversePinpoint.php
@@ -0,0 +1,65 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Marker
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Marker/Icon.php
+ */
+require_once 'Image/Graph/Marker/Icon.php';
+
+/**
+ * Data marker using a (reverse) pinpoint as marker.
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Marker
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Marker_ReversePinpoint extends Image_Graph_Marker_Icon
+{
+
+ /**
+ * Create the marker as a reverse pin point
+ */
+ function Image_Graph_Marker_ReversePinpoint()
+ {
+ parent::Image_Graph_Marker_Icon(
+ dirname(__FILE__).'/../Images/Icons/pinpointr.png'
+ );
+ $this->setPointX(10);
+ $this->setPointY(13);
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Marker/Star.php b/config/dspam/pear/Image/Graph/Marker/Star.php
new file mode 100644
index 00000000..67b2b9b3
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Marker/Star.php
@@ -0,0 +1,88 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Marker
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Marker.php
+ */
+require_once 'Image/Graph/Marker.php';
+
+/**
+ * Data marker as a triangle.
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Marker
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Marker_Star extends Image_Graph_Marker
+{
+
+ /**
+ * Draw the marker on the canvas
+ *
+ * @param int $x The X (horizontal) position (in pixels) of the marker on
+ * the canvas
+ * @param int $y The Y (vertical) position (in pixels) of the marker on the
+ * canvas
+ * @param array $values The values representing the data the marker 'points'
+ * to
+ * @access private
+ */
+ function _drawMarker($x, $y, $values = false)
+ {
+ $this->_getFillStyle();
+ $this->_getLineStyle();
+
+ $d = $this->_size / 5;
+ $x = round($x);
+ $y = round($y);
+
+ $this->_canvas->addVertex(array('x' => $x, 'y' => $y - $this->_size));
+ $this->_canvas->addVertex(array('x' => $x + round($d), 'y' => $y - round($d)));
+ $this->_canvas->addVertex(array('x' => $x + $this->_size, 'y' => $y - round($d)));
+ $this->_canvas->addVertex(array('x' => $x + round(2 * $d), 'y' => $y + round($d)));
+ $this->_canvas->addVertex(array('x' => $x + round(3 * $d), 'y' => $y + $this->_size));
+ $this->_canvas->addVertex(array('x' => $x, 'y' => $y + round(3 * $d)));
+ $this->_canvas->addVertex(array('x' => $x - round(3 * $d), 'y' => $y + $this->_size));
+ $this->_canvas->addVertex(array('x' => $x - round(2 * $d), 'y' => $y + round($d)));
+ $this->_canvas->addVertex(array('x' => $x - $this->_size, 'y' => $y - round($d)));
+ $this->_canvas->addVertex(array('x' => $x - round($d), 'y' => $y - round($d)));
+ $this->_canvas->polygon(array('connect' => true));
+
+ parent::_drawMarker($x, $y, $values);
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Marker/Triangle.php b/config/dspam/pear/Image/Graph/Marker/Triangle.php
new file mode 100644
index 00000000..626f2589
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Marker/Triangle.php
@@ -0,0 +1,75 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Marker
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Marker.php
+ */
+require_once 'Image/Graph/Marker.php';
+
+/**
+ * Data marker as a triangle.
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Marker
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Marker_Triangle extends Image_Graph_Marker
+{
+
+ /**
+ * Draw the marker on the canvas
+ *
+ * @param int $x The X (horizontal) position (in pixels) of the marker on
+ * the canvas
+ * @param int $y The Y (vertical) position (in pixels) of the marker on the
+ * canvas
+ * @param array $values The values representing the data the marker 'points'
+ * to
+ * @access private
+ */
+ function _drawMarker($x, $y, $values = false)
+ {
+ $this->_getFillStyle();
+ $this->_getLineStyle();
+ $this->_canvas->addVertex(array('x' => $x - $this->_size, 'y' => $y + $this->_size));
+ $this->_canvas->addVertex(array('x' => $x, 'y' => $y - $this->_size));
+ $this->_canvas->addVertex(array('x' => $x + $this->_size, 'y' => $y + $this->_size));
+ $this->_canvas->polygon(array('connect' => true));
+ parent::_drawMarker($x, $y, $values);
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Marker/Value.php b/config/dspam/pear/Image/Graph/Marker/Value.php
new file mode 100644
index 00000000..24f142f3
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Marker/Value.php
@@ -0,0 +1,214 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Marker
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Marker.php
+ */
+require_once 'Image/Graph/Marker.php';
+
+/**
+ * A marker showing the data value.
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Marker
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Marker_Value extends Image_Graph_Marker
+{
+
+ /**
+ * Datapreproccesor to format the value
+ * @var DataPreprocessor
+ * @access private
+ */
+ var $_dataPreprocessor = null;
+
+ /**
+ * Which value to use from the data set, ie the X or Y value
+ * @var int
+ * @access private
+ */
+ var $_useValue;
+
+ /**
+ * Create a value marker, ie a box containing the value of the 'pointing
+ * data'
+ *
+ * @param int $useValue Defines which value to use from the dataset, i.e. the
+ * X or Y value
+ */
+ function Image_Graph_Marker_Value($useValue = IMAGE_GRAPH_VALUE_X)
+ {
+ parent::Image_Graph_Marker();
+ $this->_padding = array('left' => 2, 'top' => 2, 'right' => 2, 'bottom' => 2);
+ $this->_useValue = $useValue;
+ $this->_fillStyle = 'white';
+ $this->_borderStyle = 'black';
+ }
+
+ /**
+ * Sets the background fill style of the element
+ *
+ * @param Image_Graph_Fill $background The background
+ * @see Image_Graph_Fill
+ */
+ function setBackground(& $background)
+ {
+ $this->setFillStyle($background);
+ }
+
+ /**
+ * Sets the background color of the element
+ *
+ * @param mixed $color The color
+ */
+ function setBackgroundColor($color)
+ {
+ $this->setFillColor($color);
+ }
+
+ /**
+ * Sets a data preprocessor for formatting the values
+ *
+ * @param DataPreprocessor $dataPreprocessor The data preprocessor
+ * @return Image_Graph_DataPreprocessor The data preprocessor
+ */
+ function &setDataPreprocessor(& $dataPreprocessor)
+ {
+ $this->_dataPreprocessor =& $dataPreprocessor;
+ return $dataPreprocessor;
+ }
+
+ /**
+ * Get the value to display
+ *
+ * @param array $values The values representing the data the marker 'points'
+ * to
+ * @return string The display value, this is the pre-preprocessor value, to
+ * support for customized with multiple values. i.e show 'x = y' or '(x, y)'
+ * @access private
+ */
+ function _getDisplayValue($values)
+ {
+ switch ($this->_useValue) {
+ case IMAGE_GRAPH_VALUE_X:
+ $value = $values['X'];
+ break;
+
+ case IMAGE_GRAPH_PCT_X_MIN:
+ $value = $values['PCT_MIN_X'];
+ break;
+
+ case IMAGE_GRAPH_PCT_X_MAX:
+ $value = $values['PCT_MAX_X'];
+ break;
+
+ case IMAGE_GRAPH_PCT_Y_MIN:
+ $value = $values['PCT_MIN_Y'];
+ break;
+
+ case IMAGE_GRAPH_PCT_Y_MAX:
+ $value = $values['PCT_MAX_Y'];
+ break;
+
+ case IMAGE_GRAPH_PCT_Y_TOTAL:
+ if (isset($values['SUM_Y'])) {
+ $value = 100 * $values['Y'] / $values['SUM_Y'];
+ }
+ else {
+ $value = 0;
+ }
+ break;
+
+ case IMAGE_GRAPH_POINT_ID:
+ $value = $values['ID'];
+ break;
+
+ default:
+ $value = $values['Y'];
+ break;
+ }
+ return $value;
+ }
+
+ /**
+ * Draw the marker on the canvas
+ *
+ * @param int $x The X (horizontal) position (in pixels) of the marker on
+ * the canvas
+ * @param int $y The Y (vertical) position (in pixels) of the marker on the
+ * canvas
+ * @param array $values The values representing the data the marker 'points'
+ * to
+ * @access private
+ */
+ function _drawMarker($x, $y, $values = false)
+ {
+ parent::_drawMarker($x, $y, $values);
+
+ $value = $this->_getDisplayValue($values);
+
+ if ($this->_dataPreprocessor) {
+ $value = $this->_dataPreprocessor->_process($value);
+ }
+
+ if ($this->_defaultFontOptions !== false) {
+ $this->_canvas->setFont($this->_defaultFontOptions);
+ } else {
+ $this->_canvas->setFont($this->_getFont());
+ }
+
+ $width = $this->_canvas->textWidth($value);
+ $height = $this->_canvas->textHeight($value);
+ $offsetX = $width/2 + $this->_padding['left'];
+ $offsetY = $height/2 + $this->_padding['top'];
+
+ $this->_getFillStyle();
+ $this->_getBorderStyle();
+ $this->_canvas->rectangle(
+ array(
+ 'x0' => $x - $offsetX,
+ 'y0' => $y - $offsetY,
+ 'x1' => $x + $offsetX,
+ 'y1' => $y + $offsetY
+ )
+ );
+
+ $this->write($x, $y, $value, IMAGE_GRAPH_ALIGN_CENTER);
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Plot.php b/config/dspam/pear/Image/Graph/Plot.php
new file mode 100644
index 00000000..4a6c16d3
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Plot.php
@@ -0,0 +1,824 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Plot
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Plotarea/Element.php
+ */
+require_once 'Image/Graph/Plotarea/Element.php';
+
+/**
+ * Framework for a chart
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Plot
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ * @abstract
+ */
+class Image_Graph_Plot extends Image_Graph_Plotarea_Element
+{
+
+ /**
+ * The dataset to plot
+ * @var Dataset
+ * @access private
+ */
+ var $_dataset;
+
+ /**
+ * The marker to plot the data set as
+ * @var Marker
+ * @access private
+ */
+ var $_marker = null;
+
+ /**
+ * The dataselector to use for data marking
+ * @var DataSelector
+ * @access private
+ */
+ var $_dataSelector = null;
+
+ /**
+ * The Y axis to associate the plot with
+ * @var int
+ * @access private
+ */
+ var $_axisY = IMAGE_GRAPH_AXIS_Y;
+
+ /**
+ * The type of the plot if multiple datasets are used
+ * @var string
+ * @access private
+ */
+ var $_multiType = 'normal';
+
+ /**
+ * The title of the plot, used for legending in case of simple plots
+ * @var string
+ * @access private
+ */
+ var $_title = 'plot';
+
+ /**
+ * PlotType [Constructor]
+ *
+ * Valid values for multiType are:
+ *
+ * 'normal' Plot is normal, multiple datasets are displayes next to one
+ * another
+ *
+ * 'stacked' Datasets are stacked on top of each other
+ *
+ * 'stacked100pct' Datasets are stacked and displayed as percentages of the
+ * total sum
+ *
+ * I no title is specified a default is used, which is basically the plot
+ * type (fx. for a 'Image_Graph_Plot_Smoothed_Area' default title is
+ * 'Smoothed Area')
+ *
+ * @param Image_Graph_Dataset $dataset The data set (value containter) to
+ * plot or an array of datasets
+ * @param string $multiType The type of the plot
+ * @param string $title The title of the plot (used for legends,
+ * {@link Image_Graph_Legend})
+ */
+ function Image_Graph_Plot(& $dataset, $multiType = 'normal', $title = '')
+ {
+ if (!is_a($dataset, 'Image_Graph_Dataset')) {
+ if (is_array($dataset)) {
+ $keys = array_keys($dataset);
+ foreach ($keys as $key) {
+ if (!is_a($dataset[$key], 'Image_Graph_Dataset')) {
+ $this->_error('Invalid dataset passed to ' . get_class($this));
+ }
+ }
+ unset($keys);
+ } else {
+ $this->_error('Invalid dataset passed to ' . get_class($this));
+ }
+ }
+
+ parent::Image_Graph_Common();
+ if ($dataset) {
+ if (is_array($dataset)) {
+ $this->_dataset =& $dataset;
+ } else {
+ $this->_dataset = array(&$dataset);
+ }
+ }
+ if ($title) {
+ $this->_title = $title;
+ } else {
+ $this->_title = str_replace('_', ' ', substr(get_class($this), 17));
+ }
+
+ $multiType = strtolower($multiType);
+ if (($multiType == 'normal') ||
+ ($multiType == 'stacked') ||
+ ($multiType == 'stacked100pct'))
+ {
+ $this->_multiType = $multiType;
+ } else {
+ $this->_error(
+ 'Invalid multitype: ' . $multiType .
+ ' expected (normal|stacked|stacked100pct)'
+ );
+ $this->_multiType = 'normal';
+ }
+ }
+
+ /**
+ * Sets the title of the plot, used for legend
+ *
+ * @param string $title The title of the plot
+ */
+ function setTitle($title)
+ {
+ $this->_title = $title;
+ }
+
+ /**
+ * Parses the URL mapping data in the point and adds it to the parameter array used by
+ * Image_Canvas
+ *
+ * @param array $point The data point (from the dataset)
+ * @param array $canvasData The The for the canvas method
+ * @return array The union of the canvas data points and the appropriate points for the dataset
+ * @access private
+ */
+ function _mergeData($point, $canvasData)
+ {
+ if (isset($point['data'])) {
+ if (isset($point['data']['url'])) {
+ $canvasData['url'] = $point['data']['url'];
+ }
+ if (isset($point['data']['target'])) {
+ $canvasData['target'] = $point['data']['target'];
+ }
+ if (isset($point['data']['alt'])) {
+ $canvasData['alt'] = $point['data']['alt'];
+ }
+ if (isset($point['data']['htmltags'])) {
+ $canvasData['htmltags'] = $point['data']['htmltags'];
+ }
+ }
+
+ return $canvasData;
+ }
+
+ /**
+ * Sets the Y axis to plot the data
+ *
+ * @param int $axisY The Y axis (either IMAGE_GRAPH_AXIS_Y / 'y' or
+ * IMAGE_GRAPH_AXIS_Y_SECONDARY / 'ysec' (defaults to IMAGE_GRAPH_AXIS_Y))
+ * @access private
+ */
+ function _setAxisY($axisY)
+ {
+ if ($axisY == 'y') {
+ $this->_axisY = IMAGE_GRAPH_AXIS_Y;
+ } elseif ($axisY == 'ysec') {
+ $this->_axisY = IMAGE_GRAPH_AXIS_Y_SECONDARY;
+ } else {
+ $this->_axisY = $axisY;
+ }
+ }
+
+ /**
+ * Sets the marker to 'display' data points on the graph
+ *
+ * @param Marker $marker The marker
+ */
+ function &setMarker(& $marker)
+ {
+ $this->add($marker);
+ $this->_marker =& $marker;
+ return $marker;
+ }
+
+ /**
+ * Sets the dataselector to specify which data should be displayed on the
+ * plot as markers and which are not
+ *
+ * @param DataSelector $dataSelector The dataselector
+ */
+ function setDataSelector(& $dataSelector)
+ {
+ $this->_dataSelector =& $dataSelector;
+ }
+
+ /**
+ * Calculate marker point data
+ *
+ * @param array Point The point to calculate data for
+ * @param array NextPoint The next point
+ * @param array PrevPoint The previous point
+ * @param array Totals The pre-calculated totals, if needed
+ * @return array An array containing marker point data
+ * @access private
+ */
+ function _getMarkerData($point, $nextPoint, $prevPoint, & $totals)
+ {
+ if (is_array($this->_dataset)) {
+ if ($this->_multiType == 'stacked') {
+ if (!isset($totals['SUM_Y'])) {
+ $totals['SUM_Y'] = array();
+ }
+ $x = $point['X'];
+ if (!isset($totals['SUM_Y'][$x])) {
+ $totals['SUM_Y'][$x] = 0;
+ }
+ } elseif ($this->_multiType == 'stacked100pct') {
+ $x = $point['X'];
+ if ($totals['TOTAL_Y'][$x] != 0) {
+ if (!isset($totals['SUM_Y'])) {
+ $totals['SUM_Y'] = array();
+ }
+ if (!isset($totals['SUM_Y'][$x])) {
+ $totals['SUM_Y'][$x] = 0;
+ }
+ }
+ }
+
+ if (isset($totals['ALL_SUM_Y'])) {
+ $point['SUM_Y'] = $totals['ALL_SUM_Y'];
+ }
+
+ if (!$prevPoint) {
+ $point['AX'] = -5;
+ $point['AY'] = 5;
+ $point['PPX'] = 0;
+ $point['PPY'] = 0;
+ $point['NPX'] = $nextPoint['X'];
+ $point['NPY'] = $nextPoint['Y'];
+ } elseif (!$nextPoint) {
+ $point['AX'] = 5;
+ $point['AY'] = 5;
+ $point['PPX'] = $prevPoint['X'];
+ $point['PPY'] = $prevPoint['Y'];
+ $point['NPX'] = 0;
+ $point['NPY'] = 0;
+ } else {
+ $point['AX'] = $this->_pointY($prevPoint) - $this->_pointY($nextPoint);
+ $point['AY'] = $this->_pointX($nextPoint) - $this->_pointX($prevPoint);
+ $point['PPX'] = $prevPoint['X'];
+ $point['PPY'] = $prevPoint['Y'];
+ $point['NPX'] = $nextPoint['X'];
+ $point['NPY'] = $nextPoint['Y'];
+ }
+
+ $point['APX'] = $point['X'];
+ $point['APY'] = $point['Y'];
+
+ if ((isset($totals['MINIMUM_X'])) && ($totals['MINIMUM_X'] != 0)) {
+ $point['PCT_MIN_X'] = 100 * $point['X'] / $totals['MINIMUM_X'];
+ }
+ if ((isset($totals['MAXIMUM_X'])) && ($totals['MAXIMUM_X'] != 0)) {
+ $point['PCT_MAX_X'] = 100 * $point['X'] / $totals['MAXIMUM_X'];
+ }
+
+ if ((isset($totals['MINIMUM_Y'])) && ($totals['MINIMUM_Y'] != 0)) {
+ $point['PCT_MIN_Y'] = 100 * $point['Y'] / $totals['MINIMUM_Y'];
+ }
+ if ((isset($totals['MAXIMUM_Y'])) && ($totals['MAXIMUM_Y'] != 0)) {
+ $point['PCT_MAX_Y'] = 100 * $point['Y'] / $totals['MAXIMUM_Y'];
+ }
+
+ $point['LENGTH'] = sqrt($point['AX'] * $point['AX'] +
+ $point['AY'] * $point['AY']);
+
+ if ((isset($point['LENGTH'])) && ($point['LENGTH'] != 0)) {
+ $point['ANGLE'] = asin($point['AY'] / $point['LENGTH']);
+ }
+
+ if ((isset($point['AX'])) && ($point['AX'] > 0)) {
+ $point['ANGLE'] = pi() - $point['ANGLE'];
+ }
+
+ if ($this->_parent->_horizontal) {
+ $point['MARKER_Y1'] = $this->_pointY($point) -
+ (isset($totals['WIDTH']) ? $totals['WIDTH'] : 0);
+
+ $point['MARKER_Y2'] = $this->_pointY($point) +
+ (isset($totals['WIDTH']) ? $totals['WIDTH'] : 0);
+
+ $point['COLUMN_WIDTH'] = abs($point['MARKER_Y2'] -
+ $point['MARKER_Y1']) / count($this->_dataset);
+
+ $point['MARKER_Y'] = $point['MARKER_Y1'] +
+ ((isset($totals['NUMBER']) ? $totals['NUMBER'] : 0) + 0.5) *
+ $point['COLUMN_WIDTH'];
+
+ $point['MARKER_X'] = $this->_pointX($point);
+
+ if ($this->_multiType == 'stacked') {
+ $point['MARKER_Y'] =
+ ($point['MARKER_Y1'] + $point['MARKER_Y2']) / 2;
+
+ $P1 = array('Y' => $totals['SUM_Y'][$x]);
+ $P2 = array('Y' => $totals['SUM_Y'][$x] + $point['Y']);
+
+ $point['MARKER_X'] =
+ ($this->_pointX($P1) + $this->_pointX($P2)) / 2;
+ } elseif ($this->_multiType == 'stacked100pct') {
+ $x = $point['X'];
+ if ($totals['TOTAL_Y'][$x] != 0) {
+ $point['MARKER_Y'] =
+ ($point['MARKER_Y1'] + $point['MARKER_Y2']) / 2;
+
+ $P1 = array(
+ 'Y' => 100 * $totals['SUM_Y'][$x] / $totals['TOTAL_Y'][$x]
+ );
+
+ $P2 = array(
+ 'Y' => 100 * ($totals['SUM_Y'][$x] + $point['Y']) / $totals['TOTAL_Y'][$x]
+ );
+
+ $point['MARKER_X'] =
+ ($this->_pointX($P1) + $this->_pointX($P2)) / 2;
+ } else {
+ $point = false;
+ }
+ }
+ }
+ else {
+ $point['MARKER_X1'] = $this->_pointX($point) -
+ (isset($totals['WIDTH']) ? $totals['WIDTH'] : 0);
+
+ $point['MARKER_X2'] = $this->_pointX($point) +
+ (isset($totals['WIDTH']) ? $totals['WIDTH'] : 0);
+
+ $point['COLUMN_WIDTH'] = abs($point['MARKER_X2'] -
+ $point['MARKER_X1']) / count($this->_dataset);
+
+ $point['MARKER_X'] = $point['MARKER_X1'] +
+ ((isset($totals['NUMBER']) ? $totals['NUMBER'] : 0) + 0.5) *
+ $point['COLUMN_WIDTH'];
+
+ $point['MARKER_Y'] = $this->_pointY($point);
+
+ if ($this->_multiType == 'stacked') {
+ $point['MARKER_X'] =
+ ($point['MARKER_X1'] + $point['MARKER_X2']) / 2;
+
+ $P1 = array('Y' => $totals['SUM_Y'][$x]);
+ $P2 = array('Y' => $totals['SUM_Y'][$x] + $point['Y']);
+
+ $point['MARKER_Y'] =
+ ($this->_pointY($P1) + $this->_pointY($P2)) / 2;
+ } elseif ($this->_multiType == 'stacked100pct') {
+ $x = $point['X'];
+ if ($totals['TOTAL_Y'][$x] != 0) {
+ $point['MARKER_X'] =
+ ($point['MARKER_X1'] + $point['MARKER_X2']) / 2;
+
+ $P1 = array(
+ 'Y' => 100 * $totals['SUM_Y'][$x] / $totals['TOTAL_Y'][$x]
+ );
+
+ $P2 = array(
+ 'Y' => 100 * ($totals['SUM_Y'][$x] + $point['Y']) / $totals['TOTAL_Y'][$x]
+ );
+
+ $point['MARKER_Y'] =
+ ($this->_pointY($P1) + $this->_pointY($P2)) / 2;
+ } else {
+ $point = false;
+ }
+ }
+ }
+ return $point;
+ }
+ }
+
+ /**
+ * Draws markers on the canvas
+ *
+ * @access private
+ */
+ function _drawMarker()
+ {
+ if (($this->_marker) && (is_array($this->_dataset))) {
+ $this->_canvas->startGroup(get_class($this) . '_marker');
+
+ $totals = $this->_getTotals();
+ $totals['WIDTH'] = $this->width() / ($this->_maximumX() + 2) / 2;
+
+ $number = 0;
+ $keys = array_keys($this->_dataset);
+ foreach ($keys as $key) {
+ $dataset =& $this->_dataset[$key];
+ $totals['MINIMUM_X'] = $dataset->minimumX();
+ $totals['MAXIMUM_X'] = $dataset->maximumX();
+ $totals['MINIMUM_Y'] = $dataset->minimumY();
+ $totals['MAXIMUM_Y'] = $dataset->maximumY();
+ $totals['NUMBER'] = $number ++;
+ $dataset->_reset();
+ while ($point = $dataset->_next()) {
+ $prevPoint = $dataset->_nearby(-2);
+ $nextPoint = $dataset->_nearby();
+
+ $x = $point['X'];
+ $y = $point['Y'];
+ if (((!is_object($this->_dataSelector)) ||
+ ($this->_dataSelector->_select($point))) && ($point['Y'] !== null))
+ {
+
+ $point = $this->_getMarkerData(
+ $point,
+ $nextPoint,
+ $prevPoint,
+ $totals
+ );
+
+ if (is_array($point)) {
+ $this->_marker->_drawMarker(
+ $point['MARKER_X'],
+ $point['MARKER_Y'],
+ $point
+ );
+ }
+ }
+ if (!isset($totals['SUM_Y'])) {
+ $totals['SUM_Y'] = array();
+ }
+ if (isset($totals['SUM_Y'][$x])) {
+ $totals['SUM_Y'][$x] += $y;
+ } else {
+ $totals['SUM_Y'][$x] = $y;
+ }
+ }
+ }
+ unset($keys);
+ $this->_canvas->endGroup();
+ }
+ }
+
+ /**
+ * Get the minimum X value from the dataset
+ *
+ * @return double The minimum X value
+ * @access private
+ */
+ function _minimumX()
+ {
+ if (!is_array($this->_dataset)) {
+ return 0;
+ }
+
+ $min = false;
+ if (is_array($this->_dataset)) {
+ $keys = array_keys($this->_dataset);
+ foreach ($keys as $key) {
+ if ($min === false) {
+ $min = $this->_dataset[$key]->minimumX();
+ } else {
+ $min = min($min, $this->_dataset[$key]->minimumX());
+ }
+ }
+ unset($keys);
+ }
+ return $min;
+ }
+
+ /**
+ * Get the maximum X value from the dataset
+ *
+ * @return double The maximum X value
+ * @access private
+ */
+ function _maximumX()
+ {
+ if (!is_array($this->_dataset)) {
+ return 0;
+ }
+
+ $max = 0;
+ if (is_array($this->_dataset)) {
+ $keys = array_keys($this->_dataset);
+ foreach ($keys as $key) {
+ $max = max($max, $this->_dataset[$key]->maximumX());
+ }
+ unset($keys);
+ }
+ return $max;
+ }
+
+ /**
+ * Get the minimum Y value from the dataset
+ *
+ * @return double The minimum Y value
+ * @access private
+ */
+ function _minimumY()
+ {
+ if (!is_array($this->_dataset)) {
+ return 0;
+ }
+
+ $min = false;
+ if (is_array($this->_dataset)) {
+ $keys = array_keys($this->_dataset);
+ foreach ($keys as $key) {
+ if ($this->_multiType == 'normal') {
+ if ($min === false) {
+ $min = $this->_dataset[$key]->minimumY();
+ } else {
+ $min = min($min, $this->_dataset[$key]->minimumY());
+ }
+ } else {
+ if ($min === false) {
+ $min = 0;
+ }
+ $dataset =& $this->_dataset[$key];
+ $dataset->_reset();
+ while ($point = $dataset->_next()) {
+ if ($point['Y'] < 0) {
+ $x = $point['X'];
+ if ((!isset($total)) || (!isset($total[$x]))) {
+ $total[$x] = $point['Y'];
+ } else {
+ $total[$x] += $point['Y'];
+ }
+ if (isset($min)) {
+ $min = min($min, $total[$x]);
+ } else {
+ $min = $total[$x];
+ }
+ }
+ }
+ }
+ }
+ unset($keys);
+ }
+ return $min;
+ }
+
+ /**
+ * Get the maximum Y value from the dataset
+ *
+ * @return double The maximum Y value
+ * @access private
+ */
+ function _maximumY()
+ {
+ if ($this->_multiType == 'stacked100pct') {
+ return 100;
+ }
+
+ $maxY = 0;
+ if (is_array($this->_dataset)) {
+ $keys = array_keys($this->_dataset);
+ foreach ($keys as $key) {
+ $dataset =& $this->_dataset[$key];
+
+ if ($this->_multiType == 'normal') {
+ if (isset($maxY)) {
+ $maxY = max($maxY, $dataset->maximumY());
+ } else {
+ $maxY = $dataset->maximumY();
+ }
+ } else {
+ $dataset->_reset();
+ while ($point = $dataset->_next()) {
+ if ($point['Y'] > 0) {
+ $x = $point['X'];
+ if ((!isset($total)) || (!isset($total[$x]))) {
+ $total[$x] = $point['Y'];
+ } else {
+ $total[$x] += $point['Y'];
+ }
+ if (isset($maxY)) {
+ $maxY = max($maxY, $total[$x]);
+ } else {
+ $maxY = $total[$x];
+ }
+ }
+ }
+ }
+ }
+ unset($keys);
+ }
+ return $maxY;
+ }
+
+ /**
+ * Get the X pixel position represented by a value
+ *
+ * @param double $point The value to get the pixel-point for
+ * @return double The pixel position along the axis
+ * @access private
+ */
+ function _pointX($point)
+ {
+ $point['AXIS_Y'] = $this->_axisY;
+ return parent::_pointX($point);
+ }
+
+ /**
+ * Get the Y pixel position represented by a value
+ *
+ * @param double $point the value to get the pixel-point for
+ * @return double The pixel position along the axis
+ * @access private
+ */
+ function _pointY($point)
+ {
+ $point['AXIS_Y'] = $this->_axisY;
+ return parent::_pointY($point);
+ }
+
+ /**
+ * Update coordinates
+ *
+ * @access private
+ */
+ function _updateCoords()
+ {
+ $this->_setCoords($this->_parent->_plotLeft, $this->_parent->_plotTop, $this->_parent->_plotRight, $this->_parent->_plotBottom);
+ parent::_updateCoords();
+ }
+
+ /**
+ * Get the dataset
+ *
+ * @return Image_Graph_Dataset The dataset(s)
+ */
+ function &dataset()
+ {
+ return $this->_dataset;
+ }
+
+ /**
+ * Calulate totals
+ *
+ * @return array An associated array with the totals
+ * @access private
+ */
+ function _getTotals()
+ {
+ $total = array(
+ 'MINIMUM_X' => $this->_minimumX(),
+ 'MAXIMUM_X' => $this->_maximumX(),
+ 'MINIMUM_Y' => $this->_minimumY(),
+ 'MAXIMUM_Y' => $this->_maximumY()
+ );
+ $total['ALL_SUM_Y'] = 0;
+
+ $keys = array_keys($this->_dataset);
+ foreach ($keys as $key) {
+ $dataset =& $this->_dataset[$key];
+
+ $dataset->_reset();
+ while ($point = $dataset->_next()) {
+ $x = $point['X'];
+
+ if (is_numeric($point['Y'])) {
+ $total['ALL_SUM_Y'] += $point['Y'];
+ if (isset($total['TOTAL_Y'][$x])) {
+ $total['TOTAL_Y'][$x] += $point['Y'];
+ } else {
+ $total['TOTAL_Y'][$x] = $point['Y'];
+ }
+ }
+
+ if (is_numeric($point['X'])) {
+ if (isset($total['TOTAL_X'][$x])) {
+ $total['TOTAL_X'][$x] += $point['X'];
+ } else {
+ $total['TOTAL_X'][$x] = $point['X'];
+ }
+ }
+ }
+ }
+ unset($keys);
+ return $total;
+ }
+
+ /**
+ * Perform the actual drawing on the legend.
+ *
+ * @param int $x0 The top-left x-coordinate
+ * @param int $y0 The top-left y-coordinate
+ * @param int $x1 The bottom-right x-coordinate
+ * @param int $y1 The bottom-right y-coordinate
+ * @access private
+ */
+ function _drawLegendSample($x0, $y0, $x1, $y1)
+ {
+ $this->_canvas->rectangle(array('x0' => $x0, 'y0' => $y0, 'x1' => $x1, 'y1' => $y1));
+ }
+
+ /**
+ * Draw a sample for use with legend
+ *
+ * @param array $param The parameters for the legend
+ * @access private
+ */
+ function _legendSample(&$param)
+ {
+ if (!is_array($this->_dataset)) {
+ return false;
+ }
+
+ if (is_a($this->_fillStyle, 'Image_Graph_Fill')) {
+ $this->_fillStyle->_reset();
+ }
+
+ $count = 0;
+ $keys = array_keys($this->_dataset);
+ foreach ($keys as $key) {
+ $dataset =& $this->_dataset[$key];
+ $count++;
+
+ $caption = ($dataset->_name ? $dataset->_name : $this->_title);
+
+ $this->_canvas->setFont($param['font']);
+ $width = 20 + $param['width'] + $this->_canvas->textWidth($caption);
+ $param['maxwidth'] = max($param['maxwidth'], $width);
+ $x2 = $param['x'] + $width;
+ $y2 = $param['y'] + $param['height'] + 5;
+
+ if ((($param['align'] & IMAGE_GRAPH_ALIGN_VERTICAL) != 0) && ($y2 > $param['bottom'])) {
+ $param['y'] = $param['top'];
+ $param['x'] = $x2;
+ $y2 = $param['y'] + $param['height'];
+ } elseif ((($param['align'] & IMAGE_GRAPH_ALIGN_VERTICAL) == 0) && ($x2 > $param['right'])) {
+ $param['x'] = $param['left'];
+ $param['y'] = $y2;
+ $x2 = $param['x'] + 20 + $param['width'] + $this->_canvas->textWidth($caption);
+ }
+
+ $x = $x0 = $param['x'];
+ $y = $param['y'];
+ $y0 = $param['y'];
+ $x1 = $param['x'] + $param['width'];
+ $y1 = $param['y'] + $param['height'];
+
+ if (!isset($param['simulate'])) {
+ $this->_getFillStyle($key);
+ $this->_getLineStyle();
+ $this->_drawLegendSample($x0, $y0, $x1, $y1);
+
+ if (($this->_marker) && ($dataset) && ($param['show_marker'])) {
+ $dataset->_reset();
+ $point = $dataset->_next();
+ $prevPoint = $dataset->_nearby(-2);
+ $nextPoint = $dataset->_nearby();
+
+ $tmp = array();
+ $point = $this->_getMarkerData($point, $nextPoint, $prevPoint, $tmp);
+ if (is_array($point)) {
+ $point['MARKER_X'] = $x+$param['width']/2;
+ $point['MARKER_Y'] = $y;
+ unset ($point['AVERAGE_Y']);
+ $this->_marker->_drawMarker($point['MARKER_X'], $point['MARKER_Y'], $point);
+ }
+ }
+ $this->write($x + $param['width'] + 10, $y + $param['height'] / 2, $caption, IMAGE_GRAPH_ALIGN_CENTER_Y | IMAGE_GRAPH_ALIGN_LEFT, $param['font']);
+ }
+
+ if (($param['align'] & IMAGE_GRAPH_ALIGN_VERTICAL) != 0) {
+ $param['y'] = $y2;
+ } else {
+ $param['x'] = $x2;
+ }
+ }
+ unset($keys);
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Plot/Area.php b/config/dspam/pear/Image/Graph/Plot/Area.php
new file mode 100644
index 00000000..a5288e1a
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Plot/Area.php
@@ -0,0 +1,194 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Plot
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Plot.php
+ */
+require_once 'Image/Graph/Plot.php';
+
+/**
+ * Area Chart plot.
+ *
+ * An area chart plots all data points similar to a {@link
+ * Image_Graph_Plot_Line}, but the area beneath the line is filled and the whole
+ * area 'the-line', 'the right edge', 'the x-axis' and 'the left edge' is
+ * bounded. Smoothed charts are only supported with non-stacked types
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Plot
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Plot_Area extends Image_Graph_Plot
+{
+
+ /**
+ * Perform the actual drawing on the legend.
+ *
+ * @param int $x0 The top-left x-coordinate
+ * @param int $y0 The top-left y-coordinate
+ * @param int $x1 The bottom-right x-coordinate
+ * @param int $y1 The bottom-right y-coordinate
+ * @access private
+ */
+ function _drawLegendSample($x0, $y0, $x1, $y1)
+ {
+ $dx = abs($x1 - $x0) / 3;
+ $dy = abs($y1 - $y0) / 3;
+ $this->_canvas->addVertex(array('x' => $x0, 'y' => $y1));
+ $this->_canvas->addVertex(array('x' => $x0, 'y' => $y0 + $dy));
+ $this->_canvas->addVertex(array('x' => $x0 + $dx, 'y' => $y0));
+ $this->_canvas->addVertex(array('x' => $x0 + 2*$dx, 'y' => $y0 + 2*$dy));
+ $this->_canvas->addVertex(array('x' => $x1, 'y' => $y0 + $dy));
+ $this->_canvas->addVertex(array('x' => $x1, 'y' => $y1));
+ $this->_canvas->polygon(array('connect' => true));
+ }
+
+ /**
+ * Output the plot
+ *
+ * @return bool Was the output 'good' (true) or 'bad' (false).
+ * @access private
+ */
+ function _done()
+ {
+ if (parent::_done() === false) {
+ return false;
+ }
+
+ $this->_canvas->startGroup(get_class($this) . '_' . $this->_title);
+
+ $this->_clip(true);
+
+ $base = array();
+ if ($this->_multiType == 'stacked') {
+ reset($this->_dataset);
+ $key = key($this->_dataset);
+ $dataset =& $this->_dataset[$key];
+
+ $first = $dataset->first();
+ $point = array ('X' => $first['X'], 'Y' => '#min_pos#');
+ $base[] = array();
+ $base[] = $this->_pointY($point);
+ $first = $this->_pointX($point);
+ $base[] = $first;
+
+ $last = $dataset->last();
+ $point = array ('X' => $last['X'], 'Y' => '#min_pos#');
+ $base[] = array();
+ $base[] = $this->_pointY($point);
+ $base[] = $this->_pointX($point);
+
+ $current = array();
+ }
+
+ $minYaxis = $this->_parent->_getMinimum($this->_axisY);
+ $maxYaxis = $this->_parent->_getMaximum($this->_axisY);
+
+ $keys = array_keys($this->_dataset);
+ foreach ($keys as $key) {
+ $dataset =& $this->_dataset[$key];
+ $dataset->_reset();
+ if ($this->_multiType == 'stacked') {
+ $plotarea = array_reverse($base);
+ $base = array();
+ while ($point = $dataset->_next()) {
+ $x = $point['X'];
+ $p = $point;
+ if (isset($current[$x])) {
+ $p['Y'] += $current[$x];
+ } else {
+ $current[$x] = 0;
+ }
+ $x1 = $this->_pointX($p);
+ $y1 = $this->_pointY($p);
+ $plotarea[] = $x1;
+ $plotarea[] = $y1;
+ $plotarea[] = $point;
+ $base[] = array();
+ $base[] = $y1;
+ $base[] = $x1;
+ $current[$x] += $point['Y'];
+ }
+ } else {
+ $first = true;
+ $plotarea = array();
+ while ($point = $dataset->_next()) {
+ if ($first) {
+ $firstPoint = array ('X' => $point['X'], 'Y' => '#min_pos#');
+ $plotarea[] = $this->_pointX($firstPoint);
+ $plotarea[] = $this->_pointY($firstPoint);
+ $plotarea[] = array();
+ }
+ $plotarea[] = $this->_pointX($point);
+ $plotarea[] = $this->_pointY($point);
+ $plotarea[] = $point;
+ $lastPoint = $point;
+ $first = false;
+ }
+ $endPoint['X'] = $lastPoint['X'];
+ $endPoint['Y'] = '#min_pos#';
+ $plotarea[] = $this->_pointX($endPoint);
+ $plotarea[] = $this->_pointY($endPoint);
+ $plotarea[] = array();
+ }
+
+ reset($plotarea);
+ while (list(, $x) = each($plotarea)) {
+ list(, $y) = each($plotarea);
+ list(, $data) = each($plotarea);
+ $this->_canvas->addVertex(
+ $this->_mergeData(
+ $data,
+ array('x' => $x, 'y' => $y)
+ )
+ );
+ }
+
+ $this->_getFillStyle($key);
+ $this->_getLineStyle($key);
+ $this->_canvas->polygon(array('connect' => true, 'map_vertices' => true));
+ }
+ unset($keys);
+ $this->_drawMarker();
+ $this->_clip(false);
+
+ $this->_canvas->endGroup();
+
+ return true;
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Plot/Band.php b/config/dspam/pear/Image/Graph/Plot/Band.php
new file mode 100644
index 00000000..3d5b629a
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Plot/Band.php
@@ -0,0 +1,205 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Plot
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ * @since File available since Release 0.3.0dev2
+ */
+
+/**
+ * Include file Image/Graph/Plot.php
+ */
+require_once 'Image/Graph/Plot.php';
+
+/**
+ * "Band" (area chart with min AND max) chart.
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Plot
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ * @since Class available since Release 0.3.0dev2
+ */
+class Image_Graph_Plot_Band extends Image_Graph_Plot
+{
+
+ /**
+ * Perform the actual drawing on the legend.
+ *
+ * @param int $x0 The top-left x-coordinate
+ * @param int $y0 The top-left y-coordinate
+ * @param int $x1 The bottom-right x-coordinate
+ * @param int $y1 The bottom-right y-coordinate
+ * @access private
+ */
+ function _drawLegendSample($x0, $y0, $x1, $y1)
+ {
+ $h = abs($y1 - $y0) / 6;
+ $w = round(abs($x1 - $x0) / 5);
+ $y = ($y0 + $y1) / 2;
+
+ $this->_canvas->addVertex(array('x' => $x0, 'y' => $y - $h * 3));
+ $this->_canvas->addVertex(array('x' => $x0 + $w, 'y' => $y - 4 * $h));
+ $this->_canvas->addVertex(array('x' => $x0 + 2 * $w, 'y' => $y - $h * 2));
+ $this->_canvas->addVertex(array('x' => $x0 + 3 * $w, 'y' => $y - $h * 4));
+ $this->_canvas->addVertex(array('x' => $x0 + 4 * $w, 'y' => $y - $h * 3));
+ $this->_canvas->addVertex(array('x' => $x1, 'y' => $y - $h * 2));
+ $this->_canvas->addVertex(array('x' => $x1, 'y' => $y + $h * 3));
+ $this->_canvas->addVertex(array('x' => $x0 + 4 * $w, 'y' => $y + $h));
+ $this->_canvas->addVertex(array('x' => $x0 + 3 * $w, 'y' => $y + 2 * $h));
+ $this->_canvas->addVertex(array('x' => $x0 + 2 * $w, 'y' => $y + 1 * $h));
+ $this->_canvas->addVertex(array('x' => $x0 + 1 * $w, 'y' => $y));
+ $this->_canvas->addVertex(array('x' => $x0, 'y' => $y + $h));
+
+ $this->_getLineStyle();
+ $this->_getFillStyle();
+ $this->_canvas->polygon(array('connect' => true));
+ }
+
+ /**
+ * Output the plot
+ *
+ * @return bool Was the output 'good' (true) or 'bad' (false).
+ * @access private
+ */
+ function _done()
+ {
+ if (parent::_done() === false) {
+ return false;
+ }
+
+ if (!is_array($this->_dataset)) {
+ return false;
+ }
+
+ $current = array();
+
+ $this->_canvas->startGroup(get_class($this) . '_' . $this->_title);
+
+ $this->_clip(true);
+
+
+ $keys = array_keys($this->_dataset);
+ foreach ($keys as $key) {
+ $dataset =& $this->_dataset[$key];
+ $dataset->_reset();
+ $upperBand = array();
+ $lowerBand = array();
+ while ($data = $dataset->_next()) {
+ if ($this->_parent->_horizontal) {
+ $point['X'] = $data['X'];
+
+ $point['Y'] = $data['Y']['high'];
+ $y = $this->_pointY($point);
+ $x_high = $this->_pointX($point);
+
+ $point['Y'] = $data['Y']['low'];
+ $x_low = $this->_pointX($point);
+
+ $data = array('X' => $x_high, 'Y' => $y);
+ if (isset($point['data'])) {
+ $data['data'] = $point['data'];
+ } else {
+ $data['data'] = array();
+ }
+ $upperBand[] = $data;
+
+ $data = array('X' => $x_low, 'Y' => $y);
+ if (isset($point['data'])) {
+ $data['data'] = $point['data'];
+ } else {
+ $data['data'] = array();
+ }
+ $lowerBand[] = $data;
+ }
+ else {
+ $point['X'] = $data['X'];
+ $y = $data['Y'];
+
+ $point['Y'] = $data['Y']['high'];
+ $x = $this->_pointX($point);
+ $y_high = $this->_pointY($point);
+
+ $point['Y'] = $data['Y']['low'];
+ $y_low = $this->_pointY($point);
+
+ $data = array('X' => $x, 'Y' => $y_high);
+ if (isset($point['data'])) {
+ $data['data'] = $point['data'];
+ } else {
+ $data['data'] = array();
+ }
+ $upperBand[] = $data;
+
+ $data = array('X' => $x, 'Y' => $y_low);
+ if (isset($point['data'])) {
+ $data['data'] = $point['data'];
+ } else {
+ $data['data'] = array();
+ }
+ $lowerBand[] = $data;
+ }
+ }
+ $lowerBand = array_reverse($lowerBand);
+ foreach ($lowerBand as $point) {
+ $this->_canvas->addVertex(
+ $this->_mergeData(
+ $point['data'],
+ array('x' => $point['X'], 'y' => $point['Y'])
+ )
+ );
+ }
+ foreach ($upperBand as $point) {
+ $this->_canvas->addVertex(
+ $this->_mergeData(
+ $point['data'],
+ array('x' => $point['X'], 'y' => $point['Y'])
+ )
+ );
+ }
+ unset($upperBand);
+ unset($lowerBand);
+
+ $this->_getLineStyle($key);
+ $this->_getFillStyle($key);
+ $this->_canvas->polygon(array('connect' => true, 'map_vertices' => true));
+ }
+ unset($keys);
+ $this->_drawMarker();
+ $this->_clip(false);
+
+ $this->_canvas->endGroup();
+
+ return true;
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Plot/Bar.php b/config/dspam/pear/Image/Graph/Plot/Bar.php
new file mode 100644
index 00000000..3e35f92c
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Plot/Bar.php
@@ -0,0 +1,307 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Plot
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Plot.php
+ */
+require_once 'Image/Graph/Plot.php';
+
+/**
+ * A bar chart.
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Plot
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Plot_Bar extends Image_Graph_Plot
+{
+
+ /**
+ * The space between 2 bars (should be a multipla of 2)
+ * @var int
+ * @access private
+ */
+ var $_space = 4;
+
+ /**
+ * The width of the bars
+ * @var array
+ * @access private
+ */
+ var $_width = 'auto';
+
+ /**
+ * Perform the actual drawing on the legend.
+ *
+ * @param int $x0 The top-left x-coordinate
+ * @param int $y0 The top-left y-coordinate
+ * @param int $x1 The bottom-right x-coordinate
+ * @param int $y1 The bottom-right y-coordinate
+ * @access private
+ */
+ function _drawLegendSample($x0, $y0, $x1, $y1)
+ {
+ $dx = abs($x1 - $x0) / 7;
+ $this->_canvas->rectangle(array('x0' => $x0 + $dx, 'y0' => $y0, 'x1' => $x1 - $dx, 'y1' => $y1));
+ }
+
+ /**
+ * Set the spacing between 2 neighbouring bars
+ *
+ * @param int $space The number of pixels between 2 bars, should be a
+ * multipla of 2 (ie an even number)
+ */
+ function setSpacing($space)
+ {
+ $this->_space = (int) ($space / 2);
+ }
+
+ /**
+ * Set the width of a bars.
+ *
+ * Specify 'auto' to auto calculate the width based on the positions on the
+ * x-axis.
+ *
+ * Supported units are:
+ *
+ * '%' The width is specified in percentage of the total plot width
+ *
+ * 'px' The width specified in pixels
+ *
+ * @param string $width The width of any bar
+ * @param string $unit The unit of the width
+ */
+ function setBarWidth($width, $unit = false)
+ {
+ if ($width == 'auto') {
+ $this->_width = $width;
+ } else {
+ $this->_width = array(
+ 'width' => $width,
+ 'unit' => $unit
+ );
+ }
+ }
+
+ /**
+ * Output the plot
+ *
+ * @return bool Was the output 'good' (true) or 'bad' (false).
+ * @access private
+ */
+ function _done()
+ {
+ if (parent::_done() === false) {
+ return false;
+ }
+
+ if (!is_array($this->_dataset)) {
+ return false;
+ }
+
+ $this->_canvas->startGroup(get_class($this) . '_' . $this->_title);
+
+ $this->_clip(true);
+
+ if ($this->_width == 'auto') {
+ $width = $this->_parent->_labelDistance(IMAGE_GRAPH_AXIS_X) / 2;
+ } elseif ($this->_width['unit'] == '%') {
+ $width = $this->_width['width'] * $this->width() / 200;
+ } elseif ($this->_width['unit'] == 'px') {
+ $width = $this->_width['width'] / 2;
+ }
+
+ if ($this->_multiType == 'stacked100pct') {
+ $total = $this->_getTotals();
+ }
+
+ $minYaxis = $this->_parent->_getMinimum($this->_axisY);
+ $maxYaxis = $this->_parent->_getMaximum($this->_axisY);
+
+ $number = 0;
+ $keys = array_keys($this->_dataset);
+ foreach ($keys as $key) {
+ $dataset =& $this->_dataset[$key];
+ $dataset->_reset();
+ while ($point = $dataset->_next()) {
+
+ if ($this->_parent->_horizontal) {
+ $y1 = $this->_pointY($point) - $width;
+ $y2 = $this->_pointY($point) + $width;
+
+ if ($y2 - $this->_space > $y1 + $this->_space) {
+ /*
+ * Take bar spacing into account _only_ if the space doesn't
+ * turn the bar "inside-out", i.e. if the actual bar width
+ * is smaller than the space between the bars
+ */
+ $y2 -= $this->_space;
+ $y1 += $this->_space;
+ }
+ }
+ else {
+ $x1 = $this->_pointX($point) - $width;
+ $x2 = $this->_pointX($point) + $width;
+
+ if ($x2 - $this->_space > $x1 + $this->_space) {
+ /*
+ * Take bar spacing into account _only_ if the space doesn't
+ * turn the bar "inside-out", i.e. if the actual bar width
+ * is smaller than the space between the bars
+ */
+ $x2 -= $this->_space;
+ $x1 += $this->_space;
+ }
+ }
+
+
+ if (($this->_multiType == 'stacked') ||
+ ($this->_multiType == 'stacked100pct'))
+ {
+ $x = $point['X'];
+
+ if ($point['Y'] >= 0) {
+ if (!isset($current[$x])) {
+ $current[$x] = 0;
+ }
+
+ if ($this->_multiType == 'stacked') {
+ $p0 = array(
+ 'X' => $point['X'],
+ 'Y' => $current[$x]
+ );
+ $p1 = array(
+ 'X' => $point['X'],
+ 'Y' => $current[$x] + $point['Y']
+ );
+ } else {
+ $p0 = array(
+ 'X' => $point['X'],
+ 'Y' => 100 * $current[$x] / $total['TOTAL_Y'][$x]
+ );
+ $p1 = array(
+ 'X' => $point['X'],
+ 'Y' => 100 * ($current[$x] + $point['Y']) / $total['TOTAL_Y'][$x]
+ );
+ }
+ $current[$x] += $point['Y'];
+ } else {
+ if (!isset($currentNegative[$x])) {
+ $currentNegative[$x] = 0;
+ }
+
+ $p0 = array(
+ 'X' => $point['X'],
+ 'Y' => $currentNegative[$x]
+ );
+ $p1 = array(
+ 'X' => $point['X'],
+ 'Y' => $currentNegative[$x] + $point['Y']
+ );
+ $currentNegative[$x] += $point['Y'];
+ }
+ } else {
+ if (count($this->_dataset) > 1) {
+ $w = 2 * ($width - $this->_space) / count($this->_dataset);
+ if ($this->_parent->_horizontal) {
+ $y2 = ($y1 = ($y1 + $y2) / 2 - ($width - $this->_space) + $number * $w) + $w;
+ }
+ else {
+ $x2 = ($x1 = ($x1 + $x2) / 2 - ($width - $this->_space) + $number * $w) + $w;
+ }
+ }
+ $p0 = array('X' => $point['X'], 'Y' => 0);
+ $p1 = $point;
+ }
+
+ if ((($minY = min($p0['Y'], $p1['Y'])) < $maxYaxis) &&
+ (($maxY = max($p0['Y'], $p1['Y'])) > $minYaxis)
+ ) {
+ $p0['Y'] = $minY;
+ $p1['Y'] = $maxY;
+
+ if ($p0['Y'] < $minYaxis) {
+ $p0['Y'] = '#min_pos#';
+ }
+ if ($p1['Y'] > $maxYaxis) {
+ $p1['Y'] = '#max_neg#';
+ }
+
+ if ($this->_parent->_horizontal) {
+ $x1 = $this->_pointX($p0);
+ $x2 = $this->_pointX($p1);
+ }
+ else {
+ $y1 = $this->_pointY($p0);
+ $y2 = $this->_pointY($p1);
+ }
+
+ $ID = $point['ID'];
+ if (($ID === false) && (count($this->_dataset) > 1)) {
+ $ID = $key;
+ }
+ $this->_getFillStyle($ID);
+ $this->_getLineStyle($ID);
+
+ if (($y1 != $y2) && ($x1 != $x2)) {
+ $this->_canvas->rectangle(
+ $this->_mergeData(
+ $point,
+ array(
+ 'x0' => min($x1, $x2),
+ 'y0' => min($y1, $y2),
+ 'x1' => max($x1, $x2),
+ 'y1' => max($y1, $y2)
+ )
+ )
+ );
+ }
+ }
+ }
+ $number ++;
+ }
+ unset($keys);
+
+ $this->_drawMarker();
+
+ $this->_clip(false);
+
+ $this->_canvas->endGroup();
+
+ return true;
+ }
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Plot/BoxWhisker.php b/config/dspam/pear/Image/Graph/Plot/BoxWhisker.php
new file mode 100644
index 00000000..59c1ee44
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Plot/BoxWhisker.php
@@ -0,0 +1,298 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Plot
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ * @since File available since Release 0.3.0dev2
+ */
+
+/**
+ * Include file Image/Graph/Plot.php
+ */
+require_once 'Image/Graph/Plot.php';
+
+/**
+ * Box & Whisker chart.
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Plot
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ * @since Class available since Release 0.3.0dev2
+ */
+class Image_Graph_Plot_BoxWhisker extends Image_Graph_Plot
+{
+ /**
+ * Whisker circle size
+ * @var int
+ * @access private
+ */
+ var $_whiskerSize = false;
+
+ /**
+ * Draws a box & whisker
+ *
+ * @param int $x The x position
+ * @param int $w The width of the box
+ * @param int $r The radius of the circle markers
+ * @param int $y_min The Y position of the minimum value
+ * @param int $y_q1 The Y position of the median of the first quartile
+ * @param int $y_med The Y position of the median
+ * @param int $y_q3 The Y position of the median of the third quartile
+ * @param int $y_max The Y position of the maximum value
+ * @param int $key The ID tag
+ * @access private
+ */
+ function _drawBoxWhiskerV($x, $w, $r, $y_min, $y_q1, $y_med, $y_q3, $y_max, $key = false)
+ {
+ // draw circles
+ $this->_getLineStyle();
+ $this->_getFillStyle('min');
+ $this->_canvas->ellipse(array('x' => $x, 'y' => $y_min, 'rx' => $r, 'ry' => $r));
+
+ $this->_getLineStyle();
+ $this->_getFillStyle('quartile1');
+ $this->_canvas->ellipse(array('x' => $x, 'y' => $y_q1, 'rx' => $r, 'ry' => $r));
+
+ $this->_getLineStyle();
+ $this->_getFillStyle('median');
+ $this->_canvas->ellipse(array('x' => $x, 'y' => $y_med, 'rx' => $r, 'ry' => $r));
+
+ $this->_getLineStyle();
+ $this->_getFillStyle('quartile3');
+ $this->_canvas->ellipse(array('x' => $x, 'y' => $y_q3, $r, 'rx' => $r, 'ry' => $r));
+
+ $this->_getLineStyle();
+ $this->_getFillStyle('max');
+ $this->_canvas->ellipse(array('x' => $x, 'y' => $y_max, $r, 'rx' => $r, 'ry' => $r));
+
+ // draw box and lines
+
+ $this->_getLineStyle();
+ $this->_canvas->line(array('x0' => $x, 'y0' => $y_min, 'x1' => $x, 'y1' => $y_q1));
+ $this->_getLineStyle();
+ $this->_canvas->line(array('x0' => $x, 'y0' => $y_q3, 'x1' => $x, 'y1' => $y_max));
+
+ $this->_getLineStyle();
+ $this->_getFillStyle('box');
+ $this->_canvas->rectangle(array('x0' => $x - $w, 'y0' => $y_q1, 'x1' => $x + $w, 'y1' => $y_q3));
+
+ $this->_getLineStyle();
+ $this->_canvas->line(array('x0' => $x - $w, 'y0' => $y_med, 'x1' => $x + $w, 'y1' => $y_med));
+ }
+
+ /**
+ * Draws a box & whisker
+ *
+ * @param int $y The x position
+ * @param int $h The width of the box
+ * @param int $r The radius of the circle markers
+ * @param int $x_min The Y position of the minimum value
+ * @param int $x_q1 The Y position of the median of the first quartile
+ * @param int $x_med The Y position of the median
+ * @param int $x_q3 The Y position of the median of the third quartile
+ * @param int $x_max The Y position of the maximum value
+ * @param int $key The ID tag
+ * @access private
+ */
+ function _drawBoxWhiskerH($y, $h, $r, $x_min, $x_q1, $x_med, $x_q3, $x_max, $key = false)
+ {
+ // draw circles
+ $this->_getLineStyle();
+ $this->_getFillStyle('min');
+ $this->_canvas->ellipse(array('x' => $x_min, 'y' => $y, 'rx' => $r, 'ry' => $r));
+
+ $this->_getLineStyle();
+ $this->_getFillStyle('quartile1');
+ $this->_canvas->ellipse(array('x' => $x_q1, 'y' => $y, 'rx' => $r, 'ry' => $r));
+
+ $this->_getLineStyle();
+ $this->_getFillStyle('median');
+ $this->_canvas->ellipse(array('x' => $x_med, 'y' => $y, 'rx' => $r, 'ry' => $r));
+
+ $this->_getLineStyle();
+ $this->_getFillStyle('quartile3');
+ $this->_canvas->ellipse(array('x' => $x_q3, 'y' => $y, $r, 'rx' => $r, 'ry' => $r));
+
+ $this->_getLineStyle();
+ $this->_getFillStyle('max');
+ $this->_canvas->ellipse(array('x' => $x_max, 'y' => $y, $r, 'rx' => $r, 'ry' => $r));
+
+ // draw box and lines
+
+ $this->_getLineStyle();
+ $this->_canvas->line(array('x0' => $x_min, 'y0' => $y, 'x1' => $x_q1, 'y1' => $y));
+ $this->_getLineStyle();
+ $this->_canvas->line(array('x0' => $x_q3, 'y0' => $y, 'x1' => $x_max, 'y1' => $y));
+
+ $this->_getLineStyle();
+ $this->_getFillStyle('box');
+ $this->_canvas->rectangle(array('x0' => $x_q1, 'y0' => $y - $h, 'x1' => $x_q3, 'y1' => $y + $h));
+
+ $this->_getLineStyle();
+ $this->_canvas->line(array('x0' => $x_med, 'y0' => $y - $h, 'x1' => $x_med, 'y1' => $y + $h));
+ }
+
+ /**
+ * Perform the actual drawing on the legend.
+ *
+ * @param int $x0 The top-left x-coordinate
+ * @param int $y0 The top-left y-coordinate
+ * @param int $x1 The bottom-right x-coordinate
+ * @param int $y1 The bottom-right y-coordinate
+ * @access private
+ */
+ function _drawLegendSample($x0, $y0, $x1, $y1)
+ {
+ $x = round(($x0 + $x1) / 2);
+ $h = abs($y1 - $y0) / 9;
+ $w = round(abs($x1 - $x0) / 5);
+ $r = 2;//round(abs($x1 - $x0) / 13);
+ $this->_drawBoxWhiskerV($x, $w, $r, $y1, $y1 - 2 * $h, $y1 - 4 * $h, $y0 + 3 * $h, $y0);
+ }
+
+ /**
+ * Sets the whisker circle size
+ *
+ * @param int $size Size (radius) of the whisker circle/dot
+ */
+ function setWhiskerSize($size = false)
+ {
+ $this->_whiskerSize = $size;
+ }
+
+ /**
+ * Output the plot
+ *
+ * @return bool Was the output 'good' (true) or 'bad' (false).
+ * @access private
+ */
+ function _done()
+ {
+ if (parent::_done() === false) {
+ return false;
+ }
+
+ if (!is_array($this->_dataset)) {
+ return false;
+ }
+
+ $this->_canvas->startGroup(get_class($this) . '_' . $this->_title);
+
+ $this->_clip(true);
+
+ if ($this->_multiType == 'stacked100pct') {
+ $total = $this->_getTotals();
+ }
+ $current = array();
+ $number = 0;
+ $width = floor(0.5 * $this->_parent->_labelDistance(IMAGE_GRAPH_AXIS_X) / 2);
+
+ if ($this->_whiskerSize !== false) {
+ $r = $this->_whiskerSize;
+ } else {
+ $r = min(5, $width / 10);
+ }
+
+ $keys = array_keys($this->_dataset);
+ foreach ($keys as $key) {
+ $dataset =& $this->_dataset[$key];
+ $dataset->_reset();
+ while ($data = $dataset->_next()) {
+ if ($this->_parent->_horizontal) {
+ $point['X'] = $data['X'];
+ $y = $data['Y'];
+
+ $min = min($y);
+ $max = max($y);
+ $q1 = $dataset->_median($y, 'first');
+ $med = $dataset->_median($y, 'second');
+ $q3 = $dataset->_median($y, 'third');
+
+ $point['Y'] = $min;
+ $y = $this->_pointY($point);
+ $x_min = $this->_pointX($point);
+
+ $point['Y'] = $max;
+ $x_max = $this->_pointX($point);
+
+ $point['Y'] = $q1;
+ $x_q1 = $this->_pointX($point);
+
+ $point['Y'] = $med;
+ $x_med = $this->_pointX($point);
+
+ $point['Y'] = $q3;
+ $x_q3 = $this->_pointX($point);
+
+ $this->_drawBoxWhiskerH($y, $width, $r, $x_min, $x_q1, $x_med, $x_q3, $x_max, $key);
+ }
+ else {
+ $point['X'] = $data['X'];
+ $y = $data['Y'];
+
+ $min = min($y);
+ $max = max($y);
+ $q1 = $dataset->_median($y, 'first');
+ $med = $dataset->_median($y, 'second');
+ $q3 = $dataset->_median($y, 'third');
+
+ $point['Y'] = $min;
+ $x = $this->_pointX($point);
+ $y_min = $this->_pointY($point);
+
+ $point['Y'] = $max;
+ $y_max = $this->_pointY($point);
+
+ $point['Y'] = $q1;
+ $y_q1 = $this->_pointY($point);
+
+ $point['Y'] = $med;
+ $y_med = $this->_pointY($point);
+
+ $point['Y'] = $q3;
+ $y_q3 = $this->_pointY($point);
+
+ $this->_drawBoxWhiskerV($x, $width, $r, $y_min, $y_q1, $y_med, $y_q3, $y_max, $key);
+ }
+ }
+ }
+ unset($keys);
+ $this->_drawMarker();
+
+ $this->_clip(false);
+
+ $this->_canvas->endGroup();
+ return true;
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Plot/CandleStick.php b/config/dspam/pear/Image/Graph/Plot/CandleStick.php
new file mode 100644
index 00000000..b050aea1
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Plot/CandleStick.php
@@ -0,0 +1,251 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Plot
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ * @since File available since Release 0.3.0dev2
+ */
+
+/**
+ * Include file Image/Graph/Plot.php
+ */
+require_once 'Image/Graph/Plot.php';
+
+/**
+ * Candlestick chart.
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Plot
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ * @since Class available since Release 0.3.0dev2
+ */
+class Image_Graph_Plot_CandleStick extends Image_Graph_Plot
+{
+
+ /**
+ * (Add basic description here)
+ *
+ * @access private
+ */
+ function _drawCandleStickH($y, $h, $x_min, $x_open, $x_close, $x_max, $ID)
+ {
+ $this->_getLineStyle($ID);
+ $this->_canvas->line(
+ array(
+ 'x0' => min($x_open, $x_close),
+ 'y0' => $y,
+ 'x1' => $x_min,
+ 'y1' => $y
+ )
+ );
+ $this->_getLineStyle($ID);
+ $this->_canvas->line(
+ array(
+ 'x0' => max($x_open, $x_close),
+ 'y0' => $y,
+ 'x1' => $x_max,
+ 'y1' => $y
+ )
+ );
+
+ $this->_getLineStyle($ID);
+ $this->_getFillStyle($ID);
+ $this->_canvas->rectangle(
+ array(
+ 'x0' => min($x_open, $x_close),
+ 'y0' => $y - $h,
+ 'x1' => max($x_open, $x_close),
+ 'y1' => $y + $h
+ )
+ );
+ }
+
+ /**
+ * (Add basic description here)
+ *
+ * @access private
+ */
+ function _drawCandleStickV($x, $w, $y_min, $y_open, $y_close, $y_max, $ID)
+ {
+ $this->_getLineStyle($ID);
+ $this->_canvas->line(
+ array(
+ 'x0' => $x,
+ 'y0' => min($y_open, $y_close),
+ 'x1' => $x,
+ 'y1' => $y_max
+ )
+ );
+ $this->_getLineStyle($ID);
+ $this->_canvas->line(
+ array(
+ 'x0' => $x,
+ 'y0' => max($y_open, $y_close),
+ 'x1' => $x,
+ 'y1' => $y_min
+ )
+ );
+
+ $this->_getLineStyle($ID);
+ $this->_getFillStyle($ID);
+ $this->_canvas->rectangle(
+ array(
+ 'x0' => $x - $w,
+ 'y0' => min($y_open, $y_close),
+ 'x1' => $x + $w,
+ 'y1' => max($y_open, $y_close)
+ )
+ );
+ }
+
+ /**
+ * Perform the actual drawing on the legend.
+ *
+ * @param int $x0 The top-left x-coordinate
+ * @param int $y0 The top-left y-coordinate
+ * @param int $x1 The bottom-right x-coordinate
+ * @param int $y1 The bottom-right y-coordinate
+ * @access private
+ */
+ function _drawLegendSample($x0, $y0, $x1, $y1)
+ {
+ $x = round(($x0 + $x1) / 2);
+ $h = abs($y1 - $y0) / 4;
+ $w = round(abs($x1 - $x0) / 5);
+ $this->_drawCandleStickV($x, $w, $y1, $y1 - $h, $y0 + $h, $y0, 'green');
+ }
+
+ /**
+ * Output the plot
+ *
+ * @return bool Was the output 'good' (true) or 'bad' (false).
+ * @access private
+ */
+ function _done()
+ {
+ if (parent::_done() === false) {
+ return false;
+ }
+
+ if (!is_array($this->_dataset)) {
+ return false;
+ }
+
+ $this->_canvas->startGroup(get_class($this) . '_' . $this->_title);
+
+ $this->_clip(true);
+
+ if ($this->_multiType == 'stacked100pct') {
+ $total = $this->_getTotals();
+ }
+ $current = array();
+ $number = 0;
+ $width = floor(0.8 * $this->_parent->_labelDistance(IMAGE_GRAPH_AXIS_X) / 2);
+
+ $lastClosed = false;
+ $keys = array_keys($this->_dataset);
+ foreach ($keys as $key) {
+ $dataset =& $this->_dataset[$key];
+ $dataset->_reset();
+ while ($data = $dataset->_next()) {
+ if ($this->_parent->_horizontal) {
+ $point['X'] = $data['X'];
+ //$y = $data['Y'];
+
+ if (isset($data['Y']['open'])) {
+ $point['Y'] = $data['Y']['open'];
+ } else {
+ $point['Y'] = $lastClosed;
+ }
+ $y = $this->_pointY($point);
+ $x_open = $this->_pointX($point);
+
+ $lastClosed = $point['Y'] = $data['Y']['close'];
+ $x_close = $this->_pointX($point);
+
+ $point['Y'] = $data['Y']['min'];
+ $x_min = $this->_pointX($point);
+
+ $point['Y'] = $data['Y']['max'];
+ $x_max = $this->_pointX($point);
+
+ if ($data['Y']['close'] < $data['Y']['open']) {
+ $ID = 'red';
+ } else {
+ $ID = 'green';
+ }
+
+ $this->_drawCandleStickH($y, $width, $x_min, $x_open, $x_close, $x_max, $ID);
+ }
+ else {
+ $point['X'] = $data['X'];
+ //$y = $data['Y'];
+
+ if (isset($data['Y']['open'])) {
+ $point['Y'] = $data['Y']['open'];
+ } else {
+ $point['Y'] = $lastClosed;
+ }
+ $x = $this->_pointX($point);
+ $y_open = $this->_pointY($point);
+
+ $lastClosed = $point['Y'] = $data['Y']['close'];
+ $y_close = $this->_pointY($point);
+
+ $point['Y'] = $data['Y']['min'];
+ $y_min = $this->_pointY($point);
+
+ $point['Y'] = $data['Y']['max'];
+ $y_max = $this->_pointY($point);
+
+ if ($data['Y']['close'] < $data['Y']['open']) {
+ $ID = 'red';
+ } else {
+ $ID = 'green';
+ }
+
+ $this->_drawCandleStickV($x, $width, $y_min, $y_open, $y_close, $y_max, $ID);
+ }
+ }
+ }
+ unset($keys);
+ $this->_drawMarker();
+
+ $this->_clip(false);
+
+ $this->_canvas->endGroup($this->_title);
+
+ return true;
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Plot/Dot.php b/config/dspam/pear/Image/Graph/Plot/Dot.php
new file mode 100644
index 00000000..19352567
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Plot/Dot.php
@@ -0,0 +1,99 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Plot
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Plot.php
+ */
+require_once 'Image/Graph/Plot.php';
+
+/**
+ * Dot / scatter chart (only marker).
+ *
+ * This plot type only displays a {@link Image_Graph_Marker} for the datapoints.
+ * The marker must explicitly be defined using {@link Image_Graph_Plot::
+ * setMarker()}.
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Plot
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Plot_Dot extends Image_Graph_Plot
+{
+
+ /**
+ * Perform the actual drawing on the legend.
+ *
+ * @param int $x0 The top-left x-coordinate
+ * @param int $y0 The top-left y-coordinate
+ * @param int $x1 The bottom-right x-coordinate
+ * @param int $y1 The bottom-right y-coordinate
+ * @access private
+ */
+ function _drawLegendSample($x0, $y0, $x1, $y1)
+ {
+ if (isset($this->_marker)) {
+ $key = key($this->_dataset);
+ $samplePoint = $this->_dataset[$key]->_nearby();
+ $this->_marker->_drawMarker(($x0 + $x1) / 2, ($y0 + $y1) / 2, $samplePoint);
+ }
+ }
+
+ /**
+ * Output the plot
+ *
+ * @return bool Was the output 'good' (true) or 'bad' (false).
+ * @access private
+ */
+ function _done()
+ {
+ if (Image_Graph_Plot::_done() === false) {
+ return false;
+ }
+
+ $this->_canvas->startGroup(get_class($this) . '_' . $this->_title);
+
+ $this->_clip(true);
+
+ $this->_drawMarker();
+
+ $this->_clip(false);
+
+ $this->_canvas->endGroup();
+
+ return true;
+ }
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Plot/Fit/Line.php b/config/dspam/pear/Image/Graph/Plot/Fit/Line.php
new file mode 100644
index 00000000..07f3b9cc
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Plot/Fit/Line.php
@@ -0,0 +1,118 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Plot
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Plot.php
+ */
+require_once 'Image/Graph/Plot.php';
+
+/**
+ * Include file Image/Graph/Tool.php
+ */
+require_once 'Image/Graph/Tool.php';
+
+/**
+ * Fit the graph (to a line using linear regression).
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Plot
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Plot_Fit_Line extends Image_Graph_Plot
+{
+
+ /**
+ * Perform the actual drawing on the legend.
+ *
+ * @param int $x0 The top-left x-coordinate
+ * @param int $y0 The top-left y-coordinate
+ * @param int $x1 The bottom-right x-coordinate
+ * @param int $y1 The bottom-right y-coordinate
+ * @access private
+ */
+ function _drawLegendSample($x0, $y0, $x1, $y1)
+ {
+ $y = ($y0 + $y1) / 2;
+ $dy = abs($y1 - $y0) / 6;
+ $this->_canvas->addVertex(array('x' => $x0, 'y' => $y + $dy));
+ $this->_canvas->addVertex(array('x' => $x1, 'y' => $y - $dy));
+ $this->_canvas->polygon(array('connect' => false));
+ }
+
+ /**
+ * Output the plot
+ *
+ * @return bool Was the output 'good' (true) or 'bad' (false).
+ * @access private
+ */
+ function _done()
+ {
+ if (Image_Graph_Plot::_done() === false) {
+ return false;
+ }
+
+ $this->_canvas->startGroup(get_class($this) . '_' . $this->_title);
+ $this->_clip(true);
+ $keys = array_keys($this->_dataset);
+ foreach ($keys as $key) {
+ $dataset =& $this->_dataset[$key];
+ $dataset->_reset();
+ $data = array();
+ while ($point = $dataset->_next()) {
+ $data[] = array(
+ 'X' => $this->_pointX($point),
+ 'Y' => $this->_pointY($point)
+ );
+ }
+
+ $regression = Image_Graph_Tool::calculateLinearRegression($data);
+ $this->_getLineStyle($key);
+ $this->_canvas->line(
+ array(
+ 'x0' => $this->_left,
+ 'y0' => $this->_left * $regression['slope'] + $regression['intersection'],
+ 'x1' => $this->_right,
+ 'y1' => $this->_right * $regression['slope'] + $regression['intersection']
+ )
+ );
+ }
+ $this->_clip(false);
+ $this->_canvas->endGroup();
+
+ return true;
+ }
+}
+
+?>
diff --git a/config/dspam/pear/Image/Graph/Plot/Impulse.php b/config/dspam/pear/Image/Graph/Plot/Impulse.php
new file mode 100644
index 00000000..91372cd1
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Plot/Impulse.php
@@ -0,0 +1,204 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Plot
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Plot.php
+ */
+require_once 'Image/Graph/Plot.php';
+
+/**
+ * Impulse chart.
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Plot
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Plot_Impulse extends Image_Graph_Plot
+{
+
+ /**
+ * Perform the actual drawing on the legend.
+ *
+ * @param int $x0 The top-left x-coordinate
+ * @param int $y0 The top-left y-coordinate
+ * @param int $x1 The bottom-right x-coordinate
+ * @param int $y1 The bottom-right y-coordinate
+ * @access private
+ */
+ function _drawLegendSample($x0, $y0, $x1, $y1)
+ {
+ $x = ($x0 + $x1) / 2;
+ $this->_canvas->line(array('x0' => $x, 'y0' => $y0, 'x1' => $x, 'y1' => $y1));
+ }
+
+ /**
+ * Output the plot
+ *
+ * @return bool Was the output 'good' (true) or 'bad' (false).
+ * @access private
+ */
+ function _done()
+ {
+ if (parent::_done() === false) {
+ return false;
+ }
+
+ if (!is_array($this->_dataset)) {
+ return false;
+ }
+
+ $this->_canvas->startGroup(get_class($this) . '_' . $this->_title);
+ $this->_clip(true);
+
+ if ($this->_multiType == 'stacked100pct') {
+ $total = $this->_getTotals();
+ }
+ $current = array();
+ $number = 0;
+
+ $minYaxis = $this->_parent->_getMinimum($this->_axisY);
+ $maxYaxis = $this->_parent->_getMaximum($this->_axisY);
+
+ $keys = array_keys($this->_dataset);
+ foreach ($keys as $key) {
+ $dataset =& $this->_dataset[$key];
+ $dataset->_reset();
+ while ($point = $dataset->_next()) {
+ $x0 = $this->_pointX($point);
+ if (($this->_multiType == 'stacked') ||
+ ($this->_multiType == 'stacked100pct'))
+ {
+ $x = $point['X'];
+
+ if ($point['Y'] >= 0) {
+ if (!isset($current[$x])) {
+ $current[$x] = 0;
+ }
+
+ if ($this->_multiType == 'stacked') {
+ $p0 = array(
+ 'X' => $point['X'],
+ 'Y' => $current[$x]
+ );
+ $p1 = array(
+ 'X' => $point['X'],
+ 'Y' => $current[$x] + $point['Y']
+ );
+ } else {
+ $p0 = array(
+ 'X' => $point['X'],
+ 'Y' => 100 * $current[$x] / $total['TOTAL_Y'][$x]
+ );
+ $p1 = array(
+ 'X' => $point['X'],
+ 'Y' => 100 * ($current[$x] + $point['Y']) / $total['TOTAL_Y'][$x]
+ );
+ }
+ $current[$x] += $point['Y'];
+ } else {
+ if (!isset($currentNegative[$x])) {
+ $currentNegative[$x] = 0;
+ }
+
+ $p0 = array(
+ 'X' => $point['X'],
+ 'Y' => $currentNegative[$x]
+ );
+ $p1 = array(
+ 'X' => $point['X'],
+ 'Y' => $currentNegative[$x] + $point['Y']
+ );
+ $currentNegative[$x] += $point['Y'];
+ }
+ } else {
+ $p0 = array('X' => $point['X'], 'Y' => 0);
+ $p1 = $point;
+ }
+
+ if ((($minY = min($p0['Y'], $p1['Y'])) < $maxYaxis) &&
+ (($maxY = max($p0['Y'], $p1['Y'])) > $minYaxis)
+ ) {
+ $p0['Y'] = $minY;
+ $p1['Y'] = $maxY;
+
+ if ($p0['Y'] < $minYaxis) {
+ $p0['Y'] = '#min_pos#';
+ }
+ if ($p1['Y'] > $maxYaxis) {
+ $p1['Y'] = '#max_neg#';
+ }
+
+ $x1 = $this->_pointX($p0);
+ $y1 = $this->_pointY($p0);
+
+ $x2 = $this->_pointX($p1);
+ $y2 = $this->_pointY($p1);
+
+ if ($this->_multiType == 'normal') {
+ $offset = 5*$number;
+ $x1 += $offset;
+ $x2 += $offset;
+ }
+
+ $ID = $point['ID'];
+ if (($ID === false) && (count($this->_dataset) > 1)) {
+ $ID = $key;
+ }
+ $this->_getLineStyle($key);
+ $this->_canvas->line(
+ $this->_mergeData(
+ $point,
+ array(
+ 'x0' => $x1,
+ 'y0' => $y1,
+ 'x1' => $x2,
+ 'y1' => $y2
+ )
+ )
+ );
+ }
+ }
+ $number++;
+ }
+ unset($keys);
+ $this->_drawMarker();
+ $this->_clip(false);
+ $this->_canvas->endGroup();
+ return true;
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Plot/Line.php b/config/dspam/pear/Image/Graph/Plot/Line.php
new file mode 100644
index 00000000..009b4e1f
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Plot/Line.php
@@ -0,0 +1,171 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Plot
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Plot.php
+ */
+require_once 'Image/Graph/Plot.php';
+
+/**
+ * Linechart.
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Plot
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Plot_Line extends Image_Graph_Plot
+{
+
+ /**
+ * Gets the fill style of the element
+ *
+ * @return int A GD filestyle representing the fill style
+ * @see Image_Graph_Fill
+ * @access private
+ */
+ function _getFillStyle($ID = false)
+ {
+ return IMG_COLOR_TRANSPARENT;
+ }
+
+ /**
+ * Perform the actual drawing on the legend.
+ *
+ * @param int $x0 The top-left x-coordinate
+ * @param int $y0 The top-left y-coordinate
+ * @param int $x1 The bottom-right x-coordinate
+ * @param int $y1 The bottom-right y-coordinate
+ * @access private
+ */
+ function _drawLegendSample($x0, $y0, $x1, $y1)
+ {
+ $y = ($y0 + $y1) / 2;
+ $dx = abs($x1 - $x0) / 3;
+ $dy = abs($y1 - $y0) / 5;
+ $this->_canvas->addVertex(array('x' => $x0, 'y' => $y));
+ $this->_canvas->addVertex(array('x' => $x0 + $dx, 'y' => $y - $dy * 2));
+ $this->_canvas->addVertex(array('x' => $x1 - $dx, 'y' => $y + $dy));
+ $this->_canvas->addVertex(array('x' => $x1, 'y' => $y - $dy));
+ $this->_canvas->polygon(array('connect' => false));
+ }
+
+ /**
+ * Output the plot
+ *
+ * @return bool Was the output 'good' (true) or 'bad' (false).
+ * @access private
+ */
+ function _done()
+ {
+ if (parent::_done() === false) {
+ return false;
+ }
+
+ if (!is_array($this->_dataset)) {
+ return false;
+ }
+
+ $this->_canvas->startGroup(get_class($this) . '_' . $this->_title);
+ $this->_clip(true);
+ reset($this->_dataset);
+
+ if ($this->_multiType == 'stacked100pct') {
+ $total = $this->_getTotals();
+ }
+
+ $p1 = false;
+
+ $keys = array_keys($this->_dataset);
+ foreach ($keys as $key) {
+ $dataset =& $this->_dataset[$key];
+ $dataset->_reset();
+ $numPoints = 0;
+ while ($point = $dataset->_next()) {
+ if (($this->_multiType == 'stacked') ||
+ ($this->_multiType == 'stacked100pct'))
+ {
+ $x = $point['X'];
+ if (!isset($current[$x])) {
+ $current[$x] = 0;
+ }
+ if ($this->_multiType == 'stacked') {
+ $py = $current[$x] + $point['Y'];
+ } else {
+ $py = 100 * ($current[$x] + $point['Y']) / $total['TOTAL_Y'][$x];
+ }
+ $current[$x] += $point['Y'];
+ $point['Y'] = $py;
+ }
+
+ if ($point['Y'] === null) {
+ if ($numPoints > 1) {
+ $this->_getLineStyle($key);
+ $this->_canvas->polygon(array('connect' => false, 'map_vertices' => true));
+ }
+ else {
+ $this->_canvas->reset();
+ }
+ $numPoints = 0;
+ } else {
+ $p2['X'] = $this->_pointX($point);
+ $p2['Y'] = $this->_pointY($point);
+
+ $this->_canvas->addVertex(
+ $this->_mergeData(
+ $point,
+ array('x' => $p2['X'], 'y' => $p2['Y'])
+ )
+ );
+ $numPoints++;
+ }
+ }
+ if ($numPoints > 1) {
+ $this->_getLineStyle($key);
+ $this->_canvas->polygon(array('connect' => false, 'map_vertices' => true));
+ }
+ else {
+ $this->_canvas->reset();
+ }
+ }
+ unset($keys);
+ $this->_drawMarker();
+ $this->_clip(false);
+ $this->_canvas->endGroup();
+ return true;
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Plot/Odo.php b/config/dspam/pear/Image/Graph/Plot/Odo.php
new file mode 100644
index 00000000..d6bf7969
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Plot/Odo.php
@@ -0,0 +1,719 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Plot
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Plot.php
+ */
+require_once 'Image/Graph/Plot.php';
+
+/**
+ * Include file Image/Graph/Tool.php
+ */
+require_once 'Image/Graph/Tool.php';
+
+/**
+ * 2D Odochart.
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Plot
+ * @author Maxime Delorme <mdelorme@tennaxia.com>
+ * @copyright Copyright (C) 2005 Maxime Delorme
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Plot_Odo extends Image_Graph_Plot
+{
+ /**
+ * the percent of the radius of the chart that will be use as the width of the range
+ * @access private
+ * @var int
+ */
+ var $_radiusPercent = 50;
+
+ /**
+ * the minimun value of the chart or the start value
+ * @access private
+ * @var int
+ */
+ var $_value_min = 0;
+
+ /**
+ * the maximum value of the chart or the end value
+ * @access private
+ * @var int
+ */
+ var $_value_max = 100;
+
+ /**
+ * the start angle
+ * @access private
+ * @var int
+ */
+ var $_deg_offset = 135;
+
+ /**
+ * the angle of the chart , the length of the chart
+ * 180 min a half circle
+ * @access private
+ * @var int
+ */
+ var $_deg_width = 270;
+
+ /**
+ * the length of the big ticks
+ * the small ones will be half ot it, the values 160% of it
+ * 180 min a half circle
+ * @access private
+ * @var int
+ */
+ var $_tickLength = 14;
+
+ /**
+ * how many small ticks a big tick appears
+ * the small ticks appear every 6°
+ * so with the default value of 5, every 30° there is a value and a big tick
+ * 180 min a half circle
+ * @access private
+ * @var int
+ */
+ var $_axisTicks = 5;
+
+ /**
+ * Arrow marker
+ * @access private
+ * @var Image_Graph_Marker
+ */
+ var $_arrowMarker;
+
+ /**
+ * Range marker fill style
+ * @access private
+ * @var Image_Graph_Fill
+ */
+ var $_rangeFillStyle = null;
+
+ /**
+ * The width of the arrow
+ * @access private
+ * @var int
+ */
+ var $_arrowWidth = 5;
+
+ /**
+ * The length of the arrow
+ * @access private
+ * @var int
+ */
+ var $_arrowLength = 80;
+
+ /**
+ * The radius of the plot
+ * @access private
+ * @var int
+ */
+ var $_radius = false;
+
+ /**
+ * The total Y
+ * @access private
+ * @var int
+ */
+ var $_totalY = false;
+
+ /**
+ * Center X of odometer "circle"
+ * @access private
+ * @var int
+ */
+ var $_centerX = false;
+
+ /**
+ * Center y of odometer "circle"
+ * @access private
+ * @var int
+ */
+ var $_centerY = false;
+
+ /**
+ * Plot_Odo [Constructor]
+ *
+ * dataset with one data per arrow
+ * @param Image_Graph_Dataset $dataset The data set (value containter) to
+ * plot or an array of datasets
+ * {@link Image_Graph_Legend}
+ */
+ function Image_Graph_Plot_Odo(&$dataset)
+ {
+ parent::Image_Graph_Plot($dataset);
+
+ $keys = array_keys($this->_dataset);
+ foreach ($keys as $key) {
+ $dataset =& $this->_dataset[$key];
+ if (isset($min)) {
+ $min = min($dataset->minimumY(), $min);
+ }
+ else {
+ $min = $dataset->minimumY();
+ }
+ if (isset($max)) {
+ $max = max($dataset->maximumY(), $max);
+ }
+ else {
+ $max = $dataset->maximumY();
+ }
+ }
+ $this->_value_min = $min;
+ $this->_value_max = $max;
+ }
+
+ /**
+ * Set the center of the odometer
+ *
+ * @param int $centerX The center x point
+ * @param int $centerY The center y point
+ */
+ function setCenter($centerX, $centerY)
+ {
+ $this->_centerX = $centerX;
+ $this->_centerY = $centerY;
+ }
+
+ /**
+ * Convert a value to the angle position onto the odometer
+ *
+ * @access private
+ * @param int $value the value to convert
+ * @return int the angle'position onto the odometer
+ */
+ function _value2angle($value)
+ {
+ return $this->_deg_width * (($value - $this->_value_min) / $this->_totalY) + $this->_deg_offset;
+ }
+
+ /**
+ * set some internal var
+ *
+ * @access private
+ */
+ function _initialize()
+ {
+ $v1 = $this->_deg_offset;
+ $v2 = $this->_deg_offset + $this->_deg_width;
+
+ $dimensions = Image_Graph_Tool::calculateArcDimensionAndCenter($v1, $v2);
+
+ $radiusX = ($this->width() / 2) / $dimensions['rx'];
+ $radiusY = ($this->height() / 2) / $dimensions['ry'];
+
+ $this->_radius = min($radiusX, $radiusY);
+
+ if ($this->_marker) {
+ $this->_radius = $this->_radius * 0.85;
+ }
+
+ //the center of the plot
+ if ($this->_centerX === false) {
+ $this->_centerX = (int) (($this->_left + $this->_right) / 2) +
+ $this->_radius * ($dimensions['cx'] - 0.5);
+ }
+
+ if ($this->_centerY === false) {
+ $this->_centerY = (int) (($this->_top + $this->_bottom) / 2) +
+ $this->_radius * ($dimensions['cy'] - 0.5);
+ }
+
+ //the max range
+ $this->_totalY = abs($this->_value_max - $this->_value_min);
+ }
+
+ /**
+ * set min and max value of the range
+ *
+ * @access public
+ * @param integer $value_min the minimun value of the chart or the start value
+ * @param integer $value_max the maximum value of the chart or the end value
+ */
+ function setRange($value_min, $value_max)
+ {
+ $this->_value_min = $value_min;
+ $this->_value_max = $value_max;
+ }
+
+ /**
+ * Set start's angle and amplitude of the chart
+ *
+ * @access public
+ * @param integer $deg_offset the start angle
+ * @param integer $deg_width the angle of the chart (the length)
+ */
+ function setAngles($deg_offset, $deg_width)
+ {
+ $this->_deg_offset = min(360, abs($deg_offset));
+ $this->_deg_width = min(360, abs($deg_width));
+ }
+
+ /**
+ * set the width of the chart
+ *
+ * @access public
+ * @param string $radius_percent a value between 0 and 100
+ */
+ function setRadiusWidth($radius_percent)
+ {
+ $this->_radiusPercent = $radius_percent;
+ }
+
+ /**
+ * set the width and length of the arrow (in percent of the total plot "radius")
+ *
+ * @param int length The length in percent
+ * @param int width The width in percent
+ */
+ function setArrowSize($length, $width)
+ {
+ $this->_arrowWidth = max(0, min(100, $width));
+ $this->_arrowLength = max(0, min(100, $length));
+ }
+
+ /**
+ * Set the arrow marker
+ * @param Image_Graph_Marker $marker The marker to set for arrow marker
+ */
+ function setArrowMarker(&$marker)
+ {
+ $this->_arrowMarker =& $marker;
+ }
+
+
+ /**
+ * Output the plot
+ *
+ * @return bool Was the output 'good' (true) or 'bad' (false).
+ * @access private
+ */
+ function _done()
+ {
+ if (parent::_done() === false) {
+ return false;
+ }
+ $this->_initialize();
+ $this->_drawRange();
+ $this->_drawAxis();
+ $this->_drawArrow();
+ $this->_drawMarker();
+ return true;
+ }
+
+ /**
+ * set the length of the ticks
+ *
+ * @access public
+ * @param string $radius_percent a value between 0 and 100
+ */
+ function setTickLength($radius)
+ {
+ $this->_tickLength = $radius;
+ }
+
+ /**
+ * set the length of the ticks
+ *
+ * @access public
+ * @param string $radius_percent a value between 0 and 100
+ */
+ function setAxisTicks($int)
+ {
+ $this->_axisTicks = $int;
+ }
+
+ /**
+ * Draw the outline and the axis
+ *
+ * @access private
+ */
+ function _drawAxis()
+ {
+ //draw outline
+ $this->_getLineStyle();
+ $this->_canvas->pieslice(
+ array(
+ 'x' => $this->_centerX,
+ 'y' => $this->_centerY,
+ 'rx' => $this->_radius,
+ 'ry' => $this->_radius,
+ 'v1' => $this->_deg_offset,
+ 'v2' => $this->_deg_offset+$this->_deg_width,
+ 'srx' => $this->_radius * (1 - $this->_radiusPercent / 100),
+ 'sry' => $this->_radius * (1 - $this->_radiusPercent / 100)
+ )
+ );
+
+ //step for every 6°
+ $step = (int) ($this->_totalY / $this->_deg_width * 6);
+ $value = $this->_value_min;
+ $i = 0;
+ while ($value <= $this->_value_max) {
+ $angle = $this->_value2angle($value);
+
+ $cos = cos(deg2rad($angle));
+ $sin = sin(deg2rad($angle));
+ $point = array('Y' => $value);
+ $point['AX'] = $cos;
+ $point['AY'] = $sin;
+ $point['LENGTH'] = 1;
+ $x = $this->_centerX + $this->_radius * $cos;
+ $y = $this->_centerY + $this->_radius * $sin;
+ $deltaX = - $cos * $this->_tickLength ;
+ $deltaY = - $sin * $this->_tickLength ;
+ $this->_getLineStyle();
+ if(($i % $this->_axisTicks) == 0){
+ $this->_canvas->line(array('x0' => $x, 'y0' => $y, 'x1' => $x + $deltaX, 'y1' => $y + $deltaY));
+ if ($this->_arrowMarker) {
+ $this->_arrowMarker->_drawMarker($x + $deltaX * 1.6, $y + $deltaY *1.6, $point);
+ }
+ } else {
+ $this->_canvas->line(array('x0' => $x, 'y0' => $y, 'x1' => $x + $deltaX * 0.5, 'y1' => $y + $deltaY * 0.5));
+ }
+ $i++;
+ $value += $step;
+ }
+
+ }
+
+ /**
+ * Set the line style of the arrows
+ *
+ * @param Image_Graph_Line $lineStyle The line style of the Arrow
+ * @see Image_Graph_Line
+ * @access public
+ */
+ function setArrowLineStyle($lineStyle)
+ {
+ $this->_arrowLineStyle = &$lineStyle;
+ }
+
+ /**
+ * Set the fillstyle of the arrows
+ *
+ * @param Image_Graph_Fill $fillStyle The fill style of the arrows
+ * @see Image_Graph_Fill
+ * @access public
+ */
+ function setArrowFillStyle($fillStyle)
+ {
+ $this->_arrowFillStyle = &$fillStyle;
+ }
+
+ /**
+ * Draw the arrows
+ *
+ * @access private
+ */
+ function _drawArrow()
+ {
+ $keys = array_keys($this->_dataset);
+ foreach ($keys as $key) {
+ $dataset =& $this->_dataset[$key];
+ $dataset->_reset();
+ $this->setLineStyle($this->_arrowLineStyle);
+ $this->setFillStyle($this->_arrowFillStyle);
+ while ($point = $dataset->_next()) {
+ $ID = $point['ID'];
+ $this->_getFillStyle($ID);
+ $this->_getLineStyle($ID);
+ $deg = $this->_value2angle($point['Y']);
+ list($xr,$yr) = Image_Graph_Tool::rotate($this->_centerX + $this->_arrowLength * $this->_radius / 100, $this->_centerY, $this->_centerX, $this->_centerY, $deg);
+ $this->_canvas->addVertex(array('x' => $xr, 'y' => $yr));
+ list($xr,$yr) = Image_Graph_Tool::rotate($this->_centerX, $this->_centerY - $this->_arrowWidth * $this->_radius/100, $this->_centerX, $this->_centerY, $deg);
+ $this->_canvas->addVertex(array('x' => $xr, 'y' => $yr));
+ list($xr,$yr) = Image_Graph_Tool::rotate($this->_centerX - $this->_arrowWidth * $this->_radius / 100, $this->_centerY, $this->_centerX, $this->_centerY, $deg);
+ $this->_canvas->addVertex(array('x' => $xr, 'y' => $yr));
+ list($xr,$yr) = Image_Graph_Tool::rotate($this->_centerX,$this->_centerY + $this->_arrowWidth * $this->_radius / 100, $this->_centerX, $this->_centerY, $deg);
+ $this->_canvas->addVertex(array('x' => $xr, 'y' => $yr));
+ $this->_canvas->polygon(array('connect' => true));
+ }
+ }
+ }
+
+ /**
+ * Calculate marker point data
+ *
+ * @param array $point The point to calculate data for
+ * @param array $nextPoint The next point
+ * @param array $prevPoint The previous point
+ * @param array $totals The pre-calculated totals, if needed
+ * @return array An array containing marker point data
+ * @access private
+ */
+ function _getMarkerData($point, $nextPoint, $prevPoint, &$totals)
+ {
+ $point = parent::_getMarkerData($point, $nextPoint, $prevPoint, $totals);
+
+ $point['ANGLE'] = $this->_value2angle($point['Y']);
+
+ $point['ANG_X'] = cos(deg2rad($point['ANGLE']));
+ $point['ANG_Y'] = sin(deg2rad($point['ANGLE']));
+
+ $point['AX'] = -$point['ANG_X'];
+ $point['AY'] = -$point['ANG_Y'];
+
+ $point['LENGTH'] = 2.5; //$radius;
+
+ $point['MARKER_X'] = $totals['CENTER_X'] +
+ $totals['ODO_RADIUS'] * $point['ANG_X'];
+ $point['MARKER_Y'] = $totals['CENTER_Y'] +
+ $totals['ODO_RADIUS'] * $point['ANG_Y'];
+
+ return $point;
+ }
+
+ /**
+ * Draws markers of the arrows on the canvas
+ *
+ * @access private
+ */
+ function _drawMarker()
+ {
+
+ if ($this->_marker) {
+ $this->_marker->_radius += $this->_radius / 2;
+ $totals = $this->_getTotals();
+
+ $totals['CENTER_X'] = $this->_centerX;
+ $totals['CENTER_Y'] = $this->_centerY;
+
+
+ /* $keys = array_keys($this->_dataset);
+ foreach ($keys as $key) { */
+ $dataset =& $this->_dataset[0];
+
+ $totals['RADIUS0'] = false;
+ $totals['ODO_RADIUS'] = 1.1 * $this->_radius * $this->_arrowLength / 100;
+ $totals['ALL_SUM_Y'] = $this->_totalY;
+
+ $dataset->_reset();
+ while ($point = $dataset->_next()) {
+ if ((!is_object($this->_dataSelector)) ||
+ ($this->_dataSelector->select($point))
+ ) {
+ $point = $this->_getMarkerData(
+ $point,
+ false,
+ false,
+ $totals
+ );
+ if (is_array($point)) {
+ $this->_marker->_drawMarker(
+ $point['MARKER_X'],
+ $point['MARKER_Y'],
+ $point
+ );
+ }
+ }
+ }
+ /* }
+ unset($keys); */
+ }
+ }
+
+ /**
+ * Set range
+ *
+ * dataset with two data start and end value of the range
+ * @param Image_Graph_Dataset $dataset The data set (value containter) to
+ * plot or an array of datasets
+ *
+ */
+ function addRangeMarker($min, $max, $id = false)
+ {
+ $this->_range[] =
+ array(
+ 'min' => max($this->_value_min, min($min, $max)),
+ 'max' => min($this->_value_max, max($min, $max)),
+ 'id' => $id
+ );
+ }
+
+ /**
+ * Set the fillstyle of the ranges
+ *
+ * @param Image_Graph_Fill $fillStyle The fill style of the range
+ * @see Image_Graph_Fill
+ * @access public
+ */
+ function &setRangeMarkerFillStyle(&$rangeMarkerFillStyle)
+ {
+ $this->_rangeFillStyle = $rangeMarkerFillStyle;
+ }
+
+ /**
+ * Draw the ranges
+ *
+ * @access private
+ */
+ function _drawRange()
+ {
+ if($this->_range){
+ $radius0 = $this->_radius * (1 - $this->_radiusPercent/100);
+ foreach ($this->_range as $range) {
+ $angle1 = $this->_value2angle($range['min']);
+ $angle2 = $this->_value2angle($range['max']);
+
+ if (is_object($this->_rangeFillStyle)) {
+ $this->_canvas->setFill($this->_rangeFillStyle->_getFillStyle($range['id']));
+ } elseif ($this->_rangeFillStyle != null) {
+ $this->_canvas->setFill($this->_rangeFillStyle);
+ }
+ $this->_getLineStyle();
+ $this->_canvas->Pieslice(
+ array(
+ 'x' => $this->_centerX,
+ 'y' => $this->_centerY,
+ 'rx' => $this->_radius,
+ 'ry' => $this->_radius,
+ 'v1' => $angle1,
+ 'v2' => $angle2,
+ 'srx' => $radius0,
+ 'sry' => $radius0
+ )
+ );
+ }
+ }
+ }
+
+ /**
+ * Perform the actual drawing on the legend.
+ *
+ * @param int $x0 The top-left x-coordinate
+ * @param int $y0 The top-left y-coordinate
+ * @param int $x1 The bottom-right x-coordinate
+ * @param int $y1 The bottom-right y-coordinate
+ * @access private
+ */
+ function _drawLegendSample($x0, $y0, $x1, $y1)
+ {
+ $dx = abs($x1 - $x0) / 4;
+ $this->_canvas->addVertex(array('x' => $x0 + $dx , 'y' => $y1));
+ $this->_canvas->addVertex(array('x' => ($x0 + $x1) / 2, 'y' => $y0 ));
+ $this->_canvas->addVertex(array('x' => $x1 - $dx , 'y' => $y1));
+ $this->_canvas->polygon(array('connect' => true));
+ }
+
+ /**
+ * Draw a sample for use with legend
+ *
+ * @param array $param The parameters for the legend
+ * @access private
+ */
+ function _legendSample(&$param)
+ {
+ if (is_array($this->_dataset)) {
+
+ $this->_canvas->startGroup(get_class($this) . '_' . $this->_title);
+ $this->_clip(true);
+
+ $totals = $this->_getTotals();
+ $totals['CENTER_X'] = (int) (($this->_left + $this->_right) / 2);
+ $totals['CENTER_Y'] = (int) (($this->_top + $this->_bottom) / 2);
+ $totals['RADIUS'] = min($this->height(), $this->width()) * 0.75 * 0.5;
+ $totals['CURRENT_Y'] = 0;
+
+ if (is_a($this->_fillStyle, "Image_Graph_Fill")) {
+ $this->_fillStyle->_reset();
+ }
+
+ $count = 0;
+ $keys = array_keys($this->_dataset);
+ foreach ($keys as $key) {
+ $dataset =& $this->_dataset[$key];
+ $count++;
+
+ $dataset->_reset();
+ while ($point = $dataset->_next()) {
+ $caption = $point['X'];
+
+ $this->_canvas->setFont($param['font']);
+ $width = 20 + $param['width'] + $this->_canvas->textWidth($caption);
+ $param['maxwidth'] = max($param['maxwidth'], $width);
+ $x2 = $param['x'] + $width;
+ $y2 = $param['y'] + $param['height'] + 5;
+
+ if ((($param['align'] & IMAGE_GRAPH_ALIGN_VERTICAL) != 0) && ($y2 > $param['bottom'])) {
+ $param['y'] = $param['top'];
+ $param['x'] = $x2;
+ $y2 = $param['y'] + $param['height'];
+ } elseif ((($param['align'] & IMAGE_GRAPH_ALIGN_VERTICAL) == 0) && ($x2 > $param['right'])) {
+ $param['x'] = $param['left'];
+ $param['y'] = $y2;
+ $x2 = $param['x'] + 20 + $param['width'] + $this->_canvas->textWidth($caption);
+ }
+
+ $x = $x0 = $param['x'];
+ $y = $param['y'];
+ $y0 = $param['y'] - $param['height'] / 2;
+ $x1 = $param['x'] + $param['width'];
+ $y1 = $param['y'] + $param['height'] / 2;
+
+ if (!isset($param['simulate'])) {
+ $this->_getFillStyle($point['ID']);
+ $this->_getLineStyle($point['ID']);
+ $this->_drawLegendSample($x0, $y0, $x1, $y1);
+
+ if (($this->_marker) && ($dataset) && ($param['show_marker'])) {
+ $prevPoint = $dataset->_nearby(-2);
+ $nextPoint = $dataset->_nearby();
+
+ $p = $this->_getMarkerData($point, $nextPoint, $prevPoint, $totals);
+ if (is_array($point)) {
+ $p['MARKER_X'] = $x+$param['width'] / 2;
+ $p['MARKER_Y'] = $y;
+ unset ($p['AVERAGE_Y']);
+ $this->_marker->_drawMarker($p['MARKER_X'], $p['MARKER_Y'], $p);
+ }
+ }
+ $this->write($x + $param['width'] + 10, $y, $caption, IMAGE_GRAPH_ALIGN_CENTER_Y | IMAGE_GRAPH_ALIGN_LEFT, $param['font']);
+ }
+
+ if (($param['align'] & IMAGE_GRAPH_ALIGN_VERTICAL) != 0) {
+ $param['y'] = $y2;
+ } else {
+ $param['x'] = $x2;
+ }
+ }
+ }
+ unset($keys);
+ $this->_clip(false);
+ $this->_canvas->endGroup();
+ }
+ }
+}
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Plot/Pie.php b/config/dspam/pear/Image/Graph/Plot/Pie.php
new file mode 100644
index 00000000..f0e872c3
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Plot/Pie.php
@@ -0,0 +1,623 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Plot
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Plot.php
+ */
+require_once 'Image/Graph/Plot.php';
+
+/**
+ * 2D Piechart.
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Plot
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Plot_Pie extends Image_Graph_Plot
+{
+
+ /**
+ * The radius of the 'pie' spacing
+ * @access private
+ * @var int
+ */
+ var $_radius = 3;
+
+ /**
+ * Explode pie slices.
+ * @access private
+ * @var mixed
+ */
+ var $_explode = false;
+
+ /**
+ * The starting angle of the plot
+ * @access private
+ * @var int
+ */
+ var $_startingAngle = 0;
+
+ /**
+ * The angle direction (1 = CCW, -1 = CW)
+ * @access private
+ * @var int
+ */
+ var $_angleDirection = 1;
+
+ /**
+ * The diameter of the pie plot
+ * @access private
+ * @var int
+ */
+ var $_diameter = false;
+
+ /**
+ * Group items below this limit together as "the rest"
+ * @access private
+ * @var double
+ */
+ var $_restGroupLimit = false;
+
+ /**
+ * Rest group title
+ * @access private
+ * @var string
+ */
+ var $_restGroupTitle = 'The rest';
+
+ /**
+ * Perform the actual drawing on the legend.
+ *
+ * @param int $x0 The top-left x-coordinate
+ * @param int $y0 The top-left y-coordinate
+ * @param int $x1 The bottom-right x-coordinate
+ * @param int $y1 The bottom-right y-coordinate
+ * @access private
+ */
+ function _drawLegendSample($x0, $y0, $x1, $y1)
+ {
+ $y = ($y0 + $y1) / 2;
+ $this->_canvas->pieslice(
+ array(
+ 'x' => $x1,
+ 'y' => $y,
+ 'rx' => abs($x1 - $x0) / 2,
+ 'ry' => abs($y1 - $y0) / 2,
+ 'v1' => 45,
+ 'v2' => 315
+ )
+ );
+ }
+
+ /**
+ * Calculate marker point data
+ *
+ * @param array $point The point to calculate data for
+ * @param array $nextPoint The next point
+ * @param array $prevPoint The previous point
+ * @param array $totals The pre-calculated totals, if needed
+ * @return array An array containing marker point data
+ * @access private
+ */
+ function _getMarkerData($point, $nextPoint, $prevPoint, &$totals)
+ {
+ $point = parent::_getMarkerData($point, $nextPoint, $prevPoint, $totals);
+
+ $y = $totals['CURRENT_Y'];
+
+ if ($this->_angleDirection < 0) {
+ $y = $totals['ALL_SUM_Y'] - $y;
+ }
+
+ $point['ANGLE'] = 360 * (($y + ($point['Y'] / 2)) / $totals['ALL_SUM_Y']) + $this->_startingAngle;
+ $totals['CURRENT_Y'] += $point['Y'];
+
+ $point['ANG_X'] = cos(deg2rad($point['ANGLE']));
+ $point['ANG_Y'] = sin(deg2rad($point['ANGLE']));
+
+ $point['AX'] = -10 * $point['ANG_X'];
+ $point['AY'] = -10 * $point['ANG_Y'];
+
+ if ((isset($totals['ALL_SUM_Y'])) && ($totals['ALL_SUM_Y'] != 0)) {
+ $point['PCT_MIN_Y'] = $point['PCT_MAX_Y'] = (100 * $point['Y'] / $totals['ALL_SUM_Y']);
+ }
+
+ $point['LENGTH'] = 10; //$radius;
+
+ $x = $point['X'];
+ $explodeRadius = 0;
+ if ((is_array($this->_explode)) && (isset($this->_explode[$x]))) {
+ $explodeRadius = $this->_explode[$x];
+ } elseif (is_numeric($this->_explode)) {
+ $explodeRadius = $this->_explode;
+ }
+
+ $point['MARKER_X'] = $totals['CENTER_X'] +
+ ($totals['RADIUS'] + $explodeRadius) * $point['ANG_X'];
+ $point['MARKER_Y'] = $totals['CENTER_Y'] +
+ ($totals['RADIUS'] + $explodeRadius) * $point['ANG_Y'];
+
+ return $point;
+ }
+
+ /**
+ * Draws markers on the canvas
+ *
+ * @access private
+ */
+ function _drawMarker()
+ {
+
+ if ($this->_marker) {
+ $totals = $this->_getTotals();
+
+ $totals['CENTER_X'] = (int) (($this->_left + $this->_right) / 2);
+ $totals['CENTER_Y'] = (int) (($this->_top + $this->_bottom) / 2);
+
+ $totals['CURRENT_Y'] = 0;
+ $number = 0;
+
+ $diameter = $this->_getDiameter();
+
+ $keys = array_keys($this->_dataset);
+ foreach ($keys as $key) {
+ $dataset =& $this->_dataset[$key];
+
+ if (count($this->_dataset) == 1) {
+ $totals['RADIUS0'] = false;
+ $totals['RADIUS'] = $diameter / 2;
+ } else {
+ $dr = $diameter / (2 * count($this->_dataset));
+
+ $totals['RADIUS0'] = $number * $dr + ($number > 0 ? $this->_radius : 0);
+ $totals['RADIUS'] = ($number + 1) * $dr;
+ }
+
+ $totals['ALL_SUM_Y'] = 0;
+ $totals['CURRENT_Y'] = 0;
+ $dataset->_reset();
+ while ($point = $dataset->_next()) {
+ $totals['ALL_SUM_Y'] += $point['Y'];
+ }
+
+ $dataset->_reset();
+ $currentY = 0;
+ $the_rest = 0;
+ while ($point = $dataset->_next()) {
+ if (($this->_restGroupLimit !== false) && ($point['Y'] <= $this->_restGroupLimit)) {
+ $the_rest += $point['Y'];
+ }
+ else {
+ if ((!is_object($this->_dataSelector)) ||
+ ($this->_dataSelector->select($point))
+ ) {
+ $point = $this->_getMarkerData(
+ $point,
+ false,
+ false,
+ $totals
+ );
+ if (is_array($point)) {
+ $this->_marker->_drawMarker(
+ $point['MARKER_X'],
+ $point['MARKER_Y'],
+ $point
+ );
+ }
+ }
+ }
+ }
+ if ($the_rest > 0) {
+ $point = array('X' => $this->_restGroupTitle, 'Y' => $the_rest);
+ $point = $this->_getMarkerData(
+ $point,
+ false,
+ false,
+ $totals
+ );
+ if (is_array($point)) {
+ $this->_marker->_drawMarker(
+ $point['MARKER_X'],
+ $point['MARKER_Y'],
+ $point
+ );
+ }
+ }
+ $number++;
+ }
+ unset($keys);
+ }
+ }
+
+ /**
+ * Explodes a piece of this pie chart
+ *
+ * @param int $explode Radius to explode with (or an array)
+ * @param string $x The 'x' value to explode or omitted
+ */
+ function explode($explode, $x = false)
+ {
+ if ($x === false) {
+ $this->_explode = $explode;
+ } else {
+ $this->_explode[$x] = $explode;
+ }
+ }
+
+ /**
+ * Set the starting angle of the plot
+ *
+ * East is 0 degrees
+ * South is 90 degrees
+ * West is 180 degrees
+ * North is 270 degrees
+ *
+ * It is also possible to specify the direction of the plot angles (i.e. clockwise 'cw' or
+ * counterclockwise 'ccw')
+ */
+ function setStartingAngle($angle = 0, $direction = 'ccw')
+ {
+ $this->_startingAngle = ($angle % 360);
+ $this->_angleDirection = ($direction == 'ccw' ? 1 : -1);
+ }
+
+ /**
+ * Set the diameter of the pie plot (i.e. the number of pixels the
+ * pie plot should be across)
+ *
+ * Use 'max' for the maximum possible diameter
+ *
+ * Use negative values for the maximum possible - minus this value (fx -2
+ * to leave 1 pixel at each side)
+ *
+ * @param mixed @diameter The number of pixels
+ */
+ function setDiameter($diameter)
+ {
+ $this->_diameter = $diameter;
+ }
+
+ /**
+ * Set the limit for the y-value, where values below are grouped together
+ * as "the rest"
+ *
+ * @param double $limit The limit
+ * @param string $title The title to display in the legends (default 'The
+ * rest')
+ */
+ function setRestGroup($limit, $title = 'The rest')
+ {
+ $this->_restGroupLimit = $limit;
+ $this->_restGroupTitle = $title;
+ }
+
+ /**
+ * Get the diameter of the plot
+ * @return int The number of pixels the diameter is
+ * @access private
+ */
+ function _getDiameter()
+ {
+ $diameter = 0;
+ if ($this->_diameter === false) {
+ $diameter = min($this->height(), $this->width()) * 0.75;
+ }
+ else {
+ if ($this->_diameter === 'max') {
+ $diameter = min($this->height(), $this->width());
+ }
+ elseif ($this->_diameter < 0) {
+ $diameter = min($this->height(), $this->width()) + $this->_diameter;
+ } else {
+ $diameter = $this->_diameter;
+ }
+ }
+ return $diameter;
+ }
+
+
+ /**
+ * Output the plot
+ *
+ * @return bool Was the output 'good' (true) or 'bad' (false).
+ * @access private
+ */
+ function _done()
+ {
+ if (parent::_done() === false) {
+ return false;
+ }
+
+ $number = 0;
+
+ $keys = array_keys($this->_dataset);
+ foreach ($keys as $key) {
+ $dataset =& $this->_dataset[$key];
+
+ $totalY = 0;
+ $dataset->_reset();
+ while ($point = $dataset->_next()) {
+ $totalY += $point['Y'];
+ }
+
+ $centerX = (int) (($this->_left + $this->_right) / 2);
+ $centerY = (int) (($this->_top + $this->_bottom) / 2);
+ $diameter = $this->_getDiameter();
+ if ($this->_angleDirection < 0) {
+ $currentY = $totalY;
+ } else {
+ $currentY = 0; //rand(0, 100)*$totalY/100;
+ }
+ $dataset->_reset();
+
+ if (count($this->_dataset) == 1) {
+ $radius0 = false;
+ $radius1 = $diameter / 2;
+ } else {
+ $dr = $diameter / (2 * count($this->_dataset));
+
+ $radius0 = $number * $dr + ($number > 0 ? $this->_radius : 0);
+ $radius1 = ($number + 1) * $dr;
+ }
+
+ $the_rest = 0;
+ while ($point = $dataset->_next()) {
+ if (($this->_restGroupLimit !== false) && ($point['Y'] <= $this->_restGroupLimit)) {
+ $the_rest += $point['Y'];
+ }
+ else {
+ $angle1 = 360 * ($currentY / $totalY) + $this->_startingAngle;
+ $currentY += $this->_angleDirection * $point['Y'];
+ $angle2 = 360 * ($currentY / $totalY) + $this->_startingAngle;
+
+ $x = $point['X'];
+ $id = $point['ID'];
+
+ $dX = 0;
+ $dY = 0;
+ $explodeRadius = 0;
+ if ((is_array($this->_explode)) && (isset($this->_explode[$x]))) {
+ $explodeRadius = $this->_explode[$x];
+ } elseif (is_numeric($this->_explode)) {
+ $explodeRadius = $this->_explode;
+ }
+
+ if ($explodeRadius > 0) {
+ $dX = $explodeRadius * cos(deg2rad(($angle1 + $angle2) / 2));
+ $dY = $explodeRadius * sin(deg2rad(($angle1 + $angle2) / 2));
+ }
+
+ $ID = $point['ID'];
+ $this->_getFillStyle($ID);
+ $this->_getLineStyle($ID);
+ $this->_canvas->pieslice(
+ $this->_mergeData(
+ $point,
+ array(
+ 'x' => $centerX + $dX,
+ 'y' => $centerY + $dY,
+ 'rx' => $radius1,
+ 'ry' => $radius1,
+ 'v1' => $angle1,
+ 'v2' => $angle2,
+ 'srx' => $radius0,
+ 'sry' => $radius0
+ )
+ )
+ );
+ }
+ }
+
+ if ($the_rest > 0) {
+ $angle1 = 360 * ($currentY / $totalY) + $this->_startingAngle;
+ $currentY += $this->_angleDirection * $the_rest;
+ $angle2 = 360 * ($currentY / $totalY) + $this->_startingAngle;
+
+ $x = 'rest';
+ $id = 'rest';
+
+ $dX = 0;
+ $dY = 0;
+ $explodeRadius = 0;
+ if ((is_array($this->_explode)) && (isset($this->_explode[$x]))) {
+ $explodeRadius = $this->_explode[$x];
+ } elseif (is_numeric($this->_explode)) {
+ $explodeRadius = $this->_explode;
+ }
+
+ if ($explodeRadius > 0) {
+ $dX = $explodeRadius * cos(deg2rad(($angle1 + $angle2) / 2));
+ $dY = $explodeRadius * sin(deg2rad(($angle1 + $angle2) / 2));
+ }
+
+ $ID = $id;
+ $this->_getFillStyle($ID);
+ $this->_getLineStyle($ID);
+ $this->_canvas->pieslice(
+ $this->_mergeData(
+ $point,
+ array(
+ 'x' => $centerX + $dX,
+ 'y' => $centerY + $dY,
+ 'rx' => $radius1,
+ 'ry' => $radius1,
+ 'v1' => $angle1,
+ 'v2' => $angle2,
+ 'srx' => $radius0,
+ 'sry' => $radius0
+ )
+ )
+ );
+ }
+ $number++;
+ }
+ unset($keys);
+ $this->_drawMarker();
+ return true;
+ }
+
+ /**
+ * Draw a sample for use with legend
+ *
+ * @param array $param The parameters for the legend
+ * @access private
+ */
+ function _legendSample(&$param)
+ {
+ if (is_array($this->_dataset)) {
+
+ $this->_canvas->startGroup(get_class($this) . '_' . $this->_title);
+ $this->_clip(true);
+
+ $totals = $this->_getTotals();
+ $totals['CENTER_X'] = (int) (($this->_left + $this->_right) / 2);
+ $totals['CENTER_Y'] = (int) (($this->_top + $this->_bottom) / 2);
+ $totals['RADIUS'] = min($this->height(), $this->width()) * 0.75 * 0.5;
+ $totals['CURRENT_Y'] = 0;
+
+ if (is_a($this->_fillStyle, "Image_Graph_Fill")) {
+ $this->_fillStyle->_reset();
+ }
+
+ $count = 0;
+ $keys = array_keys($this->_dataset);
+ foreach ($keys as $key) {
+ $dataset =& $this->_dataset[$key];
+ $count++;
+
+ $dataset->_reset();
+ $the_rest = 0;
+ while ($point = $dataset->_next()) {
+ $caption = $point['X'];
+ if (($this->_restGroupLimit !== false) && ($point['Y'] <= $this->_restGroupLimit)) {
+ $the_rest += $point['Y'];
+ }
+ else {
+ $this->_canvas->setFont($param['font']);
+ $width = 20 + $param['width'] + $this->_canvas->textWidth($caption);
+ $param['maxwidth'] = max($param['maxwidth'], $width);
+ $x2 = $param['x'] + $width;
+ $y2 = $param['y'] + $param['height']+5;
+
+ if ((($param['align'] & IMAGE_GRAPH_ALIGN_VERTICAL) != 0) && ($y2 > $param['bottom'])) {
+ $param['y'] = $param['top'];
+ $param['x'] = $x2;
+ $y2 = $param['y'] + $param['height'];
+ } elseif ((($param['align'] & IMAGE_GRAPH_ALIGN_VERTICAL) == 0) && ($x2 > $param['right'])) {
+ $param['x'] = $param['left'];
+ $param['y'] = $y2;
+ $x2 = $param['x'] + 20 + $param['width'] + $this->_canvas->textWidth($caption);
+ }
+
+ $x = $x0 = $param['x'];
+ $y = $param['y'];
+ $y0 = $param['y'] - $param['height']/2;
+ $x1 = $param['x'] + $param['width'];
+ $y1 = $param['y'] + $param['height']/2;
+
+ if (!isset($param['simulate'])) {
+ $this->_getFillStyle($point['ID']);
+ $this->_getLineStyle($point['ID']);
+ $this->_drawLegendSample($x0, $y0, $x1, $y1);
+
+ if (($this->_marker) && ($dataset) && ($param['show_marker'])) {
+ $prevPoint = $dataset->_nearby(-2);
+ $nextPoint = $dataset->_nearby();
+
+ $p = $this->_getMarkerData($point, $nextPoint, $prevPoint, $totals);
+ if (is_array($point)) {
+ $p['MARKER_X'] = $x+$param['width']/2;
+ $p['MARKER_Y'] = $y;
+ unset ($p['AVERAGE_Y']);
+ $this->_marker->_drawMarker($p['MARKER_X'], $p['MARKER_Y'], $p);
+ }
+ }
+ $this->write($x + $param['width'] +10, $y, $caption, IMAGE_GRAPH_ALIGN_CENTER_Y | IMAGE_GRAPH_ALIGN_LEFT, $param['font']);
+ }
+
+ if (($param['align'] & IMAGE_GRAPH_ALIGN_VERTICAL) != 0) {
+ $param['y'] = $y2;
+ } else {
+ $param['x'] = $x2;
+ }
+ }
+ }
+ if ($the_rest > 0) {
+ $this->_canvas->setFont($param['font']);
+ $width = 20 + $param['width'] + $this->_canvas->textWidth($this->_restGroupTitle);
+ $param['maxwidth'] = max($param['maxwidth'], $width);
+ $x2 = $param['x'] + $width;
+ $y2 = $param['y'] + $param['height']+5;
+
+ if ((($param['align'] & IMAGE_GRAPH_ALIGN_VERTICAL) != 0) && ($y2 > $param['bottom'])) {
+ $param['y'] = $param['top'];
+ $param['x'] = $x2;
+ $y2 = $param['y'] + $param['height'];
+ } elseif ((($param['align'] & IMAGE_GRAPH_ALIGN_VERTICAL) == 0) && ($x2 > $param['right'])) {
+ $param['x'] = $param['left'];
+ $param['y'] = $y2;
+ $x2 = $param['x'] + 20 + $param['width'] + $this->_canvas->textWidth($this->_restGroupTitle);
+ }
+
+ $x = $x0 = $param['x'];
+ $y = $param['y'];
+ $y0 = $param['y'] - $param['height']/2;
+ $x1 = $param['x'] + $param['width'];
+ $y1 = $param['y'] + $param['height']/2;
+
+ if (!isset($param['simulate'])) {
+ $this->_getFillStyle('rest');
+ $this->_getLineStyle('rest');
+ $this->_drawLegendSample($x0, $y0, $x1, $y1);
+
+ $this->write($x + $param['width'] + 10, $y, $this->_restGroupTitle, IMAGE_GRAPH_ALIGN_CENTER_Y | IMAGE_GRAPH_ALIGN_LEFT, $param['font']);
+ }
+
+ if (($param['align'] & IMAGE_GRAPH_ALIGN_VERTICAL) != 0) {
+ $param['y'] = $y2;
+ } else {
+ $param['x'] = $x2;
+ }
+ }
+ }
+ unset($keys);
+ $this->_clip(false);
+ $this->_canvas->endGroup();
+ }
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Plot/Radar.php b/config/dspam/pear/Image/Graph/Plot/Radar.php
new file mode 100644
index 00000000..1bfd9da7
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Plot/Radar.php
@@ -0,0 +1,118 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Plot
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Plot.php
+ */
+require_once 'Image/Graph/Plot.php';
+
+/**
+ * Radar chart.
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Plot
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Plot_Radar extends Image_Graph_Plot
+{
+
+ /**
+ * Perform the actual drawing on the legend.
+ *
+ * @param int $x0 The top-left x-coordinate
+ * @param int $y0 The top-left y-coordinate
+ * @param int $x1 The bottom-right x-coordinate
+ * @param int $y1 The bottom-right y-coordinate
+ * @access private
+ */
+ function _drawLegendSample($x0, $y0, $x1, $y1)
+ {
+ $p = 10;
+ $rx = abs($x1 - $x0) / 2;
+ $ry = abs($x1 - $x0) / 2;
+ $r = min($rx, $ry);
+ $cx = ($x0 + $x1) / 2;
+ $cy = ($y0 + $y1) / 2;
+ $max = 5;
+ for ($i = 0; $i < $p; $i++) {
+ $v = 2 * pi() * $i / $p;
+ $t = $r * rand(3, $max) / $max;
+ $x = $cx + $t * cos($v);
+ $y = $cy + $t * sin($v);
+ $this->_canvas->addVertex(array('x' => $x, 'y' => $y));
+ }
+ $this->_canvas->polygon(array('connect' => true));
+ }
+
+ /**
+ * Output the plot
+ *
+ * @return bool Was the output 'good' (true) or 'bad' (false).
+ * @access private
+ */
+ function _done()
+ {
+ $this->_canvas->startGroup(get_class($this) . '_' . $this->_title);
+ $this->_clip(true);
+ if (is_a($this->_parent, 'Image_Graph_Plotarea_Radar')) {
+ $keys = array_keys($this->_dataset);
+ foreach ($keys as $key) {
+ $dataset =& $this->_dataset[$key];
+ $maxY = $dataset->maximumY();
+ $count = $dataset->count();
+
+ $dataset->_reset();
+ while ($point = $dataset->_next()) {
+ $this->_canvas->addVertex(array('x' =>
+ $this->_pointX($point), 'y' =>
+ $this->_pointY($point)
+ ));
+ }
+ $this->_getFillStyle($key);
+ $this->_getLineStyle($key);
+ $this->_canvas->polygon(array('connect' => true));
+ }
+ unset($keys);
+ }
+ $this->_drawMarker();
+
+ $this->_clip(false);
+ $this->_canvas->endGroup();
+ return parent::_done();
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Plot/Smoothed/Area.php b/config/dspam/pear/Image/Graph/Plot/Smoothed/Area.php
new file mode 100644
index 00000000..8ea469dd
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Plot/Smoothed/Area.php
@@ -0,0 +1,145 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Plot
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Plot/Smoothed/Bezier.php
+ */
+require_once 'Image/Graph/Plot/Smoothed/Bezier.php';
+
+/**
+ * Bezier smoothed area chart
+ *
+ * Similar to an {@link Image_Graph_Plot_Area}, but the interconnecting lines
+ * between two datapoints are smoothed using a Bezier curve, which enables the
+ * chart to appear as a nice curved plot instead of the sharp edges of a
+ * conventional {@link Image_Graph_Plot_Area}. Smoothed charts are only supported
+ * with non-stacked types
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Plot
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Plot_Smoothed_Area extends Image_Graph_Plot_Smoothed_Bezier
+{
+
+ /**
+ * Perform the actual drawing on the legend.
+ *
+ * @param int $x0 The top-left x-coordinate
+ * @param int $y0 The top-left y-coordinate
+ * @param int $x1 The bottom-right x-coordinate
+ * @param int $y1 The bottom-right y-coordinate
+ * @access private
+ */
+ function _drawLegendSample($x0, $y0, $x1, $y1)
+ {
+
+ $this->_canvas->addVertex(array('x' => $x0, 'y' => $y1));
+ $this->_addSamplePoints($x0, $y0, $x1, $y1);
+ $this->_canvas->addVertex(array('x' => $x1, 'y' => $y1));
+ $this->_canvas->polygon(array('connect' => true));
+ }
+
+ /**
+ * Output the Bezier smoothed plot as an Area Chart
+ *
+ * @return bool Was the output 'good' (true) or 'bad' (false).
+ * @access private
+ */
+ function _done()
+ {
+ if (parent::_done() === false) {
+ return false;
+ }
+
+ $this->_canvas->startGroup(get_class($this) . '_' . $this->_title);
+ $this->_clip(true);
+
+ $keys = array_keys($this->_dataset);
+ foreach ($keys as $key) {
+ $dataset =& $this->_dataset[$key];
+ $dataset->_reset();
+ $first = true;
+ while ($p1 = $dataset->_next()) {
+ $p0 = $dataset->_nearby(-2);
+ $p2 = $dataset->_nearby(0);
+ $p3 = $dataset->_nearby(1);
+ if ($first) {
+ $p = $p1;
+ $p['Y'] = '#min_pos#';
+ $x = $this->_pointX($p);
+ $y = $this->_pointY($p);
+ $this->_canvas->addVertex(array('x' => $x, 'y' => $y));
+ }
+
+ if ($p2) {
+ $cp = $this->_getControlPoints($p1, $p0, $p2, $p3);
+ $this->_canvas->addSpline(
+ array(
+ 'x' => $cp['X'],
+ 'y' => $cp['Y'],
+ 'p1x' => $cp['P1X'],
+ 'p1y' => $cp['P1Y'],
+ 'p2x' => $cp['P2X'],
+ 'p2y' => $cp['P2Y']
+ )
+ );
+ } else {
+ $x = $this->_pointX($p1);
+ $y = $this->_pointY($p1);
+ $this->_canvas->addVertex(array('x' => $x, 'y' => $y));
+ }
+ $lastPoint = $p1;
+ $first = false;
+ }
+ $lastPoint['Y'] = '#min_pos#';
+ $x = $this->_pointX($lastPoint);
+ $y = $this->_pointY($lastPoint);
+ $this->_canvas->addVertex(array('x' => $x, 'y' => $y));
+
+ $this->_getFillStyle($key);
+ $this->_getLineStyle($key);
+ $this->_canvas->polygon(array('connect' => true));
+ }
+ unset($keys);
+ $this->_drawMarker();
+ $this->_clip(false);
+ $this->_canvas->endGroup();
+ return true;
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Plot/Smoothed/Bezier.php b/config/dspam/pear/Image/Graph/Plot/Smoothed/Bezier.php
new file mode 100644
index 00000000..bc21b4c8
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Plot/Smoothed/Bezier.php
@@ -0,0 +1,173 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Plot
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Plot.php
+ */
+require_once 'Image/Graph/Plot.php';
+
+/**
+ * Include file Image/Graph/Tool.php
+ */
+require_once 'Image/Graph/Tool.php';
+
+/**
+ * Bezier smoothed plottype.
+ *
+ * The framework for calculating the Bezier smoothed curve from the dataset.
+ * Used in {@link Image_Graph_Plot_Smoothed_Line} and {@link
+ * Image_Graph_Plot_Smoothed_Area}. Smoothed charts are only supported with non-
+ * stacked types
+ * @link http://homepages.borland.com/efg2lab/Graphics/Jean-
+ * YvesQueinecBezierCurves.htm efg computer lab - description of bezier curves
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Plot
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ * @abstract
+ */
+class Image_Graph_Plot_Smoothed_Bezier extends Image_Graph_Plot
+{
+
+ /**
+ * Image_Graph_Plot_Smoothed_Bezier [Constructor]
+ *
+ * Only 'normal' multitype supported
+ *
+ * @param Dataset $dataset The data set (value containter) to plot
+ * @param string $title The title of the plot (used for legends, {@link
+ * Image_Graph_Legend})
+ */
+ function Image_Graph_Plot_Smoothed_Bezier(& $dataset, $title = '')
+ {
+ parent::Image_Graph_Plot($dataset, 'normal', $title);
+ }
+
+ /**
+ * Return the minimum Y point
+ *
+ * @return double The minumum Y point
+ * @access private
+ */
+ function _minimumY()
+ {
+ return 1.05 * parent::_minimumY();
+ }
+
+ /**
+ * Return the maximum Y point
+ *
+ * @return double The maximum Y point
+ * @access private
+ */
+ function _maximumY()
+ {
+ return 1.05 * parent::_maximumY();
+ }
+
+ /**
+ * Calculates all Bezier points, for the curve
+ *
+ * @param array $p1 The actual point to calculate control points for
+ * @param array $p0 The point "just before" $p1
+ * @param array $p2 The point "just after" $p1
+ * @param array $p3 The point "just after" $p2
+ * @return array Array of Bezier points
+ * @access private
+ */
+ function _getControlPoints($p1, $p0, $p2, $p3)
+ {
+ $p1 = $this->_pointXY($p1);
+ if ($p2) {
+ $p2 = $this->_pointXY($p2);
+ }
+ if (!$p0) {
+ $p0['X'] = $p1['X'] - abs($p2['X'] - $p1['X']);
+ $p0['Y'] = $p1['Y']; //-($p2['Y']-$p1['Y']);
+ } else {
+ $p0 = $this->_pointXY($p0);
+ }
+ if (!$p3) {
+ $p3['X'] = $p1['X'] + 2*abs($p1['X'] - $p0['X']);
+ $p3['Y'] = $p1['Y'];
+ } else {
+ $p3 = $this->_pointXY($p3);
+ }
+
+ if (!$p2) {
+ $p2['X'] = $p1['X'] + abs($p1['X'] - $p0['X']);
+ $p2['Y'] = $p1['Y'];
+ }
+
+ $pC1['X'] = Image_Graph_Tool::controlPoint($p0['X'], $p1['X'], $p2['X']);
+ $pC1['Y'] = Image_Graph_Tool::controlPoint($p0['Y'], $p1['Y'], $p2['Y']);
+ $pC2['X'] = Image_Graph_Tool::controlPoint($p3['X'], $p2['X'], $p1['X']);
+ $pC2['Y'] = Image_Graph_Tool::controlPoint($p3['Y'], $p2['Y'], $p1['Y']);
+
+ return array(
+ 'X' => $p1['X'],
+ 'Y' => $p1['Y'],
+ 'P1X' => $pC1['X'],
+ 'P1Y' => $pC1['Y'],
+ 'P2X' => $pC2['X'],
+ 'P2Y' => $pC2['Y']
+ );
+ }
+
+ /**
+ * Create legend sample data for the canvas.
+ *
+ * Common for all smoothed plots
+ *
+ * @access private
+ */
+ function _addSamplePoints($x0, $y0, $x1, $y1)
+ {
+ $p = abs($x1 - $x0);
+ $cy = ($y0 + $y1) / 2;
+ $h = abs($y1 - $y0);
+ $dy = $h / 4;
+ $dw = abs($x1 - $x0) / $p;
+ for ($i = 0; $i < $p; $i++) {
+ $v = 2 * pi() * $i / $p;
+ $x = $x0 + $i * $dw;
+ $y = $cy + 2 * $v * sin($v);
+ $this->_canvas->addVertex(array('x' => $x, 'y' => $y));
+ }
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Plot/Smoothed/Line.php b/config/dspam/pear/Image/Graph/Plot/Smoothed/Line.php
new file mode 100644
index 00000000..00692839
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Plot/Smoothed/Line.php
@@ -0,0 +1,172 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Plot
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Plot/Smoothed/Bezier.php
+ */
+require_once 'Image/Graph/Plot/Smoothed/Bezier.php';
+
+/**
+ * Bezier smoothed line chart.
+ *
+ * Similar to a {@link Image_Graph_Plot_Line}, but the interconnecting lines
+ * between two datapoints are smoothed using a Bezier curve, which enables the
+ * chart to appear as a nice curved plot instead of the sharp edges of a
+ * conventional {@link Image_Graph_Plot_Line}. Smoothed charts are only supported
+ * with non-stacked types
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Plot
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Plot_Smoothed_Line extends Image_Graph_Plot_Smoothed_Bezier
+{
+
+ /**
+ * Gets the fill style of the element
+ *
+ * @return int A GD filestyle representing the fill style
+ * @see Image_Graph_Fill
+ * @access private
+ */
+ function _getFillStyle($ID = false)
+ {
+ return IMG_COLOR_TRANSPARENT;
+ }
+
+ /**
+ * Perform the actual drawing on the legend.
+ *
+ * @param int $x0 The top-left x-coordinate
+ * @param int $y0 The top-left y-coordinate
+ * @param int $x1 The bottom-right x-coordinate
+ * @param int $y1 The bottom-right y-coordinate
+ * @access private
+ */
+ function _drawLegendSample($x0, $y0, $x1, $y1)
+ {
+ $this->_addSamplePoints($x0, $y0, $x1, $y1);
+ $this->_canvas->polygon(array('connect' => false));
+ }
+
+ /**
+ * Output the Bezier smoothed plot as an Line Chart
+ *
+ * @return bool Was the output 'good' (true) or 'bad' (false).
+ * @access private
+ */
+ function _done()
+ {
+ if (parent::_done() === false) {
+ return false;
+ }
+
+ $this->_canvas->startGroup(get_class($this) . '_' . $this->_title);
+ $this->_clip(true);
+ $keys = array_keys($this->_dataset);
+ foreach ($keys as $key) {
+ $dataset =& $this->_dataset[$key];
+ $dataset->_reset();
+ $numPoints = 0;
+ while ($p1 = $dataset->_next()) {
+ if ($p1['Y'] === null) {
+ if ($numPoints > 1) {
+ $this->_getLineStyle($key);
+ $this->_canvas->polygon(array('connect' => false, 'map_vertices' => true));
+ }
+ else {
+ $this->_canvas->reset();
+ }
+ $numPoints = 0;
+ } else {
+ $p0 = $dataset->_nearby(-2);
+ $p2 = $dataset->_nearby(0);
+ $p3 = $dataset->_nearby(1);
+
+ if (($p0) && ($p0['Y'] === null)) {
+ $p0 = false;
+ }
+ if (($p2) && ($p2['Y'] === null)) {
+ $p2 = false;
+ }
+ if (($p3) && ($p3['Y'] === null)) {
+ $p3 = false;
+ }
+
+ if ($p2) {
+ $cp = $this->_getControlPoints($p1, $p0, $p2, $p3);
+ $this->_canvas->addSpline(
+ $this->_mergeData(
+ $p1,
+ array(
+ 'x' => $cp['X'],
+ 'y' => $cp['Y'],
+ 'p1x' => $cp['P1X'],
+ 'p1y' => $cp['P1Y'],
+ 'p2x' => $cp['P2X'],
+ 'p2y' => $cp['P2Y']
+ )
+ )
+ );
+ } else {
+ $x = $this->_pointX($p1);
+ $y = $this->_pointY($p1);
+ $this->_canvas->addVertex(
+ $this->_mergeData(
+ $p1,
+ array('x' => $x, 'y' => $y)
+ )
+ );
+ }
+ $numPoints++;
+ }
+ }
+ if ($numPoints > 1) {
+ $this->_getLineStyle();
+ $this->_canvas->polygon(array('connect' => false, 'map_vertices' => true));
+ }
+ else {
+ $this->_canvas->reset();
+ }
+ }
+ unset($keys);
+ $this->_drawMarker();
+ $this->_clip(false);
+ $this->_canvas->endGroup();
+ return true;
+ }
+
+}
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Plot/Smoothed/Radar.php b/config/dspam/pear/Image/Graph/Plot/Smoothed/Radar.php
new file mode 100644
index 00000000..d505a11f
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Plot/Smoothed/Radar.php
@@ -0,0 +1,142 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Plot
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ * @since File available since Release 0.3.0dev2
+ */
+
+/**
+ * Include file Image/Graph/Plot/Smoothed/Bezier.php
+ */
+require_once 'Image/Graph/Plot/Smoothed/Bezier.php';
+
+/**
+ * Smoothed radar chart.
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Plot
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ * @since Class available since Release 0.3.0dev2
+ */
+class Image_Graph_Plot_Smoothed_Radar extends Image_Graph_Plot_Smoothed_Bezier
+{
+
+ /**
+ * Output the plot
+ *
+ * @return bool Was the output 'good' (true) or 'bad' (false).
+ * @access private
+ */
+ function _done()
+ {
+ $this->_canvas->startGroup(get_class($this) . '_' . $this->_title);
+ $this->_clip(true);
+ if (is_a($this->_parent, 'Image_Graph_Plotarea_Radar')) {
+ $keys = array_keys($this->_dataset);
+ foreach ($keys as $key) {
+ $dataset =& $this->_dataset[$key];
+ if ($dataset->count() >= 3) {
+ $dataset->_reset();
+ $p1_ = $dataset->_next();
+ $p2_ = $dataset->_next();
+ $p3_ = $dataset->_next();
+ $plast_ = false;
+ if ($p3_) {
+ while ($p = $dataset->_next()) {
+ $plast_ = $p;
+ }
+ }
+
+ if ($plast_ === false) {
+ $plast_ = $p3_;
+ }
+ $dataset->_reset();
+ while ($p1 = $dataset->_next()) {
+ $p0 = $dataset->_nearby(-2);
+ $p2 = $dataset->_nearby(0);
+ $p3 = $dataset->_nearby(1);
+
+ if ($p0 === false) {
+ $p0 = $plast_;
+ }
+
+ if ($p2 === false) {
+ $p2 = $p1_;
+ $p3 = $p2_;
+ } elseif ($p3 === false) {
+ $p3 = $p1_;
+ }
+
+
+ $cp = $this->_getControlPoints($p1, $p0, $p2, $p3);
+ $this->_canvas->addSpline(
+ array(
+ 'x' => $cp['X'],
+ 'y' => $cp['Y'],
+ 'p1x' => $cp['P1X'],
+ 'p1y' => $cp['P1Y'],
+ 'p2x' => $cp['P2X'],
+ 'p2y' => $cp['P2Y']
+ )
+ );
+
+ $next2last = $p0;
+ $last = $p1;
+ }
+
+ $cp = $this->_getControlPoints($p1_, $plast_, $p2_, $p3_);
+ $this->_canvas->addSpline(
+ array(
+ 'x' => $cp['X'],
+ 'y' => $cp['Y'],
+ 'p1x' => $cp['P1X'],
+ 'p1y' => $cp['P1Y'],
+ 'p2x' => $cp['P2X'],
+ 'p2y' => $cp['P2Y']
+ )
+ );
+ $this->_getFillStyle($key);
+ $this->_getLineStyle($key);
+ $this->_canvas->polygon(array('connect' => true));
+ }
+ }
+ unset($keys);
+ }
+ $this->_drawMarker();
+ $this->_clip(false);
+ $this->_canvas->endGroup($this->_title);
+ return parent::_done();
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Plot/Step.php b/config/dspam/pear/Image/Graph/Plot/Step.php
new file mode 100644
index 00000000..bc9267fe
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Plot/Step.php
@@ -0,0 +1,200 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Plot
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Plot/Bar.php
+ */
+require_once 'Image/Graph/Plot/Bar.php';
+
+/**
+ * Step chart.
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Plot
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Plot_Step extends Image_Graph_Plot
+{
+
+ /**
+ * Perform the actual drawing on the legend.
+ *
+ * @param int $x0 The top-left x-coordinate
+ * @param int $y0 The top-left y-coordinate
+ * @param int $x1 The bottom-right x-coordinate
+ * @param int $y1 The bottom-right y-coordinate
+ * @access private
+ */
+ function _drawLegendSample($x0, $y0, $x1, $y1)
+ {
+ $dx = abs($x1 - $x0) / 3;
+ $dy = abs($y1 - $y0) / 3;
+ $this->_canvas->addVertex(array('x' => $x0, 'y' => $y1));
+ $this->_canvas->addVertex(array('x' => $x0, 'y' => $y0 + $dy));
+
+ $this->_canvas->addVertex(array('x' => $x0 + $dx, 'y' => $y0 + $dy));
+ $this->_canvas->addVertex(array('x' => $x0 + $dx, 'y' => $y0));
+
+ $this->_canvas->addVertex(array('x' => $x0 + 2*$dx, 'y' => $y0));
+ $this->_canvas->addVertex(array('x' => $x0 + 2*$dx, 'y' => $y0 + 2*$dy));
+
+ $this->_canvas->addVertex(array('x' => $x1, 'y' => $y0 + 2*$dy));
+ $this->_canvas->addVertex(array('x' => $x1, 'y' => $y1));
+ $this->_canvas->polygon(array('connect' => true));
+ }
+
+ /**
+ * PlotType [Constructor]
+ *
+ * A 'normal' step chart is 'stacked'
+ *
+ * @param Dataset $dataset The data set (value containter) to plot
+ * @param string $multiType The type of the plot
+ * @param string $title The title of the plot (used for legends,
+ * {@link Image_Graph_Legend})
+ */
+ function Image_Graph_Plot_Step(& $dataset, $multiType = 'stacked', $title = '')
+ {
+ $multiType = strtolower($multiType);
+ if (($multiType != 'stacked') && ($multiType != 'stacked100pct')) {
+ $multiType = 'stacked';
+ }
+ parent::Image_Graph_Plot($dataset, $multiType, $title);
+ }
+
+ /**
+ * Output the plot
+ *
+ * @return bool Was the output 'good' (true) or 'bad' (false).
+ * @access private
+ */
+ function _done()
+ {
+ if (Image_Graph_Plot::_done() === false) {
+ return false;
+ }
+
+ $this->_canvas->startGroup(get_class($this) . '_' . $this->_title);
+ $this->_clip(true);
+
+ if ($this->_multiType == 'stacked100pct') {
+ $total = $this->_getTotals();
+ }
+
+ if ($this->_parent->_horizontal) {
+ $width = $this->height() / ($this->_maximumX() + 2) / 2;
+ }
+ else {
+ $width = $this->width() / ($this->_maximumX() + 2) / 2;
+ }
+
+ reset($this->_dataset);
+ $key = key($this->_dataset);
+ $dataset =& $this->_dataset[$key];
+
+ $first = $dataset->first();
+ $last = $dataset->last();
+
+ $point = array ('X' => $first['X'], 'Y' => '#min_pos#');
+ $firstY = $this->_pointY($point) + ($this->_parent->_horizontal ? $width : 0);
+ $base[] = $firstY;
+ $firstX = $this->_pointX($point) - ($this->_parent->_horizontal ? 0 : $width);
+ $base[] = $firstX;
+
+ $point = array ('X' => $last['X'], 'Y' => '#min_pos#');
+ $base[] = $this->_pointY($point) - ($this->_parent->_horizontal ? $width : 0);
+ $base[] = $this->_pointX($point) + ($this->_parent->_horizontal ? 0 : $width);
+
+ $first = ($this->_parent->_horizontal ? $firstY : $firstX);
+
+ $keys = array_keys($this->_dataset);
+ foreach ($keys as $key) {
+ $dataset =& $this->_dataset[$key];
+ $dataset->_reset();
+ $polygon = array_reverse($base);
+ unset ($base);
+ $last = $first;
+ while ($point = $dataset->_next()) {
+ $x = $point['X'];
+ $p = $point;
+
+ if (!isset($current[$x])) {
+ $current[$x] = 0;
+ }
+
+ if ($this->_multiType == 'stacked100pct') {
+ $p['Y'] = 100 * ($current[$x] + $point['Y']) / $total['TOTAL_Y'][$x];
+ } else {
+ $p['Y'] += $current[$x];
+ }
+ $current[$x] += $point['Y'];
+ $point = $p;
+
+ if ($this->_parent->_horizontal) {
+ $x0 = $this->_pointX($point);
+ $y0 = $last;
+ $x1 = $this->_pointX($point);
+ $last = $y1 = $this->_pointY($point) - $width;
+ }
+ else {
+ $x0 = $last;
+ $y0 = $this->_pointY($point);
+ $last = $x1 = $this->_pointX($point) + $width;
+ $y1 = $this->_pointY($point);
+ }
+ $polygon[] = $x0; $base[] = $y0;
+ $polygon[] = $y0; $base[] = $x0;
+ $polygon[] = $x1; $base[] = $y1;
+ $polygon[] = $y1; $base[] = $x1;
+ }
+
+ while (list(, $x) = each($polygon)) {
+ list(, $y) = each($polygon);
+ $this->_canvas->addVertex(array('x' => $x, 'y' => $y));
+ }
+
+ $this->_getFillStyle($key);
+ $this->_getLineStyle($key);
+ $this->_canvas->polygon(array('connect' => true));
+ }
+ unset($keys);
+ $this->_drawMarker();
+ $this->_clip(false);
+ $this->_canvas->endGroup();
+ return true;
+ }
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Plotarea.php b/config/dspam/pear/Image/Graph/Plotarea.php
new file mode 100644
index 00000000..42aeb26a
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Plotarea.php
@@ -0,0 +1,1145 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Plotarea
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Layout.php
+ */
+require_once 'Image/Graph/Layout.php';
+
+/**
+ * Plot area used for drawing plots.
+ *
+ * The plotarea consists of an x-axis and an y-axis, the plotarea can plot multiple
+ * charts within one plotares, by simply adding them (the axis' will scale to the
+ * plots automatically). A graph can consist of more plotareas
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Plotarea
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Plotarea extends Image_Graph_Layout
+{
+
+ /**
+ * The left most pixel of the 'real' plot area on the canvas
+ * @var int
+ * @access private
+ */
+ var $_plotLeft = 0;
+
+ /**
+ * The top most pixel of the 'real' plot area on the canvas
+ * @var int
+ * @access private
+ */
+ var $_plotTop = 0;
+
+ /**
+ * The right most pixel of the 'real' plot area on the canvas
+ * @var int
+ * @access private
+ */
+ var $_plotRight = 0;
+
+ /**
+ * The bottom most pixel of the 'real' plot area on the canvas
+ * @var int
+ * @access private
+ */
+ var $_plotBottom = 0;
+
+ /**
+ * The X axis
+ * @var Axis
+ * @access private
+ */
+ var $_axisX = null;
+
+ /**
+ * The Y axis
+ * @var Axis
+ * @access private
+ */
+ var $_axisY = null;
+
+ /**
+ * The secondary Y axis
+ * @var Axis
+ * @access private
+ */
+ var $_axisYSecondary = null;
+
+ /**
+ * The border style of the 'real' plot area
+ * @var LineStyle
+ * @access private
+ */
+ var $_plotBorderStyle = null;
+
+ /**
+ * Does any plot have any data?
+ * @var bool
+ * @access private
+ */
+ var $_hasData = false;
+
+ /**
+ * Is the plotarea horizontal?
+ * @var bool
+ * @access private
+ */
+ var $_horizontal = false;
+
+ /**
+ * Image_Graph_Plotarea [Constructor]
+ *
+ * @param string $axisX The class of the X axis (if omitted a std. axis is created)
+ * @param string $axisY The class of the Y axis (if omitted a std. axis is created)
+ * @param string $direction The direction of the plotarea - 'horizontal' or 'vertical' (default)
+ */
+ function Image_Graph_Plotarea($axisX = 'Image_Graph_Axis_Category', $axisY = 'Image_Graph_Axis', $direction = 'vertical')
+ {
+ parent::Image_Graph_Layout();
+
+ $this->_padding = array('left' => 5, 'top' => 5, 'right' => 5, 'bottom' => 5);;
+
+ include_once 'Image/Graph.php';
+
+ $this->_axisX =& Image_Graph::factory($axisX, IMAGE_GRAPH_AXIS_X);
+ $this->_axisX->_setParent($this);
+
+ $this->_axisY =& Image_Graph::factory($axisY, IMAGE_GRAPH_AXIS_Y);
+ $this->_axisY->_setParent($this);
+ $this->_axisY->_setMinimum(0);
+
+ $this->_fillStyle = false;
+
+ if ($direction == 'horizontal') {
+ $this->_horizontal = true;
+ $this->_axisX->_transpose = true;
+ $this->_axisY->_transpose = true;
+ }
+ }
+
+ /**
+ * Sets the parent. The parent chain should ultimately be a GraPHP object
+ *
+ * @see Image_Graph_Common
+ * @param Image_Graph_Common $parent The parent
+ * @access private
+ */
+ function _setParent(& $parent)
+ {
+ parent::_setParent($parent);
+ if ($this->_axisX !== null) {
+ $this->_axisX->_setParent($this);
+ }
+ if ($this->_axisY !== null) {
+ $this->_axisY->_setParent($this);
+ }
+ if ($this->_axisYSecondary !== null) {
+ $this->_axisYSecondary->_setParent($this);
+ }
+ }
+
+ /**
+ * Sets the plot border line style of the element.
+ *
+ * @param Image_Graph_Line $lineStyle The line style of the border
+ * @deprecated 0.3.0dev2 - 2004-12-16
+ */
+ function setPlotBorderStyle(& $plotBorderStyle)
+ {
+ }
+
+ /**
+ * Adds an element to the plotarea
+ *
+ * @param Image_Graph_Element $element The element to add
+ * @param int $axis The axis to associate the element with, either
+ * IMAGE_GRAPH_AXIS_X, IMAGE_GRAPH_AXIS_Y, IMAGE_GRAPH_AXIS_Y_SECONDARY
+ * or the shorter string notations 'x', 'y' or 'ysec' (defaults to
+ * IMAGE_GRAPH_AXIS_Y)
+ * @return Image_Graph_Element The added element
+ * @see Image_Graph_Common::add()
+ */
+ function &add(& $element, $axis = IMAGE_GRAPH_AXIS_Y)
+ {
+ if ($axis == 'x') {
+ $axis = IMAGE_GRAPH_AXIS_X;
+ }
+ if ($axis == 'y') {
+ $axis = IMAGE_GRAPH_AXIS_Y;
+ }
+ if ($axis == 'ysec') {
+ $axis = IMAGE_GRAPH_AXIS_Y_SECONDARY;
+ }
+ if (($axis == IMAGE_GRAPH_AXIS_Y_SECONDARY) &&
+ ($this->_axisYSecondary == null))
+ {
+ $this->_axisYSecondary =& Image_Graph::factory('axis', IMAGE_GRAPH_AXIS_Y_SECONDARY);
+ $this->_axisYSecondary->_setMinimum(0);
+ if ($this->_horizontal) {
+ $this->_axisYSecondary->_transpose = true;
+ }
+ }
+
+ parent::add($element);
+
+ if (is_a($element, 'Image_Graph_Plot')) {
+ $element->_setAxisY($axis);
+ // postpone extrema calculation until we calculate coordinates
+ //$this->_setExtrema($element);
+ } elseif (is_a($element, 'Image_Graph_Grid')) {
+ switch ($axis) {
+ case IMAGE_GRAPH_AXIS_X:
+ if ($this->_axisX != null) {
+ $element->_setPrimaryAxis($this->_axisX);
+ if ($this->_axisY != null) {
+ $element->_setSecondaryAxis($this->_axisY);
+ }
+ }
+ break;
+ case IMAGE_GRAPH_AXIS_Y:
+ if ($this->_axisY != null) {
+ $element->_setPrimaryAxis($this->_axisY);
+ if ($this->_axisX != null) {
+ $element->_setSecondaryAxis($this->_axisX);
+ }
+ }
+ break;
+ case IMAGE_GRAPH_AXIS_Y_SECONDARY:
+ if ($this->_axisYSecondary != null) {
+ $element->_setPrimaryAxis($this->_axisYSecondary);
+ if ($this->_axisX != null) {
+ $element->_setSecondaryAxis($this->_axisX);
+ }
+ }
+ break;
+ }
+ } elseif (is_a($element, 'Image_Graph_Axis')) {
+ switch ($element->_type) {
+ case IMAGE_GRAPH_AXIS_X:
+ $this->_axisX =& $element;
+ break;
+
+ case IMAGE_GRAPH_AXIS_Y:
+ $this->_axisY =& $element;
+ break;
+
+ case IMAGE_GRAPH_AXIS_Y_SECONDARY:
+ $this->_axisYSecondary =& $element;
+ break;
+
+ }
+ if ($element->_getMinimum() == $element->_getMaximum()) {
+ $element->_setMinimum(0);
+ $element->_setMaximum(1);
+ }
+ }
+ return $element;
+ }
+
+ /**
+ * Get the width of the 'real' plotarea
+ *
+ * @return int The width of the 'real' plotarea, ie not including space occupied by padding and axis
+ * @access private
+ */
+ function _plotWidth()
+ {
+ return abs($this->_plotRight - $this->_plotLeft);
+ }
+
+ /**
+ * Get the height of the 'real' plotarea
+ *
+ * @return int The height of the 'real' plotarea, ie not including space
+ * occupied by padding and axis
+ * @access private
+ */
+ function _plotHeight()
+ {
+ return abs($this->_plotBottom - $this->_plotTop);
+ }
+
+ /**
+ * Set the extrema of the axis
+ *
+ * @param Image_Graph_Plot $plot The plot that 'hold' the values
+ * @access private
+ */
+ function _setExtrema(& $plot)
+ {
+ if (($this->_axisX != null) && ($this->_axisX->_isNumeric())) {
+ $this->_axisX->_setMinimum($plot->_minimumX());
+ $this->_axisX->_setMaximum($plot->_maximumX());
+ }
+
+ if (($plot->_axisY == IMAGE_GRAPH_AXIS_Y_SECONDARY) &&
+ ($this->_axisYSecondary !== null) &&
+ ($this->_axisYSecondary->_isNumeric()))
+ {
+ $this->_axisYSecondary->_setMinimum($plot->_minimumY());
+ $this->_axisYSecondary->_setMaximum($plot->_maximumY());
+ } elseif (($this->_axisY != null) && ($this->_axisY->_isNumeric())) {
+ $this->_axisY->_setMinimum($plot->_minimumY());
+ $this->_axisY->_setMaximum($plot->_maximumY());
+ }
+
+ $datasets =& $plot->dataset();
+ if (!is_array($datasets)) {
+ $datasets = array($datasets);
+ }
+
+ $keys = array_keys($datasets);
+ foreach ($keys as $key) {
+ $dataset =& $datasets[$key];
+ if ($dataset->count() > 0) {
+ $this->_hasData = true;
+ }
+
+ if (is_a($dataset, 'Image_Graph_Dataset')) {
+ if (($this->_axisX != null) && (!$this->_axisX->_isNumeric())) {
+ $this->_axisX->_applyDataset($dataset);
+ }
+
+ if (($plot->_axisY == IMAGE_GRAPH_AXIS_Y_SECONDARY) &&
+ ($this->_axisYSecondary !== null) &&
+ (!$this->_axisYSecondary->_isNumeric()))
+ {
+ $this->_axisYSecondary->_applyDataset($dataset);
+ } elseif (($this->_axisY != null) && (!$this->_axisY->_isNumeric())) {
+ $this->_axisY->_applyDataset($dataset);
+ }
+ }
+ }
+ unset($keys);
+ }
+
+ /**
+ * Left boundary of the background fill area
+ *
+ * @return int Leftmost position on the canvas
+ * @access private
+ */
+ function _fillLeft()
+ {
+ return $this->_plotLeft;
+ }
+
+ /**
+ * Top boundary of the background fill area
+ *
+ * @return int Topmost position on the canvas
+ * @access private
+ */
+ function _fillTop()
+ {
+ return $this->_plotTop;
+ }
+
+ /**
+ * Right boundary of the background fill area
+ *
+ * @return int Rightmost position on the canvas
+ * @access private
+ */
+ function _fillRight()
+ {
+ return $this->_plotRight;
+ }
+
+ /**
+ * Bottom boundary of the background fill area
+ *
+ * @return int Bottommost position on the canvas
+ * @access private
+ */
+ function _fillBottom()
+ {
+ return $this->_plotBottom;
+ }
+
+ /**
+ * Get the point from the x-axis
+ * @param array $value The value array
+ * @param int $min The minimum pixel position possible
+ * @param int $max The maximum pixel position possible
+ * @return int The pixel position from the axis
+ * @access private
+ */
+ function _axisPointX($value, $min, $max)
+ {
+ if (($this->_axisX == null) || (!isset($value['X']))) {
+ return false;
+ }
+
+ if ($value['X'] === '#min#') {
+ return $min;
+ }
+ if ($value['X'] === '#max#') {
+ return $max;
+ }
+
+ return $this->_axisX->_point($value['X']);
+ }
+
+ /**
+ * Get the point from the x-axis
+ * @param array $value The value array
+ * @param int $min The minimum pixel position possible
+ * @param int $max The maximum pixel position possible
+ * @return int The pixel position from the axis
+ * @access private
+ */
+ function _axisPointY($value, $min, $max)
+ {
+ if (!isset($value['Y'])) {
+ return false;
+ }
+
+ if (($value['Y'] === '#min_pos#') || ($value['Y'] === '#max_nex#')) {
+ // return the minimum (bottom) position or if negative then zero
+ // or the maxmum (top) position or if positive then zero
+ if ((isset($value['AXIS_Y'])) &&
+ ($value['AXIS_Y'] == IMAGE_GRAPH_AXIS_Y_SECONDARY) &&
+ ($this->_axisYSecondary !== null)
+ ) {
+ $axisY =& $this->_axisYSecondary;
+ } else {
+ $axisY =& $this->_axisY;
+ }
+ if ($value['Y'] === '#min_pos#') {
+ return $axisY->_point(max(0, $axisY->_getMinimum()));
+ } else {
+ return $axisY->_point(min(0, $axisY->_getMaximum()));
+ }
+ }
+
+ if ($value['Y'] === '#min#') {
+ return $min;
+ }
+ if ($value['Y'] === '#max#') {
+ return $max;
+ }
+
+ if ((isset($value['AXIS_Y'])) &&
+ ($value['AXIS_Y'] == IMAGE_GRAPH_AXIS_Y_SECONDARY)
+ ) {
+ if ($this->_axisYSecondary !== null) {
+ return $this->_axisYSecondary->_point($value['Y']);
+ }
+ } else {
+ if ($this->_axisY !== null) {
+ return $this->_axisY->_point($value['Y']);
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Get the X pixel position represented by a value
+ *
+ * @param double Value the value to get the pixel-point for
+ * @return double The pixel position along the axis
+ * @access private
+ */
+ function _pointX($value)
+ {
+ if ($this->_horizontal) {
+ return $this->_axisPointY($value, $this->_plotLeft, $this->_plotRight);
+ }
+ else {
+ return $this->_axisPointX($value, $this->_plotLeft, $this->_plotRight);
+ }
+ }
+
+ /**
+ * Get the Y pixel position represented by a value
+ *
+ * @param double Value the value to get the pixel-point for
+ * @return double The pixel position along the axis
+ * @access private
+ */
+ function _pointY($value)
+ {
+ if ($this->_horizontal) {
+ return $this->_axisPointX($value, $this->_plotBottom, $this->_plotTop);
+ }
+ else {
+ return $this->_axisPointY($value, $this->_plotBottom, $this->_plotTop);
+ }
+ }
+
+ /**
+ * Return the minimum value of the specified axis
+ *
+ * @param int $axis The axis to return the minimum value of (see {$link
+ * Image_Graph_Plotarea::getAxis()})
+ * @return double The minimum value of the axis
+ * @access private
+ */
+ function _getMinimum($axis = IMAGE_GRAPH_AXIS_Y)
+ {
+ $axis =& $this->getAxis($axis);
+ if ($axis !== null) {
+ return $axis->_getMinimum();
+ } else {
+ return 0;
+ }
+ }
+
+ /**
+ * Return the maximum value of the specified axis
+ *
+ * @param int $axis The axis to return the maximum value of(see {$link
+ * Image_Graph_Plotarea::getAxis()})
+ * @return double The maximum value of the axis
+ * @access private
+ */
+ function _getMaximum($axis = IMAGE_GRAPH_AXIS_Y)
+ {
+ $axis =& $this->getAxis($axis);
+ if ($axis !== null) {
+ return $axis->_getMaximum();
+ } else {
+ return 0;
+ }
+ }
+
+ /**
+ * Return the label distance for the specified axis.
+ *
+ * @param int $axis The axis to return the label distance for
+ * @return int The distance between 2 adjacent labels
+ * @access private
+ */
+ function _labelDistance($axis)
+ {
+ $axis =& $this->getAxis($axis);
+ if ($axis !== null) {
+ return $axis->_labelDistance();
+ }
+
+ return false;
+ }
+
+ /**
+ * Hides the axis
+ */
+ function hideAxis($axis = false)
+ {
+ if (((!$axis) || ($axis === $this->_axisX) || ($axis === 'x')) && ($this->_axisX != null)) {
+ $this->_axisX->hide();
+ }
+ if (((!$axis) || ($axis === $this->_axisY) || ($axis === 'y')) && ($this->_axisY != null)) {
+ $this->_axisY->hide();
+ }
+ if (((!$axis) || ($axis === $this->_axisYSecondary) || ($axis === 'y_sec')) && ($this->_axisYSecondary != null)) {
+ $this->_axisYSecondary->hide();
+ }
+ }
+
+ /**
+ * Clears/removes the axis
+ */
+ function clearAxis()
+ {
+ $this->_axisX = $this->_axisY = $this->_axisYSecondary = null;
+ }
+
+ /**
+ * Get axis.
+ *
+ * Possible values are IMAGE_GRAPH_AXIS_X, IMAGE_GRAPH_AXIS_Y,
+ * IMAGE_GRAPH_AXIS_Y_SECONDARY or a short hand notation using
+ * string identifiers: 'x', 'y', 'ysec'
+ *
+ * @param int $axis The axis to return
+ * @return Image_Graph_Axis The axis
+ */
+ function &getAxis($axis = IMAGE_GRAPH_AXIS_X)
+ {
+ switch ($axis) {
+ case IMAGE_GRAPH_AXIS_X:
+ case 'x':
+ return $this->_axisX;
+
+ case IMAGE_GRAPH_AXIS_Y:
+ case 'y':
+ return $this->_axisY;
+
+ case IMAGE_GRAPH_AXIS_Y_SECONDARY:
+ case 'ysec':
+ return $this->_axisYSecondary;
+
+ }
+ return null;
+ }
+
+ /**
+ * Update coordinates
+ *
+ * @access private
+ */
+ function _updateCoords()
+ {
+ if (is_array($this->_elements)) {
+ $keys = array_keys($this->_elements);
+ foreach ($keys as $key) {
+ $element =& $this->_elements[$key];
+ if (is_a($element, 'Image_Graph_Plot')) {
+ if (((is_a($element, 'Image_Graph_Plot_Bar')) ||
+ (is_a($element, 'Image_Graph_Plot_Step')) ||
+ (is_a($element, 'Image_Graph_Plot_Dot')) ||
+ (is_a($element, 'Image_Graph_Plot_CandleStick')) ||
+ (is_a($element, 'Image_Graph_Plot_BoxWhisker')) ||
+ (is_a($element, 'Image_Graph_Plot_Impulse'))) &&
+ ($this->_axisX != null) &&
+ (strtolower(get_class($this->_axisX)) != 'image_graph_axis') // do not push plot if x-axis is linear
+ )
+ {
+ $this->_axisX->_pushValues();
+ }
+ $this->_setExtrema($element);
+ }
+ }
+ unset($keys);
+ }
+
+ $this->_calcEdges();
+
+ $pctWidth = (int) ($this->width() * 0.05);
+ $pctHeight = (int) ($this->height() * 0.05);
+
+ $left = $this->_left + $this->_padding['left'];
+ $top = $this->_top + $this->_padding['top'];
+ $right = $this->_right - $this->_padding['right'];
+ $bottom = $this->_bottom - $this->_padding['bottom'];
+
+ // temporary place holder for axis point calculations
+ $axisPoints['x'] = array($left, $top, $right, $bottom);
+ $axisPoints['y'] = $axisPoints['x'];
+ $axisPoints['y2'] = $axisPoints['x'];
+
+ if ($this->_axisX !== null) {
+ $intersectX = $this->_axisX->_getAxisIntersection();
+ $sizeX = $this->_axisX->_size();
+ $this->_axisX->_setCoords($left, $top, $right, $bottom);
+ $this->_axisX->_updateCoords();
+ }
+
+ if ($this->_axisY !== null) {
+ $intersectY = $this->_axisY->_getAxisIntersection();
+ $sizeY = $this->_axisY->_size();
+ $this->_axisY->_setCoords($left, $top, $right, $bottom);
+ $this->_axisY->_updateCoords();
+ }
+
+ if ($this->_axisYSecondary !== null) {
+ $intersectYsec = $this->_axisYSecondary->_getAxisIntersection();
+ $sizeYsec = $this->_axisYSecondary->_size();
+ $this->_axisYSecondary->_setCoords($left, $top, $right, $bottom);
+ $this->_axisYSecondary->_updateCoords();
+ }
+
+ $axisCoordAdd = array('left' => 0, 'right' => 0, 'top' => 0, 'bottom' => 0);
+
+ if ($this->_axisY != null) {
+ if ($this->_axisX != null) {
+ $pos = $this->_axisX->_intersectPoint($intersectY['value']);
+ } else {
+ $pos = ($this->_horizontal ? $bottom : $left);
+ }
+
+ if ($this->_horizontal) {
+ if (($pos + $sizeY) > $bottom) {
+ $axisCoordAdd['bottom'] = ($pos + $sizeY) - $bottom;
+ // the y-axis position needs to be recalculated!
+ } else {
+ // top & bottom may need to be adjusted when the x-axis has been
+ // calculated!
+ $this->_axisY->_setCoords(
+ $left,
+ $pos,
+ $right,
+ $pos + $sizeY
+ );
+ $this->_axisY->_updateCoords();
+ }
+ }
+ else {
+ if (($pos - $sizeY) < $left) {
+ $axisCoordAdd['left'] = $left - ($pos - $sizeY);
+ // the y-axis position needs to be recalculated!
+ } else {
+ // top & bottom may need to be adjusted when the x-axis has been
+ // calculated!
+ $this->_axisY->_setCoords(
+ $pos - $sizeY,
+ $top,
+ $pos,
+ $bottom
+ );
+ $this->_axisY->_updateCoords();
+ }
+ }
+ }
+
+ if ($this->_axisYSecondary != null) {
+ if ($this->_axisX != null) {
+ $pos = $this->_axisX->_intersectPoint($intersectYsec['value']);
+ } else {
+ $pos = ($this->_horizontal ? $top : $right);
+ }
+
+ if ($this->_horizontal) {
+ if (($pos - $sizeYsec) < $top) {
+ $axisCoordAdd['top'] = $top - ($pos - $sizeYsec);
+ // the secondary y-axis position need to be recalculated
+ } else {
+ // top & bottom may need to be adjusted when the x-axis has been
+ // calculated!
+ $this->_axisYSecondary->_setCoords(
+ $left,
+ $pos - $sizeY,
+ $right,
+ $pos
+ );
+ $this->_axisYSecondary->_updateCoords();
+ }
+ }
+ else {
+ if (($pos + $sizeYsec) > $right) {
+ $axisCoordAdd['right'] = ($pos + $sizeYsec) - $right;
+ // the secondary y-axis position need to be recalculated
+ } else {
+ // top & bottom may need to be adjusted when the x-axis has been
+ // calculated!
+ $this->_axisYSecondary->_setCoords(
+ $pos,
+ $top,
+ $pos + $sizeY,
+ $bottom
+ );
+ $this->_axisYSecondary->_updateCoords();
+ }
+ }
+ }
+
+ if ($this->_axisX != null) {
+ if (($intersectX['axis'] == IMAGE_GRAPH_AXIS_Y_SECONDARY) &&
+ ($this->_axisYSecondary !== null)
+ ) {
+ $axis =& $this->_axisYSecondary;
+ } elseif ($this->_axisY !== null) {
+ $axis =& $this->_axisY;
+ } else {
+ $axis = false;
+ }
+
+ if ($axis !== false) {
+ $pos = $axis->_intersectPoint($intersectX['value']);
+ } else {
+ $pos = ($this->_horizontal ? $left : $bottom);
+ }
+
+ if ($this->_horizontal) {
+ if (($pos - $sizeX) < $left) {
+ $axisCoordAdd['left'] = $left - ($pos - $sizeX);
+ $pos = $left + $sizeX;
+ }
+
+ $this->_axisX->_setCoords(
+ $pos - $sizeX,
+ $top + $axisCoordAdd['top'],
+ $pos,
+ $bottom - $axisCoordAdd['bottom']
+ );
+ $this->_axisX->_updateCoords();
+ }
+ else {
+ if (($pos + $sizeX) > $bottom) {
+ $axisCoordAdd['bottom'] = ($pos + $sizeX) - $bottom;
+ $pos = $bottom - $sizeX;
+ }
+
+ $this->_axisX->_setCoords(
+ $left + $axisCoordAdd['left'],
+ $pos,
+ $right - $axisCoordAdd['right'],
+ $pos + $sizeX
+ );
+ $this->_axisX->_updateCoords();
+ }
+ }
+
+ if ($this->_horizontal) {
+ if (($this->_axisX !== null) &&
+ (($axisCoordAdd['top'] != 0) ||
+ ($axisCoordAdd['bottom'] != 0))
+ ) {
+ // readjust y-axis for better estimate of position
+ if ($this->_axisY !== null) {
+ $pos = $this->_axisX->_intersectPoint($intersectY['value']);
+ $this->_axisY->_setCoords(
+ false,
+ $pos,
+ false,
+ $pos + $sizeY
+ );
+ $this->_axisY->_updateCoords();
+ }
+
+ if ($this->_axisYSecondary !== null) {
+ $pos = $this->_axisX->_intersectPoint($intersectYsec['value']);
+ $this->_axisYSecondary->_setCoords(
+ false,
+ $pos - $sizeYsec,
+ false,
+ $pos
+ );
+ $this->_axisYSecondary->_updateCoords();
+ }
+ }
+
+ // adjust top and bottom of y-axis
+ if ($this->_axisY !== null) {
+ $this->_axisY->_setCoords(
+ $left + $axisCoordAdd['left'],
+ false,
+ $right - $axisCoordAdd['right'],
+ false
+ );
+ $this->_axisY->_updateCoords();
+ }
+
+ // adjust top and bottom of y-axis
+ if ($this->_axisYSecondary !== null) {
+ $this->_axisYSecondary->_setCoords(
+ $left + $axisCoordAdd['left'],
+ false,
+ $right - $axisCoordAdd['right'],
+ false
+ );
+ $this->_axisYSecondary->_updateCoords();
+ }
+
+ if ($this->_axisX !== null) {
+ $this->_plotTop = $this->_axisX->_top;
+ $this->_plotBottom = $this->_axisX->_bottom;
+ } else {
+ $this->_plotTop = $top;
+ $this->_plotBottom = $bottom;
+ }
+
+ if ($this->_axisY !== null) {
+ $this->_plotLeft = $this->_axisY->_left;
+ $this->_plotRight = $this->_axisY->_right;
+ } elseif ($this->_axisYSecondary !== null) {
+ $this->_plotLeft = $this->_axisYSecondary->_left;
+ $this->_plotRight = $this->_axisYSecondary->_right;
+ } else {
+ $this->_plotLeft = $this->_left;
+ $this->_plotRight = $this->_right;
+ }
+ }
+ else {
+ if (($this->_axisX !== null) &&
+ (($axisCoordAdd['left'] != 0) ||
+ ($axisCoordAdd['right'] != 0))
+ ) {
+ // readjust y-axis for better estimate of position
+ if ($this->_axisY !== null) {
+ $pos = $this->_axisX->_intersectPoint($intersectY['value']);
+ $this->_axisY->_setCoords(
+ $pos - $sizeY,
+ false,
+ $pos,
+ false
+ );
+ $this->_axisY->_updateCoords();
+ }
+
+ if ($this->_axisYSecondary !== null) {
+ $pos = $this->_axisX->_intersectPoint($intersectYsec['value']);
+ $this->_axisYSecondary->_setCoords(
+ $pos,
+ false,
+ $pos + $sizeYsec,
+ false
+ );
+ $this->_axisYSecondary->_updateCoords();
+ }
+ }
+
+ // adjust top and bottom of y-axis
+ if ($this->_axisY !== null) {
+ $this->_axisY->_setCoords(
+ false,
+ $top + $axisCoordAdd['top'],
+ false,
+ $bottom - $axisCoordAdd['bottom']
+ );
+ $this->_axisY->_updateCoords();
+ }
+
+ // adjust top and bottom of y-axis
+ if ($this->_axisYSecondary !== null) {
+ $this->_axisYSecondary->_setCoords(
+ false,
+ $top + $axisCoordAdd['top'],
+ false,
+ $bottom - $axisCoordAdd['bottom']
+ );
+ $this->_axisYSecondary->_updateCoords();
+ }
+
+ if ($this->_axisX !== null) {
+ $this->_plotLeft = $this->_axisX->_left;
+ $this->_plotRight = $this->_axisX->_right;
+ } else {
+ $this->_plotLeft = $left;
+ $this->_plotRight = $right;
+ }
+
+ if ($this->_axisY !== null) {
+ $this->_plotTop = $this->_axisY->_top;
+ $this->_plotBottom = $this->_axisY->_bottom;
+ } elseif ($this->_axisYSecondary !== null) {
+ $this->_plotTop = $this->_axisYSecondary->_top;
+ $this->_plotBottom = $this->_axisYSecondary->_bottom;
+ } else {
+ $this->_plotTop = $this->_top;
+ $this->_plotBottom = $this->_bottom;
+ }
+ }
+
+ Image_Graph_Element::_updateCoords();
+/*
+ if ($this->_axisX != null) {
+ $this->_axisX->_updateCoords();
+ }
+ if ($this->_axisY != null) {
+ $this->_axisY->_updateCoords();
+ }
+ if ($this->_axisYSecondary != null) {
+ $this->_axisYSecondary->_updateCoords();
+ }*/
+ }
+
+ /**
+ * Set the axis padding for a specified position.
+ *
+ * The axis padding is padding "inside" the plotarea (i.e. to put some space
+ * between the axis line and the actual plot).
+ *
+ * This can be specified in a number of ways:
+ *
+ * 1) Specify an associated array with 'left', 'top', 'right' and 'bottom'
+ * indices with values for the paddings. Leave out 2nd parameter.
+ *
+ * 2) Specify an overall padding as the first parameter
+ *
+ * 3) Specify the padding and position with position values as mentioned
+ * above
+ *
+ * Normally you'd only consider applying axis padding to a category x-axis.
+ *
+ * @param mixed $value The value/padding
+ * @param mixed $position The "position" of the padding
+ */
+ function setAxisPadding($value, $position = false)
+ {
+ if ($position === false) {
+ if (is_array($value)) {
+ if ($this->_horizontal) {
+ if ((isset($value['top'])) && ($this->_axisX !== null)) {
+ $this->_axisX->_setAxisPadding('low', $value['top']);
+ }
+ if ((isset($value['bottom'])) && ($this->_axisX !== null)) {
+ $this->_axisX->_setAxisPadding('high', $value['bottom']);
+ }
+ if ((isset($value['left'])) && ($this->_axisY !== null)) {
+ $this->_axisY->_setAxisPadding('low', $value['left']);
+ }
+ if ((isset($value['right'])) && ($this->_axisY !== null)) {
+ $this->_axisY->_setAxisPadding('high', $value['right']);
+ }
+ if ((isset($value['left'])) && ($this->_axisYSecondary !== null)) {
+ $this->_axisYSecondary->_setAxisPadding('low', $value['left']);
+ }
+ if ((isset($value['right'])) && ($this->_axisYSecondary !== null)) {
+ $this->_axisYSecondary->_setAxisPadding('high', $value['right']);
+ }
+ }
+ else {
+ if ((isset($value['left'])) && ($this->_axisX !== null)) {
+ $this->_axisX->_setAxisPadding('low', $value['left']);
+ }
+ if ((isset($value['right'])) && ($this->_axisX !== null)) {
+ $this->_axisX->_setAxisPadding('high', $value['right']);
+ }
+ if ((isset($value['bottom'])) && ($this->_axisY !== null)) {
+ $this->_axisY->_setAxisPadding('low', $value['bottom']);
+ }
+ if ((isset($value['top'])) && ($this->_axisY !== null)) {
+ $this->_axisY->_setAxisPadding('high', $value['top']);
+ }
+ if ((isset($value['bottom'])) && ($this->_axisYSecondary !== null)) {
+ $this->_axisYSecondary->_setAxisPadding('low', $value['bottom']);
+ }
+ if ((isset($value['top'])) && ($this->_axisYSecondary !== null)) {
+ $this->_axisYSecondary->_setAxisPadding('high', $value['top']);
+ }
+ }
+ } else {
+ if ($this->_axisX !== null) {
+ $this->_axisX->_setAxisPadding('low', $value);
+ $this->_axisX->_setAxisPadding('high', $value);
+ }
+ if ($this->_axisY !== null) {
+ $this->_axisY->_setAxisPadding('low', $value);
+ $this->_axisY->_setAxisPadding('high', $value);
+ }
+ if ($this->_axisYSecondary !== null) {
+ $this->_axisYSecondary->_setAxisPadding('low', $value);
+ $this->_axisYSecondary->_setAxisPadding('high', $value);
+ }
+ }
+ } else {
+ switch ($position) {
+ case 'left':
+ if ($this->_horizontal) {
+ if ($this->_axisY !== null) {
+ $this->_axisY->_setAxisPadding('low', $value);
+ }
+ if ($this->_axisYSecondary !== null) {
+ $this->_axisYSecondary->_setAxisPadding('low', $value);
+ }
+ }
+ else if ($this->_axisX !== null) {
+ $this->_axisX->_setAxisPadding('low', $value);
+ }
+ break;
+
+ case 'right':
+ if ($this->_horizontal) {
+ if ($this->_axisY !== null) {
+ $this->_axisY->_setAxisPadding('high', $value);
+ }
+ if ($this->_axisYSecondary !== null) {
+ $this->_axisYSecondary->_setAxisPadding('high', $value);
+ }
+ }
+ else if ($this->_axisX !== null) {
+ $this->_axisX->_setAxisPadding('high', $value);
+ }
+ break;
+
+ case 'top':
+ if (!$this->_horizontal) {
+ if ($this->_axisY !== null) {
+ $this->_axisY->_setAxisPadding('high', $value);
+ }
+ if ($this->_axisYSecondary !== null) {
+ $this->_axisYSecondary->_setAxisPadding('high', $value);
+ }
+ }
+ else if ($this->_axisX !== null) {
+ $this->_axisX->_setAxisPadding('high', $value);
+ }
+ break;
+
+ case 'bottom':
+ if (!$this->_horizontal) {
+ if ($this->_axisY !== null) {
+ $this->_axisY->_setAxisPadding('low', $value);
+ }
+ if ($this->_axisYSecondary !== null) {
+ $this->_axisYSecondary->_setAxisPadding('low', $value);
+ }
+ }
+ else if ($this->_axisX !== null) {
+ $this->_axisX->_setAxisPadding('low', $value);
+ }
+ break;
+ }
+ }
+ }
+
+ /**
+ * Output the plotarea to the canvas
+ *
+ * @return bool Was the output 'good' (true) or 'bad' (false).
+ * @access private
+ */
+ function _done()
+ {
+ if ($this->_hasData) {
+ $this->_canvas->startGroup(get_class($this));
+
+ if ($this->_axisX != null) {
+ $this->add($this->_axisX);
+ }
+ if ($this->_axisY != null) {
+ $this->add($this->_axisY);
+ }
+ if ($this->_axisYSecondary != null) {
+ $this->add($this->_axisYSecondary);
+ }
+
+ $this->_getFillStyle();
+ $this->_canvas->rectangle(
+ array(
+ 'x0' => $this->_plotLeft,
+ 'y0' => $this->_plotTop,
+ 'x1' => $this->_plotRight,
+ 'y1' => $this->_plotBottom
+ )
+ );
+ $result = parent::_done();
+ $this->_canvas->endGroup();
+ return $result;
+ } else {
+ // no data -> do nothing at all!
+ return true;
+ }
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Plotarea/Element.php b/config/dspam/pear/Image/Graph/Plotarea/Element.php
new file mode 100644
index 00000000..a7d1b8d2
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Plotarea/Element.php
@@ -0,0 +1,87 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Element.php
+ */
+require_once 'Image/Graph/Element.php';
+
+/**
+ * Representation of a element on a plotarea.
+ *
+ * @category Images
+ * @package Image_Graph
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ * @abstract
+ */
+class Image_Graph_Plotarea_Element extends Image_Graph_Element
+{
+
+ /**
+ * Get the X pixel position represented by a value
+ *
+ * @param double $point the value to get the pixel-point for
+ * @return double The pixel position along the axis
+ * @access private
+ */
+ function _pointX($point)
+ {
+ return $this->_parent->_pointX($point);
+ }
+
+ /**
+ * Get the Y pixel position represented by a value
+ *
+ * @param double $point the value to get the pixel-point for
+ * @return double The pixel position along the axis
+ * @access private
+ */
+ function _pointY($point)
+ {
+ return $this->_parent->_pointY($point);
+ }
+
+ /**
+ * Get the X and Y pixel position represented by a value
+ *
+ * @param array $point the values to get the pixel-point for
+ * @return array The (x, y) pixel position along the axis
+ * @access private
+ */
+ function _pointXY($point)
+ {
+ return array ('X' => $this->_pointX($point), 'Y' => $this->_pointY($point));
+ }
+
+}
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Plotarea/Map.php b/config/dspam/pear/Image/Graph/Plotarea/Map.php
new file mode 100644
index 00000000..888d3384
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Plotarea/Map.php
@@ -0,0 +1,304 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Plotarea
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Plotarea.php
+ */
+require_once 'Image/Graph/Plotarea.php';
+
+/**
+ * Plot area used for map plots.
+ *
+ * A map plot is a chart that displays a map (fx. a world map) in the form of .
+ * png file. The maps must be located in the /Images/Maps folder and a
+ * corresponding .txt files mush also exist in this location where named
+ * locations are mapped to an (x, y) coordinate of the map picture (this text
+ * file is tab separated with 'Name' 'X' 'Y' values, fx 'Denmark 378 223'). The
+ * x-values in the dataset are then the named locations (fx 'Denmark') and the
+ * y-values are then the data to plot. Currently the best (if not only) use is
+ * to combine a map plot area with a {@link Image_Graph_Plot_Dot} using {@link
+ * Image_Graph_Marker_PercentageCircle} as marker.
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Plotarea
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Plotarea_Map extends Image_Graph_Plotarea
+{
+
+ /**
+ * The GD image for the map
+ * @var string
+ * @access private
+ */
+ var $_imageMap;
+
+ /**
+ * The value for scaling the width and height to fit into the layout boundaries
+ * @var int
+ * @access private
+ */
+ var $_scale;
+
+ /**
+ * The (x,y)-points for the named point
+ * @var array
+ * @access private
+ */
+ var $_mapPoints;
+
+ /**
+ * The original size of the image map
+ * @var array
+ * @access private
+ */
+ var $_mapSize;
+
+ /**
+ * PlotareaMap [Constructor]
+ *
+ * @param string $map The name of the map, i.e. the [name].png and [name].
+ * txt files located in the Images/maps folder
+ */
+ function Image_Graph_Plotarea_Map($map)
+ {
+ parent::Image_Graph_Plotarea();
+
+ $this->_imageMap = dirname(__FILE__)."/../Images/Maps/$map.png";
+ $points = file(dirname(__FILE__)."/../Images/Maps/$map.txt");
+ list($width, $height) = getimagesize($this->_imageMap);
+ $this->_mapSize['X'] = $width;
+ $this->_mapSize['Y'] = $height;
+
+ if (is_array($points)) {
+ unset($this->_mapPoints);
+ foreach ($points as $line) {
+ list($country, $x, $y) = explode("\t", $line);
+ $this->_mapPoints[$country] = array('X' => $x, 'Y' => $y);
+ }
+ }
+ }
+
+ /**
+ * Left boundary of the background fill area
+ *
+ * @return int Leftmost position on the canvas
+ * @access private
+ */
+ function _fillLeft()
+ {
+ return $this->_left + $this->_padding['left'];
+ }
+
+ /**
+ * Top boundary of the background fill area
+ *
+ * @return int Topmost position on the canvas
+ * @access private
+ */
+ function _fillTop()
+ {
+ return $this->_top + $this->_padding['top'];
+ }
+
+ /**
+ * Right boundary of the background fill area
+ *
+ * @return int Rightmost position on the canvas
+ * @access private
+ */
+ function _fillRight()
+ {
+ return $this->_right - $this->_padding['right'];
+ }
+
+ /**
+ * Bottom boundary of the background fill area
+ *
+ * @return int Bottommost position on the canvas
+ * @access private
+ */
+ function _fillBottom()
+ {
+ return $this->_bottom - $this->_padding['bottom'];
+ }
+
+ /**
+ * Set the extrema of the axis
+ *
+ * @param Image_Graph_Plot $plot The plot that 'hold' the values
+ * @access private
+ */
+ function _setExtrema(& $plot)
+ {
+ }
+
+ /**
+ * Get the X pixel position represented by a value
+ *
+ * @param double $value The value to get the pixel-point for
+ * @return double The pixel position along the axis
+ * @access private
+ */
+ function _pointX($value)
+ {
+ $country = $value['X'];
+ return $this->_plotLeft+$this->_mapPoints[$country]['X']*$this->_scale;
+ }
+
+ /**
+ * Get the Y pixel position represented by a value
+ *
+ * @param double $value The value to get the pixel-point for
+ * @return double The pixel position along the axis
+ * @access private
+ */
+ function _pointY($value)
+ {
+ $country = $value['X'];
+ return $this->_plotTop+$this->_mapPoints[$country]['Y']*$this->_scale;
+ }
+
+ /**
+ * Hides the axis
+ */
+ function hideAxis()
+ {
+ }
+
+ /**
+ * Add a point to the maps
+ *
+ * @param int $latitude The latitude of the point
+ * @param int $longiude The longitude of the point
+ * @param string $name The name of the plot
+ */
+ function addMappoint($latitude, $longitude, $name)
+ {
+ $x = (($longitude + 180) * ($this->_mapSize['X'] / 360));
+ $y = ((($latitude * -1) + 90) * ($this->_mapSize['Y'] / 180));
+ $this->_mapPoints[$name] = array('X' => $x, 'Y' => $y);
+ }
+
+ /**
+ * Add a point to the maps
+ *
+ * @param int $x The latitude of the point
+ * @param int $y The longitude of the point
+ * @param string $name The name of the plot
+ */
+ function addPoint($x, $y, $name)
+ {
+ $this->_mapPoints[$name] = array('X' => $x, 'Y' => $y);
+ }
+
+ /**
+ * Update coordinates
+ *
+ * @access private
+ */
+ function _updateCoords()
+ {
+ parent::_updateCoords();
+
+ $mapAspectRatio = $this->_mapSize['X']/$this->_mapSize['Y'];
+ $plotAspectRatio = ($width = $this->_fillWidth())/($height = $this->_fillHeight());
+
+ $scaleFactorX = ($mapAspectRatio > $plotAspectRatio);
+
+ if ((($this->_mapSize['X'] <= $width) && ($this->_mapSize['Y'] <= $height)) ||
+ (($this->_mapSize['X'] >= $width) && ($this->_mapSize['Y'] >= $height)))
+ {
+ if ($scaleFactorX) {
+ $this->_scale = $width / $this->_mapSize['X'];
+ } else {
+ $this->_scale = $height / $this->_mapSize['Y'];
+ }
+ } elseif ($this->_mapSize['X'] < $width) {
+ $this->_scale = $height / $this->_mapSize['Y'];
+ } elseif ($this->_mapSize['Y'] < $height) {
+ $this->_scale = $width / $this->_mapSize['X'];
+ }
+
+ $this->_plotLeft = ($this->_fillLeft() + $this->_fillRight() -
+ $this->_mapSize['X']*$this->_scale)/2;
+
+ $this->_plotTop = ($this->_fillTop() + $this->_fillBottom() -
+ $this->_mapSize['Y']*$this->_scale)/2;
+
+ $this->_plotRight = ($this->_fillLeft() + $this->_fillRight() +
+ $this->_mapSize['X']*$this->_scale)/2;
+
+ $this->_plotBottom = ($this->_fillTop() + $this->_fillBottom() +
+ $this->_mapSize['Y']*$this->_scale)/2;
+ }
+
+ /**
+ * Output the plotarea to the canvas
+ *
+ * @return bool Was the output 'good' (true) or 'bad' (false).
+ * @access private
+ */
+ function _done()
+ {
+ $this->_getFillStyle();
+ $this->_canvas->rectangle(
+ array(
+ 'x0' => $this->_fillLeft(),
+ 'y0' => $this->_fillTop(),
+ 'x1' => $this->_fillRight(),
+ 'y1' => $this->_fillBottom()
+ )
+ );
+
+ $scaledWidth = $this->_mapSize['X']*$this->_scale;
+ $scaledHeight = $this->_mapSize['Y']*$this->_scale;
+
+ $this->_canvas->image(
+ array(
+ 'x' => $this->_plotLeft,
+ 'y' => $this->_plotTop,
+ 'filename' => $this->_imageMap,
+ 'width' => $scaledWidth,
+ 'height' => $scaledHeight
+ )
+ );
+
+ return Image_Graph_Layout::_done();
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Plotarea/Radar.php b/config/dspam/pear/Image/Graph/Plotarea/Radar.php
new file mode 100644
index 00000000..cfb200ea
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Plotarea/Radar.php
@@ -0,0 +1,243 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - PEAR PHP OO Graph Rendering Utility.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Plotarea
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Plotarea.php
+ */
+require_once 'Image/Graph/Plotarea.php';
+
+/**
+ * Plot area used for radar plots.
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Plotarea
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Plotarea_Radar extends Image_Graph_Plotarea
+{
+
+ /**
+ * Create the plotarea, implicitely creates 2 normal axis
+ */
+ function Image_Graph_Plotarea_Radar()
+ {
+ parent::Image_Graph_Element();
+ $this->_padding = array('left' => 10, 'top' => 10, 'right' => 10, 'bottom' => 10);
+ $this->_axisX =& Image_Graph::factory('Image_Graph_Axis_Radar');
+ $this->_axisX->_setParent($this);
+ $this->_axisY =& Image_Graph::factory('Image_Graph_Axis', IMAGE_GRAPH_AXIS_Y);
+ $this->_axisY->_setParent($this);
+ $this->_axisY->_setMinimum(0);
+ }
+
+ /**
+ * Get the width of the 'real' plotarea
+ *
+ * @return int The width of the 'real' plotarea, ie not including space occupied by padding and axis
+ * @access private
+ */
+ function _plotWidth()
+ {
+ return (min($this->height(), $this->width())) * 0.80;
+ }
+
+ /**
+ * Get the height of the 'real' plotarea
+ *
+ * @return int The height of the 'real' plotarea, ie not including space occupied by padding and axis
+ * @access private
+ */
+ function _plotHeight()
+ {
+ return (min($this->height(), $this->width())) * 0.80;
+ }
+
+ /**
+ * Left boundary of the background fill area
+ *
+ * @return int Leftmost position on the canvas
+ * @access private
+ */
+ function _fillLeft()
+ {
+ return (int) (($this->_left + $this->_right - $this->_plotWidth()) / 2);
+ }
+
+ /**
+ * Top boundary of the background fill area
+ *
+ * @return int Topmost position on the canvas
+ * @access private
+ */
+ function _fillTop()
+ {
+ return (int) (($this->_top + $this->_bottom - $this->_plotHeight()) / 2);
+ }
+
+ /**
+ * Right boundary of the background fill area
+ *
+ * @return int Rightmost position on the canvas
+ * @access private
+ */
+ function _fillRight()
+ {
+ return (int) (($this->_left + $this->_right + $this->_plotWidth()) / 2);
+ }
+
+ /**
+ * Bottom boundary of the background fill area
+ *
+ * @return int Bottommost position on the canvas
+ * @access private
+ */
+ function _fillBottom()
+ {
+ return (int) (($this->_top + $this->_bottom + $this->_plotHeight()) / 2);
+ }
+
+ /**
+ * Get the X pixel position represented by a value
+ *
+ * @param double $value The value to get the pixel-point for
+ * @return double The pixel position along the axis
+ * @access private
+ */
+ function _pointX($value)
+ {
+ if (is_array($value)) {
+ if ($value['Y'] == '#min#') {
+ $radius = 0;
+ } elseif (($value['Y'] == '#max#') || ($value['Y'] === false)) {
+ $radius = 1;
+ } else {
+ $radius = ($value['Y'] - $this->_axisY->_getMinimum()) /
+ ($this->_axisY->_getMaximum() - $this->_axisY->_getMinimum());
+ }
+ $x = ($this->_left + $this->_right) / 2 -
+ $radius * ($this->_plotWidth() / 2) *
+ cos(deg2rad($this->_axisX->_point($value['X'])));
+ }
+ return max($this->_plotLeft, min($this->_plotRight, $x));
+ }
+
+ /**
+ * Get the Y pixel position represented by a value
+ *
+ * @param double $value The value to get the pixel-point for
+ * @return double The pixel position along the axis
+ * @access private
+ */
+ function _pointY($value)
+ {
+ if (is_array($value)) {
+ if ($value['Y'] == '#min#') {
+ $radius = 0;
+ } elseif (($value['Y'] == '#max#') || ($value['Y'] === false)) {
+ $radius = 1;
+ } else {
+ $radius = ($value['Y'] - $this->_axisY->_getMinimum()) /
+ ($this->_axisY->_getMaximum() - $this->_axisY->_getMinimum());
+ }
+
+ $y = ($this->_top + $this->_bottom) / 2 -
+ $radius * ($this->_plotHeight() / 2) *
+ sin(deg2rad($this->_axisX->_point($value['X'])));
+ }
+ return max($this->_plotTop, min($this->_plotBottom, $y));
+ }
+
+ /**
+ * Update coordinates
+ *
+ * @access private
+ */
+ function _updateCoords()
+ {
+ if (is_array($this->_elements)) {
+ $keys = array_keys($this->_elements);
+ foreach ($keys as $key) {
+ $element =& $this->_elements[$key];
+ if (is_a($element, 'Image_Graph_Plot')) {
+ $this->_setExtrema($element);
+ }
+ }
+ unset($keys);
+ }
+
+ $this->_calcEdges();
+
+ $centerX = (int) (($this->_left + $this->_right) / 2);
+ $centerY = (int) (($this->_top + $this->_bottom) / 2);
+ $radius = min($this->_plotHeight(), $this->_plotWidth()) / 2;
+
+ if (is_object($this->_axisX)) {
+ $this->_axisX->_setCoords(
+ $centerX - $radius,
+ $centerY - $radius,
+ $centerX + $radius,
+ $centerY + $radius
+ );
+ }
+
+ if (is_object($this->_axisY)) {
+ $this->_axisY->_setCoords(
+ $centerX,
+ $centerY,
+ $centerX - $radius,
+ $centerY - $radius
+ );
+ }
+
+ $this->_plotLeft = $this->_fillLeft();
+ $this->_plotTop = $this->_fillTop();
+ $this->_plotRight = $this->_fillRight();
+ $this->_plotBottom = $this->_fillBottom();
+
+ Image_Graph_Element::_updateCoords();
+
+ if (is_object($this->_axisX)) {
+ $this->_axisX->_updateCoords();
+ }
+
+ if (is_object($this->_axisY)) {
+ $this->_axisY->_updateCoords();
+ }
+
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Simple.php b/config/dspam/pear/Image/Graph/Simple.php
new file mode 100644
index 00000000..9d14c4da
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Simple.php
@@ -0,0 +1,121 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - Main class for the graph creation.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph.php
+ */
+require_once 'Image/Graph.php';
+
+/**
+ * Class for simple creation of graphs
+ *
+ * @category Images
+ * @package Image_Graph
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Simple extends Image_Graph
+{
+
+ /**
+ * Image_Graph_Simple [Constructor]
+ *
+ * @param int $width The width of the graph in pixels
+ * @param int $height The height of the graph in pixels
+ */
+ function Image_Graph_Simple($width, $height, $plotType, $data, $title, $lineColor = 'black', $fillColor = 'white', $font = false)
+ {
+ parent::Image_Graph($width, $height);
+
+ $plotarea =& Image_Graph::factory('plotarea');
+
+ $dataset =& Image_Graph::factory('dataset', array($data));
+
+ if ($font === false) {
+ $font =& Image_Graph::factory('Image_Graph_Font');
+ } elseif (is_string($font)) {
+ $font =& Image_Graph::factory('ttf_font', $font);
+ $font->setSize(8);
+ }
+
+ $this->setFont($font);
+
+ $this->add(
+ Image_Graph::vertical(
+ Image_Graph::factory('title',
+ array(
+ $title,
+ array('size_rel' => 2)
+ )
+ ),
+ $plotarea,
+ 10
+ )
+ );
+
+ $plotarea->addNew('line_grid', array(), IMAGE_GRAPH_AXIS_Y);
+
+ $plot =& $plotarea->addNew($plotType, array(&$dataset));
+ $plot->setLineColor($lineColor);
+ $plot->setFillColor($fillColor);
+
+ $axisX =& $plotarea->getAxis(IMAGE_GRAPH_AXIS_X);
+ $axisX->showLabel(
+ IMAGE_GRAPH_LABEL_MINIMUM +
+ IMAGE_GRAPH_LABEL_ZERO +
+ IMAGE_GRAPH_LABEL_MAXIMUM
+ );
+
+ }
+
+ /**
+ * Factory method to create the Image_Simple_Graph object.
+ */
+ function &factory($width, $height, $plotType, $data, $title, $lineColor = 'black', $fillColor = 'white', $font = false)
+ {
+ $obj =& Image_Graph::factory('Image_Graph_Simple',
+ array(
+ $width,
+ $height,
+ $plotType,
+ $data,
+ $title,
+ $lineColor,
+ $fillColor,
+ $font
+ )
+ );
+ return $obj;
+ }
+
+}
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Title.php b/config/dspam/pear/Image/Graph/Title.php
new file mode 100644
index 00000000..2cffe5f3
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Title.php
@@ -0,0 +1,194 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - Main class for the graph creation.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Text
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * Include file Image/Graph/Layout.php
+ */
+require_once 'Image/Graph/Layout.php';
+
+/**
+ * Title
+ *
+ * @category Images
+ * @package Image_Graph
+ * @subpackage Text
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Title extends Image_Graph_Layout
+{
+
+ /**
+ * The text to print
+ * @var string
+ * @access private
+ */
+ var $_text;
+
+ /**
+ * The font to use
+ * @var Font
+ * @access private
+ */
+ var $_font;
+
+ /**
+ * The alignment of the title
+ * @var int
+ * @access private
+ */
+ var $_alignment = IMAGE_GRAPH_ALIGN_CENTER_X;
+
+ /**
+ * Create the title.
+ *
+ * Pass a Image_Graph_Font object - preferably by-ref (&amp;) as second
+ * parameter, the font size in pixels or an associated array with some or
+ * all of the followin keys:
+ *
+ * 'size' The size of the title
+ *
+ * 'angle' The angle at which to write the title (in degrees or 'vertical')
+ *
+ * 'color' The font-face color
+ *
+ * @param sting $text The text to represent the title
+ * @param mixed $fontOptions The font to use in the title
+ */
+ function Image_Graph_Title($text, $fontOptions = false)
+ {
+ parent::Image_Graph_Layout();
+ if (is_object($fontOptions)) {
+ $this->_font =& $fontOptions;
+ } else {
+ if (is_array($fontOptions)) {
+ $this->_fontOptions = $fontOptions;
+ } else {
+ $this->_fontOptions['size'] = $fontOptions;
+ }
+ }
+ $this->setText($text);
+ }
+
+ /**
+ * Set the text
+ *
+ * @param string $text The text to display
+ */
+ function setText($text)
+ {
+ $this->_text = $text;
+ }
+
+ /**
+ * Returns the calculated "auto" size
+ *
+ * @return int The calculated auto size
+ * @access private
+ */
+ function _getAutoSize()
+ {
+ if ($this->_defaultFontOptions !== false) {
+ $this->_canvas->setFont($this->_defaultFontOptions);
+ } else {
+ $this->_canvas->setFont($this->_getFont());
+ }
+
+ return $this->_canvas->textHeight($this->_text);
+ }
+
+ /**
+ * Set the alignment of the legend
+ *
+ * @param int $alignment The alignment
+ */
+ function setAlignment($alignment)
+ {
+ $this->_alignment = $alignment & 0x7;
+ }
+
+ /**
+ * Output the text
+ *
+ * @return bool Was the output 'good' (true) or 'bad' (false).
+ * @access private
+ */
+ function _done()
+ {
+ if ($this->_defaultFontOptions !== false) {
+ $this->_canvas->setFont($this->_defaultFontOptions);
+ } else {
+ $this->_canvas->setFont($this->_getFont());
+ }
+
+ if (is_a($this->_parent, 'Image_Graph_Plotarea')) {
+ $this->_setCoords(
+ $this->_parent->_left,
+ $this->_parent->_top,
+ $this->_parent->_right,
+ $this->_parent->_top + $this->_canvas->textHeight($this->_text)
+ );
+ } elseif (!is_a($this->_parent, 'Image_Graph_Layout')) {
+ $this->_setCoords(
+ $this->_parent->_fillLeft(),
+ $this->_parent->_fillTop(),
+ $this->_parent->_fillRight(),
+ $this->_parent->_fillTop() + $this->_canvas->textHeight($this->_text)
+ );
+ }
+
+ if (parent::_done() === false) {
+ return false;
+ }
+
+ if ($this->_alignment == IMAGE_GRAPH_ALIGN_CENTER_X) {
+ $x = ($this->_left + $this->_right) / 2;
+ } elseif ($this->_alignment == IMAGE_GRAPH_ALIGN_LEFT) {
+ $x = $this->_left;
+ } else {
+ $x = $this->_right;
+ }
+ $y = ($this->_top + $this->_bottom) / 2;
+
+ $this->write(
+ $x,
+ $y,
+ $this->_text,
+ $this->_alignment + IMAGE_GRAPH_ALIGN_CENTER_Y
+ );
+ return true;
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pear/Image/Graph/Tool.php b/config/dspam/pear/Image/Graph/Tool.php
new file mode 100644
index 00000000..cf245685
--- /dev/null
+++ b/config/dspam/pear/Image/Graph/Tool.php
@@ -0,0 +1,291 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Image_Graph - Main class for the graph creation.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version. This library is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details. You should have received a copy of
+ * the GNU Lesser General Public License along with this library; if not, write
+ * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * @category Images
+ * @package Image_Graph
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Image_Graph
+ */
+
+/**
+ * This class contains a set of tool-functions.
+ *
+ * These functions are all to be called statically
+ *
+ * @category Images
+ * @package Image_Graph
+ * @author Jesper Veggerby <pear.nosey@veggerby.dk>
+ * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Image_Graph
+ */
+class Image_Graph_Tool
+{
+
+ /**
+ * Return the average of 2 points
+ *
+ * @param double P1 1st point
+ * @param double P2 2nd point
+ * @return double The average of P1 and P2
+ * @static
+ */
+ function mid($p1, $p2)
+ {
+ return ($p1 + $p2) / 2;
+ }
+
+ /**
+ * Mirrors P1 in P2 by a amount of Factor
+ *
+ * @param double $p1 1st point, point to mirror
+ * @param double $o2 2nd point, mirror point
+ * @param double $factor Mirror factor, 0 returns $p2, 1 returns a pure
+ * mirror, ie $p1 on the exact other side of $p2
+ * @return double $p1 mirrored in $p2 by Factor
+ * @static
+ */
+ function mirror($p1, $p2, $factor = 1)
+ {
+ return $p2 + $factor * ($p2 - $p1);
+ }
+
+ /**
+ * Calculates a Bezier control point, this function must be called for BOTH
+ * X and Y coordinates (will it work for 3D coordinates!?)
+ *
+ * @param double $p1 1st point
+ * @param double $p2 Point to
+ * @param double $factor Mirror factor, 0 returns P2, 1 returns a pure
+ * mirror, i.e. P1 on the exact other side of P2
+ * @return double P1 mirrored in P2 by Factor
+ * @static
+ */
+ function controlPoint($p1, $p2, $factor, $smoothFactor = 0.75)
+ {
+ $sa = Image_Graph_Tool::mirror($p1, $p2, $smoothFactor);
+ $sb = Image_Graph_Tool::mid($p2, $sa);
+
+ $m = Image_Graph_Tool::mid($p2, $factor);
+
+ $pC = Image_Graph_Tool::mid($sb, $m);
+
+ return $pC;
+ }
+
+ /**
+ * Calculates a Bezier point, this function must be called for BOTH X and Y
+ * coordinates (will it work for 3D coordinates!?)
+ *
+ * @param double $t A position between $p2 and $p3, value between 0 and 1
+ * @param double $p1 Point to use for calculating control points
+ * @param double $p2 Point 1 to calculate bezier curve between
+ * @param double $p3 Point 2 to calculate bezier curve between
+ * @param double $p4 Point to use for calculating control points
+ * @return double The bezier value of the point t between $p2 and $p3 using
+ * $p1 and $p4 to calculate control points
+ * @static
+ */
+ function bezier($t, $p1, $p2, $p3, $p4)
+ {
+ // (1-t)^3*p1 + 3*(1-t)^2*t*p2 + 3*(1-t)*t^2*p3 + t^3*p4
+ return pow(1 - $t, 3) * $p1 +
+ 3 * pow(1 - $t, 2) * $t * $p2 +
+ 3 * (1 - $t) * pow($t, 2) * $p3 +
+ pow($t, 3) * $p4;
+ }
+
+ /**
+ * For a given point (x,y) return a point rotated by a given angle aroung the center (xy,yc)
+ *
+ * @param int $x x coordinate of the point to rotate
+ * @param int $y y coordinate of the point to rotate
+ * @param int $xc x coordinate of the center of the rotation
+ * @param int $yc y coordinate of the center of the rotation
+ * @param int $angle angle of the rotation
+ * @return array the coordinate of the new point
+ * @static
+ */
+ function rotate($x, $y, $xc, $yc, $angle)
+ {
+ $cos = cos(deg2rad($angle));
+ $sin = sin(deg2rad($angle));
+ $xr= $x - $xc;
+ $yr= $y - $yc;
+ $x1= $xc + $cos * $xr - $sin * $yr;
+ $y1= $yc + $sin * $xr + $cos * $yr;
+ return array((int) $x1,(int) $y1);
+ }
+
+ /**
+ * If a number is close 0 zero (i.e. 0 within $decimal decimals) it is rounded down to zero
+ *
+ * @param double $value The value to round
+ * @param int $decimal The number of decimals
+ * @return double The value or zero if "close enough" to zero
+ * @static
+ */
+ function close2zero($value, $decimal)
+ {
+ if (abs($value) < pow(10, -$decimal)) {
+ return 0;
+ }
+ else {
+ return $value;
+ }
+ }
+
+ /**
+ * Calculate the dimensions and center point (of gravity) for an arc
+ *
+ * @param int $v1 The angle at which the arc starts
+ * @param int $v2 The angle at which the arc ends
+ * @return array An array with the dimensions in a fraction of a circle width radius 1 'rx', 'ry' and the
+ * center point of gravity ('cx', 'cy')
+ * @static
+ */
+ function calculateArcDimensionAndCenter($v1, $v2)
+ {
+ // $v2 always larger than $v1
+ $r1x = Image_Graph_Tool::close2zero(cos(deg2rad($v1)), 3);
+ $r2x = Image_Graph_Tool::close2zero(cos(deg2rad($v2)), 3);
+
+ $r1y = Image_Graph_Tool::close2zero(sin(deg2rad($v1)), 3);
+ $r2y = Image_Graph_Tool::close2zero(sin(deg2rad($v2)), 3);
+
+ // $rx = how many percent of the x-diameter of the entire ellipse does the arc x-diameter occupy: 1 entire width, 0 no width
+ // $cx = at what percentage of the diameter does the center lie
+
+ // if the arc passes through 0/360 degrees the "highest" of r1x and r2x is replaced by 1!
+ if ((($v1 <= 0) && ($v2 >= 0)) || (($v1 <= 360) && ($v2 >= 360))) {
+ $r1x = min($r1x, $r2x);
+ $r2x = 1;
+ }
+
+ // if the arc passes through 180 degrees the "lowest" of r1x and r2x is replaced by -1!
+ if ((($v1 <= 180) && ($v2 >= 180)) || (($v1 <= 540) && ($v2 >= 540))) {
+ $r1x = max($r1x, $r2x);
+ $r2x = -1;
+ }
+
+ if ($r1x >= 0) { // start between [270; 360] or [0; 90]
+ if ($r2x >= 0) {
+ $rx = max($r1x, $r2x) / 2;
+ $cx = 0; // center lies 0 percent along this "vector"
+ }
+ else {
+ $rx = abs($r1x - $r2x) / 2;
+ $cx = abs($r2x / 2) / $rx;
+ }
+ }
+ else { // start between ]90; 270[
+ if ($r2x < 0) {
+ $rx = max(abs($r1x), abs($r2x)) / 2;
+ $cx = $rx;
+ }
+ else {
+ $rx = abs($r1x - $r2x) / 2;
+ $cx = abs($r1x / 2) / $rx;
+ }
+ }
+
+ // $ry = how many percent of the y-diameter of the entire ellipse does the arc y-diameter occupy: 1 entire, 0 none
+ // $cy = at what percentage of the y-diameter does the center lie
+
+ // if the arc passes through 90 degrees the "lowest" of r1x and r2x is replaced by -1!
+ if ((($v1 <= 90) && ($v2 >= 90)) || (($v1 <= 450) && ($v2 >= 450))) {
+ $r1y = min($r1y, $r2y);
+ $r2y = 1;
+ }
+
+ // if the arc passes through 270 degrees the "highest" of r1y and r2y is replaced by -1!
+ if ((($v1 <= 270) && ($v2 >= 270)) || (($v1 <= 630) && ($v2 >= 630))) {
+ $r1y = max($r1y, $r2y);
+ $r2y = -1;
+ }
+
+ if ($r1y >= 0) { // start between [0; 180]
+ if ($r2y >= 0) {
+ $ry = max($r1y, $r2y) / 2;
+ $cy = 0; // center lies 0 percent along this "vector"
+ }
+ else {
+ $ry = abs($r1y - $r2y) / 2;
+ $cy = abs($r2y / 2) / $ry;
+ }
+ }
+ else { // start between ]180; 360[
+ if ($r2y < 0) {
+ $ry = max(abs($r1y), abs($r2y)) / 2;
+ $cy = $ry;
+ }
+ else {
+ $ry = abs($r1y - $r2y) / 2;
+ $cy = abs($r1y / 2) / $ry;
+ }
+ }
+
+ return array(
+ 'rx' => $rx,
+ 'cx' => $cx,
+ 'ry' => $ry,
+ 'cy' => $cy
+ );
+ }
+
+ /**
+ * Calculate linear regression on a dataset
+ * @param array $data The data to calculate regression upon
+ * @return array The slope and intersection of the "best-fit" line
+ * @static
+ */
+ function calculateLinearRegression(&$data)
+ {
+ $sumX = 0;
+ $sumY = 0;
+ foreach ($data as $point) {
+ $sumX += $point['X'];
+ $sumY += $point['Y'];
+ }
+ $meanX = $sumX / count($data);
+ $meanY = $sumY / count($data);
+
+ $sumXX = 0;
+ $sumYY = 0;
+ $sumXY = 0;
+ foreach ($data as $point) {
+ $sumXX += ($point['X'] - $meanX) * ($point['X'] - $meanX);
+ $sumYY += ($point['Y'] - $meanY) * ($point['Y'] - $meanY);
+ $sumXY += ($point['X'] - $meanX) * ($point['Y'] - $meanY);
+ }
+
+ $result = array();
+ $result['slope'] = ($sumXY / $sumXX);
+ $result['intersection'] = $meanY - ($result['slope'] * $meanX);
+ return $result;
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pkg/000.mysql.sh b/config/dspam/pkg/000.mysql.sh
new file mode 100644
index 00000000..9c25c370
--- /dev/null
+++ b/config/dspam/pkg/000.mysql.sh
@@ -0,0 +1,68 @@
+#!/bin/sh
+# This file was automatically generated
+# by the pfSense service handler
+
+rc_start() {
+test_mysql_user=`cat /etc/passwd | grep mysql`
+test_mysql_group=`cat /etc/group | grep mysql`
+mysql_user="mysql"
+mysql_limits_args="-e -U ${mysql_user}"
+pidfile="/var/db/mysql/`/bin/hostname`.pid"
+command="/usr/local/bin/mysqld_safe"
+command_args="--user=${mysql_user} --datadir=/var/db/mysql --pid-file=${pidfile} --bind-address=127.0.0.1 --set-variable=max_connections=500"
+procname="/usr/local/libexec/mysqld"
+mysql_install_db="/usr/local/bin/mysql_install_db"
+mysql_install_db_args="--ldata=/var/db/mysql"
+
+/sbin/mount_fdescfs fdescfs /dev/fd
+
+if [ -z "${test_mysql_group}" ]; then
+ pw groupadd mysql -g 88
+fi
+
+if [ -z "${test_mysql_user}" ]; then
+ pw useradd mysql -u 88 -g 88 -d /nonexistent -s /sbin/nologin -c 'MySQL Daemon'
+fi
+
+if [ ! -d "/var/db/mysql" ]; then
+ mkdir /var/db/mysql && chown mysql:mysql /var/db/mysql
+fi
+
+if [ ! -d "/var/db/mysql/mysql/." ]; then
+ eval $mysql_install_db $mysql_install_db_args >/dev/null
+ [ $? -eq 0 ] && chown -R ${mysql_user}:${mysql_user} /var/db/mysql
+fi
+
+#if checkyesno mysql_limits; then
+# eval `/usr/bin/limits ${mysql_limits_args}` 2>/dev/null
+#else
+# return 0
+#fi
+
+${command} ${command_args} > /dev/null &
+}
+
+rc_stop() {
+/usr/bin/killall mysqld
+sleep 2
+}
+
+rc_restart() {
+ rc_stop
+ rc_start
+}
+
+case $1 in
+ start)
+ rc_start
+ ;;
+ stop)
+ rc_stop
+ ;;
+ restart)
+ rc_restart
+ ;;
+ *)
+ echo "Usage: $0 <start|stop|restart>"
+ ;;
+esac
diff --git a/config/dspam/pkg/010.clamav-clamd.sh b/config/dspam/pkg/010.clamav-clamd.sh
new file mode 100644
index 00000000..aeb23b04
--- /dev/null
+++ b/config/dspam/pkg/010.clamav-clamd.sh
@@ -0,0 +1,56 @@
+#!/bin/sh
+# This file was automatically generated
+# by the pfSense service handler
+
+rc_start() {
+test_clamav_group=`cat /etc/group | grep clam`
+test_clamav_user=`cat /etc/passwd | grep clam`
+
+if [ -z "${test_clamav_group}" ]; then
+ pw groupadd clamav -g 106
+fi
+
+if [ -z "${test_clamav_user}" ]; then
+ pw useradd clamav -u 106 -g 106 -d /nonexistent -s /sbin/nologin -c 'Clam Antivirus'
+fi
+
+if [ ! -d "/usr/local/share/clamav" ]; then
+ mkdir /usr/local/share/clamav && chown clamav:clamav /usr/local/share/clamav
+fi
+
+if [ ! -d "/var/log/clamav" ]; then
+ mkdir /var/log/clamav && chown clamav:clamav /var/log/clamav
+fi
+
+if [ ! -d "/var/run/clamav" ]; then
+ mkdir /var/run/clamav && chown clamav:clamav /var/run/clamav
+fi
+
+ /sbin/mount_fdescfs fdescfs /dev/fd
+ /usr/local/sbin/clamd
+}
+
+rc_stop() {
+ /usr/bin/killall clamd
+ sleep 2
+}
+
+rc_restart() {
+ rc_stop
+ rc_start
+}
+
+case $1 in
+ start)
+ rc_start
+ ;;
+ stop)
+ rc_stop
+ ;;
+ restart)
+ rc_restart
+ ;;
+ *)
+ echo "Usage: $0 <start|stop|restart>"
+ ;;
+esac
diff --git a/config/dspam/pkg/020.clamav-freshclam.sh b/config/dspam/pkg/020.clamav-freshclam.sh
new file mode 100644
index 00000000..4332d757
--- /dev/null
+++ b/config/dspam/pkg/020.clamav-freshclam.sh
@@ -0,0 +1,33 @@
+#!/bin/sh
+# This file was automatically generated
+# by the pfSense service handler
+
+rc_start() {
+ /sbin/mount_fdescfs fdescfs /dev/fd
+ /usr/local/bin/freshclam --daemon
+}
+
+rc_stop() {
+ /usr/bin/killall freshclam
+ sleep 2
+}
+
+rc_restart() {
+ rc_stop
+ rc_start
+}
+
+case $1 in
+ start)
+ rc_start
+ ;;
+ stop)
+ rc_stop
+ ;;
+ restart)
+ rc_restart
+ ;;
+ *)
+ echo "Usage: $0 <start|stop|restart>"
+ ;;
+esac
diff --git a/config/dspam/pkg/030.p3scan.sh b/config/dspam/pkg/030.p3scan.sh
new file mode 100644
index 00000000..ffd08abf
--- /dev/null
+++ b/config/dspam/pkg/030.p3scan.sh
@@ -0,0 +1,60 @@
+#!/bin/sh
+# This file was automatically generated
+# by the pfSense service handler
+
+rc_start() {
+test_p3scan_user=`cat /etc/passwd | grep p3scan`
+test_p3scan_group=`cat /etc/passwd | grep p3scan`
+
+if [ -z "${test_p3scan_group}" ]; then
+ pw groupadd p3scan -g 108
+fi
+
+if [ -z "${test_p3scan_user}" ]; then
+ pw useradd p3scan -u 108 -g p3scan -d /var/spool/p3scan -s /sbin/nologin -c 'P3Scan Daemon'
+fi
+
+if [ ! -d "/var/spool/p3scan" ]; then
+ mkdir /var/spool/p3scan && chown p3scan:p3scan /var/spool/p3scan
+fi
+
+if [ ! -d "/var/spool/p3scan/children" ]; then
+ mkdir /var/spool/p3scan/children && chown p3scan:p3scan /var/spool/p3scan/children
+fi
+
+if [ ! -d "/var/spool/p3scannotify" ]; then
+ mkdir /var/spool/p3scannotify && chown p3scan:p3scan /var/spool/p3scannotify
+fi
+
+if [ ! -d "/var/run/p3scan" ]; then
+ mkdir /var/run/p3scan && chown p3scan:p3scan /var/run/p3scan
+fi
+
+ /sbin/mount_fdescfs fdescfs /dev/fd
+ /usr/local/sbin/p3scan --configfile=/usr/local/etc/p3scan/p3scan.conf &
+}
+
+rc_stop() {
+ /usr/bin/killall p3scan
+ sleep 2
+}
+
+rc_restart() {
+ rc_stop
+ rc_start
+}
+
+case $1 in
+ start)
+ rc_start
+ ;;
+ stop)
+ rc_stop
+ ;;
+ restart)
+ rc_restart
+ ;;
+ *)
+ echo "Usage: $0 <start|stop|restart>"
+ ;;
+esac
diff --git a/config/dspam/pkg/clamd.conf b/config/dspam/pkg/clamd.conf
new file mode 100644
index 00000000..3ce0402f
--- /dev/null
+++ b/config/dspam/pkg/clamd.conf
@@ -0,0 +1,299 @@
+##
+## Example config file for the Clam AV daemon
+## Please read the clamd.conf(5) manual before editing this file.
+##
+
+
+# Comment or remove the line below.
+#Example
+
+# Uncomment this option to enable logging.
+# LogFile must be writable for the user running daemon.
+# A full path is required.
+# Default: disabled
+#LogFile /tmp/clamd.log
+LogFile /var/log/clamav/clamd.log
+
+# By default the log file is locked for writing - the lock protects against
+# running clamd multiple times (if want to run another clamd, please
+# copy the configuration file, change the LogFile variable, and run
+# the daemon with --config-file option).
+# This option disables log file locking.
+# Default: no
+#LogFileUnlock yes
+
+# Maximal size of the log file.
+# Value of 0 disables the limit.
+# You may use 'M' or 'm' for megabytes (1M = 1m = 1048576 bytes)
+# and 'K' or 'k' for kilobytes (1K = 1k = 1024 bytes). To specify the size
+# in bytes just don't use modifiers.
+# Default: 1M
+#LogFileMaxSize 2M
+
+# Log time with each message.
+# Default: no
+#LogTime yes
+
+# Also log clean files. Useful in debugging but drastically increases the
+# log size.
+# Default: no
+#LogClean yes
+
+# Use system logger (can work together with LogFile).
+# Default: no
+#LogSyslog yes
+LogSyslog yes
+
+# Specify the type of syslog messages - please refer to 'man syslog'
+# for facility names.
+# Default: LOG_LOCAL6
+#LogFacility LOG_MAIL
+
+# Enable verbose logging.
+# Default: no
+#LogVerbose yes
+
+# This option allows you to save a process identifier of the listening
+# daemon (main thread).
+# Default: disabled
+#PidFile /var/run/clamd.pid
+PidFile /var/run/clamav/clamd.pid
+
+# Optional path to the global temporary directory.
+# Default: system specific (usually /tmp or /var/tmp).
+#TemporaryDirectory /var/tmp
+
+# Path to the database directory.
+# Default: hardcoded (depends on installation options)
+#DatabaseDirectory /var/lib/clamav
+DatabaseDirectory /usr/local/share/clamav
+
+# The daemon works in a local OR a network mode. Due to security reasons we
+# recommend the local mode.
+
+# Path to a local socket file the daemon will listen on.
+# Default: disabled (must be specified by a user)
+#LocalSocket /tmp/clamd
+
+# Remove stale socket after unclean shutdown.
+# Default: no
+FixStaleSocket yes
+
+# TCP port address.
+# Default: no
+TCPSocket 3310
+
+# TCP address.
+# By default we bind to INADDR_ANY, probably not wise.
+# Enable the following to provide some degree of protectiyes
+# from the outside world.
+# Default: no
+TCPAddr 127.0.0.1
+
+# Maximum length the queue of pending connections may grow to.
+# Default: 15
+#MaxConnectionQueueLength 30
+
+# Clamd uses FTP-like protocol to receive data from remote clients.
+# If you are using clamav-milter to balance load between remote clamd daemons
+# on firewall servers you may need to tune the options below.
+
+# Close the connection when the data size limit is exceeded.
+# The value should match your MTA's limit for a maximal attachment size.
+# Default: 10M
+#StreamMaxLength 20M
+
+# Limit port range.
+# Default: 1024
+#StreamMinPort 30000
+# Default: 2048
+#StreamMaxPort 32000
+
+# Maximal number of threads running at the same time.
+# Default: 10
+#MaxThreads 20
+
+# Waiting for data from a client socket will timeout after this time (seconds).
+# Value of 0 disables the timeout.
+# Default: 120
+#ReadTimeout 300
+
+# Waiting for a new job will timeout after this time (seconds).
+# Default: 30
+#IdleTimeout 60
+
+# Maximal depth directories are scanned at.
+# Default: 15
+#MaxDirectoryRecursion 20
+
+# Follow directory symlinks.
+# Default: no
+#FollowDirectorySymlinks yes
+
+# Follow regular file symlinks.
+# Default: no
+#FollowFileSymlinks yes
+
+# Perform internal sanity check (database integrity and freshness).
+# Default: 1800 (30 min)
+#SelfCheck 600
+
+# Execute a command when virus is found. In the command string %v will
+# be replaced by a virus name.
+# Default: no
+#VirusEvent /usr/local/bin/send_sms 123456789 "VIRUS ALERT: %v"
+
+# Run as a selected user (clamd must be started by root).
+# Default: don't drop privileges
+User clamav
+
+# Initialize supplementary group access (clamd must be started by root).
+# Default: no
+AllowSupplementaryGroups yes
+
+# Stop daemon when libclamav reports out of memory condition.
+#ExitOnOOM yes
+
+# Don't fork into background.
+# Default: no
+#Foreground yes
+
+# Enable debug messages in libclamav.
+# Default: no
+#Debug yes
+
+# Do not remove temporary files (for debug purposes).
+# Default: no
+#LeaveTemporaryFiles yes
+
+##
+## Executable files
+##
+
+# PE stands for Portable Executable - it's an executable file format used
+# in all 32-bit versions of Windows operating systems. This option allows
+# ClamAV to perform a deeper analysis of executable files and it's also
+# required for decompression of popular executable packers such as UPX, FSG,
+# and Petite.
+# Default: yes
+#ScanPE yes
+
+# With this option clamav will try to detect broken executables and mark
+# them as Broken.Executable
+# Default: no
+#DetectBrokenExecutables yes
+
+
+##
+## Documents
+##
+
+# This option enables scanning of Microsoft Office document macros.
+# Default: yes
+#ScanOLE2 yes
+
+##
+## Mail files
+##
+
+# Enable internal e-mail scanner.
+# Default: yes
+#ScanMail yes
+
+# If an email contains URLs ClamAV can download and scan them.
+# WARNING: This option may open your system to a DoS attack.
+# Never use it on loaded servers.
+# Default: no
+#MailFollowURLs no
+
+
+##
+## HTML
+##
+
+# Perform HTML normalisation and decryption of MS Script Encoder code.
+# Default: yes
+#ScanHTML yes
+
+
+##
+## Archives
+##
+
+# ClamAV can scan within archives and compressed files.
+# Default: yes
+#ScanArchive yes
+
+# The options below protect your system against Denial of Service attacks
+# using archive bombs.
+
+# Files in archives larger than this limit won't be scanned.
+# Value of 0 disables the limit.
+# Default: 10M
+#ArchiveMaxFileSize 15M
+
+# Nested archives are scanned recursively, e.g. if a Zip archive contains a RAR
+# file, all files within it will also be scanned. This options specifies how
+# deep the process should be continued.
+# Value of 0 disables the limit.
+# Default: 8
+#ArchiveMaxRecursion 10
+
+# Number of files to be scanned within an archive.
+# Value of 0 disables the limit.
+# Default: 1000
+#ArchiveMaxFiles 1500
+
+# If a file in an archive is compressed more than ArchiveMaxCompressionRatio
+# times it will be marked as a virus (Oversized.ArchiveType, e.g. Oversized.Zip)
+# Value of 0 disables the limit.
+# Default: 250
+#ArchiveMaxCompressionRatio 300
+
+# Use slower but memory efficient decompression algorithm.
+# only affects the bzip2 decompressor.
+# Default: no
+#ArchiveLimitMemoryUsage yes
+
+# Mark encrypted archives as viruses (Encrypted.Zip, Encrypted.RAR).
+# Default: no
+#ArchiveBlockEncrypted no
+
+# Mark archives as viruses (e.g. RAR.ExceededFileSize, Zip.ExceededFilesLimit)
+# if ArchiveMaxFiles, ArchiveMaxFileSize, or ArchiveMaxRecursion limit is
+# reached.
+# Default: no
+#ArchiveBlockMax no
+
+
+##
+## Clamuko settings
+## WARNING: This is experimental software. It is very likely it will hang
+## up your system!!!
+##
+
+# Enable Clamuko. Dazuko (/dev/dazuko) must be configured and running.
+# Default: no
+#ClamukoScanOnAccess yes
+
+# Set access mask for Clamuko.
+# Default: no
+#ClamukoScanOnOpen yes
+#ClamukoScanOnClose yes
+#ClamukoScanOnExec yes
+
+# Set the include paths (all files in them will be scanned). You can have
+# multiple ClamukoIncludePath directives but each directory must be added
+# in a seperate line.
+# Default: disabled
+#ClamukoIncludePath /home
+#ClamukoIncludePath /students
+
+# Set the exclude paths. All subdirectories are also excluded.
+# Default: disabled
+#ClamukoExcludePath /home/bofh
+
+# Don't scan files larger than ClamukoMaxFileSize
+# Value of 0 disables the limit.
+# Default: 5M
+#ClamukoMaxFileSize 10M
diff --git a/config/dspam/pkg/default.prefs.sample b/config/dspam/pkg/default.prefs.sample
new file mode 100644
index 00000000..d9be27ed
--- /dev/null
+++ b/config/dspam/pkg/default.prefs.sample
@@ -0,0 +1,43 @@
+# $Id$
+# default.prefs v3.2
+# Default preferences for DSPAM
+
+# This file serves two purposes. First, it sets the default preferences each
+# user will see when using the preferences section of the DSPAM Control
+# Center. Second, it may be symbolically linked (or copied) into DSPAM_HOME to
+# set the system-wide default preferences, overriding any commandline or
+# dspam.conf parameters. If symlinked, an administrator can edit these options
+# in the DSPAM Administrative Suite.
+
+# Training Mode: TEFT, TOE, TUM, NOTRAIN
+trainingMode=TEFT
+
+# Spam Action: quarantine, tag
+spamAction=quarantine
+
+# Spam Subject: the text to be prepended onto the subject line of tagged spams
+spamSubject=[SPAM]
+
+# Bayesian Noise Reduction: on/off
+enableBNR=on
+
+# Automatic Whitelisting: on/off
+enableWhitelist=on
+
+# Statistical Sedation: 0-10
+statisticalSedation=5
+
+# Signature Location: message, headers, attachment
+signatureLocation=message
+
+# Whitelist Threshold: the minimum number of innocent hits from a recipient to
+# be automatically whitelisted. Do not set this value too low!
+whitelistThreshold=10
+
+# showFactors: when set to on, the determining factors for each message will
+# be added to a X-DSPAM-Factors message header.
+showFactors=off
+
+# optIn/optOut: Depending on the opt mode set, you can also use one of these.
+#optIn=on
+#optOut=off
diff --git a/config/dspam/pkg/dspam-config.inc b/config/dspam/pkg/dspam-config.inc
new file mode 100644
index 00000000..211bee51
--- /dev/null
+++ b/config/dspam/pkg/dspam-config.inc
@@ -0,0 +1,42 @@
+<?php
+/* $Id$ */
+/* Copyright (C) 2006 Daniel S. Haischt */
+
+$CONFIG = array('DSPAM_HOME' => '/var/db/dspam',
+ 'DSPAM_BIN' => '/usr/local/bin',
+ 'DSPAM' => '/usr/local/bin/dspam',
+ 'DSPAM_STATS' => '/usr/local/bin/dspam_stats',
+ 'DSPAM_WWW' => '/usr/local/pkg',
+ 'DSPAM_ARGS' => '--deliver=innocent --class=innocent ' .
+ '--source=error --user %CURRENT_USER% -d %u',
+ 'DSPAM_ADMIN_GROUP' => 'dspam_admins',
+ 'ALL_PROCS' => 'ps auxw',
+ 'MAIL_QUEUE' => 'mailq | grep \'^[0-9,A-F]\' | wc -l',
+ 'HISTORY_SIZE' => 799,
+ 'HISTORY_PER_PAGE' => 100,
+ 'QUARANTINE_PER_PAGE' => 100,
+ 'HISTORY_DUPLICATES' => 'yes',
+ 'MAX_COL_LEN' => 26,
+ 'QNAV_BUTTONS' => 20,
+ 'HNAV_BUTTONS' => 22,
+ 'SORT_DEFAULT' => 'Rating',
+ '3D_GRAPHS' => 1,
+ 'USE_MAILPARSE' => 1,
+ 'OPTMODE' => 'NONE',
+ 'LOCAL_DOMAIN' => 'localhost',
+ 'AUTODETECT' => 1,
+ 'OPENSOURCE' => 0,
+ /* Is there a website which provides dedicated infos? */
+ 'PACKAGE_WEBSITE' => 'http://www.pfsense.com/',
+ /* Is there a forum which provides dedicated infos? */
+ 'PACKAGE_FORUM' => 'http://www.pfsense.com/',
+ /*
+ * Is there a issue tracker which allows to fill a
+ * support request or a bug report?
+ */
+ 'PACKAGE_TRACKER' => 'http://www.pfsense.com/',
+ /* 'DATE_FORMAT' => '%d.%m.%Y %H:%M' */
+ 'DATE_FORMAT' => '%b %d %H:%M'
+ );
+
+?>
diff --git a/config/dspam/pkg/dspam-guifunc.inc b/config/dspam/pkg/dspam-guifunc.inc
new file mode 100644
index 00000000..121bc8b5
--- /dev/null
+++ b/config/dspam/pkg/dspam-guifunc.inc
@@ -0,0 +1,2606 @@
+<?php
+/* $Id$ */
+/* Copyright (C) 2006 Daniel S. Haischt */
+require_once("functions.inc");
+require_once("dspam.inc");
+
+/* ========================================================================== */
+/* = A D M I N S T A T U S F U N C T I O N S = */
+/* ========================================================================== */
+
+function DisplayAdminPreferences(&$statusmsg) {
+ return DisplayPreferences("admin", $statusmsg);
+}
+
+function DisplayUserStatistics() {
+ global $CONFIG, $DATA;
+ $b = "rowEven";
+
+ $sl_total = 0;
+ $il_total = 0;
+ $sm_total = 0;
+ $fp_total = 0;
+ $sc_total = 0;
+ $ic_total = 0;
+ $mailbox_total = 0;
+
+ $pd = popen("{$CONFIG['DSPAM_STATS']} 2>&1", "r");
+
+ while (!feof($pd)) {
+ $line = chop( fgets($pd, 4096) );
+
+ if ($b == "qrowEven") {
+ $b = "qrowOdd";
+ } else {
+ $b = "qrowEven";
+ }
+
+ $line = preg_replace('/:/', ' ', $line);
+
+ list($username, , $sl, , $il, , $fp, , $sm, , $sc, , $ic)
+ = (preg_split('/\s+/', $line));
+ if ($username == "" && $sl == "") {
+ /* we do not want to display data that
+ * does not bleong to any user
+ */
+ continue;
+ } else if ($sl == "") {
+ $line = fgets($pd, 4096);
+ $line = preg_replace('/:/', ' ', $line);
+ list(, , $sl, , $il, , $fp, , $sm, , $sc, , $ic)
+ = (preg_split('/\s+/', $line));
+ }
+
+ $PREFS =& GetPrefs($username, GetPath($username).".prefs");
+ if ($PREFS['enableBNR'] == "on") { $PREFS['enableBNR'] = "OFF"; }
+ if ($PREFS['enableWhitelist'] == "on") { $PREFS['enableWhitelist'] = "OFF"; }
+ $PREFS['spamAction'] = ucfirst($PREFS['spamAction']);
+ $PREFS['enableBNR'] = strtoupper($PREFS['enableBNR']);
+ $PREFS['enableWhitelist'] = strtoupper($PREFS['enableWhitelist']);
+
+ $mailbox = GetPath($username).".mbox";
+ if ( file_exists($mailbox) ) {
+ $mailbox_size = filesize($mailbox);
+ $mailbox_display = sprintf("%2.1f KB", ($mailbox_size / 1024));
+ $mailbox_total += $mailbox_size;
+ }
+ else {
+ $mailbox_display = "--";
+ }
+
+ $sl_total += $sl;
+ $il_total += $il;
+ $sm_total += $sm;
+ $fp_total += $fp;
+ $sc_total += $sc;
+ $ic_total += $ic;
+
+ $DATA['TABLE'] .= "<tr><td class=\"{$b}\"><a href=\"{$CONFIG['DSPAM_CGI']}?user={$username}\">{$username}</A></td>" .
+ " <td class=\"{$b} rowDivider\" align=\"right\" nowrap=\"nowrap\">{$mailbox_display}</td>" .
+ " <td class=\"{$b} rowDivider\">{$sl}</td>" .
+ " <td class=\"{$b}\">{$il}</td>" .
+ " <td class=\"{$b}\">{$fp}</td>" .
+ " <td class=\"{$b}\">{$sm}</td>" .
+ " <td class=\"{$b}\">{$sc}</td>" .
+ " <td class=\"{$b}\">{$ic}</td>" .
+ " <td class=\"{$b} rowDivider\">{$PREFS['trainingMode']}</td>" .
+ " <td class=\"{$b}\">{$PREFS['spamAction']}</td>" .
+ " <td class=\"{$b}\">{$PREFS['enableBNR']}</td>" .
+ " <td class=\"{$b}\">{$PREFS['enableWhitelist']}</td>" .
+ " <td class=\"{$b}\">{$PREFS['statisticalSedation']}</td>" .
+ " <td class=\"{$b}\">{$PREFS['signatureLocation']}</td>" .
+ "</tr>\n";
+ }
+ pclose($pd);
+
+ $mailbox_total_display = sprintf("%2.1f KB", ($mailbox_total / 1024));
+
+ $b = "listhdrr";
+ $DATA['TABLE'] .= "<tr><td class=\"{$b}\">Total</td>".
+ " <td class=\"{$b} rowDivider\" align=\"right\" nowrap=\"nowrap\">{$mailbox_total_display}</td>".
+ " <td class=\"{$b} rowDivider\">{$sl_total}</td>".
+ " <td class=\"{$b}\">{$il_total}</td>".
+ " <td class=\"{$b}\">{$sm_total}</td>".
+ " <td class=\"{$b}\">{$fp_total}</td>".
+ " <td class=\"{$b}\">{$sc_total}</td>".
+ " <td class=\"{$b}\">{$ic_total}</td>".
+ " <td class=\"{$b} rowDivider\">&nbsp;</td>".
+ " <td class=\"{$b}\">&nbsp;</td>".
+ " <td class=\"{$b}\">&nbsp;</td>".
+ " <td class=\"{$b}\">&nbsp;</td>".
+ " <td class=\"{$b}\">&nbsp;</td>".
+ " <td class=\"{$b}\">&nbsp;</td>".
+ "</tr>\n";
+}
+
+function &DisplayStatus() {
+ global $CONFIG, $DATA;
+
+ $LOG = "{$CONFIG['DSPAM_HOME']}/system.log";
+ $spam_daily = array();
+ $nonspam_daily = array();
+ $period_daily = array();
+ $fp_daily = array();
+ $sm_daily = array();
+ $inoc_daily = array();
+ $whitelist_daily = array();
+ $spam_weekly = array();
+ $nonspam_weekly = array();
+ $period_weekly = array();
+ $fp_weekly = array();
+ $sm_weekly = array();
+ $inoc_weekly = array();
+ $$whitelist_weekly = array();
+ $msgpersecond = array();
+ $classes = array();
+
+ list (, $min, $hour, $mday, $mon, $year, , ,) = (localtime(time()));
+ $hmstart = time() - 60;
+ $daystart = mktime(0, 0, 0, $mon, $mday, $year);
+ $periodstart = $daystart - (3600*24*24); /* 2 Weeks ago */
+ $dailystart = time() - (3600*23);
+ $c_weekly = 0; /* Cursor to most recent time slot */
+ $c_daily = 0;
+
+ if (! file_exists($LOG)) {
+ return $input_errors[] = "No historical data is available (log file »{$LOG}« does not exist).";
+ }
+
+ /* Initialize each individual time period */
+
+ for ($i = 0; $i <= 23; $i++) {
+ $h = To12Hour($hour - (23-$i));
+ $period_daily[$i] = $h;
+ $spam_daily[$i] = 0;
+ $nonspam_daily[$i] = 0;
+ $sm_daily[$i] = 0;
+ $fp_daily[$i] = 0;
+ $inoc_daily[$i] = 0;
+ }
+
+ for ($i = 0; $i <= 23; $i++) {
+ $d = $daystart - (3600 * 24 * (24 - $i));
+ list (, , , $lday, $lmon, $lyear, , ,) = (localtime($d));
+ $lmon++;
+ $lyear += 1900;
+ $period_weekly[$i] = "{$lmon}/{$lday}/{$lyear}";
+ $spam_weekly[$i] = 0;
+ $nonspam_weekly[$i] = 0;
+ $sm_weekly[$i] = 0;
+ $fp_weekly[$i] = 0;
+ $inoc_weekly[$i] = 0;
+ }
+
+ if($fd = @fopen("{$LOG}", "r")) {
+ while (!feof($fd)) {
+ $line = fgets($fd, 4096);
+ list ($t_log, $c_log, , $signature, , $e_log) = preg_split('/\t/', $line);
+ if ($t_log > time()) { continue; }
+
+ $last_message = $t_log;
+
+ /* Only Parse Log Data in our Time Period */
+ if ($t_log >= $periodstart) {
+ list (, $tmin, $thour, $tday, $tmon, $tyear) = (localtime($t_log));
+ $tmon++;
+ $tyear += 1900;
+
+ /* Weekly Graph */
+ $c_weekly = 0;
+ while($period_weekly[$c_weekly] <> "{$tmon}/{$tday}/{$tyear}" && $c_weekly < 24) {
+ $c_weekly++;
+ }
+
+ if ($c_log == "E") {
+ if ($classes[$signature] == "S") {
+ $spam_weekly[$c_weekly]--;
+ if ($spam_weekly[$c_weekly] < 0) { $spam_weekly[$c_weekly] = 0; }
+ } else if ($classes[$signature] == "I") {
+ $nonspam_weekly[$c_weekly]--;
+ if ($nonspam_weekly[$c_weekly] < 0) { $nonspam_weekly[$c_weekly] = 0; }
+ } else if ($classes[$signature] == "W") {
+ $whitelist_weekly[$c_weekly]--;
+ if ($whitelist_weekly[$c_weekly] < 0) { $whitelist_weekly[$c_weekly] = 0; }
+ } else if ($classes[$signature] == "F") {
+ $spam_weekly[$c_weekly]++; $fp_weekly[$c_weekly]--;
+ if ($fp_weekly[$c_weekly] < 0) { $fp_weekly[$c_weekly] = 0; }
+ } else if ($classes[$signature] == "M") {
+ $sm_weekly[$c_weekly]--; $nonspam_weekly[$c_weekly]++;
+ if ($sm_weekly[$c_weekly] < 0) { $sm_weekly[$c_weekly] = 0; }
+ } else if ($classes[$signature] == "N") {
+ $inoc_weekly[$c_weekly]--;
+ if ($inoc_weekly[$c_weekly] < 0) { $inoc_weekly[$c_weekly] = 0; }
+ }
+ } else {
+ $classes[$signature] = $c_log;
+ }
+
+ if ($c_log == "S") { $spam_weekly[$c_weekly]++; }
+ if ($c_log == "I") { $nonspam_weekly[$c_weekly]++; }
+ if ($c_log == "W") { $whitelist_weekly[$c_weekly]++; }
+ if ($c_log == "F")
+ { $spam_weekly[$c_weekly]--; $fp_weekly[$c_weekly]++;
+ if ($spam_weekly[$c_weekly] < 0) { $spam_weekly[$c_weekly] = 0; }
+ }
+ if ($c_log == "M")
+ { $sm_weekly[$c_weekly]++; $nonspam_weekly[$c_weekly]--;
+ if ($nonspam_weekly[$c_weekly] < 0) { $nonspam_weekly[$c_weekly] = 0; }
+ }
+ if ($c_log == "N") { $inoc_weekly[$c_weekly]++; }
+
+
+ /* Daily Graph */
+ if ($t_log >= $dailystart) {
+ while($period_daily[$c_daily] <> To12Hour($thour) && $c_daily < 24) {
+ $c_daily++;
+ }
+
+ if ($c_log == "E") {
+ if ($classes[$signature] == "S") {
+ $spam_daily[$c_daily]--;
+ if ($spam_daily[$c_daily] < 0) { $spam_daily[$c_daily] = 0; }
+ } else if ($classes[$signature] == "I") {
+ $nonspam_daily[$c_daily]--;
+ if ($nonspam_daily[$c_daily] < 0) { $nonspam_daily[$c_daily] = 0; }
+ } else if ($classes[$signature] == "W") {
+ $whitelist_daily[$c_daily]--;
+ if ($whitelist_daily[$c_daily] < 0) { $whitelist_daily[$c_daily] = 0; }
+ } else if ($classes[$signature] == "F") {
+ $spam_daily[$c_daily]++; $fp_daily[$c_daily]--;
+ if ($fp_daily[$c_daily] < 0) { $fp_daily[$c_daily] = 0; }
+ } else if ($classes[$signature] == "M") {
+ $sm_daily[$c_daily]--; $nonspam_daily[$c_daily]++;
+ if ($sm_daily[$c_daily] < 0) { $sm_daily[$c_daily] = 0; }
+ } else if ($classes[$signature] == "N") {
+ $inoc_daily[$c_daily]--;
+ if ($inoc_daily[$c_daily] < 0) { $inoc_daily[$c_daily] = 0; }
+ }
+ }
+
+ if ($c_log == "S") { $spam_daily[$c_daily]++; }
+ if ($c_log == "I") { $nonspam_daily[$c_daily]++; }
+ if ($c_log == "W") { $whitelist_daily[$c_daily]++; }
+ if ($c_log == "F")
+ { $spam_daily[$c_daily]--; $fp_daily[$c_daily]++;
+ if ($spam_daily[$c_daily] < 0) { $spam_daily[$c_daily] = 0; }
+ }
+ if ($c_log == "M")
+ { $sm_daily[$c_daily]++; $nonspam_daily[$c_daily]--;
+ if ($nonspam_daily[$c_daily] < 0) { $nonspam_daily[$c_daily] = 0; }
+ }
+ if ($c_log == "N") { $inoc_daily[$c_daily]++; }
+ }
+
+ /* Last Half-Minute */
+ if ($t_log >= $hmstart) {
+ $msgpersecond[$t_log]++;
+ $DATA['AVG_PROCESSING_TIME'] += $e_log;
+ $keycount_exectime++;
+ }
+ }
+ } // end while
+
+ fclose($fd);
+ } else {
+ return $input_errors[] = "Unable to open logfile: {$LOG}.";
+ } // end if
+
+ /* Calculate Avg. Messages Per Second */
+ foreach(array_values($msgpersecond) as $el) {
+ $DATA['AVG_MSG_PER_SECOND'] += $el;
+ }
+ $DATA['AVG_MSG_PER_SECOND'] /= 60;
+ $DATA['AVG_MSG_PER_SECOND'] = sprintf("%2.2f", $DATA['AVG_MSG_PER_SECOND']);
+
+ /* Calculate Avg. Processing Time */
+ if ($keycount_exectime == 0) {
+ $DATA['AVG_PROCESSING_TIME'] = 0;
+ } else {
+ $DATA['AVG_PROCESSING_TIME'] /= $keycount_exectime;
+ }
+ $DATA['AVG_PROCESSING_TIME'] = sprintf("%01.6f", $DATA['AVG_PROCESSING_TIME']);
+
+ /* Calculate Number of processes, Uptime and Mail Queue length */
+ $pd = popen("{$CONFIG['ALL_PROCS']} | grep dspam | grep -v grep | grep -v cgi | grep -v sock | wc -l", "r");
+ $DATA['DSPAM_PROCESSES'] = fgets($pd, 4096);
+ pclose($pd);
+
+ $pd = popen("uptime", "r");
+ $DATA['UPTIME'] = fgets($pd, 4096);
+ pclose($pd);
+
+ $pd = popen("{$CONFIG['MAIL_QUEUE']}", "r");
+ $DATA['MAIL_QUEUE'] = fgets($pd, 4096);
+ pclose($pd);
+
+ /* Calculate Graphs */
+ $DATA['SPAM_TODAY'] = $spam_weekly[24];
+ $DATA['NONSPAM_TODAY'] = $nonspam_weekly[24];
+ $DATA['SM_TODAY'] = $sm_weekly[24];
+ $DATA['FP_TODAY'] = $fp_weekly[24];
+ $DATA['INOC_TODAY'] = $inoc_weekly[24];
+ $DATA['TOTAL_TODAY'] = $DATA['SPAM_TODAY'] + $DATA['NONSPAM_TODAY'] + $DATA['SM_TODAY']
+ + $DATA['FP_TODAY'] + $DATA['INOC_TODAY'];
+
+ $DATA['SPAM_THIS_HOUR'] = $spam_daily[23];
+ $DATA['NONSPAM_THIS_HOUR'] = $nonspam_daily[23];
+ $DATA['SM_THIS_HOUR'] = $sm_daily[23];
+ $DATA['FP_THIS_HOUR'] = $fp_daily[23];
+ $DATA['INOC_THIS_HOUR'] = $inoc_daily[23];
+ $DATA['TOTAL_THIS_HOUR'] = $DATA['SPAM_THIS_HOUR'] +
+ + $DATA['NONSPAM_THIS_HOUR']
+ + $DATA['SM_THIS_HOUR']
+ + $DATA['FP_THIS_HOUR']
+ + $DATA['INOC_THIS_HOUR'];
+
+ if (is_array($spam_daily) &&
+ is_array($nonspam_daily) &&
+ is_array($sm_daily) &&
+ is_array($fp_daily) &&
+ is_array($inoc_daily) &&
+ is_array($whitelist_daily) &&
+ is_array($period_daily)) {
+ $DATA['DATA_DAILY'] = join(",", $spam_daily)
+ . "_"
+ . join(",", $nonspam_daily)
+ . "_"
+ . join(",", $sm_daily)
+ . "_"
+ . join(",", $fp_daily)
+ . "_"
+ . join(",", $inoc_daily)
+ . "_"
+ . join(",", $whitelist_daily)
+ . "_"
+ . join(",", $period_daily);
+
+ foreach($spam_daily as $el){ $DATA['TS_DAILY'] += $el; };
+ foreach($nonspam_daily as $el){ $DATA['TI_DAILY'] += $el; }
+ foreach($sm_daily as $el){ $DATA['SM_DAILY'] += $el; }
+ foreach($fp_daily as $el){ $DATA['FP_DAILY'] += $el; }
+ foreach($inoc_daily as $el){ $DATA['INOC_DAILY'] += $el; }
+ foreach($whitelist_daily as $el){ $DATA['TI_DAILY'] += $el; }
+ }
+
+ if (is_array($spam_weekly) &&
+ is_array($nonspam_weekly) &&
+ is_array($sm_weekly) &&
+ is_array($fp_weekly) &&
+ is_array($inoc_weekly) &&
+ is_array($whitelist_weekly) &&
+ is_array($period_weekly)) {
+ $DATA['DATA_WEEKLY'] = join(",", $spam_weekly)
+ . "_"
+ . join(",", $nonspam_weekly)
+ . "_"
+ . join(",", $sm_weekly)
+ . "_"
+ . join(",", $fp_weekly)
+ . "_"
+ . join(",", $inoc_weekly)
+ . "_"
+ . join(",", $whitelist_weekly)
+ . "_"
+ . join(",", $period_weekly);
+
+ foreach($spam_weekly as $el){ $DATA['TS_WEEKLY'] += $el; }
+ foreach($nonspam_weekly as $el){ $DATA['TI_WEEKLY'] += $el; }
+ foreach($sm_weekly as $el){ $DATA['SM_WEEKLY'] += $el; }
+ foreach($fp_weekly as $el){ $DATA['FP_WEEKLY'] += $el; }
+ foreach($inoc_weekly as $el){ $DATA['INOC_WEEKLY'] += $el; }
+ foreach($whitelist_weekly as $el){ $DATA['TI_WEEKLY'] += $el; }
+ }
+}
+
+function &DisplayInfos() {
+ global $CONFIG, $DATA, $g;
+ $validity = "valide";
+
+ $pd = @popen("{$CONFIG['DSPAM']} --version", "r");
+ fgets($pd, 4096); // ignore 1st line
+ $DATA['DSPAM_VERSION'] = fgets($pd, 4096);
+ fgets($pd, 4096); // ignore next line
+ $DATA['DSPAM_COPYRIGHT'] = fgets($pd, 4096);
+ $DATA['DSPAM_WEBSITE'] = fgets($pd, 4096);
+ fgets($pd, 4096); // ignore next line
+ $DATA['DSPAM_COPYRIGHT_TEXT'] = fgets($pd, 4096);
+ $DATA['DSPAM_COPYRIGHT_TEXT'] .= " " . fgets($pd, 4096);
+ fgets($pd, 4096); // ignore next line
+ $DATA['DSPAM_CONFIGURE_ARGS'] = str_replace("Configuration parameters: ", "", fgets($pd, 4096));
+
+ pclose($pd);
+
+ if (file_exists("{$g['conf_path']}/nione.lic") &&
+ file_exists("{$g['conf_path']}/nione.lic.sha1")) {
+ if ($fd = @fopen("{$g['conf_path']}/nione.lic", "r")) {
+ $owneru = str_replace("Licensed User: ", "", fgets($fd, 4096));
+ if ($owneru == "") { $validity = "invalide (owner data not found)"; }
+ $ownerc = str_replace("Company: ", "", fgets($fd, 4096));
+ if ($ownerc == "") { $validity = "invalide (company not found)"; }
+ $lkey = str_replace("License Key: ", "", fgets($fd, 4096));
+ if ($lkey == "") { $validity = "invalide (license key not found)"; }
+ $pdate = strtotime( str_replace("Purchase Date: ", "", fgets($fd, 4096)) );
+ if ($pdate == "") { $validity = "invalide (purchase date not found)"; }
+
+ fclose($fd);
+ } else {
+ $validity = "invalide (license files not found)";
+ }
+
+ if(! extension_loaded( 'bcompiler' )) {
+ if(@dl( 'bcompiler.so' )) {
+ require_once ("knione");
+ $gen_lkey = getNIONEKey(trim($owneru), trim($ownerc));
+ if (trim($lkey) <> $gen_lkey) { $validity = "invalide (wrong license key)"; }
+
+ $cdate = mktime(0, 0, 0, date("m"),
+ date("d"),
+ date("Y"));
+
+ $edate = mktime(0, 0, 0, date("m", $pdate),
+ date("d", $pdate),
+ date("Y", $pdate)+1);
+
+ if ($edate < $cdate ||
+ $pdate > $cdate) {
+ $validity = "invalide (license expired)";
+ }
+
+ if ($fd = @fopen("{$g['conf_path']}/nione.lic.sha1", "r")) {
+ $chksum = str_replace("SHA1 (nione.lic) = ", "", fgets($fd, 4096));
+ $chksum_new = sha1_file("{$g['conf_path']}/nione.lic");
+
+ if (trim($chksum) !== trim($chksum_new)) {
+ $validity = "invalide (wrong license file checksum)";
+ }
+
+ fclose($fd);
+ } else {
+ $validity = "invalide (license files not found)";
+ }
+ } else {
+ $validity = "invalide (extension missing, which is necessary to validate license data.)";
+ }
+ }
+ } else {
+ $validity = "invalide (license files not found)";
+ }
+
+ $DATA['OWNER'] = $owneru;
+ $DATA['COMPANY'] = $ownerc;
+ $DATA['LICENSE_KEY'] = $lkey;
+ $DATA['LICENSE_VALIDITY'] = $validity;
+ $DATA['PURCHASE_DATE'] = date("F j, Y", $pdate);
+ $DATA['EXPIRY_DATE'] = date("F j, Y", $edate);
+}
+
+/* ========================================================================== */
+/* = H I S T O R Y F U N C T I O N S = */
+/* ========================================================================== */
+
+function &DisplayFragment($sigID = "",
+ $from = "",
+ $subject = "",
+ $info = "",
+ $time = "") {
+ global $DATA, $USER;
+
+ $sigID = preg_replace('/\/', '///', $sigID);
+
+ $DATA['FROM'] = $from;
+ $DATA['SUBJECT'] = $subject;
+ $DATA['INFO'] = $info;
+ $DATA['TIME'] = $time;
+
+ if($fd = @fopen("{$USER}.frag/{$sigID}.frag", "r")) {
+ while (!feof($fd)) {
+ /* sanitize HTML markup */
+ $line = preg_replace("/</e", "'&lt;'", fgets($fd, 4096));
+ $line = preg_replace("/>/e", "'&gt;'", $line);
+ $DATA['MESSAGE'] .= $line;
+ }
+ fclose($fd);
+ } else {
+ return $input_errors[] = "Unable to open file {$USER}.frag/{$sigID}.frag.";
+ }
+}
+
+function &DisplayHistory($command = "",
+ $sigID= "",
+ $retrainChecked = array(),
+ $username = "",
+ $retrainParam = "",
+ $currentPage = 1,
+ $hPerPage = 0) {
+ global $CONFIG, $USER, $CURRENT_USER, $DATA;
+
+ $buffer = array();
+ $history = array();
+ $rec = array();
+ $rowclass = "rowEven";
+
+ if ($command == "retrainChecked" && count ($retrainChecked) > 0) {
+ foreach($retrainChecked as $el) {
+ list ($retrain, $signature) = split(":", $el);
+ if ($retrain == "innocent") {
+ ProcessFalsePositive(quotemeta($signature));
+ } else if ($retrain == "innocent" || $retrain == "spam") {
+ system("{$CONFIG['DSPAM']} --source=error --class=" . quotemeta($retrain) .
+ " --signature=" . quotemeta($signature) .
+ " --user " . quotemeta($CURRENT_USER));
+ }
+ }
+ // TODO: Do we need the other params which were submited during the current
+ // POS/GET request?
+ pfSenseHeader("/dspam-history.php?user={$username}&page={$currentPage}&hperpage={$hPerPage}");
+ } else {
+ if ($retrainParam <> "") {
+ if ($retrainParam == "innocent") {
+ ProcessFalsePositive();
+ } else {
+ system("{$CONFIG['DSPAM']} --source=error --class=" . quotemeta($retrainParam) .
+ " --signature=" . quotemeta($sigID) .
+ " --user " . quotemeta($CURRENT_USER));
+ }
+ // TODO: Do we need the other params which were submited during the current
+ // POS/GET request?
+ pfSenseHeader("/dspam-history.php?user={$username}&page={$currentPage}&hperpage={$hPerPage}");
+ }
+ }
+
+ $LOG = "{$USER}.log";
+ if (! file_exists($LOG)) {
+ return $input_errors[] = "No historical data is available (log file »{$USER}.log« does not exist).";
+ }
+
+ /* Preseed retraining information and delivery errors */
+
+ $fd = fopen($LOG, "r");
+ while (!feof($fd)) {
+ /* TODO: If the subject line contains a <TAB>, the below array would
+ * contain more then seven elements and thus would be invalide.
+ *
+ * The below code is some kind of a bug fix.
+ */
+ $cline = fgets($fd, 4096);
+ $log_columns = preg_split("/\t/", $cline);
+ list($time, $class, $from, $signature, $subject, $info, $messageid) = $log_columns;
+ if (count ($log_columns) > 7) {
+ /* get values from the array beginning */
+ $time = array_shift($log_columns);
+ $class = array_shift($log_columns);
+ $from = array_shift($log_columns);
+ $signature = array_shift($log_columns);
+ /* get msgid and info from the array end */
+ $messageid = array_pop($log_columns);
+ $info = array_pop($log_columns);
+ /* the remaining parts are belonging to the subject */
+ $subject = implode(" ", $log_columns);
+ }
+
+ if ($signature == "") { continue; }
+ if ($class == "M" || $class == "F" || $class == "E") {
+ if ($class == "E") {
+ $rec[$signature]['info'] = $info;
+ } else if ($class == "F" || $class == "M") {
+ $rec[$signature]['class'] = $class;
+ $rec[$signature]['count']++;
+ if ($rec[$signature]['info'] == "")
+ { $rec[$signature]['info'] = $info; }
+ }
+ /* filter out resents if there are any. Since it's the same
+ * message we only allow retraining on the 1st occurence of it.
+ */
+ } else if ($messageid == "" ||
+ $rec[$signature]['messageid'] != $messageid ||
+ $CONFIG['HISTORY_DUPLICATES'] <> "no") {
+ $rec[$signature]['time'] = $time;
+ $rec[$signature]['class'] = $class;
+ $rec[$signature]['from'] = $from;
+ $rec[$signature]['signature'] = $signature;
+ $rec[$signature]['subject'] = $subject;
+ $rec[$signature]['info'] = $info;
+ $rec[$signature]['messageid'] = $messageid;
+
+ array_unshift($buffer, $rec[$signature]);
+ }
+ } // end while
+ fclose($fd);
+
+ /* if the page size wasn't specified, set a default one */
+ if ($CONFIG['HISTORY_PER_PAGE'] == 0) {
+ $CONFIG['HISTORY_PER_PAGE'] = 50;
+ }
+
+ if (isset($hPerPage) && $hPerPage > 0) {
+ $CONFIG['HISTORY_PER_PAGE'] = $hPerPage;
+ }
+
+ if (isset($currentPage) && isset($CONFIG['HISTORY_PER_PAGE'])) {
+ $pages = ceil( (count ($buffer) / $CONFIG['HISTORY_PER_PAGE']) );
+ $begin = (($currentPage - 1) * $CONFIG['HISTORY_PER_PAGE']);
+ $ranges = ceil ($pages / $CONFIG['HNAV_BUTTONS']);
+
+ /* Now lets just keep the information that we really need. */
+ $buffer = array_splice($buffer, $begin, $CONFIG['HISTORY_PER_PAGE']);
+ }
+
+ $retrain_checked_msg_no = 0;
+ while ($rec = array_pop($buffer)) {
+ $time = $rec['time'];
+ $class = $rec['class'];
+ $from = $rec['from'];
+ $signature = $rec['signature'];
+ $subject = $rec['subject'];
+ $info = $rec['info'];
+ $messageid = $rec['messageid'];
+
+ if ($signature == "") { continue; }
+ if ($rec[$signature]['displayed'] <> "") { continue; }
+ if ($class == "E") { continue; }
+ $rec[$signature]['displayed'] = 1;
+
+ /* Resends of retrained messages will need the original from/subject line */
+ if ($messageid <> "") {
+ if ($from == "<None Specified>") { $from = $rec[$messageid]['from']; }
+ if ($subject == "<None Specified>") { $subject = $rec[$messageid]['subject']; }
+
+
+ if ($rec[$messageid]['from'] == "") { $rec[$messageid]['from'] = $from; }
+ if ($rec[$messageid]['subject'] == "") { $rec[$messageid]['subject'] = $subject; }
+ }
+
+ if ($from == "") { $from = "<None Specified>"; }
+ if ($subject == "") { $subject = "<None Specified>"; }
+
+ $ctime = "";
+ if(isset($CONFIG["DATE_FORMAT"])) {
+ $ctime = strftime($CONFIG["DATE_FORMAT"], localtime($time));
+ } else {
+ /* date format was taken from ctime.pl */
+ $ctime = date ("D M d H:i:s TY",$time);
+ $ttmp = preg_split("/\s+/", $ctime);
+ $t = preg_split("/\:/", $ttmp[3]);
+ $xtmp = preg_split("/\s+/", $ctime);
+ $x = $xtmp[0];
+ $m = "a";
+ if ($t[0] > 12) { $t[0] -= 12; $m = "p"; }
+ if ($t[0] == 0) { $t[0] = 12; }
+ $ctime = "{$x} {$t[0]}:{$t[1]}{$m}";
+ }
+
+ /* Set the appropriate type and label for this message */
+
+ $cl = "";
+ $cllabel = "";
+ if ($rec[$signature]['class'] <> "") { $class = $rec[$signature]['class']; }
+ if ($class == "S") { $cl = "spam"; $cllabel="SPAM"; }
+ else if ($class == "I") { $cl = "innocent"; $cllabel="Good"; }
+ else if ($class == "F") {
+ if (fmod($rec[$signature]['count'], 2) != 0) {
+ $cl = "false"; $cllabel="Miss";
+ } else {
+ $cl = "innocent"; $cllabel="Good";
+ }
+ }
+ else if ($class == "M") {
+ if (fmod($rec[$signature]['count'], 2) != 0) {
+ $cl = "missed"; $cllabel="Miss";
+ } else {
+ $cl = "spam"; $cllabel="SPAM";
+ }
+ }
+ else if ($class == "N") { $cl = "inoculation"; $cllabel="Spam"; }
+ else if ($class == "C") { $cl = "blacklisted"; $cllabel="RBL"; }
+ else if ($class == "W") { $cl = "whitelisted"; $cllabel="Whitelist"; }
+ if ($messageid <> "") {
+ if ($rec[$messageid]['resend'] <> "") {
+ $cl = "relay";
+ $cllabel = "Resend";
+ }
+ $rec[$messageid]['resend'] = $signature;
+ }
+
+ if ($rec[$signature]['info'] <> "") { $info = $rec[$signature]['info']; }
+
+ /* sanitize HTML markup */
+ $from = preg_replace("/</e", "'&lt;'", $from);
+ $from = preg_replace("/>/e", "'&gt;'", $from);
+ $subject = preg_replace('/</e', "'&lt;'", $subject);
+ $subject = preg_replace('/>/e', "'&gt;'", $subject);
+
+ if (strlen($from) > $CONFIG['MAX_COL_LEN']) { $from = substr($from, 0, $CONFIG['MAX_COL_LEN']) . "..."; }
+ if (strlen($subject) > $CONFIG['MAX_COL_LEN']) { $subject = substr($subject, 0, $CONFIG['MAX_COL_LEN']) . "..."; }
+
+ $rclass = "";
+ if ($class == "I" || $class == "W" || $class == "F") { $rclass = "spam"; }
+ if ($class == "S" || $class == "M") { $rclass = "innocent"; }
+
+ $retrain = "";
+ if (preg_match('/^(M|F)$/', $rec[$signature]['class']) > 0 &&
+ fmod($rec[$signature]['count'], 2) != 0) {
+ $retrain = "<b>Retrained</b>";
+ }
+
+ if ($retrain == "") {
+ $retrain = "<A HREF=\"/dspam-history.php?page={$currentPage}&hperpage={$hPerPage}&user={$username}&retrain={$rclass}&signatureID={$signature}\">As " . ucfirst($rclass) . "</A>";
+ } else {
+ $retrain .= "(<A HREF=\"/dspam-history.php?page={$currentPage}&hperpage={$hPerPage}&user={$username}&retrain={$rclass}&signatureID={$signature}\">Undo</A>)";
+ }
+
+ $path = "{$USER}.frag/{$signature}.frag";
+ if (file_exists($path)) {
+ $pairs = array();
+ $pairs['template'] = "fragment";
+ $pairs['signatureID'] = $signature;
+ $sub = $subject;
+ $sub = preg_replace('/#/e', '//', $sub);
+ $sub = preg_replace("/(['])/e", '/\\$1/', $sub);
+ $pairs['subject'] = $sub;
+ $pairs['from'] = $from;
+ $pairs['info'] = $info;
+ $pairs['time'] = $ctime;
+ $pairs['user'] = $username;
+ $pairs['page'] = $currentPage;
+ $pairs['hperpage'] = $hPerPage;
+ $url = SafeVars($pairs);
+ $from = "<a href=\"javascript:openwin(580,400,1,'/dspam-hfragment.php?{$url}')\">{$from}</a>";
+ }
+
+ $entry = <<<EOD
+ <tr>
+ <td align="left" valign="top" class="{$rowclass} {$cl}" nowrap="true"><small>{$cllabel}</small></td>
+ <td align="left" valign="top" class="{$rowclass}" nowrap="true">
+ <small>
+ <input class="formfld" name="msgid{$retrain_checked_msg_no}" id="msgid{$retrain_checked_msg_no}" title="Check/Uncheck" type="checkbox" value="{$rclass}:{$signature}">
+ <label for="msgid{$retrain_checked_msg_no}">{$retrain}</label>
+ </small>
+ </td>
+ <td align="left" valign="top" class="{$rowclass}" nowrap="true"><small>{$ctime}</small></td>
+ <td align="left" valign="top" class="{$rowclass}" nowrap="true"><small>{$from}</small></td>
+ <td align="left" valign="top" class="{$rowclass}" nowrap="true"><small>{$subject}</small></td>
+ <td align="left" valign="top" class="{$rowclass}" nowrap="true"><small>{$info}</small></td>
+ </tr>
+
+EOD;
+
+ $retrain_checked_msg_no++;
+ array_push($history, $entry);
+
+ if ($rowclass == "qrowEven") {
+ $rowclass = "qrowOdd";
+ } else {
+ $rowclass = "qrowEven";
+ }
+ $hurtz++;
+ } // end while
+
+ $entry = <<<EOD
+ <input name="history_page" type="hidden" value="{$history_page}">
+
+EOD;
+ array_push($history, $entry);
+
+ while($line = array_pop($history)) { $DATA['HISTORY'] .= $line; }
+
+ if ($CONFIG['HISTORY_PER_PAGE'] > 0) {
+ /* prepare quarantine navbar */
+ if (($currentPage - 1) >= 1) { $previousPage = $currentPage - 1; }
+ else { $previousPage = 1; }
+
+ if (($currentPage + 1) <= $pages) { $nextPage = $currentPage + 1; }
+ else { $nextPage = $pages; }
+
+ $historyFooterBegin = <<<EOD
+ <tr>
+ <td align="right" valign="middle" class="listtopic" colspan="6">
+ <span class="qnavbtn" onmouseover="this.style.backgroundColor='#A5B9E1;'" onmouseout="this.style.backgroundColor='#507DCD;'" title="First Page (1)"><a href="/dspam-history.php?page=1&qperpage={$CONFIG['HISTORY_PER_PAGE']}" title="First Page (1)">|&lt;</a></span>&nbsp;
+ <span class="qnavbtn" onmouseover="this.style.backgroundColor='#A5B9E1;'" onmouseout="this.style.backgroundColor='#507DCD;'" title="Page {$previousPage}"><a href="/dspam-history.php?page={$previousPage}&qperpage={$CONFIG['HISTORY_PER_PAGE']}" title="Page {$previousPage}">&lt;</a></span>&nbsp;
+
+EOD;
+
+ $historyFooterEnd = <<<EOD
+ <span class="qnavbtn" onmouseover="this.style.backgroundColor='#A5B9E1;'" onmouseout="this.style.backgroundColor='#507DCD;'" title="Page {$nextPage}"><a href="/dspam-history.php?page={$nextPage}&qperpage={$CONFIG['HISTORY_PER_PAGE']}" title="Page {$nextPage}">&gt;</a></span>&nbsp;
+ <span class="qnavbtn" onmouseover="this.style.backgroundColor='#A5B9E1;'" onmouseout="this.style.backgroundColor='#507DCD;'" title="Last Page ({$pages})"><a href="/dspam-history.php?page={$pages}&qperpage={$CONFIG['HISTORY_PER_PAGE']}" title="Last Page ({$pages})">&gt;|</a></span>
+ </td>
+ </tr>
+
+EOD;
+
+ $ranges_array = array();
+ $rpages = $pages;
+ for ($i = 0; $i < $ranges; $i++) {
+ $range = array();
+ $range['start'] = (($i + 1)* $CONFIG['HNAV_BUTTONS']) - ($CONFIG['HNAV_BUTTONS'] - 1);
+
+ if (($i + 1) == $ranges) {
+ $range['end'] = ($range['start'] + $rpages) - 1;
+ } else {
+ $range['end'] = (($i + 1)* $CONFIG['HNAV_BUTTONS']);
+ $rpages -= $CONFIG['HNAV_BUTTONS'];
+ }
+
+ $ranges_array[$i] = $range;
+ }
+
+ /* generate nav buttons */
+ foreach($ranges_array as $range){
+ if ($currentPage >= $range['start'] && $currentPage <= $range['end']) {
+ for ($i = $range['start']; ; $i++) {
+ if ($i > $range['end']) {
+ break;
+ } else {
+ if ($i == $currentPage) {
+ $historyFooter .= "<span class=\"qnavbtnhl\">{$i}</span>&nbsp\n";
+ } else {
+ $historyFooter .= "<span class=\"qnavbtn\" onmouseover=\"this.style.backgroundColor='#A5B9E1;'\" onmouseout=\"this.style.backgroundColor='#507DCD;'\" title=\"Page {$i}\"><a href=\"/dspam-history.php?page={$i}&hperpage={$CONFIG['HISTORY_PER_PAGE']}\" title=\"Page {$i}\">{$i}</a></span>&nbsp\n";
+ }
+ }
+ }
+ }
+ }
+
+ $DATA['HISTORY_FOOTER'] = $historyFooterBegin . $historyFooter .$historyFooterEnd;
+ $DATA['HPAGES'] = $pages;
+ $DATA['HPAGE'] = $currentPage;
+
+/*
+ $DATA['HISTORY'] .= "<tr><td align=\"left\" valign=\"top\" colspan=\"6\"><center>[";
+ if (($history_pages > 1) && ($history_page > 1)) {
+ $i = $history_page - 1;
+ $DATA['HISTORY'] .= "<a href=\"/dspam-history.php?user={$username}&history_page={$i}\">&nbsp;&lt;&nbsp;</a>";
+ }
+ for($i = 1; $i <= $history_pages; $i++) {
+ if ($i == $history_page) {
+ $DATA['HISTORY'] .= "<a href=\"/dspam-history.php?user={$username}&history_page={$i}\"><big><strong>&nbsp;$i&nbsp;</strong></big></a>";
+ } else {
+ $DATA['HISTORY'] .= "<a href=\"/dspam-history.php?user={$username}&history_page={$i}\">&nbsp;{$i}&nbsp;</a>";
+ }
+ }
+ if (($history_pages > 1) && ($history_page < $history_pages)) {
+ $i = $history_page + 1;
+ $DATA['HISTORY'] .= "<a href=\"/dspam-history.php?user={$username}&history_page={$i}\">&nbsp;&gt;&nbsp;</a>";
+ }
+ $DATA['HISTORY'] .= "]</center></td></tr>";
+*/
+ } // end if
+}
+
+/* ========================================================================== */
+/* = A N A L Y S I S F U N C T I O N S = */
+/* ========================================================================== */
+
+function &DisplayAnalysis() {
+ global $USER, $CURRENT_USER, $CONFIG, $DATA;
+ $LOG = "{$USER}.log";
+
+ $Stats = array(
+ "daily" => array(),
+ "weekly" => array()
+ );
+
+ list(, $min, $hour, $mday, $mon, $year, , ,) = (localtime(time()));
+ $daystart = mktime(0, 0, 0, $mon, $mday, $year);
+ $periodstart = $daystart - (3600 * 24 * 13); /* 2 Weeks ago */
+ $dailystart = time() - (3600 * 23);
+
+ /* TODO: There's an issue that the Perl timelocal returns
+ * different values compared to PHP's mktime. There's a
+ * difference of 2678400, which will be added manually below.
+ */
+ $daystart += 2678400;
+ $periodstart += 2678400;
+
+ if (file_exists($LOG)) {
+ if ($fd = @fopen($LOG, "r")) {
+ $scount = 0;
+ $icount = 0;
+ $wcount = 0;
+ $fcount = 0;
+ $mcount = 0;
+
+ while(!feof($fd)) {
+ $buffer = fgets($fd, 4096);
+ /* drop blank lines */
+ if (strlen($buffer) == 0) { continue; }
+ list($t_log, $c_log) = preg_split("/\t/", $buffer);
+
+ /* Only Parse Log Data in our Time Period */
+ /* TODO: The below if should evaluate to true at least for some data */
+ if ($t_log >= $periodstart) {
+ list(, $tmin, $thour, $tday, $tmon, , , ,) = (localtime($t_log));
+ $tmon++;
+
+ foreach (array('weekly', 'daily') as $period) {
+ $idx = 0;
+ if ($period == "weekly") {
+ $idx= "{$tmon}/{$tday}";
+ } else {
+ if ($t_log <= $dailystart) { continue; }
+ $idx = To12Hour($thour);
+ }
+ if (is_array($Stats[$period]) && ! array_key_exists ($idx, $Stats[$period])) {
+ $Stats[$period][$idx] = array(
+ 'nonspam' => 0,
+ 'spam' => 0,
+ 'title' => $idx,
+ 'idx' => $t_log);
+ }
+ /* TODO: Is passing by reference here correct? */
+ $hr =& $Stats[$period][$idx];
+ /* S => spam */
+ if ($c_log== "S") {
+ $hr['spam']++;
+ $scount++;
+ }
+ /* I => innocent W => whitelisted */
+ if ($c_log == "I" || $c_log == "W") {
+ $hr['nonspam']++;
+ if ($c_log == "I") { $icount++; }
+ else { $wcount++; }
+ }
+ /* F => false positive */
+ if ($c_log == "F") {
+ $hr['spam']--;
+ if ($hr['spam'] < 0) { $hr['spam'] = 0; }
+ $hr['nonspam']++;
+ $fcount++;
+ }
+ /* M => spam miss */
+ if ($c_log == "M") {
+ $hr['nonspam']--;
+ if ($hr['nonspam'] < 0) { $hr['nonspam'] = 0; }
+ $hr['spam']++;
+ $mcount++;
+ }
+ }
+ }
+ }
+
+ fclose($fd);
+ } else {
+ return $input_errors[] = "Unable to open log file: {$LOG}.";
+ }
+
+ usort ((array_values ($Stats[$period])), "cmpArrayValues");
+
+ foreach (array('weekly', 'daily') as $period) {
+ $uc_period = strtoupper($period);
+ $hk = "DATA_{$uc_period}";
+ $lst = array();
+
+ foreach (array_values($Stats[$period]) as $hr) {
+ foreach (array('spam', 'nonspam', 'title') as $type ) {
+
+ if (empty($lst[$type])) {
+ $lst[$type] = array();
+ }
+
+ /* populate (newly) created array */
+ $lst[$type][] = $hr[$type];
+
+ $totk="";
+
+ if ($type == "spam") { $totk="S"; }
+ else if ($type == "nonspam") { $totk="I"; }
+
+ if ($totk == "") { continue; }
+
+ $sk="T{$totk}_{$uc_period}";
+ if (empty($DATA[$sk])) { $DATA[$sk] = 0; }
+
+ $DATA[$sk] += $hr[$type];
+ }
+ } // end foreach
+ $DATA[$hk] =
+ @join(",",$lst['spam']) . "_" .
+ @join(",",$lst['nonspam']) . "_" .
+ @join(",",$lst['title']);
+ } // end foreach
+ } else {
+ return $input_errors[] = "No historical data is available (log file »{$LOG}« does not exist).";
+ } // end if
+}
+
+function cmpArrayValues($a, $b) {
+ if ($a['idx'] == $b['idx'])
+ return 0;
+
+ return ($a['idx'] < $b['idx']) ? -1 : 1;
+}
+
+/* ========================================================================== */
+/* = P E R E F E R E N C E S F U N C T I O N S = */
+/* ========================================================================== */
+
+function &DisplayPreferences($mode = "", &$statusmsg){
+ global $USER, $CURRENT_USER, $CONFIG, $DATA;
+ $FILE = "{$USER}.prefs";
+ $username = $CURRENT_USER;
+
+ if ($_POST) {
+ $pconfig = $_POST;
+
+ if ($pconfig['chk_feature_nr'] <> "on") {
+ $pconfig['chk_feature_nr'] = "off";
+ }
+
+ if ($pconfig['chk_feature_optin'] <> "on") {
+ $pconfig['chk_feature_optin'] = "off";
+ }
+
+ if ($pconfig['chk_feature_optout'] <> "on") {
+ $pconfig['chk_feature_optout'] = "off";
+ }
+
+ if ($pconfig['chk_feature_at'] <> "on") {
+ $pconfig['chk_feature_at'] = "off";
+ }
+
+ if ($pconfig['chk_feature_aw'] <> "on") {
+ $pconfig['chk_feature_aw'] = "off";
+ }
+
+ if ($CONFIG['PREFERENCES_EXTENSION'] == 1) {
+ if ($pconfig['msgtag'] == "") {
+ $pconfig['msgtag'] = "''";
+ } else {
+ $pconfig['msgtag'] = quotemeta($pconfig['msgtag']);
+ }
+
+ exec("{$CONFIG['DSPAM_BIN']}/dspam_admin ch pref " . quotemeta($username) .
+ " trainingMode " . quotemeta($pconfig['rad_train']) . " > /dev/null");
+ exec("{$CONFIG['DSPAM_BIN']}/dspam_admin ch pref " . quotemeta($username) .
+ " spamAction " . quotemeta($pconfig['rad_train_action']) . " > /dev/null");
+ exec("{$CONFIG['DSPAM_BIN']}/dspam_admin ch pref " . quotemeta($username) .
+ " signatureLocation " . quotemeta($pconfig['signatureLocation']) . " > /dev/null");
+ exec("{$CONFIG['DSPAM_BIN']}/dspam_admin ch pref " . quotemeta($username) .
+ " spamSubject " . quotemeta($pconfig['msgtag']) . " > /dev/null");
+ exec("{$CONFIG['DSPAM_BIN']}/dspam_admin ch pref " . quotemeta($username) .
+ " statisticalSedation " . quotemeta($pconfig['rad_filter_sens']) . " > /dev/null");
+ exec("{$CONFIG['DSPAM_BIN']}/dspam_admin ch pref " . quotemeta($username) .
+ " enableBNR " . quotemeta($pconfig['chk_feature_nr']) . " > /dev/null");
+ exec("{$CONFIG['DSPAM_BIN']}/dspam_admin ch pref " . quotemeta($username) .
+ " optOut " . quotemeta($pconfig['chk_feature_optout']) . " >/dev/null");
+ exec("{$CONFIG['DSPAM_BIN']}/dspam_admin ch pref " . quotemeta($username) .
+ " optIn " . quotemeta($pconfig['chk_feature_optin']) . " >/dev/null");
+ exec("{$CONFIG['DSPAM_BIN']}/dspam_admin ch pref " . quotemeta($username) .
+ " showFactors " . quotemeta($pconfig['chk_feature_at']) . " > /dev/null");
+ exec("{$CONFIG['DSPAM_BIN']}/dspam_admin ch pref " . quotemeta($username) .
+ " enableWhitelist " . quotemeta($pconfig['chk_feature_aw']) . " > /dev/null");
+ } else {
+ $prefsstr = <<<EOD
+trainingMode={$pconfig['rad_train']}
+spamAction={$pconfig['rad_ident_action']}
+spamSubject={$pconfig['msgtag']}
+statisticalSedation={$pconfig['rad_filter_sens']}
+enableBNR={$pconfig['chk_feature_nr']}
+optIn={$pconfig['chk_feature_optin']}
+optOut={$pconfig['chk_feature_optout']}
+showFactors={$pconfig['chk_feature_at']}
+enableWhitelist={$pconfig['chk_feature_aw']}
+signatureLocation={$pconfig['rad_train_action']}
+
+EOD;
+
+ if ($fd = @fopen("{$FILE}","w")) {
+ fwrite($fd, $prefsstr);
+ fclose($fd);
+ } else {
+ return $input_errors[] = "Unable to write preferences to file: {$FILE}";
+ }
+ }
+
+ $statusmsg = "DSPAM preferences have been written to: {$FILE}.";
+ }
+
+ $PREFS =& GetPrefs($username);
+
+ $DATA["SEDATION_{$PREFS['statisticalSedation']}"] = 'checked="checked"';
+ $DATA["S_{$PREFS['trainingMode']}"] = 'checked="checked"';
+ $DATA["S_ACTION_" . strtoupper($PREFS['spamAction'])] = 'checked="checked"';
+ $DATA["S_LOC_" . strtoupper($PREFS['signatureLocation'])] = 'checked="checked"';
+ $DATA["SPAM_SUBJECT"] = $PREFS['spamSubject'];
+ if ($PREFS['optIn'] == "on") {
+ $DATA['C_OPTIN'] = 'checked="checked"';
+ }
+ if ($PREFS['optOut'] == "on") {
+ $DATA['C_OPTOUT'] = 'checked="checked"';
+ }
+ if ($PREFS['enableBNR'] == "on") {
+ $DATA['C_BNR'] = 'checked="checked"';
+ }
+ if ($PREFS['showFactors'] == "on") {
+ $DATA['C_FACTORS'] = 'checked="checked"';
+ }
+ if ($PREFS['enableWhitelist'] == "on") {
+ $DATA['C_WHITELIST'] = 'checked="checked"';
+ }
+}
+
+function sortByRating($a, $b){
+ if ($a['rating'] == $b['rating']) {
+ return 0;
+ }
+
+ return ($a['rating'] < $b['rating']) ? -1 : 1;
+}
+
+/* ========================================================================== */
+/* = Q U A R A N T I N E F U N C T I O N S = */
+/* ========================================================================== */
+
+function &ProcessQuarantine($signatures = array(),
+ $action = "None",
+ $sortBy = "Rating",
+ $currentPage = 1,
+ $qPerPage = 0){
+ switch($action){
+ case "None":
+ $input_errors =& DisplayQuarantine($sortBy, $currentPage, $qPerPage);
+ break;
+ case "manyNotSpam":
+ $input_errors =& QuarantineManyNotSpam($signatures, $sortBy, $currentPage, $qPerPage);
+ break;
+ case "deleteAll":
+ QuarantineDeleteSpam($action, $signatures, $sortBy, $currentPage, $qPerPage);
+ break;
+ default:
+ QuarantineDeleteSpam();
+ } // switch
+
+ CheckQuarantine();
+
+ return $input_errors;
+}
+
+function &ProcessFalsePositive($sigID = "",
+ $sortBy = "Rating",
+ $currentPage = 1,
+ $qPerPage = 0) {
+ global $MAILBOX, $CONFIG, $TMPFILE, $CURRENT_USER;
+ $buffer = array();
+ $head = array();
+ $singatures = array();
+ $found = 0;
+ $error = false;
+
+ if ($sigID == "") {
+ return $input_errors[] = "No Message ID Specified.";
+ }
+
+ /* read the user's mailbox line by line into a buffer */
+ $fd = fopen("{$MAILBOX}", "r");
+ while (!feof($fd)) {
+ $line = chop(fgets($fd, 4096));
+ array_push($buffer, $line);
+ }
+ fclose ($fd);
+
+ /* iterate over the mailbox buffer */
+ reset($buffer);
+ $i = 0;
+ while ($i < count($buffer)) {
+ $temp = array();
+ $head = array();
+ $mode = 0;
+ $buff = "";
+
+ /* this while tries to iterate over one single mesage including
+ * the message header and the message body.
+ */
+ while((preg_match('/^From /', $buff) == 0) && ($i < count($buffer))) {
+ $buff = $buffer[0];
+
+ /* switch mode if we are hitting DSPAMs
+ * pseudo From QUARANTINE line (without a
+ * colon after the From).
+ */
+ if (preg_match('/^From /', $buff) > 0) {
+ if ($mode == 0) { $mode = 1; }
+ else { continue; }
+ }
+
+ $buff = array_shift($buffer);
+ if (preg_match('/^From /', $buff) == 0) {
+ array_push($temp, $buff);
+ }
+
+ continue;
+ }
+
+ foreach($temp as $tempel) {
+ if ($tempel == "") { break; }
+ list($key, $val) = preg_split('/\: ?/', $tempel, 2);
+ $head[$key] = $val;
+ }
+ if ($head['X-DSPAM-Signature'] == $sigID) {
+ $found = 1;
+ $old_erep = error_reporting(E_ALL);
+ if ($pd = @popen("|{$CONFIG['DSPAM']} {$CONFIG['DSPAM_ARGS']} >{$TMPFILE} 2>&1", "w")) {
+ $pdresult = fread($handle, 2096);
+
+ foreach($temp as $tempel) {
+ fwrite($pd, "{$tempel}\n");
+ }
+
+ pclose($pd);
+ error_reporting($old_erep);
+ } else {
+ $error = true;
+ $input_errors[] = "Unable to ope process pipe in function <code>ProcessFalsePositive</code>.";
+ }
+ }
+ }
+
+ /* Couldn't find the message, so just retrain on signature */
+ if (!$found) {
+ system("$CONFIG{'DSPAM'} --source=error --class=innocent --signature=" . quotemeta($sigID) .
+ " --user " . quotemeta($CURRENT_USER));
+ }
+
+ if ($error) {
+ $log = array();
+ $fd = fopen("{$TMPFILE}", "r");
+ while (!feof($handle)) {
+ $log .= fgets($fd, 4096);
+ }
+ fclose($fd);
+ unlink("{$TMPFILE}");
+ return $input_errors[] = $log;
+ }
+
+ unlink("{$TMPFILE}");
+ $signatures[$sigID] = "on";
+ return QuarantineDeleteSpam("", $signatures, $sortBy, $currentPage, $qPerPage);
+}
+
+function &QuarantineManyNotSpam($signatures = array(), $sortBy = "Rating", $currentPage = 1, $qPerPage = 0){
+ global $MAILBOX, $USER;
+ $buffer = array();
+ $errors = array();
+
+ /* read the user's mailbox line by line into a buffer */
+ $fd = fopen("{$MAILBOX}", "r");
+ while (!feof($fd)) {
+ $line = chop(fgets($fd, 4096));
+ array_push($buffer, $line);
+ }
+ fclose ($fd);
+
+ if ($fd_FILE = @fopen("{$MAILBOX}", "w")) {
+ $fd_RETRAIN = fopen("{$USER}.retrain.log", "a");
+
+ /* iterate over the mailbox buffer */
+ reset($buffer);
+ $i = 0;
+ while ($i < count($buffer)) {
+ $temp = array();
+ $head = array();
+ $mode = 0;
+ $buff = "";
+
+ /* this while tries to iterate over one single mesage including
+ * the message header and the message body.
+ */
+ while((preg_match('/^From /', $buff) == 0) && ($i < count($buffer))) {
+ $buff = $buffer[0];
+
+ /* switch mode if we are hitting DSPAMs
+ * pseudo From QUARANTINE line (without a
+ * colon after the From).
+ */
+ if (preg_match('/^From /', $buff) > 0) {
+ if ($mode == 0) {
+ $mode = 1;
+ $buff = array_shift($buffer);
+ array_push($temp, $buff);
+ $buff = "";
+ continue;
+ } else {
+ continue;
+ }
+ }
+
+ $buff = array_shift($buffer);
+ array_push($temp, $buff);
+
+ continue;
+ }
+
+ /* populate the header array with header fields */
+ foreach($temp as $tempel) {
+ if ($tempel == "") { break; }
+ list($key, $val) = preg_split('/\: ?/', $tempel, 2);
+ $head[$key] = $val;
+ }
+
+ $delivered = 0;
+ if ($signatures["chkmsg-{$head['X-DSPAM-Signature']}"] <> "") {
+ $err = Deliver($temp);
+ if ($err == "") {
+ $delivered = 1;
+ } else {
+ array_push($errors, $err);
+ }
+ }
+ if (!$delivered) {
+ foreach($temp as $tempel) {
+ fwrite($fd_FILE, "{$tempel}\n");
+ }
+ } else {
+ fwrite($fd_RETRAIN, strval(time()) . "\t{$head['X-DSPAM-Signature']}\tinnocent\n");
+ }
+
+ $i++;
+ } // end while
+
+ fclose($fd_FILE);
+ fclose($fd_RETRAIN);
+ } else {
+ return $input_errors[] = "Unable to open mailbox file: {$MAILBOX}.";
+ }
+
+ if (count($errors) > 0) {
+ return $errors;
+ }
+
+ return DisplayQuarantine($sortBy, $currentPage, $qPerPage);
+}
+
+function Deliver($temp = array()) {
+ global $CONFIG;
+
+ if (! file_exists("/tmp/dspam-error-output.txt")) {
+ touch("/tmp/dspam-error-output.txt");
+ }
+ $descriptorspec = array(
+ 0 => array("pipe", "r"), // stdin is a pipe that the child will read from
+ 1 => array("pipe", "w"), // stdout is a pipe that the child will write to
+ 2 => array("file", "/tmp/dspam-error-output.txt", "a") // stderr is a file to write to
+ );
+
+ list($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$sizeb,
+ $atime,$mtimeb,$ctime,$blksize,$blocks)
+ = stat("/tmp/dspam-error-output.txt");
+ clearstatcache();
+
+ $cwd = '/tmp';
+ $process = @proc_open("{$CONFIG['DSPAM']} {$CONFIG['DSPAM_ARGS']}",
+ $descriptorspec,
+ $pipes);
+
+ if (is_resource($process)) {
+ foreach($temp as $tempel) {
+ if (! @fwrite($pipes[0], "{$tempel}\n")) {
+ return "error while writting to pipe.";
+ }
+ }
+
+ fclose($pipes[0]);
+ fclose($pipes[1]);
+ $return_value = proc_close($process);
+
+ /* this isn't an elegant solution to determine whether
+ * DSPAM did report some errors, but it works for now
+ */
+ list($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$sizea,
+ $atime,$mtimea,$ctime,$blksize,$blocks)
+ = stat("/tmp/dspam-error-output.txt");
+
+ if ($mtimeb <> $mtimea) { return "DSPAM did report some errors to /tmp/dspam-error-output.txt.\n" .
+ "Please check this particular file."; }
+ } else {
+ return "process is not a resource type.";
+ }
+
+ return "";
+}
+
+function getLayoutedMessage($msgbuffer = "", $sigID = "", $showpart = 0, $ctype = 0){
+
+ if ($msgbuffer == "") {
+ return '<span class="errmsg">An error occured while parsing the message (no message).</span>';
+ }
+ if ($sigID == "") {
+ return '<span class="errmsg">An error occured while parsing the message (no signature).</span>';
+ }
+
+ if( extension_loaded( 'mailparse' ) ) {
+ $msgdate = "N/A";
+ $msgfrom = "N/A";
+ $msgsub = "N/A";
+ $msgto = "N/A";
+
+ $mime = mailparse_msg_create();
+ mailparse_msg_parse($mime, $msgbuffer);
+ /* return an array of message parts - this contsists of the
+ * names of the parts only.
+ */
+ $struct = mailparse_msg_get_structure($mime);
+ $htmlstr = <<<EOD
+ <tr>
+ <td align="left" valign="top" class="listtopic" colspan="3">Message Infos</td>
+ </tr>
+ <tr>
+ <td valign="baseline" class="vncell" colspan="1">Date:</td>
+ <td class="vtable" colspan="2">%MSGDATE%</td>
+ </tr>
+ <tr>
+ <td valign="baseline" class="vncell" colspan="1">From:</td>
+ <td class="vtable" colspan="2">%MSGFROM%</td>
+ </tr>
+ <tr>
+ <td valign="baseline" class="vncell" colspan="1">Subject:</td>
+ <td class="vtable" colspan="2">%MSGSUB%</td>
+ </tr>
+ <tr>
+ <td valign="baseline" class="vncell" colspan="1">To:</td>
+ <td class="vtable" colspan="2">%MSGTO%</td>
+ </tr>
+ <tr>
+ <td class="list" height="12" colspan="3">&nbsp;</td>
+ </tr>
+ <tr>
+ <td align="left" valign="top" class="listtopic">Message Part</td>
+ <td align="left" valign="top" class="listtopic">Part Type</td>
+ <td align="left" valign="top" class="listtopic">Part Encoding</td>
+ </tr>
+ <tr>
+
+EOD;
+
+ /* print a choice of sections */
+ foreach($struct as $st) {
+
+ /* get a handle on the message resource for a subsection */
+ $section = mailparse_msg_get_part($mime, $st);
+ /* get content-type, encoding and header information for that section */
+ $info = mailparse_msg_get_part_data($section);
+
+ /* replace placeholder with real data */
+ if ($info['headers']['date'] <> "") {
+ $htmlstr = str_replace("%MSGDATE%", $info['headers']['date'], $htmlstr);
+ }
+ if ($info['headers']['from'] <> "") {
+ $htmlstr = str_replace("%MSGFROM%", $info['headers']['from'], $htmlstr);
+ }
+ if ($info['headers']['subject'] <> "") {
+ $htmlstr = str_replace("%MSGSUB%", $info['headers']['subject'], $htmlstr);
+ }
+ if ($info['headers']['to'] <> "") {
+ $htmlstr = str_replace("%MSGTO%", $info['headers']['to'], $htmlstr);
+ }
+
+ $fontStyle = "";
+ if ($showpart && $showpart == $st) { $fontStyle = " style=\"font-weight: bolder;\""; }
+
+ if ($info["content-type"] == "text/html") {
+ $htmlstr .= "<td align=\"left\" valign=\"top\" class=\"vncell\"{$fontStyle}>" .
+ "<a href=\"/dspam-viewmsg.php?ctype=1&showpart={$st}&signatureID={$sigID}&command=viewMessage\">{$st}</a>" .
+ "</td>\n";
+ } else {
+ $htmlstr .= "<td align=\"left\" valign=\"top\" class=\"vncell\"{$fontStyle}>" .
+ "<a href=\"/dspam-viewmsg.php?showpart={$st}&signatureID={$sigID}&command=viewMessage\">{$st}</a>" .
+ "</td>\n";
+ }
+
+ $htmlstr .= <<<EOD
+ <td align="left" valign="top" class="vtable"{$fontStyle}>{$info["content-type"]}</td>
+ <td align="left" valign="top" class="vtable"{$fontStyle}>{$info["charset"]}</td>
+ </tr>
+
+EOD;
+ } // end foreach
+
+ /* if we were called to display a part, do so now */
+ if ($showpart) {
+ /* get a handle on the message resource for the desired part */
+ $sec = mailparse_msg_get_part($mime, $showpart);
+
+ $htmlstr .= <<<EOD
+ <tr>
+ <td class="list" height="12" colspan="3">&nbsp;</td>
+ </tr>
+ <tr>
+ <td align="left" valign="top" class="listtopic" colspan="3">Section {$showpart}</td>
+ </tr>
+ <tr>
+ <td align="top" valign="left" colspan="3" class="vncell">
+EOD;
+
+ ob_start();
+ mailparse_msg_extract_part($sec, $msgbuffer);
+ $contents = ob_get_contents();
+ ob_end_clean();
+ $contents = wordwrap( str_replace("&gt;", "&gt;\n", $contents), 100, "\n" );
+ /* quote the message for safe display in a browser */
+ if ($ctype = 1) {
+ /* a html email message */
+ $htmlstr .= "<pre style=\"font-size: 1.4em;\">" . $contents . "</pre></td>\n</tr>\n";
+ } else {
+ /* an ASCII (text) email message */
+ $htmlstr .= htmlentities($contents) . "</td>\n</tr>\n";
+ }
+ }
+
+ return $htmlstr;
+ } else {
+ return '<span class="errmsg">Could not load mailparse extension.</span>';
+ }
+}
+
+function &QuarantineViewMessage($sigID = "",
+ $showpart = 0,
+ $ctype = 0,
+ $sortBy = "Rating",
+ $currentPage = 1,
+ $qPerPage = 0) {
+ global $MAILBOX, $DATA;
+ $buffer = array(); // mailbox buffer
+
+ if ($sigID == "") {
+ return $input_errors[] = "No Message ID Specified.";
+ }
+
+ /* save data to be displayed as HTML form data */
+ $DATA['MESSAGE_ID'] = $sigID;
+ $DATA['SHOWPART'] = $showpart;
+ $DATA['CONTENT_TYPE'] = $ctype;
+ $DATA['QPAGE'] = $currentPage;
+ $DATA['SORTBY'] = $sortBy;
+
+ if ($qPerPage > 0) { $CONFIG['QUARANTINE_PER_PAGE'] = $qPerPage; }
+
+ /* read the user's mailbox line by line into a buffer */
+ $fd = fopen("{$MAILBOX}", "r");
+ while (!feof($fd)) {
+ $line = chop(fgets($fd, 4096));
+ array_push($buffer, $line);
+ }
+ fclose ($fd);
+
+ /* iterate over the mailbox buffer */
+ reset($buffer);
+ $i = 0;
+ while ($i < count($buffer)) {
+ $temp = array();
+ $head = array();
+ $mode = 0;
+ $buff = "";
+
+ /* this while tries to iterate over one single mesage including
+ * the message header and the message body.
+ */
+ while((preg_match('/^From /', $buff) == 0) && ($i < count($buffer))) {
+ $buff = $buffer[0];
+
+ /* switch mode if we are hitting DSPAMs
+ * pseudo From QUARANTINE line (without a
+ * colon after the From).
+ */
+ if (preg_match('/^From /', $buff) > 0) {
+ if ($mode == 0) { $mode = 1; }
+ else { continue; }
+ }
+
+ $buff = array_shift($buffer);
+ if (preg_match('/^From /', $buff) == 0) {
+ array_push($temp, $buff);
+ }
+
+ continue;
+ }
+
+ /* populate the header array with header fields */
+ foreach($temp as $tempel) {
+ if ($tempel == "") { break; }
+ list($key, $val) = preg_split('/\: ?/', $tempel, 2);
+ $head[$key] = $val;
+ }
+ if ($head['X-DSPAM-Signature'] == $sigID) {
+ foreach($temp as $tempel) {
+ $tempel = preg_replace("/</e", "'&lt;'", $tempel);
+ $tempel = preg_replace("/>/e", "'&gt;'", $tempel);
+ $DATA['MESSAGE'] .= "{$tempel}\n";
+ }
+ }
+
+ $i ++;
+ } // end while
+}
+
+function QuarantineDeleteSpam($deleteAll = "", $signatures = array(), $sortBy = "Rating", $currentPage = 1, $qPerPage = 0){
+ global $USER, $MAILBOX;
+ $buffer = array();
+
+ /* this is the most easiest operation: If the user wants
+ * to completly delete any quarantined message, simply
+ * open his mailbox in write mode, which empties the
+ * user's mailbox file.
+ */
+ if ($deleteAll <> "") {
+
+ list($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
+ $atime,$mtime,$ctime,$blksize,$blocks) = stat("{$USER}.mbox");
+
+ $fd = fopen("{$USER}.mbox.size", "r");
+ $sz = chop(fgets($fd, 4096));
+ fclose($fd);
+
+ if ($sz == $size) {
+ $fd = fopen("{$MAILBOX}", "w");
+ fclose($fd);
+ unlink("{$USER}.mbox.size");
+ unlink("{$USER}.mboxwarn");
+ } else {
+ return DisplayQuarantine($sortBy, $currentPage, $qPerPage);
+ }
+
+ //$FORM{'template'} = "performance";
+ CheckQuarantine();
+ return DisplayIndex();
+ }
+
+ /* iterate over the user's mailbox and store its contents in a buffer */
+ $fd = fopen("{$MAILBOX}", "r");
+ while (!feof($fd)) {
+ $line = chop(fgets($fd, 4096));
+ array_push($buffer, $line);
+ }
+ fclose($fd);
+
+ /* open the user's mailbox in write mode. This empties the mailbox! */
+ fopen("{$MAILBOX}", "w");
+
+ /* iterate over the mailbox buffer */
+ reset($buffer);
+ $i = 0;
+ while ($i < count($buffer)) {
+ $temp = array();
+ $head = array();
+ $mode = 0;
+
+ /* this while tries to iterate over one single mesage including
+ * the message header and the message body.
+ */
+ while((preg_match('/^From /', $buff) == 0) && ($i < count($buffer))) {
+ $buff = $buffer[0];
+
+ /* switch mode if we are hitting DSPAMs
+ * pseude From QUARANTINE line (without a
+ * colon after the From).
+ */
+ if (preg_match('/^From /', $buff) > 0) {
+ if ($mode == 0) {
+ $mode = 1;
+ $buff = array_shift($buffer);
+ array_push($temp, $buff);
+ $buff = "";
+ continue;
+ } else {
+ continue;
+ }
+ }
+ $buff = array_shift($buffer);
+ array_push($temp, $buff);
+
+ continue;
+ }
+
+ /* populate the header array with header fields */
+ foreach($temp as $tempel) {
+ if ($tempel == "") { break; }
+ list($key, $val) = preg_split('/\: ?/', $tempel, 2);
+ $head[$key] = $val;
+ }
+
+ /* if the current DSPAM signature wasn't selected by the
+ * user to be deleted, write it back to the user's mailbox.
+ */
+ if ($signatures["chkmsg-{$head['X-DSPAM-Signature']}"] == "") {
+ foreach($temp as $tempel) {
+ fwrite($fd, "{$tempel}\n");
+ }
+ }
+
+ $i++;
+ } // end while
+ fclose($fd);
+
+ return;
+}
+
+function sortBySubject($a, $b){
+ $lca = strtolower ($a['Subject']);
+ $lcb = strtolower ($b['Subject']);
+
+ return strcmp($lca, $lcb);
+}
+
+function sortByFrom($a, $b){
+ $lca = strtolower ($a['From']);
+ $lcb = strtolower ($b['From']);
+
+ return strcmp($lca, $lcb);
+}
+
+function &DisplayQuarantine($sortBy = "Rating", $currentPage = 1, $qPerPage = 0) {
+ global $USER, $CURRENT_USER, $CONFIG, $DATA, $MAILBOX;
+ $alertcfg = &$config['installedpackages']['dspamalerts']['config'];
+ $alerts = array();
+
+ if (file_exists("{$USER}.mbox")) {
+ list($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
+ $atime,$mtime,$ctime,$blksize,$blocks) = stat("{$USER}.mbox");
+
+ $fd = fopen("{$USER}.mbox.size", "w");
+ fwrite($fd, "{$size}");
+ fclose($fd);
+
+ $fd = fopen("{$MAILBOX}.stamp", "a+");
+ fclose($fd);
+ chmod("{$MAILBOX}.stamp", 0660);
+
+ /* process alert names */
+ if (is_array($alertcfg)) {
+ $alert_counter = 0;
+
+ foreach ($alertcfg as $alert) {
+ $alerts[$alert_counter] = $alert['alertname'];
+ $alert_counter++;
+ }
+ }
+
+ $mode = "";
+ $buffer = array();
+ $headings = array();
+ $rowclass = "qrowEven";
+ $fd = fopen("{$MAILBOX}", "r");
+
+ while (!feof($fd)) {
+ $mbxline = chop(fgets($fd, 4096));
+
+ if ($mbxline <> "") {
+ if (($mode == "")) {
+ if (preg_match('/^From /', $mbxline) > 0) {
+ $mode = 1;
+ } else {
+ continue;
+ }
+ }
+
+ array_push($buffer, $mbxline);
+ continue;
+ }
+
+ if ($mode == "") { continue; }
+
+ $alert = 0;
+ $new = array();
+
+ foreach($buffer as $buf_element){
+ foreach($alerts as $al){
+ if (preg_match("/{$al}/i", $buf_element) > 0) {
+ $alert = 1;
+ }
+ }
+
+ if (preg_match('/^From /', $buf_element) > 0) {
+ $a = split(' ', $buf_element);
+ $x = 2;
+
+ for ($i = 0; $i < count ($a); $i++) {
+ if ((preg_match('/\@|>/', $a[$i]) > 0) && $i > $x) {
+ $x = $i + 1;
+ }
+ }
+
+ for ($i = 1; $i < $x; $i++) { array_shift($a); }
+ $start = join(" ", $a);
+ } else {
+ list($key, $val) = preg_split('/\: ?/', $buf_element, 2);
+ $new[$key] = $val;
+ }
+ }
+
+ if ($rowclass == "qrowEven") {
+ $rowclass = "qrowOdd";
+ } else {
+ $rowclass = "qrowEven";
+ }
+
+ $new['alert'] = $alert;
+
+ if ($alert) { $rowclass="qrowAlert"; }
+
+ $new['Sub2'] = $new['X-DSPAM-Signature'];
+ if (strlen($new['Subject']) > $CONFIG['MAX_COL_LEN']) {
+ $new['Subject'] = substr($new['Subject'], 0, $CONFIG['MAX_COL_LEN']) . "...";
+ }
+
+ if (strlen($new['From']) > $CONFIG['MAX_COL_LEN']) {
+ $new['From'] = substr($new['From'], 0, $CONFIG['MAX_COL_LEN']) . "...";
+ }
+
+ if ($new['Subject'] == "") {
+ $new['Subject'] = "<None Specified>";
+ }
+
+ //$new->{'rating'} = $new->{'X-DSPAM-Probability'} * $new->{'X-DSPAM-Confidence'};
+ $new['rating'] = $new['X-DSPAM-Confidence'];
+
+ foreach(array_keys($new) as $key) {
+ if ($key == "X-DSPAM-Signature") { continue; }
+ preg_replace('/</', '/\&lt\;/', $new[$key]);
+ preg_replace('/>/', '/\&gt\;/', $new[$key]);
+ }
+
+ array_push($headings, $new);
+
+ $buffer = array();
+ $mode = "";
+ continue;
+ } // end while (!feof($fd))
+
+ if (! isset($sortBy) || $sortBy == "") {
+ $sortBy = $CONFIG['SORT_DEFAULT'];
+ }
+ if ($sortBy == "Rating") {
+ usort($headings, "sortByRating");
+ }
+ if ($sortBy == "Subject") {
+ usort($headings, "sortBySubject");
+ }
+ if ($sortBy == "From") {
+ usort($headings, "sortByFrom");
+ }
+ if ($sortBy == "Date") {
+ array_reverse ($headings);
+ }
+
+ /*
+
+ <tr>
+ <td align="left" valign="top" class="listtopic" width="8%">&nbsp;</td>
+ <td align="left" valign="top" class="listtopic" width="5%" onclick="sortmsg('Rating');" style="cursor: pointer;">Rating</td>
+ <td align="left" valign="top" class="listtopic" width="20%" onclick="sortmsg('Date');" style="cursor: pointer;">Date</td>
+ <td align="left" valign="top" class="listtopic" width="25%" onclick="sortmsg('From');" style="cursor: pointer;">From</td>
+ <td align="left" valign="top" class="listtopic" width="42%" onclick="sortmsg('Subject');" style="cursor: pointer;">Subject</td>
+ </tr>
+
+ */
+
+ $DATA['SORTBY'] = $sortBy;
+ $DATA['SORT_SELECTOR'] .= <<<EOD
+ <tr>
+ <td align="left" valign="top" class="listtopic" width="10%">&nbsp;</td>
+
+EOD;
+
+ if ($sortBy == "Rating") {
+ $DATA{'SORT_SELECTOR'} .= "<td align=\"left\" valign=\"top\" class=\"listtopic\" width=\"5%\" onclick=\"sortmsg('Rating');\" style=\"cursor: pointer;\">Rating&nbsp;&nbsp;&loz;</td>";
+ } else {
+ $DATA{'SORT_SELECTOR'} .= "<td align=\"left\" valign=\"top\" class=\"listtopic\" width=\"5%\" onclick=\"sortmsg('Rating');\" style=\"cursor: pointer;\">Rating</td>";
+ }
+ if ($sortBy == "Date") {
+ $DATA{'SORT_SELECTOR'} .= "<td align=\"left\" valign=\"top\" class=\"listtopic\" width=\"20%\" onclick=\"sortmsg('Date');\" style=\"cursor: pointer;\">Date&nbsp;&nbsp;&loz;</td>";
+ } else {
+ $DATA{'SORT_SELECTOR'} .= "<td align=\"left\" valign=\"top\" class=\"listtopic\" width=\"20%\" onclick=\"sortmsg('Date');\" style=\"cursor: pointer;\">Date</td>";
+ }
+ if ($sortBy == "Subject") {
+ $DATA{'SORT_SELECTOR'} .= "<td align=\"left\" valign=\"top\" class=\"listtopic\" width=\"40%\" onclick=\"sortmsg('Subject');\" style=\"cursor: pointer;\">Subject&nbsp;&nbsp;&loz;</td>";
+ } else {
+ $DATA{'SORT_SELECTOR'} .= "<td align=\"left\" valign=\"top\" class=\"listtopic\" width=\"40%\" onclick=\"sortmsg('Subject');\" style=\"cursor: pointer;\">Subject</td>";
+ }
+ if ($sortBy == "From") {
+ $DATA{'SORT_SELECTOR'} .= "<td align=\"left\" valign=\"top\" class=\"listtopic\" width=\"25%\" onclick=\"sortmsg('From');\" style=\"cursor: pointer;\">From&nbsp;&nbsp;&loz;</td>";
+ } else {
+ $DATA{'SORT_SELECTOR'} .= "<td align=\"left\" valign=\"top\" class=\"listtopic\" width=\"25%\" onclick=\"sortmsg('From');\" style=\"cursor: pointer;\">From</td>";
+ }
+
+ $DATA{'SORT_SELECTOR'} .= "\n </tr>";
+
+ if (isset($qPerPage) && $qPerPage > 0) {
+ $CONFIG['QUARANTINE_PER_PAGE'] = $qPerPage;
+ }
+
+ if (isset($currentPage) && isset($CONFIG['QUARANTINE_PER_PAGE'])) {
+ $pages = ceil( (count ($headings) / $CONFIG['QUARANTINE_PER_PAGE']) );
+ $begin = (($currentPage - 1) * $CONFIG['QUARANTINE_PER_PAGE']);
+ $ranges = ceil ($pages / $CONFIG['QNAV_BUTTONS']);
+
+ /* Now lets just keep the information that we really need. */
+ $headings = array_splice ($headings, $begin, $CONFIG['QUARANTINE_PER_PAGE']);
+ }
+
+ $rowclass = "qrowEven";
+ foreach ($headings as $row) {
+ $rating = sprintf("%3.0f%%", $row['rating'] * 100.0);
+ if ($row['rating'] > 0.8) {
+ $markclass = "high";
+ } else {
+ if ($row['rating'] < 0.7) {
+ $markclass = "low";
+ } else {
+ $markclass = "medium";
+ }
+ }
+
+ $PAIRS = array();
+
+ $PAIRS['signatureID'] = $row['X-DSPAM-Signature'];
+ $PAIRS['command'] = "viewMessage";
+ $PAIRS['user'] = $CURRENT_USER;
+ $PAIRS['page'] = $currentPage;
+ $PAIRS['sortby'] = $sortBy;
+ $PAIRS['qperpage'] = $CONFIG['QUARANTINE_PER_PAGE'];
+ // $PAIRS['template'] = "quarantine";
+
+ $url = SafeVars($PAIRS);
+ $sender = htmlentities ($row['From']);
+ $rsubject = htmlentities ($row['Subject']);
+
+ if ($row['alert']) {
+ $outclass = "qrowAlert";
+ } else {
+ $outclass = $rowclass;
+ }
+
+ $ptfields = preg_split('/\s+/', $row['X-DSPAM-Processed']);
+ $times = preg_split('/\:/', $ptfields[3]);
+ $ptime = "";
+ if($CONFIG["DATE_FORMAT"]) {
+ $month = array();
+ $month['Jan'] = 0;
+ $month['Feb'] = 1;
+ $month['Mar'] = 2;
+ $month['Apr'] = 3;
+ $month['May'] = 4;
+ $month['Jun'] = 5;
+ $month['Jul'] = 6;
+ $month['Aug'] = 7;
+ $month['Sep'] = 8;
+ $month['Oct'] = 9;
+ $month['Nov'] = 10;
+ $month['Dec'] = 11;
+ $ptime = strftime($CONFIG["DATE_FORMAT"],
+ mktime($times[2],
+ $times[1],
+ $times[0],
+ $ptfields[2],
+ $month[$ptfields[1]],
+ $ptfields[4] - 1900));
+ } else {
+ $mer = "a";
+ if ($times[0] > 12) { $times[0] -= 12; $mer = "p"; }
+ if ($times[0] == 0) { $times[0] = "12"; }
+ $ptime = "{$ptfields[1]} {$ptfields[2]} {$times[0]}:{$times[1]}{$mer}";
+ }
+
+ /*
+
+ <tr>
+ <td align="left" valign="top" class="vncell">
+ <input type="checkbox" class="formfld" title="check" alt="check" name="chkmsg" id="" />
+ </td>
+ <td align="left" valign="top" class="vncell">
+ <span style="color: darkblue; font-weight: bold;">50%</span>
+ </td>
+ <td align="left" valign="top" class="vncell">Apr 1 05:59a</td>
+ <td align="left" valign="top" class="vncell">Mar 30 11:08a</td>
+ <td align="left" valign="top" class="vncell">
+ <u>Last chance to register for Frankfurt, 4 April BEA...</u>
+ </td>
+ </tr>
+
+ <tr>
+ <td align="left" valign="top" class="{$outclass}" nowrap="true">
+ <input type="checkbox" class="formfld" title="check" alt="check" name="{$row['X-DSPAM-Signature']}" id="{$row['X-DSPAM-Signature']}" />
+ </td>
+ <td align="left" valign="top" class="{$outclass} {$markclass}" nowrap="true">
+ {$rating}
+ </td>
+ <td align="left" valign="top" class="{$outclass}" nowrap="true">{$ptime}</td>
+ <td align="left" valign="top" class="{$outclass}" nowrap="true">{$row['From']}</td>
+ <td align="left" valign="top" class="{$outclass}" nowrap="true">
+ <a href="{$CONFIG['ME']}?{$url}">{$row['Subject']}</a>
+ </td>
+ </tr>
+ */
+
+ $DATA['QUARANTINE'] .= <<<EOD
+ <tr>
+ <td align="left" valign="top" class="{$outclass}" nowrap="true">
+ <input type="checkbox" class="formfld" title="check" alt="check" name="chkmsg-{$row['X-DSPAM-Signature']}" id="{$row['X-DSPAM-Signature']}" />
+ </td>
+ <td align="left" valign="top" class="{$outclass} {$markclass}" nowrap="true">
+ {$rating}
+ </td>
+ <td align="left" valign="top" class="{$outclass}" nowrap="true">{$ptime}</td>
+ <td align="left" valign="top" class="{$outclass}" nowrap="true">{$sender}</td>
+ <td align="left" valign="top" class="{$outclass}" nowrap="true">
+ <a href="/dspam-viewmsg.php?{$url}">{$rsubject}</a>
+ </td>
+ </tr>
+
+EOD;
+
+ if ($rowclass == "qrowEven") {
+ $rowclass = "qrowOdd";
+ } else {
+ $rowclass = "qrowEven";
+ }
+ } // end foreach ($headings as $row)
+
+ /* prepare quarantine navbar */
+ if (($currentPage - 1) >= 1) { $previousPage = $currentPage - 1; }
+ else { $previousPage = 1; }
+
+ if (($currentPage + 1) <= $pages) { $nextPage = $currentPage + 1; }
+ else { $nextPage = $pages; }
+
+ $quarantineFooterBegin = <<<EOD
+ <tr>
+ <td align="left" valign="top" class="listtopic">
+ <input type="checkbox" class="formfld" title="check all" alt="check all" name="checkall" id="checkall" onClick="checkallmsgs();" />
+ <label for="checkall">All</label>
+ </td>
+ <td align="right" valign="middle" class="listtopic" colspan="4">
+ <span class="qnavbtn" onmouseover="this.style.backgroundColor='#A5B9E1;'" onmouseout="this.style.backgroundColor='#507DCD;'" title="First Page (1)"><a href="/dspam-quarantine.php?page=1&qperpage={$CONFIG['QUARANTINE_PER_PAGE']}" title="First Page (1)">|&lt;</a></span>&nbsp;
+ <span class="qnavbtn" onmouseover="this.style.backgroundColor='#A5B9E1;'" onmouseout="this.style.backgroundColor='#507DCD;'" title="Page {$previousPage}"><a href="/dspam-quarantine.php?page={$previousPage}&qperpage={$CONFIG['QUARANTINE_PER_PAGE']}" title="Page {$previousPage}">&lt;</a></span>&nbsp;
+
+EOD;
+
+ $quarantineFooterEnd = <<<EOD
+ <span class="qnavbtn" onmouseover="this.style.backgroundColor='#A5B9E1;'" onmouseout="this.style.backgroundColor='#507DCD;'" title="Page {$nextPage}"><a href="/dspam-quarantine.php?page={$nextPage}&qperpage={$CONFIG['QUARANTINE_PER_PAGE']}" title="Page {$nextPage}">&gt;</a></span>&nbsp;
+ <span class="qnavbtn" onmouseover="this.style.backgroundColor='#A5B9E1;'" onmouseout="this.style.backgroundColor='#507DCD;'" title="Last Page ({$pages})"><a href="/dspam-quarantine.php?page={$pages}&qperpage={$CONFIG['QUARANTINE_PER_PAGE']}" title="Last Page ({$pages})">&gt;|</a></span>
+ </td>
+ </tr>
+
+EOD;
+
+ $ranges_array = array();
+ $rpages = $pages;
+ for ($i = 0; $i < $ranges; $i++) {
+ $range = array();
+ $range['start'] = (($i + 1)* $CONFIG['QNAV_BUTTONS']) - ($CONFIG['QNAV_BUTTONS'] - 1);
+
+ if (($i + 1) == $ranges) {
+ $range['end'] = ($range['start'] + $rpages) - 1;
+ } else {
+ $range['end'] = (($i + 1)* $CONFIG['QNAV_BUTTONS']);
+ $rpages -= $CONFIG['QNAV_BUTTONS'];
+ }
+
+ $ranges_array[$i] = $range;
+ }
+
+ /* generate nav buttons */
+ foreach($ranges_array as $range){
+ if ($currentPage >= $range['start'] && $currentPage <= $range['end']) {
+ for ($i = $range['start']; ; $i++) {
+ if ($i > $range['end']) {
+ break;
+ } else {
+ if ($i == $currentPage) {
+ $quarantineFooter .= "<span class=\"qnavbtnhl\">{$i}</span>&nbsp\n";
+ } else {
+ $quarantineFooter .= "<span class=\"qnavbtn\" onmouseover=\"this.style.backgroundColor='#A5B9E1;'\" onmouseout=\"this.style.backgroundColor='#507DCD;'\" title=\"Page {$i}\"><a href=\"/dspam-quarantine.php?page={$i}&qperpage={$CONFIG['QUARANTINE_PER_PAGE']}\" title=\"Page {$i}\">{$i}</a></span>&nbsp\n";
+ }
+ }
+ }
+ }
+ }
+
+ $DATA['QUARANTINE_FOOTER'] = $quarantineFooterBegin . $quarantineFooter .$quarantineFooterEnd;
+ $DATA['QPAGES'] = $pages;
+ $DATA['QPAGE'] = $currentPage;
+ } else {
+ $input_errors[] = "Unable to open DSPAM quarantine mailbox at »{$USER}.mbox«. " .
+ "If you are a DSPAM admin user you can savely " .
+ "ignore this error because such users usually do not " .
+ "have a DSPAM mailbox/quarantine.";
+ }
+
+ return $input_errors;
+}
+
+/* ========================================================================== */
+/* = P E R F O R M A N C E F U N C T I O N S = */
+/* ========================================================================== */
+
+function ResetStats() {
+ global $USER;
+
+ $fd = fopen("{$USER}.stats", "r");
+ $ts = chop(fgets($fd, 4096));
+ $group = chop(fgets($fd, 4096));
+ fclose($fd);
+ list($ts, $ti, $tm, $fp, $sc, $ic) = split(",", $ts);
+
+ if ($group <> "") {
+ $GROUP = GetPath($group) . ".stats";
+ $fd = fopen("{$GROUP}", "r");
+ $gts = chop(fgets($fd, 4096));
+ fclose($fd);
+ list ($gts, $gti, $gtm, $gfp, $gsc, $gic) = split(",", $gts);
+ $ts -= $gts;
+ $ti -= $gti;
+ $tm -= $gtm;
+ $fp -= $gfp;
+ $sc -= $gsc;
+ $ic -= $gic;
+ }
+
+ $fd = fopen("{$USER}.rstats", "w");
+ fputs($fd, "{$ts}" . "," . "{$ti}" . "," . "{$tm}" . "," .
+ "{$fp}" . "," . "{$sc}" . "," . "{$ic}\n");
+ fclose($fd);
+}
+
+function Tweak() {
+ global $USER;
+
+ $fd = fopen("{$USER}.rstats", "r");
+ $ts = chop(fgets($fd, 4096));
+ $group = chop($fgets($fd, 4096));
+ fclose($fd);
+ list($ts, $ti, $tm, $fp, $sc, $ic) = split(",", $ts);
+ $tm++;
+
+ $fd = fopen("{$USER}.rstats", "w");
+ fputs($fd, "{$ts},{$ti},{$tm},{$fp},{$sc},{$ic}\n");
+ fclose($fd);
+}
+
+function &DisplayIndex() {
+ global $USER, $CONFIG, $DATA, $CURRENT_STORE, $CURRENT_USER;
+
+ if (strpos ($CURRENT_USER, "@") === false) {
+ if (GetDomain($CURRENT_STORE) <> "")
+ $domain = GetDomain($CURRENT_STORE);
+ else
+ $domain = $config['system']['domain'];
+
+ $spamalias = "spam-{$CURRENT_USER}@{$domain}";
+ } else {
+ $spamalias = "spam-{$CURRENT_USER}";
+ }
+
+ if ($handle = @fopen ("{$USER}.stats", "r")) {
+ $spam .= chop(fgets($handle, 4096));
+ $group .= chop(fgets($handle, 4096));
+ fclose($handle);
+ list($spam, $innocent, $misses, $fp, $sc, $ic) = split(",", $spam);
+
+ if ($group <> "") {
+ $GROUP = GetPath($group) . ".stats";
+ $fd = fopen("{$GROUP}", "r");
+ $gspam = chop(fgets($fd, 4096));
+ fclose($fd);
+
+ list($gspam, $ginnocent, $gfp, $gmisses, $gsc, $gic) = preg_split('/\,/', $gspam);
+ $spam -= $gspam;
+ $innocent -= $ginnocent;
+ $misses -= $gmisses;
+ $fp -= $gfp;
+ $sc -= $gsc;
+ $ic -= $gic;
+ }
+
+ if ($spam + $innocent > 0) {
+ $ratio = sprintf("%2.3f",
+ (($spam+$misses)/($spam+$misses+$fp+$innocent)*100));
+ } else {
+ $ratio = 0;
+ }
+
+ if (file_exists("{$USER}.rstats")) {
+ $handle = fopen ("{$USER}.rstats", "r");
+ $buffer = chop(fgets($handle, 4096));
+
+ fclose ($handle);
+
+ list($rts, $rti, $rtm, $rfp) = split(",", $buffer);
+
+ $real_missed = $misses - $rtm;
+ $real_caught = $spam - $rts;
+ $real_fp = $fp - $rfp;
+
+ if ($real_fp < 0) { $real_fp = 0; }
+
+ $real_innocent = $innocent - $rti;
+
+ if (($spam - $rts > 0) && ($spam - $rts + $misses - $rtm != 0) &&
+ ($real_caught + $real_missed > 0) && ($real_fp + $real_innocent > 0)) {
+ $monthly = sprintf("%2.3f",
+ (100.0-(($real_missed)/($real_caught+$real_missed))*100.0));
+ $overall = sprintf("%2.3f",
+ (100-((($real_missed+$real_fp) /
+ ($real_fp+$real_innocent+$real_caught+$real_missed))*100)));
+ } else {
+ if ($real_caught == 0 && $real_missed > 0) {
+ $monthly = 0;
+ $overall = 0;
+ } else {
+ $monthly = 100;
+ $overall = 100;
+ }
+ }
+
+ if ($real_fp + $real_innocent > 0) {
+ $fpratio = sprintf("%2.3f", ($real_fp/($real_fp+$real_innocent)*100));
+ } else {
+ $fpratio = 0;
+ }
+
+ } else {
+ $rts = $spam + $misses;
+ $rti = $innocent;
+ $rtm = $misses;
+ $rfp = $fp;
+
+ $handle = fopen ("{$USER}.rstats", "w");
+ fwrite("{$rts},{$rti},{$rtm},{$rfp}\n");
+ fclose($handle);
+
+ $monthly = "N/A";
+ $fpratio = "N/A";
+ $overall = "N/A";
+ }
+
+ $DATA['TIME'] = $time;
+ $DATA['TOTAL_SPAM_SCANNED'] = $spam;
+ $DATA['TOTAL_SPAM_LEARNED'] = $misses;
+ $DATA['TOTAL_NONSPAM_SCANNED'] = $innocent;
+ $DATA['TOTAL_NONSPAM_LEARNED'] = $fp;
+ $DATA['SPAM_RATIO'] = $ratio;
+ $DATA['SPAM_ACCURACY'] = $monthly;
+ $DATA['NONSPAM_ERROR_RATE'] = $fpratio;
+ $DATA['OVERALL_ACCURACY'] = $overall;
+ $DATA['TOTAL_SPAM_CORPUSFED'] = $sc;
+ $DATA['TOTAL_NONSPAM_CORPUSFED'] = $ic;
+ $DATA['TOTAL_SPAM_MISSED'] = $real_missed;
+ $DATA['TOTAL_SPAM_CAUGHT'] = $real_caught;
+ $DATA['TOTAL_NONSPAM_MISSED'] = $real_fp;
+ $DATA['TOTAL_NONSPAM_CAUGHT'] = $real_innocent;
+ $DATA['SPAM_ALIAS'] = $spamalias;
+
+ $DATA['LOCAL_DOMAIN'] = $CONFIG['LOCAL_DOMAIN'];
+ } else {
+ $DATA['SPAM_ACCURACY'] = "N/A";
+ $DATA['NONSPAM_ERROR_RATE'] = "N/A";
+ $DATA['OVERALL_ACCURACY'] = "N/A";
+ $DATA['SPAM_RATIO'] = "N/A";
+ $DATA['TOTAL_SPAM_MISSED'] = 0;
+ $DATA['TOTAL_SPAM_CAUGHT'] = 0;
+ $DATA['SPAM_RATIO'] = "N/A";
+ $DATA['TOTAL_NONSPAM_MISSED'] = 0;
+ $DATA['TOTAL_NONSPAM_CAUGHT'] = 0;
+ $DATA['NONSPAM_ERROR_RATE'] = "N/A";
+ $DATA['TOTAL_SPAM_LEARNED'] = 0;
+ $DATA['TOTAL_SPAM_SCANNED'] = 0;
+ $DATA['TOTAL_NONSPAM_LEARNED'] = 0;
+ $DATA['TOTAL_NONSPAM_SCANNED'] = 0;
+ $DATA['TOTAL_SPAM_CORPUSFED'] = 0;
+ $DATA['TOTAL_NONSPAM_CORPUSFED'] = 0;
+ $DATA['SPAM_ALIAS'] = $spamalias;
+
+ $input_errors[] = "Unable to open DSPAM stats at »{$USER}.stats«. " .
+ "If you are a DSPAM admin user you can savely " .
+ "ignore this error because such users usually do not " .
+ "have a DSPAM mailbox/quarantine.";
+ }
+
+ return $input_errors;
+}
+
+function getJScriptFunction($whichOne = 0) {
+ $changeuser_msg = gettext("Do you realy want to change the current user?") . "\\n" .
+ gettext("This requires a logout followed by a login.");
+
+ switch ($whichOne) {
+ case 0:
+ $scriptstr = '
+
+ /* applicable for almost any dspam related page */
+ function changeuser() {
+ check = confirm("' . $changeuser_msg . '");
+
+ if (check == true)
+ window.location.href = "/index.php?logout=true";
+ }
+ ';
+
+ break;
+ case 1:
+ $scriptstr = '
+
+ /* applicable for dspam-quarantine.php */
+ function checkallmsgs(enable) {
+ var endis = (document.iform.checkall.checked || enable);
+ var elem = document.iform.elements.length;
+
+ for (i = 0; i < elem; i++) {
+ if (document.iform.elements[i].name.indexOf("chkmsg") >= 0) {
+ document.iform.elements[i].checked = endis;
+ }
+ }
+ }
+ ';
+
+ break;
+ case 2:
+ $scriptstr = '
+
+ /* applicable for dspam-quarantine.php */
+ function sortmsg(criterion) {
+ var baseURL = "/dspam-quarantine.php?page=" + document.iform.qpage.value;
+ var qperpage = document.getElementsByName("qperpage")[0].value;
+
+ window.location.href = baseURL + "&qperpage=" + qperpage + "&sortby=" + criterion;
+ }
+ ';
+
+ break;
+ case 3:
+ $scriptstr = '
+
+ /* applicable for dspam-quarantine.php */
+ function processmsg(what) {
+ var elem = document.iform.elements.length;
+ var checked = false;
+
+ switch (what) {
+ case 0:
+ for (i = 0; i < elem; i++) {
+ if (document.iform.elements[i].name.indexOf("chkmsg") >= 0 &&
+ document.iform.elements[i].checked == true) {
+ checked = true;
+ break;
+ }
+ }
+
+ if (checked) {
+ document.iform.processAction.value = "manyNotSpam";
+ } else {
+ alert("You did not select any message that should be processed as not beeing Spam.");
+ return false;
+ }
+ break;
+ case 1:
+ for (i = 0; i < elem; i++) {
+ if (document.iform.elements[i].name.indexOf("chkmsg") >= 0 &&
+ document.iform.elements[i].checked == true) {
+ checked = true;
+ break;
+ }
+ }
+
+ if (checked) {
+ if (confirm("Are you sure you want to delete SELECTED messages in quarantine?") == false) {
+ return false;
+ } else {
+ document.iform.processAction.value = "manySpam";
+ }
+ } else {
+ alert("You did not select any message that should be processed as beeing Spam.");
+ return false;
+ }
+ break;
+ case 2:
+ if (confirm("Are you sure you want to delete ALL messages in quarantine?") == false) {
+ return false;
+ } else {
+ document.iform.processAction.value = "deleteAll";
+ }
+ break;
+ }
+
+ document.iform.submit();
+ }
+ ';
+
+ break;
+ case 4:
+ $scriptstr = '
+
+ /* applicable for dspam-quarantine.php nad dspam-history.php */
+ function changeQPerPage(originator) {
+ var elementName = "";
+ var baseURL = "";
+
+ if (originator.name == "qperpage") {
+ baseURL = "/dspam-quarantine.php?page=" + document.iform.qpage.value;
+ elementName = "qperpage";
+ } else {
+ baseURL = "/dspam-history.php?page=" + document.iform.hpage.value;
+ elementName = "hperpage";
+ }
+
+ for (var i = 0; i < 2; i++) {
+ document.getElementsByName(elementName)[i].value = originator.value;
+ }
+
+ if (originator.name == "qperpage")
+ window.location.href = baseURL + "&qperpage=" + originator.value;
+ else
+ window.location.href = baseURL + "&hperpage=" + originator.value;
+ }
+ ';
+
+ break;
+ case 5:
+ $scriptstr = '
+
+ /* applicable for dspam-settings.php */
+
+ function fadeTableRow(rowid, fadeType, opts){
+ if(!opts){
+ opts = {};
+ }
+
+ var row = $(rowid);
+ var cells= row.childNodes;
+ for(i=0;i<cells.length;i++){
+ if(cells[i].tagName == "TD"){
+ if (fadeType == 0)
+ new Effect.Fade(cells[i],opts);
+ else
+ new Effect.Appear(cells[i],opts);
+ }
+ }
+ if (fadeType == 0)
+ new Effect.Fade(row,opts);
+ else
+ new Effect.Appear(row,opts);
+ }
+
+ function toggleDSPAMDomain(enable_over, originator) {
+ var endis = !(originator.checked || enable_over);
+
+ if (endis) {
+ fadeTableRow("emailnotitb", 1);
+ } else {
+ fadeTableRow("emailnotitb", 0);
+ }
+ }
+
+ function toggleDBSettings(idx) {
+ if (idx)
+ idx = idx;
+ else
+ idx = document.iform.sdriver.selectedIndex;
+
+ switch (idx) {
+ case 0:
+ fadeTableRow("DBmysql", 1);
+ fadeTableRow("DBsqlite", 0);
+ fadeTableRow("DBbdb", 0);
+ fadeTableRow("DBpgsql", 0);
+ fadeTableRow("DBoracle", 0);
+ fadeTableRow("DBhash", 0);
+ break;
+ case 1:
+ fadeTableRow("DBmysql", 0);
+ fadeTableRow("DBsqlite", 1);
+ fadeTableRow("DBbdb", 0);
+ fadeTableRow("DBpgsql", 0);
+ fadeTableRow("DBoracle", 0);
+ fadeTableRow("DBhash", 0);
+ break;
+ case 2:
+ fadeTableRow("DBmysql", 0);
+ fadeTableRow("DBsqlite", 0);
+ fadeTableRow("DBbdb", 1);
+ fadeTableRow("DBpgsql", 0);
+ fadeTableRow("DBoracle", 0);
+ fadeTableRow("DBhash", 0);
+ break;
+ case 3:
+ fadeTableRow("DBmysql", 0);
+ fadeTableRow("DBsqlite", 0);
+ fadeTableRow("DBbdb", 0);
+ fadeTableRow("DBpgsql", 1);
+ fadeTableRow("DBoracle", 0);
+ fadeTableRow("DBhash", 0);
+ break;
+ case 4:
+ fadeTableRow("DBmysql", 0);
+ fadeTableRow("DBsqlite", 0);
+ fadeTableRow("DBbdb", 0);
+ fadeTableRow("DBpgsql", 0);
+ fadeTableRow("DBoracle", 1);
+ fadeTableRow("DBhash", 0);
+ break;
+ case 5:
+ fadeTableRow("DBmysql", 0);
+ fadeTableRow("DBsqlite", 0);
+ fadeTableRow("DBbdb", 0);
+ fadeTableRow("DBpgsql", 0);
+ fadeTableRow("DBoracle", 0);
+ fadeTableRow("DBhash", 1);
+ break;
+ }
+ }
+
+ function enable_change(enable_over, originator) {
+ var endis;
+
+ switch (originator) {
+ case 0:
+ endis = !(document.iform.enabledbg.checked || enable_over);
+ endis ? document.iform.debug.style.backgroundColor = "#D4D0C8" : document.iform.debug.style.backgroundColor = "#FFFFFF";
+ document.iform.debug.disabled = endis;
+ endis ? document.iform.dopt.style.backgroundColor = "#D4D0C8" : document.iform.dopt.style.backgroundColor = "#FFFFFF";
+ document.iform.dopt.disabled = endis;
+ case 1:
+ endis = !(document.iform.enableldap.checked || enable_over);
+ document.iform.ldapmode.disabled = endis;
+ endis ? document.iform.ldaphost.style.backgroundColor = "#D4D0C8" : document.iform.ldaphost.style.backgroundColor = "#FFFFFF";
+ document.iform.ldaphost.disabled = endis;
+ endis ? document.iform.ldapfilter.style.backgroundColor = "#D4D0C8" : document.iform.ldapfilter.style.backgroundColor = "#FFFFFF";
+ document.iform.ldapfilter.disabled = endis;
+ endis ? document.iform.ldapbase.style.backgroundColor = "#D4D0C8" : document.iform.ldapbase.style.backgroundColor = "#FFFFFF";
+ document.iform.ldapbase.disabled = endis;
+ case 2:
+ endis = !(document.iform.enablesbl.checked || enable_over);
+ endis ? document.iform.sblhost.style.backgroundColor = "#D4D0C8" : document.iform.sblhost.style.backgroundColor = "#FFFFFF";
+ document.iform.sblhost.disabled = endis;
+ case 3:
+ endis = !(document.iform.enableclam.checked || enable_over);
+ endis ? document.iform.clamport.style.backgroundColor = "#D4D0C8" : document.iform.clamport.style.backgroundColor = "#FFFFFF";
+ document.iform.clamport.disabled = endis;
+ endis ? document.iform.clamhost.style.backgroundColor = "#D4D0C8" : document.iform.clamhost.style.backgroundColor = "#FFFFFF";
+ document.iform.clamhost.disabled = endis;
+ document.iform.clamresp.disabled = endis;
+ case 4:
+ endis = !(document.iform.enabledsclient.checked || enable_over);
+ endis ? document.iform.dsclhost.style.backgroundColor = "#D4D0C8" : document.iform.dsclhost.style.backgroundColor = "#FFFFFF";
+ document.iform.dsclhost.disabled = endis;
+ endis ? document.iform.dsclport.style.backgroundColor = "#D4D0C8" : document.iform.dsclport.style.backgroundColor = "#FFFFFF";
+ document.iform.dsclport.disabled = endis;
+ endis ? document.iform.dsclident.style.backgroundColor = "#D4D0C8" : document.iform.dsclident.style.backgroundColor = "#FFFFFF";
+ document.iform.dsclident.disabled = endis;
+ case 5:
+ endis = !(document.iform.tcpipdel.checked || enable_over);
+ endis ? document.iform.dhost.style.backgroundColor = "#D4D0C8" : document.iform.dhost.style.backgroundColor = "#FFFFFF";
+ document.iform.dhost.disabled = endis;
+ endis ? document.iform.dport.style.backgroundColor = "#D4D0C8" : document.iform.dport.style.backgroundColor = "#FFFFFF";
+ document.iform.dport.disabled = endis;
+ endis ? document.iform.dident.style.backgroundColor = "#D4D0C8" : document.iform.dident.style.backgroundColor = "#FFFFFF";
+ document.iform.dident.disabled = endis;
+ document.iform.delproto.disabled = endis;
+ case 6:
+ endis = !(document.iform.enablenoti.checked || enable_over);
+ document.iform.whichdomain.disabled = endis;
+ endis ? document.iform.dspamdomain.style.backgroundColor = "#D4D0C8" : document.iform.dspamdomain.style.backgroundColor = "#FFFFFF";
+ document.iform.dspamdomain.disabled = endis;
+ endis ? document.iform.dspamcontact.style.backgroundColor = "#D4D0C8" : document.iform.dspamcontact.style.backgroundColor = "#FFFFFF";
+ document.iform.dspamcontact.disabled = endis;
+ }
+ }
+ ';
+
+ break;
+ case 6:
+ $scriptstr = '
+
+ function checkDisabledState(form) {
+ for (i = 0; i < form.elements.length; i++) {
+ if (form.elements[i].disabled && form.elements[i].type == "text")
+ form.elements[i].style.backgroundColor = "#D4D0C8";
+ else if (form.elements[i].type == "text")
+ form.elements[i].style.backgroundColor = "#FFFFFF";
+ }
+ }
+ ';
+
+ break;
+ }
+
+ return $scriptstr;
+}
+
+?>
diff --git a/config/dspam/pkg/dspam-pkgfunc.inc b/config/dspam/pkg/dspam-pkgfunc.inc
new file mode 100644
index 00000000..31a7fa06
--- /dev/null
+++ b/config/dspam/pkg/dspam-pkgfunc.inc
@@ -0,0 +1,548 @@
+<?php
+/* $Id$ */
+/* Copyright (C) 2006 Daniel S. Haischt */
+require_once("functions.inc");
+require_once("dspam.inc");
+
+function sync_package_dspam() {
+ global $config, $g;
+ conf_mount_rw();
+ config_lock();
+ $fd = fopen("/etc/dspam.conf","w");
+
+ $dspamcfg = <<<EOD
+## dspam.conf -- DSPAM configuration file
+## Generated by pfSense
+Home /var/db/dspam
+## Database Settings
+StorageDriver /usr/local/lib/libmysql_drv.so
+MySQLServer /tmp/mysql.sock
+MySQLPort
+MySQLUser dspam
+MySQLPass dspam
+MySQLDb dspam
+MySQLCompress true
+MySQLSupressQuote off
+MySQLConnectionCache 10
+MySQLUIDInSignature on
+## Delivery Settings
+TrustedDeliveryAgent "/usr/bin/mail"
+DeliveryHost 192.168.1.6
+DeliveryPort 24
+DeliveryIdent localhost
+DeliveryProto smtp
+OnFail error
+## DSPAM Privileges
+Trust root
+Trust mail
+Trust mailnull
+Trust smmsp
+Trust daemon
+## DSPAM Engine Settings
+TrainingMode teft
+TestConditionalTraining on
+Feature chained
+Feature whitelist
+Algorithm graham burton
+PValue graham
+ImprobabilityDrive on
+Preference "spamAction=quarantine"
+Preference "signatureLocation=message"
+Preference "showFactors=on"
+AllowOverride trainingMode
+AllowOverride spamAction spamSubject
+AllowOverride statisticalSedation
+AllowOverride enableBNR
+AllowOverride enableWhitelist
+AllowOverride signatureLocation
+AllowOverride showFactors
+AllowOverride optIn optOut
+AllowOverride whitelistThreshold
+## Miscellaneous Settings
+FailoverAttempts 1
+IgnoreHeader X-Spam-Scanned
+IgnoreHeader X-Spam-Status
+IgnoreHeader X-Virus-Scanner-Result
+RBLInoculate on
+Notifications on
+## Maintainance Settings
+PurgeSignatures 14
+PurgeNeutral 90
+PurgeUnused 90
+PurgeHapaxes 30
+PurgeHits1S 15
+PurgeHits1I 15
+## System Settings
+LocalMX 127.0.0.1
+SystemLog on
+UserLog on
+Opt out
+ParseToHeaders on
+ChangeModeOnParse on
+ChangeUserOnParse on
+Broken returnCodes
+Broken case
+Broken lineStripping
+MaxMessageSize 307200
+ProcessorBias on
+## ClamAV Engine Settings
+ClamAVPort 3310
+ClamAVHost 127.0.0.1
+ClamAVResponse accept
+## DSPAM Daemon Settings (Server)
+ServerPort 24
+ServerQueueSize 32
+ServerPID /var/run/dspam/dspam.pid
+ServerMode standard
+ServerParameters "--deliver=innocent -d %u"
+ServerIdent "abysseleven.abyssworld.de"
+ServerDomainSocketPath "/var/run/dspam/dspam.sock"
+## EOF
+
+EOD;
+
+ /* flush the default config to the file */
+ fwrite($fd, $dspamcfg);
+ fclose($fd);
+
+ $fd = fopen("/usr/local/bin/dspam_spamfeed","w");
+
+ $spamfeed = <<<EOD
+#!/bin/sh
+#
+# automatically generated by pfSense
+
+cat \${2} | dspam --mode=teft --source=corpus --class=spam --feature=chained,noise --user \${1}
+
+EOD;
+
+ fwrite($fd, $spamfeed);
+ fclose($fd);
+ mwexec("chmod a+x /usr/local/bin/dspam_spamfeed");
+
+ $fd = fopen("/usr/local/bin/dspam_innocentfeed","w");
+
+ $innocentfeed = <<<EOD
+#!/bin/sh
+#
+# automatically generated by pfSense
+
+cat \${2} | dspam --mode=teft --source=corpus --class=innocent --feature=chained,noise --user \${1}
+
+EOD;
+
+ fwrite($fd, $innocentfeed);
+ fclose($fd);
+ mwexec("chmod a+x /usr/local/bin/dspam_innocentfeed");
+
+ $start = <<<EOD
+test_dspam_user=`cat /etc/passwd | grep dspam`
+test_dspam_db=`mysql information_schema -e "select schema_name from schemata" | grep dspam`
+test_dspam_db_user=`mysql mysql -e "select User from user" | grep dspam`
+
+if [ -z "\${test_dspam_user}" ]; then
+ pw useradd dspam -u 107 -g mail -d /var/db/dspam -s /bin/csh -c 'DSPAM Daemon User'
+fi
+
+if [ ! -d "/var/run/dspam" ]; then
+ mkdir /var/run/dspam && chown dspam:mail /var/run/dspam
+fi
+
+if [ -z "\${test_dspam_db}" ]; then
+ mysql -D mysql -e "create database dspam"
+ if [ -z "\${test_dspam_db_user}" ]; then
+ mysql -D mysql -e "GRANT ALL PRIVILEGES ON dspam.* TO dspam@localhost IDENTIFIED BY 'dspam'"
+ fi
+ mysql -udspam -pdspam dspam < /usr/local/share/examples/dspam/mysql/mysql_objects-space.sql && \
+ mysql -udspam -pdspam dspam < /usr/local/share/examples/dspam/mysql/virtual_users.sql
+fi
+
+/sbin/mount_fdescfs fdescfs /dev/fd
+/usr/local/bin/dspam --daemon &
+
+EOD;
+
+ $stop = "/usr/bin/killall dspam\n" .
+ "sleep 2";
+ write_rcfile(array(
+ "file" => "dspam.sh",
+ "start" => $start,
+ "stop" => $stop
+ )
+ );
+ conf_mount_ro();
+ config_unlock();
+
+ if (! file_exists("/usr/local/etc/dspam.conf")) {
+ mwexec("ln -s /etc/dspam.conf /usr/local/etc/dspam.conf");
+ }
+
+ mwexec("/usr/local/etc/rc.d/dspam.sh stop");
+ mwexec("/usr/local/etc/rc.d/dspam.sh start");
+
+ return 0;
+}
+
+function dspam_configure() {
+ global $config, $g;
+
+ $dspamcfg = $config['installedpackages']['dspam']['config'][0];
+
+ if ($g['booting'])
+ echo "Starting DSPAM service... ";
+ else
+ sleep(1);
+
+ /* write dhcpd.conf */
+ $fd = fopen("/usr/local/etc/dspam.conf", "w");
+ if (!$fd) {
+ printf("Error: cannot open dhcpd.conf in services_dhcpd_configure().\n");
+ return 1;
+ }
+
+ $dspamconf = <<<EOD
+## dspam.conf -- DSPAM configuration file
+## Generated by pfSense
+Home /var/db/dspam
+## Database Settings
+
+EOD;
+
+ if ($dspamcfg['storage-driver'] == "mysql") {
+ $dspamconf .= "StorageDriver\t\t/usr/local/lib/libmysql_drv.so\n";
+ $dspamconf .= <<<EOD
+MySQLServer {$dspamcfg['dbsettings'][0]['mysql-server']}
+MySQLPort {$dspamcfg['dbsettings'][0]['mysql-port']}
+MySQLUser {$dspamcfg['dbsettings'][0]['mysql-user']}
+MySQLPass {$dspamcfg['dbsettings'][0]['mysql-password']}
+MySQLDb {$dspamcfg['dbsettings'][0]['mysql-database']}
+
+EOD;
+ isset($dspamcfg['dbsettings'][0]['mysql-compress']) ? $dspamconf .= "MySQLCompress\t\ttrue\n" : $dspamconf .= "MySQLCompress\tfalse\n";
+ isset($dspamcfg['dbsettings'][0]['mysql-squote']) ? $dspamconf .= "MySQLSupressQuote\ton\n" : $dspamconf .= "MySQLSupressQuote\toff\n";
+ isset($dspamcfg['dbsettings'][0]['mysql-ccache']) ? $dspamconf .= "MySQLConnectionCache\t{$dspamcfg['dbsettings'][0]['mysql-ccache']}\n" : $dspamconf .= "MySQLConnectionCache\t10\n";
+ isset($dspamcfg['dbsettings'][0]['mysql-uid']) ? $dspamconf .= "MySQLUIDInSignature\ton\n" : $dspamconf .= "MySQLUIDInSignature\toff\n";
+ } else if ($dspamcfg['storage-driver'] == "sqlite") {
+ $dspamconf .= "StorageDriver\t\t/usr/local/lib/libsqlite3_drv.so\n";
+ if (isset($dspamcfg['dbsettings'][0]['sqlite-pragma'])) $dspamconf .= "SQLitePragma\t\t{$dspamcfg['dbsettings'][0]['sqlite-pragma']}\n";
+ } else if ($dspamcfg['storage-driver'] == "pgsql") {
+ $dspamconf .= "StorageDriver\t\t/usr/local/lib/libpgsql_drv.so\n";
+ $dspamconf .= <<<EOD
+PgSQLServer {$dspamcfg['dbsettings'][0]['pgsql-server']}
+PgSQLPort {$dspamcfg['dbsettings'][0]['pgsql-port']}
+PgSQLUser {$dspamcfg['dbsettings'][0]['pgsql-user']}
+PgSQLPass {$dspamcfg['dbsettings'][0]['pgsql-password']}
+PgSQLDb {$dspamcfg['dbsettings'][0]['pgsql-database']}
+
+EOD;
+ isset($dspamcfg['dbsettings'][0]['pgsql-ccache']) ? $dspamconf .= "PgSQLConnectionCache\t{$dspamcfg['dbsettings'][0]['pgsql-ccache']}\n" : $dspamconf .= "PgSQLConnectionCache\t3\n";
+ isset($dspamcfg['dbsettings'][0]['pgsql-uid']) ? $dspamconf .= "PgSQLUIDInSignature\ton\n" : $dspamconf .= "PgSQLUIDInSignature\toff\n";
+ } else if ($dspamcfg['storage-driver'] == "oracle") {
+ $dspamconf .= "StorageDriver\t/usr/local/lib/libora_drv.so\n";
+ $dspamconf .= <<<EOD
+OraServer {$dspamcfg['dbsettings'][0]['ora-server']}
+OraUser {$dspamcfg['dbsettings'][0]['ora-user']}
+OraPass {$dspamcfg['dbsettings'][0]['ora-password']}
+OraSchema {$dspamcfg['dbsettings'][0]['ora-schema']}
+
+EOD;
+ } else if ($dspamcfg['storage-driver'] == "hash") {
+ $dspamconf .= "StorageDriver\t\t/usr/local/lib/libhash_drv.so\n";
+ $dspamconf .= <<<EOD
+HashRecMax {$dspamcfg['dbsettings'][0]['hash-rec-max']}
+HashMaxExtents {$dspamcfg['dbsettings'][0]['hash-max-ext']}
+HashExtentSize {$dspamcfg['dbsettings'][0]['hash-ext-size']}
+HashMaxSeek {$dspamcfg['dbsettings'][0]['hash-max-seek']}
+HashConnectionCache {$dspamcfg['dbsettings'][0]['hash-co-cache']}
+
+EOD;
+ isset($dspamcfg['dbsettings'][0]['hash-auto-ex']) ? $dspamconf .= "HashAutoExtend\t\ton\n" : $dspamconf .= "HashAutoExtend\toff\n";
+ if (isset($dspamcfg['dbsettings'][0]['hash-co-user'])) $dspamconf .= "HashConcurrentUser\t{$dspamcfg['dbsettings'][0]['hash-co-user']}\n";
+ }
+
+ $dspamconf .= "## Delivery Settings\n";
+
+ if ($dspamcfg['tdelivery-agent'] == "procmail") {
+ $dspamconf .= "TrustedDeliveryAgent\t\"/usr/local/bin/procmail\"\n";
+ } else if ($dspamcfg['tdelivery-agent'] == "mail") {
+ $dspamconf .= "TrustedDeliveryAgent\t\"/usr/bin/mail\"\n";
+ } else if ($dspamcfg['tdelivery-agent'] == "mail.local") {
+ $dspamconf .= "TrustedDeliveryAgent\t\"/usr/libexec/mail.local\"\n";
+ } else if ($dspamcfg['tdelivery-agent'] == "deliver") {
+ $dspamconf .= "TrustedDeliveryAgent\t\"/usr/local/cyrus/bin/deliver\"\n";
+ } else if ($dspamcfg['tdelivery-agent'] == "maildrop") {
+ $dspamconf .= "TrustedDeliveryAgent\t\"/usr/local/bin/maildrop\"\n";
+ } else if ($dspamcfg['tdelivery-agent'] == "exim") {
+ $dspamconf .= "TrustedDeliveryAgent\t\"/usr/local/sbin/exim -oMr spam-scanned\"\n";
+ }
+
+ if (isset($dspamcfg['tcpip-delivery'])) {
+ $dspamconf .= <<<EOD
+DeliveryHost {$dspamcfg['tcpip-delivery-host']}
+DeliveryPort {$dspamcfg['tcpip-delivery-port']}
+DeliveryIdent {$dspamcfg['tcpip-delivery-ident']}
+DeliveryProto {$dspamcfg['tcpip-delivery-proto']}
+
+EOD;
+ }
+
+ /* TODO: If required add the following, currently
+ missing options:
+
+ - QuarantineAgent
+ - EnablePlusedDetail
+ - QuarantineMailbox
+ */
+
+ $dspamconf .= "OnFail\t\t\t{$dspamcfg['delivery-onfail']}\n";
+ $dspamconf .= "## DSPAM Privileges\n";
+
+ $t_users = &$dspamcfg['tuser'];
+
+ foreach ($t_users as $user) {
+ $dspamconf .= "Trust\t\t\t{$user['name']}\n";
+ }
+
+ if (isset($dspamcfg['debug-enable'])) {
+ $dspamconf .= "## DSPAM Debugging Options\n";
+ $dspamconf .= "Debug\t\t\t{$dspamcfg['debug-whom']}\n";
+ $dspamconf .= "DebugOpt\t\t{$dspamcfg['debug-options']}\n";
+ }
+
+ $dspamconf .= "## DSPAM Engine Settings\n";
+ $dspamconf .= "TrainingMode\t\t{$dspamcfg['training-mode']}\n";
+ isset($dspamcfg['test-cond-training']) ? $dspamconf .= "TestConditionalTraining\ton\n" : $dspamconf .= "TestConditionalTraining\toff\n";
+
+ $t_features = &$dspamcfg['feature'];
+
+ foreach ($t_features as $feature) {
+ $dspamconf .= "Feature\t\t\t{$feature['name']}\n";
+ }
+
+ $t_algos = &$dspamcfg['algorithm'];
+
+ if (count($t_algos) > 0) {
+ $dspamconf .= "Algorithm\t\t";
+
+ foreach ($t_algos as $algo) {
+ $dspamconf .= "{$algo['name']} ";
+ }
+
+ $dspamconf .= "\n";
+ }
+
+ $dspamconf .= "PValue\t\t\t{$dspamcfg['pvalue']}\n";
+ isset($dspamcfg['improbability-drive']) ? $dspamconf .= "ImprobabilityDrive\ton\n" : $dspamconf .= "ImprobabilityDrive\toff\n";
+
+ $t_prefs = &$dspamcfg['preference'];
+
+ foreach ($t_prefs as $pref) {
+ $dspamconf .= "Preference\t\t{$pref['value']}\n";
+ }
+
+ $t_overr = &$dspamcfg['override'];
+
+ foreach ($t_overr as $over) {
+ $dspamconf .= "AllowOverride\t\t{$over['value']}\n";
+ }
+
+ if (isset($dspamcfg['ldap-enable'])) {
+ $dspamconf .= <<<EOD
+## LDAP Settings
+LDAPMode {$dspamcfg['ldap-mode']}
+LDAPHost {$dspamcfg['ldap-host']}
+LDAPFilter {$dspamcfg['ldap-filter']}
+LDAPBase {$dspamcfg['ldap-base']}
+
+EOD;
+ }
+
+ $dspamconf .= "## Miscellaneous Settings\n";
+ if (isset($dspamcfg['failover-attempts'])) $dspamconf .= "FailoverAttempts\t{$dspamcfg['failover-attempts']}\n";
+
+ $t_headers = &$dspamcfg['header'];
+
+ if (is_array($t_headers)) {
+ foreach ($t_headers as $header) {
+ $dspamconf .= "IgnoreHeader\t\t{$header['name']}\n";
+ }
+ }
+
+ if (isset($dspamcfg['sbl-enable'])) {
+ $dspamconf .= "Lookup\t\t\t\"{$dspamcfg['sbl-host']}\"\n";
+ }
+
+ isset($dspamcfg['rbl-inoculate']) ? $dspamconf .= "RBLInoculate\t\ton\n" : $dspamconf .= "RBLInoculate\toff\n";
+ isset($dspamcfg['notification-email']) ? $dspamconf .= "Notifications\t\ton\n" : $dspamconf .= "Notifications\toff\n";
+
+ $dspamconf .= <<<EOD
+## Maintainance Settings
+PurgeSignatures {$dspamcfg['purge-signatures']}
+PurgeNeutral {$dspamcfg['purge-neutral']}
+PurgeUnused {$dspamcfg['purge-unused']}
+PurgeHapaxes {$dspamcfg['purge-hapaxes']}
+PurgeHits1S {$dspamcfg['purge-hits-1s']}
+PurgeHits1I {$dspamcfg['purge-hits-1s']}
+
+EOD;
+
+ $dspamconf .= "## System Settings\n";
+ $dspamconf .= "LocalMX\t\t\t{$dspamcfg['local-mx']}\n";
+ isset($dspamcfg['system-log']) ? $dspamconf .= "SystemLog\t\ton\n" : $dspamconf .= "SystemLog\toff\n";
+ isset($dspamcfg['user-log']) ? $dspamconf .= "UserLog\t\t\ton\n" : $dspamconf .= "UserLog\toff\n";
+ $dspamconf .= "Opt\t\t\t{$dspamcfg['filter-opt']}\n";
+ isset($dspamcfg['parse-to-headers']) ? $dspamconf .= "ParseToHeaders\t\ton\n" : $dspamconf .= "ParseToHeaders\toff\n";
+ isset($dspamcfg['change-mode-on-parse']) ? $dspamconf .= "ChangeModeOnParse\ton\n" : $dspamconf .= "ChangeModeOnParse\toff\n";
+ isset($dspamcfg['change-user-on-parse']) ? $dspamconf .= "ChangeUserOnParse\ton\n" : $dspamconf .= "ChangeUserOnParse\toff\n";
+
+ if (isset($dspamcfg['broken-mta-settings'])) {
+ $t_bmtas = &$dspamcfg['bmta'];
+
+ foreach ($t_bmtas as $bmta) {
+ $dspamconf .= "Broken\t\t\t{$bmta['name']}\n";
+ }
+ }
+
+ $dspamconf .= "MaxMessageSize\t\t{$dspamcfg['max-message-size']}\n";
+ isset($dspamcfg['processor-bias']) ? $dspamconf .= "ProcessorBias\t\ton\n" : $dspamconf .= "ProcessorBias\toff\n";
+
+ if (isset($dspamcfg['clamav-enable'])) {
+ $dspamconf .= <<<EOD
+## ClamAV Engine Settings
+ClamAVPort {$dspamcfg['clamav-port']}
+ClamAVHost {$dspamcfg['clamav-host']}
+ClamAVResponse {$dspamcfg['clamav-response']}
+
+EOD;
+ }
+
+ $dspamconf .= <<<EOD
+## DSPAM Daemon Settings (Server)
+ServerPort {$dspamcfg['dspam-server-port']}
+ServerQueueSize {$dspamcfg['dspam-server-queue-size']}
+ServerPID {$dspamcfg['dspam-server-pid']}
+ServerMode {$dspamcfg['dspam-server-mode']}
+
+EOD;
+
+ if ($dspamcfg['dspam-server-mode'] == "dspam") {
+ $t_spwds = &$dspamcfg['server-pwd'];
+ $i = 1;
+
+ if (is_array($t_spwds)) {
+ foreach ($t_spwds as $spwd) {
+ $dspamconf .= "ServerPass.Relay{$i}\t\"{$spwd['value']}\"\n";
+ $i++;
+ }
+ }
+ } else if ($dspamcfg['dspam-server-mode'] == "standard") {
+ $dspamconf .= <<<EOD
+ServerParameters "{$dspamcfg['dspam-server-params']}"
+ServerIdent "{$dspamcfg['dspam-server-id']}"
+
+EOD;
+ }
+
+ if (isset($dspamcfg['dspam-server-socket'])) {
+ $dspamconf .= "ServerDomainSocketPath\t\"{$dspamcfg['dspam-server-socket']}\"\n";
+ }
+
+ if (isset($dspamcfg['dspam-client-enable']) && $dspamcfg['dspam-client-enable'] <> "") {
+ $dspamconf .= <<<EOD
+## DSPAM Daemon Settings (Client)
+ClientHost {$dspamcfg['dspam-client-host']}
+ClientIdent {$dspamcfg['dspam-client-id']}
+
+EOD;
+
+ if (isset($dspamcfg['dspam-client-port']) && $dspamcfg['dspam-client-port'] <> "") {
+ $dspamconf .= "ClientPort\t\t{$dspamcfg['dspam-client-port']}\n";
+ }
+ }
+
+ $dspamconf .= "## EOF\n";
+
+ fwrite($fd, $dspamconf);
+ fclose($fd);
+
+ /* fire up dspam --daemon */
+ mwexec("/usr/local/etc/rc.d/dspam.sh stop");
+ mwexec("/usr/local/etc/rc.d/dspam.sh start");
+
+ if ($g['booting']) {
+ print "done.\n";
+ }
+
+ return 0;
+}
+
+function custom_php_install_command() {
+ global $config, $g;
+ /* create a default config */
+ sync_package_dspam();
+}
+
+function custom_php_deinstall_command() {
+ global $config, $g;
+ conf_mount_rw();
+ unlink_if_exists("/usr/local/etc/rc.d/dspam.sh");
+ unlink_if_exists("/usr/local/etc/dspam.conf");
+ unlink_if_exists("/usr/local/bin/dspam_spamfeed");
+ unlink_if_exists("/usr/local/bin/dspam_innocentfeed");
+ conf_mount_ro();
+}
+
+function checkForLDAPSupport() {
+ $pd = popen("ldd /usr/local/bin/dspam", "r");
+ while (!feof($pd)) {
+ $dspamstr .= fgets($pd, 4096);
+ }
+ pclose($pd);
+
+ if (strpos($dspamstr, "libldap") !== false &&
+ file_exists("/usr/local/lib/libldap.so") &&
+ file_exists("/usr/local/lib/liblber.so")) {
+ return true;
+ }
+
+ return false;
+}
+
+function checkForPgSQLSupport() {
+ if (file_exists("/usr/local/lib/libpgsql_drv.so") &&
+ file_exists("/usr/local/lib/libpq.so")) {
+ return true;
+ }
+
+ return false;
+}
+
+function checkForMySQLSupport() {
+ if (file_exists("/usr/local/lib/libmysql_drv.so") &&
+ file_exists("/usr/local/lib/mysql/libmysqlclient.so")) {
+ return true;
+ }
+
+ return false;
+}
+
+function checkForSQLiteSupport() {
+ if (file_exists("/usr/local/lib/libsqlite3_drv.so") &&
+ file_exists("/usr/local/lib/mysql/libsqlite3.so")) {
+ return true;
+ }
+
+ return false;
+}
+
+function checkForClamAVSupport() {
+ if (file_exists("/usr/local/bin/clamdscan") &&
+ file_exists("/usr/local/bin/clamscan") &&
+ file_exists("/usr/local/sbin/clamd")) {
+ return true;
+ }
+
+ return false;
+}
+
+?>
diff --git a/config/dspam/pkg/dspam-utilfunc.inc b/config/dspam/pkg/dspam-utilfunc.inc
new file mode 100644
index 00000000..903790b8
--- /dev/null
+++ b/config/dspam/pkg/dspam-utilfunc.inc
@@ -0,0 +1,458 @@
+<?php
+/* $Id$ */
+/* Copyright (C) 2006 Daniel S. Haischt */
+require_once("functions.inc");
+require_once("dspam.inc");
+
+function &GetPrefs($user) {
+ global $CONFIG, $USER;
+ $prefs = array();
+ $FILE = "{$USER}.prefs";
+
+ if ($CONFIG['PREFERENCES_EXTENSION'] == 1) {
+ $handle = popen ("{$CONFIG['DSPAM_BIN']}/dspam_admin agg pref " . quotemeta($user));
+
+ while (!feof($handle)) {
+ $buffer = chop(fgets($handle, 4096));
+ list($key, $value) = split("=", $buffer);
+ $prefs[$key] = $value;
+ }
+
+ pclose($handle);
+
+ }
+
+ if (count(array_keys($prefs)) == 0 || $CONFIG['PREFERENCES_EXTENSION'] != 1) {
+
+ /* This step is only required if the user
+ * wants to use the legacy DSPAm CGI app.
+ */
+ if (! file_exists("{$CONFIG['DSPAM_WWW']}/default.prefs")) {
+ /* try to copy the sample file */
+ if (file_exists("{$CONFIG['DSPAM_WWW']}/default.prefs.sample")) {
+ copy("{$CONFIG['DSPAM_WWW']}/default.prefs.sample",
+ "{$CONFIG['DSPAM_WWW']}/default.prefs");
+ }
+ }
+ $handle = fopen ("{$CONFIG['DSPAM_WWW']}/default.prefs", "r");
+
+ while (!feof($handle)) {
+ $buffer = chop(fgets($handle, 4096));
+ list($key, $value) = split("=", $buffer);
+ $prefs[$key] = $value;
+ }
+
+ fclose($handle);
+
+ if(file_exists($FILE)) {
+ $handle = fopen ($FILE, "r");
+
+ while (!feof($handle)) {
+ $buffer = chop(fgets($handle, 4096));
+ list($key, $value) = split("=", $buffer);
+ $prefs[$key] = $value;
+ }
+ }
+ }
+ return $prefs;
+}
+
+function CheckQuarantine() {
+ global $MAILBOX, $DATA;
+ $f = 0;
+
+ if (file_exists($MAILBOX)) {
+ $handle = fopen($MAILBOX, "r");
+
+ while (!feof($handle)) {
+ $buffer = fgets($handle, 4096);
+ if (preg_match('/^From /', $buffer) <= 0) {continue;}
+ $f++;
+ }
+
+ fclose ($handle);
+ }
+
+ if ($f == 0) {
+ $f = "Empty";
+ }
+
+ $DATA['TOTAL_QUARANTINED_MESSAGES'] = $f;
+}
+
+function http_parse_query( $array = NULL, $convention = '%s' ) {
+ if( count( $array ) == 0 ) {
+ return '';
+ } else {
+ if( function_exists( 'http_build_query' ) ){
+ $query = http_build_query( $array );
+ } else {
+ $query = '';
+
+ foreach( $array as $key => $value ) {
+ if( is_array( $value ) ){
+ $new_convention = sprintf( $convention, $key ) . '[%s]';
+ $query .= http_parse_query( $value, $new_convention );
+ } else {
+ $key = urlencode( $key );
+ $value = urlencode( $value );
+ $query .= sprintf( $convention, $key ) . "=$value&";
+ }
+ }
+ }
+
+ return $query;
+ }
+}
+
+/* just a wrapper function */
+function SafeVars($PAIRS) {
+ $url = http_parse_query($PAIRS);
+ return $url;
+}
+
+function To12Hour($h) {
+ if ($h < 0) { $h += 24; }
+ if ($h > 11) { if ($h > 12) { $h -= 12; } $h .= "p"; }
+ else { if ($h == 0) { $h = "12"; } $h .= "a"; }
+ return $h;
+}
+
+function GetPath($store) {
+ global $CONFIG, $USER;
+ $PATH = "";
+
+ /* Domain-scalen */
+ if ($CONFIG['DOMAIN_SCALE'] == 1) {
+ $splittmp = (split('@', $store));
+ $VPOPUSERNAME = $splittmp[0];
+ $VPOPDOMAIN = $splittmp[1];
+ if ($VPOPDOMAIN == "") {$VPOPDOMAIN = "local";}
+
+ $PATH = "{$CONFIG['DSPAM_HOME']}/data/{$VPOPDOMAIN}/{$VPOPUSERNAME}/" .
+ "{$VPOPUSERNAME}";
+ return $PATH;
+
+ /* Normal scale */
+ } else if ($CONFIG['LARGE_SCALE'] == 0) {
+ $PATH = "{$CONFIG['DSPAM_HOME']}/data/{$USER}/{$USER}";
+ return $PATH;
+
+ /* Large-scale */
+ } else {
+ if (strlen($USER) > 1) {
+ $PATH = "{$CONFIG['DSPAM_HOME']}/data/" . substr($USER, 0, 1) .
+ "/". substr($USER, 1, 1) . "/{$USER}/{$USER}";
+ } else {
+ $PATH = "{$CONFIG['DSPAM_HOME']}/data/{$USER}/{$USER}";
+ }
+ return $PATH;
+ }
+}
+
+function GetUserDir($store) {
+ global $CONFIG, $USER;
+ $PATH = "";
+
+ /* Domain-scalen */
+ if ($CONFIG['DOMAIN_SCALE'] == 1) {
+ $splittmp = (split('@', $store));
+ $VPOPUSERNAME = $splittmp[0];
+ $VPOPDOMAIN = $splittmp[1];
+ if ($VPOPDOMAIN == "") {$VPOPDOMAIN = "local";}
+
+ $PATH = "{$CONFIG['DSPAM_HOME']}/data/{$VPOPDOMAIN}/{$VPOPUSERNAME}";
+ return $PATH;
+
+ /* Normal scale */
+ } else if ($CONFIG['LARGE_SCALE'] == 0) {
+ $PATH = "{$CONFIG['DSPAM_HOME']}/data/{$USER}/";
+ return $PATH;
+
+ /* Large-scale */
+ } else {
+ if (strlen($USER) > 1) {
+ $PATH = "{$CONFIG['DSPAM_HOME']}/data/" . substr($USER, 0, 1) .
+ "/". substr($USER, 1, 1) . "/{$USER}/{$USER}";
+ } else {
+ $PATH = "{$CONFIG['DSPAM_HOME']}/data/{$USER}";
+ }
+ return $PATH;
+ }
+}
+
+function GetDomain($store) {
+ global $CONFIG, $USER;
+ $PATH = "";
+
+ /* Domain-scalen */
+ if ($CONFIG['DOMAIN_SCALE'] == 1) {
+ $splittmp = (split('@', $store));
+ $VPOPUSERNAME = $splittmp[0];
+ $VPOPDOMAIN = $splittmp[1];
+ if ($VPOPDOMAIN == "") {$VPOPDOMAIN = "local";}
+
+ return $VPOPDOMAIN;
+ }
+}
+
+function isDSPAMAdmin($username = "") {
+ global $config, $CONFIG;
+
+ $groupindex = index_groups();
+ $userindex = index_users();
+
+ if ($username == "") { return 0; }
+
+ $gname = $config['system']['group'][$groupindex[$config['system']['user'][$userindex[$username]]['groupname']]]['name'];
+
+ if (isset($gname)) {
+ return ($gname === $CONFIG['DSPAM_ADMIN_GROUP']);
+ }
+
+ return 0;
+}
+
+function createUserNotificationMessages() {
+ global $config, $CONFIG, $USER, $CURRENT_USER, $CURRENT_STORE;
+
+ $firstrun = "{$USER}.firstrun";
+ $firstspam = "{$USER}.firstspam";
+ $quarantinefull = "{$USER}.quarantinefull";
+ $savemsg = "";
+
+ if (isset($config['installedpackages']['dspam']['config'][0]['dspam-domain']))
+ $domain = $config['installedpackages']['dspam']['config'][0]['dspam-domain'];
+ else
+ $domain = $config['system']['domain'];
+
+ if (GetDomain($CURRENT_STORE) <> "")
+ $user_domain = GetDomain($CURRENT_STORE);
+ else
+ $user_domain = $config['system']['domain'];
+
+ $userdir = GetUserDir($CURRENT_STORE);
+ $hostname = $config['system']['hostname'];
+ $support_user = $config['installedpackages']['dspam']['config'][0]['dspam-contact'];
+
+ /* return if there are no sample files */
+ if (! file_exists("{$CONFIG['DSPAM_HOME']}/firstrun.txt.sample") ||
+ ! file_exists("{$CONFIG['DSPAM_HOME']}/firstspam.txt.sample") ||
+ ! file_exists("{$CONFIG['DSPAM_HOME']}/quarantinefull.txt.sample") ||
+ ! file_exists($userdir)) {
+ return;
+ }
+
+ /* create firstrun.txt */
+ if (! file_exists("{$firstrun}")) {
+ $sample_msg = file_get_contents("{$CONFIG['DSPAM_HOME']}/firstrun.txt.sample");
+
+ $sample_msg = str_replace("support", $support_user, $sample_msg);
+ $sample_msg = str_replace("configureme.com", $user_domain, $sample_msg);
+ $sample_msg = str_replace("http://www.yourdomain.com/dspam/",
+ "http://{$hostname}.{$domain}/dspam.php",
+ $sample_msg);
+
+ @file_put_contents("{$firstrun}", $sample_msg);
+ $savemsg .= " »{$firstrun}«, ";
+ }
+
+ /* create firstspam.txt */
+ if (! file_exists("{$firstspam}")) {
+ $sample_msg = file_get_contents("{$CONFIG['DSPAM_HOME']}/firstspam.txt.sample");
+
+ $sample_msg = str_replace("support", $support_user, $sample_msg);
+ $sample_msg = str_replace("configureme.com", $user_domain, $sample_msg);
+ $sample_msg = str_replace("http://www.yourdomain.com/dspam/",
+ "http://{$hostname}.{$domain}/dspam.php",
+ $sample_msg);
+
+ @file_put_contents("{$firstspam}", $sample_msg);
+ $savemsg .= " »{$firstspam}«, ";
+ }
+
+ /* create quarantinefull.txt */
+ if (! file_exists("{$quarantinefull}")) {
+ $sample_msg = file_get_contents("{$CONFIG['DSPAM_HOME']}/quarantinefull.txt.sample");
+
+ $sample_msg = str_replace("support", $support_user, $sample_msg);
+ $sample_msg = str_replace("configureme.com", $user_domain, $sample_msg);
+ $sample_msg = str_replace("http://www.yourdomain.com/dspam/",
+ "http://{$hostname}.{$domain}/dspam.php",
+ $sample_msg);
+
+ @file_put_contents("{$quarantinefull}", $sample_msg);
+ $savemsg .= " »{$quarantinefull}«.";
+ }
+
+ if ($savemsg <> "") {
+ $savemsg = gettext("The following files were created: ") . $savemsg;
+ return $savemsg;
+ }
+
+ return;
+}
+
+function createNotificationMessages() {
+ global $config, $CONFIG, $USER, $CURRENT_USER;
+
+ $firstrun = "{$CONFIG['DSPAM_HOME']}/firstrun.txt";
+ $firstspam = "{$CONFIG['DSPAM_HOME']}/firstspam.txt";
+ $quarantinefull = "{$CONFIG['DSPAM_HOME']}/quarantinefull.txt";
+ $savemsg = "";
+
+ if (isset($config['installedpackages']['dspam']['config'][0]['dspam-domain']))
+ $domain = $config['installedpackages']['dspam']['config'][0]['dspam-domain'];
+ else
+ $domain = $config['system']['domain'];
+
+ $hostname = $config['system']['hostname'];
+ $support_user = $config['installedpackages']['dspam']['config'][0]['dspam-contact'];
+
+ /* return if there are no sample files */
+ if (! file_exists("{$CONFIG['DSPAM_HOME']}/firstrun.txt.sample") ||
+ ! file_exists("{$CONFIG['DSPAM_HOME']}/firstspam.txt.sample") ||
+ ! file_exists("{$CONFIG['DSPAM_HOME']}/quarantinefull.txt.sample")) {
+ return;
+ }
+
+ /* create firstrun.txt */
+ if (! file_exists("{$CONFIG['DSPAM_HOME']}/firstrun.txt")) {
+ $sample_msg = file_get_contents("{$CONFIG['DSPAM_HOME']}/firstrun.txt.sample");
+
+ $sample_msg = str_replace("support", $support_user, $sample_msg);
+ $sample_msg = str_replace("configureme.com", $domain, $sample_msg);
+ $sample_msg = str_replace("http://www.yourdomain.com/dspam/",
+ "http://{$hostname}.{$domain}/dspam.php",
+ $sample_msg);
+
+ @file_put_contents("{$firstrun}", $sample_msg);
+ $savemsg .= " »{$firstrun}«, ";
+ }
+
+ /* create firstspam.txt */
+ if (! file_exists("{$CONFIG['DSPAM_HOME']}/firstspam.txt")) {
+ $sample_msg = file_get_contents("{$CONFIG['DSPAM_HOME']}/firstspam.txt.sample");
+
+ $sample_msg = str_replace("support", $support_user, $sample_msg);
+ $sample_msg = str_replace("configureme.com", $domain, $sample_msg);
+ $sample_msg = str_replace("http://www.yourdomain.com/dspam/",
+ "http://{$hostname}.{$domain}/dspam.php",
+ $sample_msg);
+
+ @file_put_contents("{$firstspam}", $sample_msg);
+ $savemsg .= " »{$firstspam}«, ";
+ }
+
+ /* create quarantinefull.txt */
+ if (! file_exists("{$CONFIG['DSPAM_HOME']}/quarantinefull.txt")) {
+ $sample_msg = file_get_contents("{$CONFIG['DSPAM_HOME']}/quarantinefull.txt.sample");
+
+ $sample_msg = str_replace("support", $support_user, $sample_msg);
+ $sample_msg = str_replace("configureme.com", $domain, $sample_msg);
+ $sample_msg = str_replace("http://www.yourdomain.com/dspam/",
+ "http://{$hostname}.{$domain}/dspam.php",
+ $sample_msg);
+
+ @file_put_contents("{$quarantinefull}", $sample_msg);
+ $savemsg .= " »{$quarantinefull}«.";
+ }
+
+ if ($savemsg <> "") {
+ $savemsg = gettext("The following files were created: ") . $savemsg;
+ return $savemsg;
+ }
+
+ return;
+}
+
+function &check_dspam_installation() {
+ global $config;
+
+ /* create RC files if necessary */
+ if (! file_exists("/usr/local/etc/rc.d")) {
+ @mkdir("/usr/local/etc/rc.d");
+ }
+ if (! file_exists("/usr/local/etc/rc.d/000.mysql.sh")) {
+ @copy("/usr/local/pkg/000.mysql.sh", "/usr/local/etc/rc.d/000.mysql.sh");
+ @chmod("/usr/local/etc/rc.d/000.mysql.sh", 0755);
+ }
+ if (! file_exists("/usr/local/etc/rc.d/010.clamav-clamd.sh")) {
+ @copy("/usr/local/pkg/010.clamav-clamd.sh",
+ "/usr/local/etc/rc.d/010.clamav-clamd.sh");
+ @chmod("/usr/local/etc/rc.d/010.clamav-clamd.sh", 0755);
+ }
+ if (! file_exists("/usr/local/etc/rc.d/020.clamav-freshclam.sh")) {
+ @copy("/usr/local/pkg/020.clamav-freshclam.sh",
+ "/usr/local/etc/rc.d/020.clamav-freshclam.sh");
+ @chmod("/usr/local/etc/rc.d/020.clamav-freshclam.sh", 0755);
+ }
+ if (! file_exists("/usr/local/etc/rc.d/030.p3scan.sh")) {
+ @copy("/usr/local/pkg/030.p3scan.sh",
+ "/usr/local/etc/rc.d/030.p3scan.sh");
+ @chmod("/usr/local/etc/rc.d/030.p3scan.sh", 0755);
+ }
+
+ /* create conf files for those packages DSPAM depends on */
+ if (! file_exists("/usr/local/etc/clamd.conf")) {
+ @copy("/usr/local/pkg/clamd.conf",
+ "/usr/local/etc/clamd.conf");
+ }
+ if (! file_exists("/usr/local/etc/freshclam.conf")) {
+ @copy("/usr/local/pkg/freshclam.conf",
+ "/usr/local/etc/freshclam.conf");
+ }
+
+ if (! is_service_running("dspam")) {
+ $input_errors[] = "The DSPAM daemon process is not running. " .
+ "If you are certain that you did configure DSPAM " .
+ "appropriatly, you can start the corresponding process " .
+ "using the service control panel which is part of the " .
+ "»Status« menu item.";
+ }
+ if (! is_service_running("p3scan")) {
+ $input_errors[] = "The POP3 proxy process is not running. " .
+ "If you are certain that you did configure the POP3 proxy " .
+ "appropriatly, you can start the corresponding process " .
+ "using the service control panel which is part of the " .
+ "»Status« menu item.";
+ }
+ if (! is_service_running("clamd")) {
+ $input_errors[] = "The ClamAV daemon process is not running. " .
+ "If you are certain that you did configure DSPAM " .
+ "appropriatly, you can start the corresponding process " .
+ "using the service control panel which is part of the " .
+ "»Status« menu item (ClamAV does not need any configuration).";
+ }
+ if (! is_service_running("freshclam")) {
+ $input_errors[] = "The freshclam daemon process is not running. " .
+ "If you are certain that you did configure DSPAM " .
+ "appropriatly, you can start the corresponding process " .
+ "using the service control panel which is part of the " .
+ "»Status« menu item (freshclam does not need any configuration).";
+ }
+ if (! is_service_running("mysql")) {
+ $input_errors[] = "The MySQL daemon process is not running. " .
+ "If you are certain that you did configure DSPAM " .
+ "appropriatly, you can start the corresponding process " .
+ "using the service control panel which is part of the " .
+ "»Status« menu item (MySQL does not need any configuration).";
+ }
+
+ if (empty($config['installedpackages']['dspam']['config']) ||
+ empty($config['installedpackages']['dspam']['config'][0]['storage-driver']) ||
+ (file_exists('/usr/local/etc/dspam.conf') == false)) {
+ /* create default config files etc. */
+ sync_package_dspam();
+
+ $input_errors[] = "It seems that you are using DSPAM for the very first time. " .
+ "Please run the DSPAM wizard from the »Services« menu " .
+ "if you would like to configure DSPAM right now. " .
+ "If you are not eligible to administer DSPAM you may contact " .
+ "your local DSPAM admin personal to solve this issue.";
+ }
+
+ return $input_errors;
+}
+
+?>
diff --git a/config/dspam/pkg/dspam.inc b/config/dspam/pkg/dspam.inc
new file mode 100644
index 00000000..9a821e6a
--- /dev/null
+++ b/config/dspam/pkg/dspam.inc
@@ -0,0 +1,360 @@
+<?php
+/* $Id$ */
+/* Copyright (C) 2006 Daniel S. Haischt */
+
+/* include all configuration functions */
+require_once ("functions.inc");
+require_once ("dspam-config.inc");
+require_once ("dspam-guifunc.inc");
+require_once ("dspam-pkgfunc.inc");
+require_once ("dspam-utilfunc.inc");
+
+/* General TODO(s):
+ *
+ * - Use quotemeta where applicable
+ * - Issue a change message after a successful GET/POST
+ * - Issue an error message if something went wrong during a GET/POST
+ * - Revise user management (CURENT_USER, SESSION_USER etc.)
+ */
+
+$DATA = array();
+
+/*
+ * Determine which extensions are available
+ */
+if ($CONFIG['AUTODETECT'] == 1 || $CONFIG['AUTODETECT'] == "") {
+ $CONFIG['PREFERENCES_EXTENSION'] = 0;
+ $CONFIG['LARGE_SCALE'] = 0;
+ $CONFIG['DOMAIN_SCALE'] = 0;
+
+ $buffer = "";
+ $handle = popen ("/usr/local/bin/dspam --version", "r");
+
+ while (!feof($handle)) {
+ $buffer .= fgets($handle, 4096);
+ }
+
+ pclose($handle);
+
+ if (strpos($buffer, '--enable-preferences-extension') !== false) {
+ $CONFIG['PREFERENCES_EXTENSION'] = 1;
+ }
+ if (strpos($buffer, '--enable-large-scale') !== false) {
+ $CONFIG['LARGE_SCALE'] = 1;
+ }
+ if (strpos($buffer, '--enable-domain-scale') !== false) {
+ $CONFIG['DOMAIN_SCALE'] = 1;
+ }
+}
+
+/*
+ * Determine admin status
+ */
+
+$CONFIG['ADMIN'] = isDSPAMAdmin($HTTP_SERVER_VARS['AUTH_USER']);
+
+/*
+ * Determine which user should be used to display DSPAm related data
+ */
+$CURRENT_USER = $HTTP_SERVER_VARS['AUTH_USER'];
+
+if (empty($CONFIG['ADMIN']) &&
+ strpos($_SERVER['SCRIPT_NAME'], "wizard.php") !== false) {
+
+ $group = $config['system']['user'][$userindex[$HTTP_SERVER_VARS['AUTH_USER']]]['groupname'];
+ $home = "/" . getGroupHomePage($group);
+ if ($home == "/") { $home = "/index.php"; }
+
+ if (! headers_sent()) {
+ pfSenseHeader($home);
+ exit;
+ } else {
+ $htmlstr = <<< EOD
+<html>
+ <head>
+ <title>Unauthorized Access</title>
+ <meta http-equiv="refresh" content="2; URL={$home}">
+ </head>
+ <body>
+ <h3>Unauthorized Access - You will be redirected shortly!</h3>
+ </body>
+</html>
+EOD;
+ print $htmlstr;
+ exit;
+ }
+}
+
+/*
+ * only DSPAM admins can change the current user without logging out
+ * and logging in as another user again.
+ */
+if ($_POST) {
+ if (! empty($_POST['username']) && $CONFIG['ADMIN'] == 1) {
+ $CURRENT_USER = $_POST['username'];
+ }
+}
+if ($_GET) {
+ if (! empty($_GET['user']) && $CONFIG['ADMIN'] == 1) {
+ $CURRENT_USER = $_GET['user'];
+ }
+}
+
+if ($CURRENT_USER == "") {
+ $input_errors[] = "System Error. I was unable to determine your identity.";
+}
+
+preg_replace('/%CURRENT_USER%/', $CURRENT_USER, $CONFIG['DSPAM_ARGS']);
+
+/* current store */
+$PREF =& GetPrefs($CURRENT_USER);
+$CURRENT_STORE = $PREF['localStore'];
+if ($CURRENT_STORE == "") {$CURRENT_STORE = $CURRENT_USER; }
+
+$USER = GetPath($CURRENT_STORE);
+$MAILBOX = $USER . ".mbox";
+$TMPFILE = $USER . ".tmp";
+
+/*
+ * Set up initial display variables
+ */
+CheckQuarantine();
+$DATA['REMOTE_USER'] = $CURRENT_USER;
+
+/*
+ * Check whether DSPAM is already configured.
+ */
+$install_errors =& check_dspam_installation();
+$input_errors = array_merge($input_errors, $install_errors);
+
+/*
+ * Check whether we should generate notification messages
+ */
+if (isset($config['installedpackages']['dspam']['config'][0]['notification-email'])) {
+ $tmpmsg = createNotificationMessages();
+ if (! empty($tmpmsg))
+ $tmpmsg .= "\n" . createUserNotificationMessages();
+ else
+ $tmpmsg = createUserNotificationMessages();
+
+ $savemsg =& $tmpmsg;
+}
+
+/*
+ * Process Commands
+ */
+if (isset($pgtitle) && is_array($pgtitle)) {
+ /* Performance */
+ if (basename($_SERVER['SCRIPT_NAME']) == "dspam-perf.php") {
+ if ($_GET) {
+ if ($GET['command'] == "resetStats") {
+ ResetStats();
+ } else if ($GET['command'] == "tweak") {
+ Tweak();
+ }
+ }
+
+ $display_errors =& DisplayIndex();
+ $input_errors = array_merge($input_errors, $display_errors);
+ }
+
+ /* Preferences */
+ else if (basename($_SERVER['SCRIPT_NAME']) == "dspam-prefs.php") {
+ $savemsg = "";
+ $prefs_errors =& DisplayPreferences(NULL, $savemsg);
+ $input_errors = array_merge($input_errors, $prefs_errors);
+ }
+
+ /* Quarantine */
+ else if (basename($_SERVER['SCRIPT_NAME']) == "dspam-quarantine.php") {
+ if ($_GET) {
+ if ($_GET['command'] == "viewMessage") {
+ $showpart = 0;
+ $ctype = 0;
+ $sortby = "Rating";
+ $currentPage = 1;
+ $qPerPage = 0;
+
+ if (isset($_GET['showpart'])) { $showpart = $_GET['showpart']; }
+ if (isset($_GET['ctype'])) { $ctype = intval($_GET['ctype']); }
+ if (isset($_GET['sortby'])) { $sortby = $_GET['sortby']; }
+ if (isset($_GET['page'])) { $currentPage = $_GET['page']; }
+ if (isset($_GET['qperpage'])) { $qPerPage = $_GET['qperpage']; }
+
+ $quarantine_errors =& QuarantineViewMessage($_GET['signatureID'],
+ $showpart,
+ $ctype,
+ $sortby,
+ $currentPage,
+ $qPerPage);
+ $input_errors = array_merge($input_errors, $quarantine_errors);
+ } else if (isset($_GET['sortby'])) {
+ $qperpage = $CONFIG['QUARANTINE_PER_PAGE'];
+ if (isset($_GET['qperpage'])) { $qperpage = $_GET['qperpage']; }
+ $page = 1;
+ if (isset($_GET['page'])) { $page = $_GET['page']; }
+
+ $quarantine_errors =& DisplayQuarantine($_GET['sortby'],
+ intval($page),
+ intval($qperpage));
+ $input_errors = array_merge($input_errors, $quarantine_errors);
+ } else if (isset($_GET['qperpage'])) {
+ if (isset($_GET['page'])) {
+ $quarantine_errors =& DisplayQuarantine($CONFIG['SORT_DEFAULT'],
+ intval($_GET['page']),
+ intval($_GET['qperpage']));
+ $input_errors = array_merge($input_errors, $quarantine_errors);
+ } else {
+ $quarantine_errors =& DisplayQuarantine($CONFIG['SORT_DEFAULT'],
+ 1,
+ intval($_GET['qperpage']));
+ $input_errors = array_merge($input_errors, $quarantine_errors);
+ }
+ } else {
+ $displayq_errors =& DisplayQuarantine($CONFIG['SORT_DEFAULT'], 1);
+ $input_errors = array_merge($input_errors, $displayq_errors);
+ }
+ } else if ($_POST) {
+ if ($_POST['command'] == "processQuarantine") {
+ $signatures = array();
+
+ while (list($key, $val) = each($_POST)) {
+ if (strpos($key, "chkmsg") !== false) {
+ $signatures[$key] = $val;
+ }
+ }
+ if ($_POST['processAction']) {
+ $processq_errors =& ProcessQuarantine($signatures,
+ $_POST['processAction'],
+ $_POST['sortby'],
+ intval($_POST['qpage']),
+ intval($_POST['qperpage']));
+ $input_errors = array_merge($input_errors, $processq_errors);
+ } else {
+ $processq_errors =& ProcessQuarantine($signatures,
+ "None",
+ $_POST['sortby'],
+ intval($_POST['qpage']),
+ intval($_POST['qperpage']));
+ $input_errors = array_merge($input_errors, $processq_errors);
+ }
+ } else if ($_POST['command'] == "processFalsePositive") {
+ $processfp_errors =& ProcessFalsePositive($_POST['signatureID'],
+ $_POST['sortby'],
+ intval($_POST['qpage']),
+ intval($_POST['qperpage']));
+ $input_errors = array_merge($input_errors, $processfp_errors);
+ $displayq_errors =& DisplayQuarantine($_POST['sortby'],
+ intval($_POST['qpage']),
+ intval($_POST['qperpage']));
+ $input_errors = array_merge($input_errors, $displayq_errors);
+ }
+ } else {
+ /* usually this particular line of code should not be hit because
+ * the user always triggers a GET or POST action. Unfortunatly at
+ * the time, the alerts page is implemented in a way that neither
+ * triggers a GET nor a POST action if initially accessed via the
+ * tab. Hence this final catch all else.
+ */
+ $displayq_errors =& DisplayQuarantine($CONFIG['SORT_DEFAULT'], 1);
+ $input_errors = array_merge($input_errors, $displayq_errors);
+ }
+ }
+
+ /* Analysis */
+ else if (basename($_SERVER['SCRIPT_NAME']) == "dspam-analysis.php") {
+ $displaya_errors =& DisplayAnalysis();
+ $input_errors = array_merge($input_errors, $displaya_errors);
+ }
+
+ /* History */
+ else if (in_array(gettext("History"), $pgtitle)) {
+ if ($_POST) {
+ /* Form fields that may be submited via POST:
+ * - command
+ * - username
+ * - msgid$retrain_checked_msg_no (checkbox, multible times)
+ */
+ $checked = array();
+
+ while (list($key, $val) = each($_POST)) {
+ if (strpos($key, "msgid") !== false) {
+ $checked[] = $val;
+ }
+ }
+
+ $displayh_errors =& DisplayHistory($_POST['command'],
+ "",
+ $checked,
+ $_POST['username'],
+ "",
+ $_POST['hpage'],
+ $_POST['hperpage']);
+ $input_errors = array_merge($input_errors, $displayh_errors);
+ } else if ($_GET) {
+ /* Form fields that may be submited via GET:
+ * - history_page
+ * - command
+ * - signatureID
+ * - retrain
+ * - user
+ */
+ $displayh_errors =& DisplayHistory($_GET['command'],
+ $_GET['signatureID'],
+ NULL,
+ $_GET['user'],
+ $_GET['retrain'],
+ isset($_GET['page']) ? intval($_GET['page']) : 1,
+ isset($_GET['hperpage']) ? $_GET['hperpage'] : $CONFIG['QUARANTINE_PER_PAGE']);
+ $input_errors = array_merge($input_errors, $displayh_errors);
+ } else {
+ $displayh_errors =& DisplayHistory("", // command
+ "", // signature ID
+ NULL, // signatures to be retrained
+ $CURRENT_USER);
+ $input_errors = array_merge($input_errors, $displayh_errors);
+ }
+ } else if (in_array(gettext("Fragment"), $pgtitle)) {
+ if ($_GET) {
+ $displayf_errors =& DisplayFragment($_GET['signatureID'],
+ $_GET['from'],
+ $_GET['subject'],
+ $_GET['info'],
+ $_GET['time']);
+ $input_errors = array_merge($input_errors, $displayf_errors);
+ }
+ }
+
+ /* Info Page */
+ else if (basename($_SERVER['SCRIPT_NAME']) == "dspam.php") {
+ $info_errors =& DisplayInfos();
+ $input_errors = array_merge($input_errors, $info_errors);
+ }
+
+/* ========================================================================== */
+/* = A D M I N R E L A T E D F U N C T I O N C A L L S = */
+/* ========================================================================== */
+
+ /* Status */
+ else if (basename($_SERVER['SCRIPT_NAME']) == "dspam-admin.php" && $CONFIG['ADMIN']) {
+ $displays_errors =& DisplayStatus();
+ $input_errors = array_merge($input_errors, $displays_errors);
+ }
+
+ /* User Statistics */
+ else if (basename($_SERVER['SCRIPT_NAME']) == "dspam-admin-stats.php" && $CONFIG['ADMIN']) {
+ $displayus_errors =& DisplayUserStatistics();
+ $input_errors = array_merge($input_errors, $displayus_errors);
+ }
+
+ /* Preferences */
+ else if (basename($_SERVER['SCRIPT_NAME']) == "dspam-admin-prefs.php" && $CONFIG['ADMIN']) {
+ $savemsg = "";
+ $displayap_errors =& DisplayAdminPreferences($savemsg);
+ $input_errors = array_merge($input_errors, $displayap_errors);
+ }
+} else {
+ $input_errors[] = "The page you did request can't be processed by <code>dspam.inc</code>.";
+}
+
+?> \ No newline at end of file
diff --git a/config/dspam/pkg/dspam.xml b/config/dspam/pkg/dspam.xml
new file mode 100644
index 00000000..59740ae1
--- /dev/null
+++ b/config/dspam/pkg/dspam.xml
@@ -0,0 +1,342 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE packagegui SYSTEM "../../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../../xsl/package.xsl"?>
+<packagegui>
+ <copyright><![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]></copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>dspam</name>
+ <version>1.0</version>
+ <title>Services: DSPAM: Main</title>
+ <include_file>/usr/local/pkg/dspam.inc</include_file>
+ <!-- Menu is where this packages menu will appear -->
+ <menu>
+ <name>dspam</name>
+ <section>Services</section>
+ <configfile>dspam.xml</configfile>
+ <url>/dspam-perf.php</url>
+ </menu>
+ <menu>
+ <name>DSPAM Legacy WebGUI</name>
+ <tooltiptext>Original Perl-based GUI</tooltiptext>
+ <section>Services</section>
+ <url>/vhosts/dspam/dspam.cgi</url>
+ </menu>
+ <service>
+ <name>dspam</name>
+ <rcfile>/usr/local/etc/rc.d/dspam.sh</rcfile>
+ </service>
+ <tabs>
+ <tab>
+ <text>Overview</text>
+ <url>/dspam.php</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Performance</text>
+ <url>/dspam-perf.php</url>
+ </tab>
+ <tab>
+ <text>Preferences</text>
+ <url>/dspam-prefs.php</url>
+ </tab>
+ <tab>
+ <text>Alerts</text>
+ <url>/pkg.php?xml=dspam_alerts.xml</url>
+ </tab>
+ <tab>
+ <text>Quarantine</text>
+ <url>/dspam-quarantine.php</url>
+ </tab>
+ <tab>
+ <text>Analysis</text>
+ <url>/dspam-analysis.php</url>
+ </tab>
+ <tab>
+ <text>History</text>
+ <url>/dspam-history.php</url>
+ </tab>
+ </tabs>
+ <!--
+ configpath gets expanded out automatically and config items
+ will be stored in that location
+ -->
+ <configpath>['installedpackages']['dspam']['config']</configpath>
+ <!-- PHP files -->
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/dspam/www/dspam.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/dspam/www/dspam-perf.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/dspam/www/dspam-admin.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/dspam/www/dspam-admin-graph.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/dspam/www/dspam-admin-prefs.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/dspam/www/dspam-admin-stats.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.abyssworld.de/packages/config/dspam_settings.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.abyssworld.de/packages/config/dspam-settings.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.abyssworld.de/packages/config/dspam-settings-algo.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.abyssworld.de/packages/config/dspam-settings-bmta.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.abyssworld.de/packages/config/dspam-settings-feat.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.abyssworld.de/packages/config/dspam-header.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.abyssworld.de/packages/config/dspam-overr.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.abyssworld.de/packages/config/dspam-settings-prefs.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.abyssworld.de/packages/config/dspam-spwd.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.abyssworld.de/packages/config/dspam-tuser.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.abyssworld.de/packages/config/dspam-train.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.abyssworld.de/packages/config/dspam-viewmsg.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.abyssworld.de/packages/config/verdana.ttf</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/dspam/www/dspam-prefs.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/dspam/www/dspam-quarantine.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/dspam/www/dspam-analysis.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/dspam/www/dspam-analysis-graph.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/dspam/www/dspam-hfragment.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/dspam/www/dspam-history.php</item>
+ </additional_files_needed>
+ <!-- package files -->
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.abyssworld.de/packages/config/dspam_alerts.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/dspam/pkg/dspam.inc</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/dspam/pkg/dspam-config.inc</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/dspam/pkg/dspam-guifunc.inc</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/dspam/pkg/dspam-pkgfunc.inc</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/dspam/pkg/dspam-utilfunc.inc</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/dspam/pkg/000.mysql.sh</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/dspam/pkg/010.clamav-clamd.sh</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/dspam/pkg/020.clamav-freshclam.sh</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/dspam/pkg/030.p3scan.sh</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/dspam/pkg/clamd.conf</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/dspam/pkg/default.prefs.sample</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/dspam/pkg/freshclam.conf</item>
+ </additional_files_needed>
+ <!-- misc files -->
+ <additional_files_needed>
+ <prefix>/usr/local/www/wizards/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/dspam/www/wizards/dspam_wizard.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/wizards/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/dspam/www/wizards/dspam-lda-proxy.png</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/wizards/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/dspam/www/wizards/dspam-pop-proxy.png</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/wizards/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/dspam/www/wizards/dspam-smtp-relay.png</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/dspam/pkg/verdana.ttf</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/themes/metallic/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/dspam/www/themes/metallic/dspam.css</item>
+ </additional_files_needed>
+ <!--
+ fields gets invoked when the user adds or edits a item. The following items
+ will be parsed and rendered for the user as a gui with input, and selectboxes.
+ -->
+ <!--
+ Arbitrary PHP Code, that gets executed if a certain event gets triggered.
+ -->
+ <custom_php_resync_config_command>
+ sync_package_dspam();
+ </custom_php_resync_config_command>
+ <custom_php_install_command>
+ custom_php_install_command();
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ custom_php_deinstall_command();
+ </custom_php_deinstall_command>
+</packagegui>
diff --git a/config/dspam/pkg/dspam_alerts.xml b/config/dspam/pkg/dspam_alerts.xml
new file mode 100644
index 00000000..ea59cfd2
--- /dev/null
+++ b/config/dspam/pkg/dspam_alerts.xml
@@ -0,0 +1,147 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../../xsl/package.xsl"?>
+<!--
+ Tags which can be used to exec arbitrary PHP code:
+
+ <custom_php_global_functions />
+ <custom_php_command_before_form />
+ <custom_delete_php_command /> if $_POST && act == del
+ <custom_add_php_command /> if $_POST && act == add
+ <custom_php_resync_config_command />
+ <custom_php_validation_command />
+ <custom_add_php_command_late />
+ <start_command /> shell exec
+ <restart_command /> shell exec
+ <custom_php_after_form_command />
+-->
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>dspamalerts</name>
+ <version>1.0</version>
+ <title>Services: DSPAM: Alerts</title>
+ <include_file>/usr/local/pkg/dspam.inc</include_file>
+ <!-- Menu is where this packages menu will appear -->
+ <tabs>
+ <tab>
+ <text>Performance</text>
+ <url>/dspam-perf.php</url>
+ </tab>
+ <tab>
+ <text>Preferences</text>
+ <url>/dspam-prefs.php</url>
+ </tab>
+ <tab>
+ <text>Alerts</text>
+ <url>/pkg.php?xml=dspam_alerts.xml</url>
+ <active />
+ </tab>
+ <tab>
+ <text>Quarantine</text>
+ <url>/dspam-quarantine.php</url>
+ </tab>
+ <tab>
+ <text>Analysis</text>
+ <url>/dspam-analysis.php</url>
+ </tab>
+ <tab>
+ <text>History</text>
+ <url>/dspam-history.php</url>
+ </tab>
+ <tab>
+ <text>Train Filter</text>
+ <url>/dspam-train.php</url>
+ </tab>
+ <tab>
+ <text>Admin Suite</text>
+ <url>/dspam-admin.php</url>
+ </tab>
+ </tabs>
+ <!--
+ configpath gets expanded out automatically and config items
+ will be stored in that location
+ -->
+ <configpath>['installedpackages']['dspam']['config']['alerts']</configpath>
+ <adddeleteeditpagefields>
+ <columnitem>
+ <fielddescr>Alert Name</fielddescr>
+ <fieldname>alertname</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Description</fielddescr>
+ <fieldname>description</fieldname>
+ </columnitem>
+ </adddeleteeditpagefields>
+ <!--
+ fields gets invoked when the user adds or edits a item. The following items
+ will be parsed and rendered for the user as a gui with input, and selectboxes.
+ -->
+ <fields>
+ <field>
+ <fielddescr>Alert Name</fielddescr>
+ <fieldname>alertname</fieldname>
+ <description>Name of an alert that should be raised</description>
+ <type>input</type>
+ <size>30</size>
+ <required />
+ </field>
+ <field>
+ <fielddescr>Description</fielddescr>
+ <fieldname>description</fieldname>
+ <description>You may enter a description here for your reference (not parsed).</description>
+ <type>input</type>
+ <size>30</size>
+ </field>
+ </fields>
+ <!--
+ Arbitrary PHP Code, that gets executed if a certain event gets triggered.
+ -->
+ <custom_delete_php_command>
+ dspam_configure();
+ </custom_delete_php_command>
+ <custom_php_resync_config_command>
+ dspam_configure();
+ </custom_php_resync_config_command>
+</packagegui> \ No newline at end of file
diff --git a/config/dspam/pkg/freshclam.conf b/config/dspam/pkg/freshclam.conf
new file mode 100644
index 00000000..173d97bf
--- /dev/null
+++ b/config/dspam/pkg/freshclam.conf
@@ -0,0 +1,110 @@
+##
+## Example config file for freshclam
+## Please read the freshclam.conf(5) manual before editing this file.
+## This file may be optionally merged with clamd.conf.
+##
+
+
+# Comment or remove the line below.
+#Example
+
+# Path to the database directory.
+# WARNING: It must match clamd.conf's directive!
+# Default: hardcoded (depends on installation options)
+#DatabaseDirectory /var/lib/clamav
+DatabaseDirectory /var/db/clamav
+
+# Path to the log file (make sure it has proper permissions)
+# Default: disabled
+#UpdateLogFile /var/log/freshclam.log
+UpdateLogFile /var/log/clamav/freshclam.log
+
+# Enable verbose logging.
+# Default: no
+#LogVerbose yes
+
+# Use system logger (can work together with UpdateLogFile).
+# Default: no
+#LogSyslog yes
+
+# Specify the type of syslog messages - please refer to 'man syslog'
+# for facility names.
+# Default: LOG_LOCAL6
+#LogFacility LOG_MAIL
+
+# This option allows you to save the process identifier of the daemyes
+# Default: disabled
+#PidFile /var/run/freshclam.pid
+PidFile /var/run/clamav/freshclam.pid
+
+# By default when started freshclam drops privileges and switches to the
+# "clamav" user. This directive allows you to change the database owner.
+# Default: clamav (may depend on installation options)
+DatabaseOwner clamav
+
+# Initialize supplementary group access (freshclam must be started by root).
+# Default: no
+AllowSupplementaryGroups yes
+
+# Use DNS to verify virus database version. Freshclam uses DNS TXT records
+# to verify database and software versions. With this directive you can change
+# the database verification domain.
+# WARNING: Do not touch it unless you're configuring freshclam to use your
+# own database verification domain.
+# Default: current.cvd.clamav.net
+#DNSDatabaseInfo current.cvd.clamav.net
+
+# Uncomment the following line and replace XY with your country
+# code. See http://www.iana.org/cctld/cctld-whois.htm for the full list.
+#DatabaseMirror db.XY.clamav.net
+
+# database.clamav.net is a round-robin record which points to our most
+# reliable mirrors. It's used as a fall back in case db.XY.clamav.net is
+# not working. DO NOT TOUCH the following line unless you know what you
+# are doing.
+DatabaseMirror database.clamav.net
+
+# How many attempts to make before giving up.
+# Default: 3 (per mirror)
+#MaxAttempts 5
+
+# Number of database checks per day.
+# Default: 12 (every two hours)
+#Checks 24
+
+# Proxy settings
+# Default: disabled
+#HTTPProxyServer myproxy.com
+#HTTPProxyPort 1234
+#HTTPProxyUsername myusername
+#HTTPProxyPassword mypass
+
+# Use aaa.bbb.ccc.ddd as client address for downloading databases. Useful for
+# multi-homed systems.
+# Default: Use OS'es default outgoing IP address.
+#LocalIPAddress aaa.bbb.ccc.ddd
+
+# Send the RELOAD command to clamd.
+# Default: no
+NotifyClamd /usr/local/etc/clamd.conf
+
+# Run command after successful database update.
+# Default: disabled
+#OnUpdateExecute command
+
+# Run command when database update process fails.
+# Default: disabled
+#OnErrorExecute command
+
+# Run command when freshclam reports outdated version.
+# In the command string %v will be replaced by the new version number.
+# Default: disabled
+#OnOutdatedExecute command
+
+# Don't fork into background.
+# Default: no
+#Foreground yes
+
+# Enable debug messages in libclamav.
+# Default: no
+#Debug yes
diff --git a/config/dspam/pkg/p3scan-pf-emer.xml b/config/dspam/pkg/p3scan-pf-emer.xml
new file mode 100644
index 00000000..7475e23c
--- /dev/null
+++ b/config/dspam/pkg/p3scan-pf-emer.xml
@@ -0,0 +1,127 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <!-- change this if configpath works -->
+ <name>p3scanpfemer</name>
+ <version>1.0</version>
+ <title>Services: POP3 Proxy: Emergency Contact</title>
+ <include_file>/usr/local/pkg/p3scan.inc</include_file>
+ <tabs>
+ <tab>
+ <text>Daemon Settings</text>
+ <url>/pkg_edit.php?xml=p3scan-pf.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Message Processing</text>
+ <url>/pkg_edit.php?xml=p3scan-pf-msg.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Emergency Contact</text>
+ <url>/pkg.php?xml=p3scan-pf-emer.xml</url>
+ <active />
+ </tab>
+ <tab>
+ <text>Virus Scanner Settings</text>
+ <url>/pkg_edit.php?xml=p3scan-pf-vir.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>SPAM Settings</text>
+ <url>/pkg_edit.php?xml=p3scan-pf-spam.xml&amp;id=0</url>
+ </tab>
+ </tabs>
+ <!--
+ configpath gets expanded out automatically and config items
+ will be stored in that location
+ -->
+ <configpath>['installedpackages']['p3scanpf']['config']['contacts']</configpath>
+ <!--
+ adddeleteeditpagefields items will appear on the first page where you can
+ add / delete or edit items. An example of this would be the nat page where
+ you add new nat redirects
+ -->
+ <adddeleteeditpagefields>
+ <columnitem>
+ <fielddescr>Email Address</fielddescr>
+ <fieldname>emailaddress</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Description</fielddescr>
+ <fieldname>description</fieldname>
+ </columnitem>
+ </adddeleteeditpagefields>
+ <!--
+ fields gets invoked when the user adds or edits a item. The following items
+ will be parsed and rendered for the user as a gui with input, and selectboxes.
+ -->
+ <fields>
+ <field>
+ <fielddescr>Email Address</fielddescr>
+ <fieldname>emailaddress</fieldname>
+ <description>
+ In the event p3scan encounters a catastrophic problem and has to terminate,
+ it will send an email to these email addresses just before setting up to
+ close down on the next iteration of a child process.
+ </description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Description</fielddescr>
+ <fieldname>description</fieldname>
+ <description>Description.</description>
+ <type>input</type>
+ </field>
+ </fields>
+ <!--
+ Arbitrary PHP Code, that gets executed if a certain event gets triggered.
+ -->
+ <custom_delete_php_command>
+ sync_package_p3scan();
+ </custom_delete_php_command>
+ <custom_php_resync_config_command>
+ sync_package_p3scan();
+ </custom_php_resync_config_command>
+</packagegui>
diff --git a/config/dspam/pkg/p3scan-pf-msg.xml b/config/dspam/pkg/p3scan-pf-msg.xml
new file mode 100644
index 00000000..b2144fe6
--- /dev/null
+++ b/config/dspam/pkg/p3scan-pf-msg.xml
@@ -0,0 +1,198 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <!-- change this if configpath works -->
+ <name>p3scanpfmsg</name>
+ <version>1.0</version>
+ <title>Services: POP3 Proxy: Message Processing</title>
+ <note>
+ This &lt;acronym title=&quot;Hypertext Markup Language&quot;&gt;HTML&lt;/acronym&gt; page uses default values, hence even if each field is
+ set, you are still required to save this page if you are editing this page
+ for the very first time!
+ </note>
+ <aftersaveredirect>pkg_edit.php?xml=p3scan-pf-msg.xml&amp;id=0</aftersaveredirect>
+ <include_file>/usr/local/pkg/p3scan.inc</include_file>
+ <tabs>
+ <tab>
+ <text>Daemon Settings</text>
+ <url>/pkg_edit.php?xml=p3scan-pf.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Message Processing</text>
+ <url>/pkg_edit.php?xml=p3scan-pf-msg.xml&amp;id=0</url>
+ <active />
+ </tab>
+ <tab>
+ <text>Emergency Contact</text>
+ <url>/pkg.php?xml=p3scan-pf-emer.xml</url>
+ </tab>
+ <tab>
+ <text>Virus Scanner Settings</text>
+ <url>/pkg_edit.php?xml=p3scan-pf-vir.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>SPAM Settings</text>
+ <url>/pkg_edit.php?xml=p3scan-pf-spam.xml&amp;id=0</url>
+ </tab>
+ </tabs>
+ <!--
+ configpath gets expanded out automatically and config items
+ will be stored in that location
+ -->
+ <configpath>['installedpackages']['p3scanpf']['config']['messaging']</configpath>
+ <!--
+ fields gets invoked when the user adds or edits a item. The following items
+ will be parsed and rendered for the user as a gui with input, and selectboxes.
+ -->
+ <fields>
+ <field>
+ <fielddescr>Just Delete</fielddescr>
+ <fieldname>justdelete</fieldname>
+ <description>
+ Instead of keeping an infected message in the Virus Directory, delete it
+ after reporting it to the user.
+ </description>
+ <type>checkbox</type>
+ <donotdisable>true</donotdisable>
+ </field>
+ <field>
+ <fielddescr>Bytes Free</fielddescr>
+ <fieldname>bytesfree</fieldname>
+ <description>The number of KB's there must be free before processing any mail.</description>
+ <type>input</type>
+ <required />
+ <default_value>10000</default_value>
+ </field>
+ <field>
+ <fielddescr>Broken Email Clients</fielddescr>
+ <fieldname>brokenec</fieldname>
+ <description>
+ Some email clients may require special processing.
+ </description>
+ <type>checkbox</type>
+ <donotdisable>true</donotdisable>
+ </field>
+ <field>
+ <fielddescr>ISP Spam</fielddescr>
+ <fieldname>ispspam</fieldname>
+ <description>
+ This option allows you to set the string your &lt;acronym title=&quot;Internet Service Provider&quot;&gt;ISP&lt;/acronym&gt; uses if it processes
+ your email for SPAM. Leave this field blank if you are not going to use
+ this option.
+ </description>
+ <type>input</type>
+ <default_value>-- Spam --</default_value>
+ </field>
+ <field>
+ <fielddescr>Subject</fielddescr>
+ <fieldname>subject</fieldname>
+ <description>
+ This option can be used to change the default subject line when
+ reporting a virus infected message.
+ </description>
+ <type>input</type>
+ <size>60</size>
+ <required />
+ <default_value>Subject: "[Virus] found in a mail to you:" &lt;virus name&gt;</default_value>
+ </field>
+ <field>
+ <fielddescr>Notify</fielddescr>
+ <fieldname>notify</fieldname>
+ <description>
+ This option can be used to change the default file deleted notification
+ that is displayed in the virus notification message when the
+ &quot;justdelete&quot; option is used.
+ </description>
+ <type>input</type>
+ <size>60</size>
+ <required />
+ <default_value>Per instruction, the message has been deleted.</default_value>
+ </field>
+ <field>
+ <fielddescr>SMTP Reject</fielddescr>
+ <fieldname>smtpreject</fieldname>
+ <description>
+ This option can be used to change the default lt;acronym title=&quot;Simple Mail Transfer Protocol&quot;&gt;SMTP&lt;/acronym&gt; Reject message that
+ is sent to the client in the event a message is rejected due to a virus.
+ The error message will have a prefix of &quot;554&quot;.
+ </description>
+ <type>input</type>
+ <size>60</size>
+ <required />
+ <default_value>Virus detected! P3scan rejected message!</default_value>
+ </field>
+ <field>
+ <fielddescr>Check SMTP size</fielddescr>
+ <fieldname>checksize</fieldname>
+ <description>
+ This option can be used to set the maximum message size (in KBytes)
+ that p3scan will use to determine if it should scan an smtp submission.
+ Leave this field blank if you are not going to use this option.
+ </description>
+ <type>input</type>
+ <default_value>1024</default_value>
+ </field>
+ <field>
+ <fielddescr>Footer</fielddescr>
+ <fieldname>footer</fieldname>
+ <description>
+ This option is used to add the virus definition info from your scanner
+ to an SMTP message. Leave this field blank if you are not going to use
+ this option.
+ </description>
+ <type>input</type>
+ <size>40</size>
+ <default_value>/usr/local/bin/clamdscan -V</default_value>
+ </field>
+ </fields>
+ <!--
+ Arbitrary PHP Code, that gets executed if a certain event gets triggered.
+ -->
+ <custom_php_resync_config_command>
+ sync_package_p3scan();
+ </custom_php_resync_config_command>
+</packagegui>
diff --git a/config/dspam/pkg/p3scan-pf-spam.xml b/config/dspam/pkg/p3scan-pf-spam.xml
new file mode 100644
index 00000000..eae78a0f
--- /dev/null
+++ b/config/dspam/pkg/p3scan-pf-spam.xml
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <!-- change this if configpath works -->
+ <name>p3scanpfspam</name>
+ <version>1.0</version>
+ <title>Services: POP3 Proxy: SPAM Settings</title>
+ <note>
+ This &lt;acronym title=&quot;Hypertext Markup Language&quot;&gt;HTML&lt;/acronym&gt; page uses default values, hence even if each field is
+ set, you are still required to save this page if you are editing this page
+ for the very first time!
+ </note>
+ <aftersaveredirect>pkg_edit.php?xml=p3scan-pf-spam.xml&amp;id=0</aftersaveredirect>
+ <include_file>/usr/local/pkg/p3scan.inc</include_file>
+ <tabs>
+ <tab>
+ <text>Daemon Settings</text>
+ <url>/pkg_edit.php?xml=p3scan-pf.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Message Processing</text>
+ <url>pkg_edit.php?xml=p3scan-pf-msg.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Emergency Contact</text>
+ <url>/pkg.php?xml=p3scan-pf-emer.xml</url>
+ </tab>
+ <tab>
+ <text>Virus Scanner Settings</text>
+ <url>/pkg_edit.php?xml=p3scan-pf-vir.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>SPAM Settings</text>
+ <url>/pkg_edit.php?xml=p3scan-pf-spam.xml&amp;id=0</url>
+ <active />
+ </tab>
+ </tabs>
+ <!--
+ configpath gets expanded out automatically and config items
+ will be stored in that location
+ -->
+ <configpath>['installedpackages']['p3scanpf']['config']['spam']</configpath>
+ <!--
+ fields gets invoked when the user adds or edits a item. The following items
+ will be parsed and rendered for the user as a gui with input, and selectboxes.
+ -->
+ <fields>
+ <field>
+ <fielddescr>Enable Spam Checking</fielddescr>
+ <fieldname>checkspam</fieldname>
+ <description>
+ If set, will scan for Spam before scanning for a virus.
+ </description>
+ <type>checkbox</type>
+ <donotdisable>true</donotdisable>
+ <enablefields>spamcheck</enablefields>
+ </field>
+ <field>
+ <fielddescr>SPAM Executable Command</fielddescr>
+ <fieldname>spamcheck</fieldname>
+ <description>The command (plus arguments) that should be invoked to check for SPAM messages.</description>
+ <type>input</type>
+ <size>70</size>
+ <default_value>
+ /usr/local/bin/dspam --user dspamuser --mode=teft --stdout --deliver=innocent,spam --feature=ch,no,wh
+ </default_value>
+ </field>
+ </fields>
+ <!--
+ Arbitrary PHP Code, that gets executed if a certain event gets triggered.
+ -->
+ <custom_php_resync_config_command>
+ sync_package_p3scan();
+ </custom_php_resync_config_command>
+</packagegui>
diff --git a/config/dspam/pkg/p3scan-pf-vir.xml b/config/dspam/pkg/p3scan-pf-vir.xml
new file mode 100644
index 00000000..ed68b8cf
--- /dev/null
+++ b/config/dspam/pkg/p3scan-pf-vir.xml
@@ -0,0 +1,162 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <!-- change this if configpath works -->
+ <name>p3scanpfvir</name>
+ <version>1.0</version>
+ <title>Services: POP3 Proxy: Virus Scanner Settings</title>
+ <note>
+ This &lt;acronym title=&quot;Hypertext Markup Language&quot;&gt;HTML&lt;/acronym&gt; page uses default values, hence even if each field is
+ set, you are still required to save this page if you are editing this page
+ for the very first time!
+ </note>
+ <aftersaveredirect>pkg_edit.php?xml=p3scan-pf-vir.xml&amp;id=0</aftersaveredirect>
+ <include_file>/usr/local/pkg/p3scan.inc</include_file>
+ <tabs>
+ <tab>
+ <text>Daemon Settings</text>
+ <url>/pkg_edit.php?xml=p3scan-pf.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Message Processing</text>
+ <url>/pkg_edit.php?xml=p3scan-pf-msg.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Emergency Contact</text>
+ <url>/pkg.php?xml=p3scan-pf-emer.xml</url>
+ </tab>
+ <tab>
+ <text>Virus Scanner Settings</text>
+ <url>/pkg_edit.php?xml=p3scan-pf-vir.xml&amp;id=0</url>
+ <active />
+ </tab>
+ <tab>
+ <text>SPAM Settings</text>
+ <url>/pkg_edit.php?xml=p3scan-pf-spam.xml&amp;id=0</url>
+ </tab>
+ </tabs>
+ <!--
+ configpath gets expanded out automatically and config items
+ will be stored in that location
+ -->
+ <configpath>['installedpackages']['p3scanpf']['config']['virus']</configpath>
+ <!--
+ fields gets invoked when the user adds or edits a item. The following items
+ will be parsed and rendered for the user as a gui with input, and selectboxes.
+ -->
+ <fields>
+ <field>
+ <fielddescr>Scanner Type</fielddescr>
+ <fieldname>scannertype</fieldname>
+ <description>Select here which type of scanner you want to use.</description>
+ <type>select</type>
+ <size>1</size>
+ <default_value>clamd</default_value>
+ <options>
+ <option><name>Kaspersky Anti-Virus for Linux</name><value>avpd</value></option>
+ <option><name>Kaspersky Anti-Virus for Linux (New)</name><value>avpd_new</value></option>
+ <option><name>Shell Script</name><value>bash</value></option>
+ <option><name>Default Scanner Type</name><value>basic</value></option>
+ <option><name>Clam Anti-Virus</name><value>clamd</value></option>
+ <option><name>Trophie Daemon</name><value>trophie</value></option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Virusscanner</fielddescr>
+ <fieldname>scanner</fieldname>
+ <description>Depends on scannertype.</description>
+ <type>input</type>
+ <required />
+ <default_value>127.0.0.1:3310</default_value>
+ </field>
+ <field>
+ <fielddescr>Scanner Returncode</fielddescr>
+ <fieldname>viruscode</fieldname>
+ <description>
+ Specify the returncode(s) which the scanner returns when
+ the mail is infected.
+ </description>
+ <type>input</type>
+ <default_value>1</default_value>
+ </field>
+ <field>
+ <fielddescr>Good Scanner return codes</fielddescr>
+ <fieldname>goodcode</fieldname>
+ <description>
+ Some scanners can report more than good or infected. Place valid return
+ codes here that will enable the message to be delivered without a warning.
+ </description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Regular Expression for Virusname</fielddescr>
+ <fieldname>virusregexp</fieldname>
+ <description>
+ Specify here a regular expression which describes where the name of
+ the virus can be found.
+ </description>
+ <type>input</type>
+ <default_value>.*: (.*) FOUND</default_value>
+ </field>
+ <field>
+ <fielddescr>deMIME Setting</fielddescr>
+ <fieldname>demime</fieldname>
+ <description>
+ Tick this if we should parse all lt;acronym title=&quot;Multipurpose Internet Mail Extensions&quot;&gt;MIME&lt;/acronym&gt;-sections instead of passing the
+ message as-is to the scanner.
+ </description>
+ <type>checkbox</type>
+ <donotdisable>true</donotdisable>
+ </field>
+ </fields>
+ <!--
+ Arbitrary PHP Code, that gets executed if a certain event gets triggered.
+ -->
+ <custom_php_resync_config_command>
+ sync_package_p3scan();
+ </custom_php_resync_config_command>
+</packagegui>
diff --git a/config/dspam/pkg/p3scan-pf.xml b/config/dspam/pkg/p3scan-pf.xml
new file mode 100644
index 00000000..f78c3912
--- /dev/null
+++ b/config/dspam/pkg/p3scan-pf.xml
@@ -0,0 +1,211 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>p3scanpf</name>
+ <version>1.0</version>
+ <title>Services: POP3 Proxy: Main</title>
+ <note>
+ This &lt;acronym title=&quot;Hypertext Markup Language&quot;&gt;HTML&lt;/acronym&gt; page uses default values, hence even if each field is
+ set, you are still required to save this page if you are editing this page
+ for the very first time!
+ </note>
+ <aftersaveredirect>pkg_edit.php?xml=p3scan-pf.xml&amp;id=0</aftersaveredirect>
+ <include_file>/usr/local/pkg/p3scan.inc</include_file>
+ <!-- Menu is where this packages menu will appear -->
+ <menu>
+ <name>p3scan</name>
+ <tooltiptext>A transparent POP3-Proxy with virus-scanning capabilities</tooltiptext>
+ <section>Services</section>
+ <configfile>p3scan.xml</configfile>
+ </menu>
+ <service>
+ <name>p3scan-pf</name>
+ <rcfile>/usr/local/etc/rc.d/030.p3scan.sh</rcfile>
+ </service>
+ <tabs>
+ <tab>
+ <text>Daemon Settings</text>
+ <url>/pkg_edit.php?xml=p3scan-pf.xml&amp;id=0</url>
+ <active />
+ </tab>
+ <tab>
+ <text>Message Processing</text>
+ <url>/pkg_edit.php?xml=p3scan-pf-msg.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Emergency Contact</text>
+ <url>/pkg.php?xml=p3scan-pf-emer.xml</url>
+ </tab>
+ <tab>
+ <text>Virus Scanner Settings</text>
+ <url>/pkg_edit.php?xml=p3scan-pf-vir.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>SPAM Settings</text>
+ <url>/pkg_edit.php?xml=p3scan-pf-spam.xml&amp;id=0</url>
+ </tab>
+ </tabs>
+ <!--
+ configpath gets expanded out automatically and config items
+ will be stored in that location
+ -->
+ <configpath>['installedpackages']['p3scanpf']['config']</configpath>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/p3scan-pf-msg.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/p3scan-pf-emer.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/p3scan-pf-vir.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/p3scan-pf-spam.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/p3scan_rules.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/p3scan.inc</item>
+ </additional_files_needed>
+ <!--
+ fields gets invoked when the user adds or edits a item. The following items
+ will be parsed and rendered for the user as a gui with input, and selectboxes.
+ -->
+ <fields>
+ <field>
+ <fielddescr>Max Child's</fielddescr>
+ <fieldname>maxchilds</fieldname>
+ <description>The maximum number of connections we will handle at once.</description>
+ <type>input</type>
+ <default_value>10</default_value>
+ </field>
+ <field>
+ <fielddescr>IP Address</fielddescr>
+ <fieldname>ipaddr</fieldname>
+ <description>The &lt;acronym title=&quot;Internet Protocol&quot;&gt;IP&lt;/acronym&gt; Address we listen on.</description>
+ <type>input</type>
+ <required />
+ <default_value>0.0.0.0</default_value>
+ </field>
+ <field>
+ <fielddescr>Port</fielddescr>
+ <fieldname>port</fieldname>
+ <description>The &lt;acronym title=&quot;Transmission Control Protocol&quot;&gt;TCP&lt;/acronym&gt; port on we should listen.</description>
+ <type>input</type>
+ <required />
+ <default_value>8110</default_value>
+ </field>
+ <field>
+ <fielddescr>SSL Port</fielddescr>
+ <fieldname>sslport</fieldname>
+ <description>The TCP &lt;acronym title=&quot;Secure Sockets Layer&quot;&gt;SSL&lt;/acronym&gt; port on we should listen.</description>
+ <type>input</type>
+ <required />
+ <default_value>995</default_value>
+ </field>
+ <field>
+ <fielddescr>Target IP</fielddescr>
+ <fieldname>targetip</fieldname>
+ <description>Target IP is the IP to connect (0.0.0.0 enables transparent mode).</description>
+ <type>input</type>
+ <required />
+ <default_value>0.0.0.0</default_value>
+ </field>
+ <field>
+ <fielddescr>Target Port</fielddescr>
+ <fieldname>targetport</fieldname>
+ <description>Target Port is the port to connect.</description>
+ <type>input</type>
+ <required />
+ <default_value>8110</default_value>
+ </field>
+ <field>
+ <fielddescr>Email Port</fielddescr>
+ <fieldname>emailport</fieldname>
+ <description>The port we should listen on to scan outgoing email messages.</description>
+ <type>input</type>
+ <required />
+ <default_value>25</default_value>
+ </field>
+ <field>
+ <fielddescr>Daemon User</fielddescr>
+ <fieldname>daemonuser</fieldname>
+ <description>The username the daemon should run as.</description>
+ <type>input</type>
+ <required />
+ <default_value>root</default_value>
+ </field>
+ </fields>
+ <!--
+ Arbitrary PHP Code, that gets executed if a certain event gets triggered.
+ -->
+ <custom_delete_php_command>
+ sync_package_p3scan();
+ </custom_delete_php_command>
+ <custom_php_resync_config_command>
+ sync_package_p3scan();
+ </custom_php_resync_config_command>
+ <custom_php_install_command>
+ custom_php_install_command();
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ custom_php_deinstall_command();
+ </custom_php_deinstall_command>
+</packagegui>
diff --git a/config/dspam/pkg/p3scan.inc b/config/dspam/pkg/p3scan.inc
new file mode 100644
index 00000000..7d675050
--- /dev/null
+++ b/config/dspam/pkg/p3scan.inc
@@ -0,0 +1,277 @@
+<?php
+/* $Id$ */
+/* Copyright (C) 2006 Daniel S. Haischt */
+
+/* include all configuration functions */
+require_once("functions.inc");
+
+function sync_package_p3scan() {
+ global $config, $g;
+ conf_mount_rw();
+ config_lock();
+ $fd = fopen("/etc/p3scan.conf","w");
+
+ /* shorten the config path */
+ $cfg = $config['installedpackages']['p3scanpf']['config'][0];
+ $cfgmsg = $config['installedpackages']['p3scanpfmsg']['config'][0];
+ $cfgemer = $config['installedpackages']['p3scanpfemer']['config'];
+ $cfgvir = $config['installedpackages']['p3scanpfvir']['config'][0];
+ $cfgspam = $config['installedpackages']['p3scanpfspam']['config'][0];
+
+ fwrite($fd, "## p3scan-pf config file - generated by pfSense.\n##\n");
+ fwrite($fd, "## at: " . date("l dS of F Y h:i:s A") . "\n##\n");
+ /* ================================================================ */
+ /* == Tab: Daemon Settings == */
+ /* ================================================================ */
+ fwrite($fd, "## Daemon Settings.\n");
+ fwrite($fd, "pidfile = /var/run/p3scan/p3scan.pid\n");
+ if (isset($cfg['maxchilds']) && $cfg['maxchilds'] <> "")
+ fwrite($fd, "maxchilds = {$cfg['maxchilds']}\n");
+ else
+ fwrite($fd, "maxchilds = 10\n");
+ if (isset($cfg['ipaddr']) && $cfg['ipaddr'] <> "")
+ fwrite($fd, "ip = {$cfg['ipaddr']}\n");
+ else
+ fwrite($fd, "ip = 0.0.0.0\n");
+ /* TODO: Even if the port is configurable, it is
+ hardcoded in p3scan.c. This needs to be
+ changed for the sake of flexebility.
+ */
+ if (isset($cfg['port']) && $cfg['port'] <> "")
+ fwrite($fd, "port = {$cfg['port']}\n");
+ else
+ fwrite($fd, "port = 8110\n");
+ if (isset($cfg['sslport']) && $cfg['sslport'] <> "")
+ fwrite($fd, "sslport = {$cfg['sslport']}\n");
+ else
+ fwrite($fd, "sslport = 995\n");
+ if (isset($cfg['targetip']) && $cfg['targetip'] <> "")
+ fwrite($fd, "targetip = {$cfg['targetip']}\n");
+ else
+ fwrite($fd, "targetip = 0.0.0.0\n");
+ if (isset($cfg['targetport']) && $cfg['targetport'] <> "")
+ fwrite($fd, "targetport = {$cfg['targetport']}\n");
+ else
+ fwrite($fd, "targetport = 8110\n");
+ if (isset($cfg['emailport']) && $cfg['emailport'] <> "")
+ fwrite($fd, "emailport = {$cfg['emailport']}\n");
+ else
+ fwrite($fd, "emailport = 25\n");
+ if (isset($cfg['daemonuser']) && $cfg['daemonuser'] <> "")
+ fwrite($fd, "user = {$cfg['daemonuser']}\n");
+ else
+ fwrite($fd, "user = root\n");
+ fwrite($fd, "notifydir = /var/spool/p3scan/notify\n");
+ fwrite($fd, "virusdir = /var/spool/p3scan\n");
+ fwrite($fd, "template = /usr/local/etc/p3scan/p3scan.mail\n");
+
+ /* ================================================================ */
+ /* == Tab: Message Processing == */
+ /* ================================================================ */
+ fwrite($fd, "## Message Processing Settings.\n");
+ if (isset($cfgmsg['justdelete']) && $cfgmsg['justdelete'] <> "")
+ fwrite($fd, "justdelete\n");
+ if (isset($cfgmsg['bytesfree']) && $cfgmsg['bytesfree'] <> "")
+ fwrite($fd, "bytesfree = {$cfgmsg['bytesfree']}\n");
+ else
+ fwrite($fd, "bytesfree = 10000\n");
+ if (isset($cfgmsg['broken']) && $cfgmsg['broken'] <> "")
+ fwrite($fd, "broken\n");
+ if (isset($cfgmsg['timeout']) && $cfgmsg['timeout'] <> "")
+ fwrite($fd, "timeout = {$cfgmsg['timeout']}\n");
+ else
+ fwrite($fd, "timeout = 30\n");
+ if (isset($cfgmsg['ispspam']) && $cfgmsg['ispspam'] <> "")
+ fwrite($fd, "ispspam = {$cfg['ispspam']}\n");
+ if (file_exists("/usr/local/bin/renattach"))
+ fwrite($fd, "renattach = /usr/local/bin/renattach\n");
+ if (isset($cfgmsg['subject']) && $cfgmsg['subject'] <> "")
+ fwrite($fd, "subject = {$cfgmsg['subject']}\n");
+ else
+ fwrite($fd, "subject = Subject: \"[Virus] found in a mail to you:\" <virus name>\n");
+ if (isset($cfgmsg['notify']) && $cfgmsg['notify'] <> "")
+ fwrite($fd, "notify = {$cfgmsg['notify']}\n");
+ else
+ fwrite($fd, "notify = Per instruction, the message has been deleted.\n");
+ if (isset($cfgmsg['smtpreject']) && $cfgmsg['smtpreject'] <> "")
+ fwrite($fd, "smtprset = {$cfgmsg['smtpreject']}\n");
+ else
+ fwrite($fd, "smtprset = Virus detected! P3scan rejected message!\n");
+ if (isset($cfgmsg['checksize']) && $cfgmsg['checksize'] <> "")
+ fwrite($fd, "checksize = {$cfgmsg['checksize']}\n");
+ if (isset($cfgmsg['footer']) && $cfgmsg['footer'] <> "")
+ fwrite($fd, "footer = {$cfgmsg['footer']}\n");
+
+ /* ================================================================ */
+ /* == Tab: Emergency Contact == */
+ /* ================================================================ */
+ fwrite($fd, "## Emergency Contacts.\n");
+ if (is_array($cfgemer)) {
+ foreach ($cfgemer as $addr) {
+ $contact .= "{$addr['emailaddress']} ";
+ }
+ if (isset($contact) && $contact <> "")
+ fwrite($fd, "emergcon = {$contact}\n");
+ }
+
+ /* ================================================================ */
+ /* == Tab: Virus Scanner Settings == */
+ /* ================================================================ */
+ fwrite($fd, "## Virus Scanner Settings.\n");
+ if (isset($cfgvir['scannertype']) && $cfgvir['scannertype'] <> "")
+ fwrite($fd, "scannertype = {$cfgvir['scannertype']}\n");
+ else
+ fwrite($fd, "scannertype = clamd\n");
+ if (isset($cfgvir['scanner']) && $cfgvir['scanner'] <> "")
+ fwrite($fd, "scanner = {$cfgvir['scanner']}\n");
+ else
+ fwrite($fd, "scanner = 127.0.0.1:3310\n");
+ if (isset($cfgvir['viruscode']) && $cfgvir['viruscode'] <> "")
+ fwrite($fd, "viruscode = {$cfgvir['viruscode']}\n");
+ else
+ fwrite($fd, "viruscode = 1\n");
+ if (isset($cfgvir['goodcode']) && $cfgvir['goodcode'] <> "")
+ fwrite($fd, "goodcode = {$cfgvir['goodcode']}\n");
+ if (isset($cfgvir['virusregexp']) && $cfgvir['virusregexp'] <> "")
+ fwrite($fd, "virusregexp = {$cfgvir['virusregexp']}\n");
+ if (isset($cfgvir['demime']) && $cfgvir['demime'] <> "")
+ fwrite($fd, "demime\n");
+
+ /* ================================================================ */
+ /* == Tab: SPAM Settings == */
+ /* ================================================================ */
+ if (isset($cfgspam['checkspam']) && $cfgpam['checkspam'] <> "") {
+ fwrite($fd, "## SPAM Settings.\n");
+ fwrite($fd, "checkspam\n");
+ if (isset($cfgvir['spamcheck']) && $cfgvir['spamcheck'] <> "")
+ fwrite($fd, "spamcheck = {$cfgspam['spamcheck']}\n");
+ else
+ fwrite($fd, "spamcheck = /usr/local/bin/dspam --user dspamuser --mode=teft --stdout --deliver=innocent,spam --feature=ch,no,wh\n");
+ }
+
+ fclose($fd);
+
+ /* NOTE: The following code requires the p3scan.inc file to be saved with
+ UNIX Linefeeds. LF that is and NOT CR LF.
+ */
+ $start = <<<EOD
+test_p3scan_user=`cat /etc/passwd | grep p3scan`
+test_p3scan_group=`cat /etc/passwd | grep p3scan`
+
+if [ -z "\${test_p3scan_group}" ]; then
+ pw groupadd p3scan -g 108
+fi
+
+if [ -z "\${test_p3scan_user}" ]; then
+ pw useradd p3scan -u 108 -g p3scan -d /var/spool/p3scan -s /sbin/nologin -c 'P3Scan Daemon'
+fi
+
+if [ ! -d "/var/spool/p3scan" ]; then
+ mkdir /var/spool/p3scan && chown p3scan:p3scan /var/spool/p3scan
+fi
+
+if [ ! -d "/var/spool/p3scan/children" ]; then
+ mkdir /var/spool/p3scan/children && chown p3scan:p3scan /var/spool/p3scan/children
+fi
+
+if [ ! -d "/var/spool/p3scannotify" ]; then
+ mkdir /var/spool/p3scannotify && chown p3scan:p3scan /var/spool/p3scannotify
+fi
+
+if [ ! -d "/var/run/p3scan" ]; then
+ mkdir /var/run/p3scan && chown p3scan:p3scan /var/run/p3scan
+fi
+
+/sbin/mount_fdescfs fdescfs /dev/fd
+/usr/local/sbin/p3scan --configfile=/usr/local/etc/p3scan/p3scan.conf &
+
+EOD;
+
+ $stop = "/usr/bin/killall p3scan\n" .
+ "sleep 2";
+
+ write_rcfile(array(
+ "file" => "030.p3scan.sh",
+ "start" => $start,
+ "stop" => $stop
+ )
+ );
+
+ conf_mount_ro();
+ config_unlock();
+
+ if (! file_exists("/usr/local/etc/p3scan")) {
+ mkdir("/usr/local/etc/p3scan");
+ }
+ if (! file_exists("/usr/local/etc/p3scan/p3scan.conf")) {
+ mwexec("ln -s /etc/p3scan.conf /usr/local/etc/p3scan/p3scan.conf");
+ }
+ if (! file_exists("/usr/local/etc/p3scan/p3scan.mail")) {
+ $fd = fopen("/usr/local/etc/p3scan/p3scan.mail","w");
+
+ $p3scanmail = <<<EOD
+MIME-Version: 1.0
+Content-Transfer-Encoding: 8bit
+Content-Type: text/plain;
+ charset="iso-8859-1"
+
+Hello %USERNAME%.
+This message body was generated automatically from P3Scan, which runs on
+%HOSTNAME%.%DOMAINNAME% for scanning all incoming email.
+
+It replaces the body of a message sent to you that contained a VIRUS!
+
+Instead of the infected email this message has been sent to you.
+
+You may look at the message header of this message for the complete
+email header information of the infected message.
+
+Virus name:
+ %VIRUSNAME%
+(Supposed) Sender of the email:
+ %MAILFROM%
+Sent To:
+ %MAILTO%
+On Date:
+ %MAILDATE%
+Subject:
+ %SUBJECT%
+Connection data:
+ %PROTOCOL% from %CLIENTIP%:%CLIENTPORT% to %SERVERIP%:%SERVERPORT%
+Message File:
+ %P3SCANID%
+Virus Definition Info:
+ %VDINFO%
+--
+%PROGNAME% %VERSION%
+by Jack S. Lai <laitcg@cox.net>
+
+EOD;
+
+ fwrite($fd, $p3scanmail);
+ fclose($fd);
+ }
+
+ mwexec("/usr/local/etc/rc.d/030.p3scan.sh stop");
+ mwexec("/usr/local/etc/rc.d/030.p3scan.sh start");
+
+ return 0;
+}
+
+function custom_php_install_command() {
+ global $config, $g;
+ sync_package_p3scan();
+}
+
+function custom_php_deinstall_command() {
+ global $config, $g;
+ conf_mount_rw();
+ unlink_if_exists("/usr/local/pkg/pf/p3scan_rules.php");
+ unlink_if_exists("/usr/local/www/p3scan_rules.php");
+ unlink_if_exists("/usr/local/etc/p3scan/p3scan.conf");
+ unlink_if_exists("/usr/local/etc/p3scan/p3scan.mail");
+ unlink_if_exists("/usr/local/etc/rc.d/030.p3scan.sh");
+ rmdir("/usr/local/etc/p3scan");
+ conf_mount_ro();
+}
+?> \ No newline at end of file
diff --git a/config/dspam/pkg/verdana.ttf b/config/dspam/pkg/verdana.ttf
new file mode 100644
index 00000000..754a9b7b
--- /dev/null
+++ b/config/dspam/pkg/verdana.ttf
Binary files differ
diff --git a/config/dspam/www/dspam-admin-graph.php b/config/dspam/www/dspam-admin-graph.php
new file mode 100644
index 00000000..508824e2
--- /dev/null
+++ b/config/dspam/www/dspam-admin-graph.php
@@ -0,0 +1,201 @@
+<?php
+/* $Id$ */
+/*
+ dspam-admin-graph.php
+
+ Copyright (C) 2006 Daniel S. Haischt.
+ All rights reserved.
+*/
+
+/* required because of system_groupmanager.php */
+$pgtitle = array(gettext("Services"),
+ gettext("DSPAM"),
+ gettext("System Status"),
+ gettext("Graph"));
+
+require_once 'Image/Graph.php';
+require_once 'Image/Canvas.php';
+require("guiconfig.inc");
+include("/usr/local/pkg/dspam.inc");
+
+if (! $_GET ||
+ strlen($_SERVER['QUERY_STRING']) == 0 ||
+ ! isDSPAMAdmin($HTTP_SERVER_VARS['AUTH_USER'])) {
+ return;
+}
+
+$FORM =& ReadParse($_SERVER['QUERY_STRING']);
+
+list($spam, $nonspam, $sm, $fp, $inoc, $wh, $period) = split('_', $FORM['data']);
+$spam = split(',', $spam);
+$nonspam = split(',', $nonspam);
+$sm = split(',', $sm);
+$fp = split(',', $fp);
+$inoc = split(',', $inoc);
+$wh = split(',', $wh);
+$period = split(',', $period);
+
+// create a PNG canvas and enable antialiasing (canvas implementation)
+$Canvas =& Image_Canvas::factory('png', array('width' => 725,
+ 'height' => 450,
+ 'antialias' => 'native'));
+
+// create the graph
+$Graph =& Image_Graph::factory('graph', $Canvas);
+// add a TrueType font
+$Font =& $Graph->addNew('font', 'Verdana');
+// set the font size to 8 pixels
+$Font->setSize(8);
+
+$Graph->setFont($Font);
+
+// setup the plotarea, legend and their layout
+$Graph->add(
+ Image_Graph::vertical(
+ Image_Graph::factory('title', array('', 12)),
+ Image_Graph::horizontal(
+ $Plotarea = Image_Graph::factory('plotarea'),
+ $Legend = Image_Graph::factory('legend'),
+ 80
+ ),
+ 0
+ )
+);
+
+// add grids
+$Grid =& $Plotarea->addNew('line_grid', IMAGE_GRAPH_AXIS_Y);
+$Grid->setLineColor('silver');
+
+// link the legend with the plotares
+$Legend->setPlotarea($Plotarea);
+
+// create the two datasets
+$i = 0;
+$spamds =& Image_Graph::factory('dataset');
+foreach($spam as $el){
+ $spamds->addPoint(strval($period[$i]), intval($el));
+ $i++;
+}
+
+$i = 0;
+$hamds =& Image_Graph::factory('dataset');
+foreach($nonspam as $el){
+ $hamds->addPoint(strval($period[$i]), intval($el));
+ $i++;
+}
+
+$i = 0;
+$smds =& Image_Graph::factory('dataset');
+foreach($sm as $el){
+ $smds->addPoint(strval($period[$i]), intval($el));
+ $i++;
+}
+
+$i = 0;
+$fpds =& Image_Graph::factory('dataset');
+foreach($fp as $el){
+ $fpds->addPoint(strval($period[$i]), intval($el));
+ $i++;
+}
+
+$i = 0;
+$inocds =& Image_Graph::factory('dataset');
+foreach($inoc as $el){
+ $inocds->addPoint(strval($period[$i]), intval($el));
+ $i++;
+}
+
+$i = 0;
+$whds =& Image_Graph::factory('dataset');
+foreach($wh as $el){
+ $whds->addPoint(strval($period[$i]), intval($el));
+ $i++;
+}
+
+// set the name/title of each dataset
+$spamds->setName('SPAM');
+$hamds->setName('Nonspam');
+$smds->setName('Spam Misses');
+$fpds->setName('False Positives');
+$inocds->setName('Inoculations');
+$whds->setName('Auto-Whitelisted');
+
+// put each dataset in a singel ds array
+$Datasets = array($inocds, $whds, $spamds, $hamds, $smds, $fpds);
+
+// create the plot as line chart using the dataset
+$Plot =& $Plotarea->addNew('Image_Graph_Plot_Bar', array($Datasets,'stacked'));
+
+// set a fill color
+$FillArray =& Image_Graph::factory('Image_Graph_Fill_Array');
+$FillArray->addColor('#000000');
+$FillArray->addColor('#BF00BF');
+$FillArray->addColor('#BF0000');
+$FillArray->addColor('#00BF00');
+$FillArray->addColor('#BFBF00');
+$FillArray->addColor('#FF7F00');
+
+// set a standard fill style
+$Plot->setFillStyle($FillArray);
+
+/* set axis labels */
+$XAxis =& $Plotarea->getAxis(IMAGE_GRAPH_AXIS_X);
+$XAxis->setTitle("{$FORM['x_label']}", array('size' => 8, 'angle' => 0));
+$XAxis->setFontAngle(60);
+$XAxis->setLabelOptions(array('offset' => intval($FORM['offset']),
+ 'showtext' => true,
+ 'position' => 'outside'), 1);
+
+
+$YAxis =& $Plotarea->getAxis(IMAGE_GRAPH_AXIS_Y);
+$YAxis->setTitle('Number of Messages', array('size' => 8, 'angle' => 90));
+
+// create a Y data value marker
+$Marker =& $Plot->addNew('Image_Graph_Marker_Value', IMAGE_GRAPH_VALUE_Y);
+$Marker->setFontSize(6);
+
+// and use the marker on the 1st plot
+$Plot->setMarker($Marker);
+$Plot->setDataSelector(Image_Graph::factory('Image_Graph_DataSelector_NoZeros'));
+
+// output the Graph
+$Graph->done();
+
+function &ReadParse($URI = "") {
+ if ($URI == "") {
+ return NULL;
+ }
+
+ $pairs = preg_split('/&/', $URI);
+ $FORM = array();
+
+ foreach($pairs as $pair){
+ list($name, $value) = preg_split('/\=/', $pair);
+ $pattern = '/%([a-fA-F0-9][a-fA-F0-9])/';
+
+ $name = preg_replace('/\+/', ' ', $name);
+ $name = preg_replace_callback(
+ $pattern,
+ create_function(
+ '$matches',
+ 'return pack("C", hexdec($matches[1]));'
+ ),
+ $name
+ );
+
+ $value = preg_replace('/\+/', ' ', $value);
+ $value = preg_replace_callback(
+ $pattern,
+ create_function(
+ '$matches',
+ 'return pack("C", hexdec($matches[1]));'
+ ),
+ $value
+ );
+
+ $FORM[$name] = $value;
+ } // end foreach
+
+ return $FORM;
+}
+?>
diff --git a/config/dspam/www/dspam-admin-prefs.php b/config/dspam/www/dspam-admin-prefs.php
new file mode 100644
index 00000000..324d961f
--- /dev/null
+++ b/config/dspam/www/dspam-admin-prefs.php
@@ -0,0 +1,249 @@
+<?php
+/* $Id$ */
+/*
+ dspam-train.php
+
+ Copyright (C) 2006 Daniel S. Haischt.
+ All rights reserved.
+*/
+
+$pgtitle = array(gettext("Services"),
+ gettext("DSPAM"),
+ gettext("Admin Preferences"));
+
+require("guiconfig.inc");
+include("/usr/local/pkg/dspam.inc");
+
+if (isDSPAMAdmin($HTTP_SERVER_VARS['AUTH_USER'])) {
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($input_errors)) {
+ input_errors2Ajax($input_errors);
+ exit;
+ }
+
+ /* if ajax is calling, give them an update message */
+ if(isAjax())
+ print_info_box_np($savemsg);
+
+ include("head.inc");
+ /* put your custom HTML head content here */
+ /* using some of the $pfSenseHead function calls */
+ $jscriptstr = <<<EOD
+<script type="text/javascript">
+<!--
+
+EOD;
+
+ $jscriptstr .= getJScriptFunction(0);
+ $jscriptstr .= <<<EOD
+//-->
+</script>
+EOD;
+
+ $pfSenseHead->addScript($jscriptstr);
+ echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<?php include("fbegin.inc"); ?>
+<form action="dspam-admin-prefs.php" method="post" name="iform" id="iform">
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+<p>
+ <span class="vexpl">
+ This page lets you configure how the filter will handle your messages.
+ </span>
+</p>
+<table width="100%" border="0" cellspacing="0" cellpadding="0">
+ <tr>
+ <td>
+<?php
+ $tab_array = array();
+ $tab_array[] = array("System Status", false, "/dspam-admin.php?user={$CURRENT_USER}");
+ $tab_array[] = array("User Statistics", false, "/dspam-admin-stats.php?user={$CURRENT_USER}");
+ $tab_array[] = array("Administration", true, "/dspam-admin-prefs.php?user={$CURRENT_USER}");
+ $tab_array[] = array("Settings", false, "/dspam-settings.php?user={$CURRENT_USER}");
+ $tab_array[] = array("Control Center", false, "/dspam.php?user={$CURRENT_USER}");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <table class="tabcont" align="center" width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td align="left" valign="top" class="listhdrr" colspan="2">Statistical SPAM Protection for...</td>
+ </tr>
+ <tr>
+ <td width="22%" valign="baseline" class="vncell">Username</td>
+ <td width="78%" class="vtable">
+ <?php if(isset($HTTP_SERVER_VARS['AUTH_USER'])): ?>
+ <input type="text" name="username" id="username" value="<?= $CURRENT_USER ?>" class="formfld user"<?php if (! isDSPAMAdmin($HTTP_SERVER_VARS['AUTH_USER'])) { echo " readonly=\"readonly\""; } ?> />
+ <?php else: ?>
+ <input type="text" name="username" id="username" value="Please provide a username" class="formfld user" onFocus="this.value='';" />
+ <?php endif; ?>
+ &nbsp;
+ <?php
+ if (! isDSPAMAdmin($HTTP_SERVER_VARS['AUTH_USER']))
+ $action = "onClick=\"changeuser();\"";
+ else
+ $action = "onClick=\"document.iform.submit();\"";
+ ?>
+ <input type="button" name="change_user" id="change_user" class="formbtn" value="Change" <?= $action ?> />
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2" class="list" height="12">&nbsp;</td>
+ </tr>
+ <tr>
+ <td align="left" valign="top" class="listtopic" colspan="2">
+ <strong>Training</strong> &ndash; Configure how the filter learns as it processes messages
+ </td>
+ </tr>
+ <tr>
+ <td align="left" valign="top" class="vncell" width="40%">
+ <p>DSPAM should train:</p>
+ <input <?= $DATA["S_TEFT"]; ?> value="TEFT" type="radio" class="formfld" title="On every new message scanned by the filter" alt="On every new message scanned by the filter" name="rad_train" id="rad_train_one" />
+ <label for="rad_train_one">&nbsp;On every new message scanned by the filter (TEFT)</label>
+ <br />
+ <input <?= $DATA["S_TOE"]; ?> value="TOE" type="radio" class="formfld" title="Only when the filter makes a mistake" alt="Only when the filter makes a mistake" name="rad_train" id="rad_train_two" />
+ <label for="rad_train_two">&nbsp;Only when the filter makes a mistake (TOE)</label>
+ <br />
+ <input <?= $DATA["S_TUM"]; ?> value="TUM" type="radio" class="formfld" title=";Only with new data or if the filter makes a mistake" alt=";Only with new data or if the filter makes a mistake" name="rad_train" id="rad_train_three" />
+ <label for="rad_train_three">&nbsp;Only with new data or if the filter makes a mistake (TUM)</label>
+ </td>
+ <td align="left" valign="top" class="vncell" width="60%">
+ <p>When I train DSPAM, I prefer:</p>
+ <input value="message" <?= $DATA["S_LOC_MESSAGE"]; ?> value="message" type="radio" class="formfld" title="To forward my spams (signature appears in message body)" alt="To forward my spams (signature appears in message body)" name="rad_train_action" id="rad_train_action_one" />
+ <label for="rad_train_action_one">&nbsp;To <u>forward</u> my spams (signature appears in message body)</label>
+ <br />
+ <input <?= $DATA["S_LOC_HEADERS"]; ?> value="headers" type="radio" class="formfld" title="To bounce my spams (signature appears in message headers)" alt="To bounce my spams (signature appears in message headers)" name="rad_train_action" id="rad_train_action_two" />
+ <label value="headers" for="rad_train_action_two">&nbsp;To <u>bounce</u> my spams (signature appears in message headers)</label>
+ </td>
+ </tr>
+ <tr>
+ <td align="left" valign="middle" class="vncell" colspan="2">
+ <p>
+ Filter sensitivity <strong>during</strong> the training period:
+ </p>
+ <p align="center">
+ <nobr>
+ <span>
+ Catch SPAM (More in Quarantine)&nbsp;
+ <input value="0" type="radio" class="formfld" title="-5" alt="-5" name="rad_filter_sens" <?= $DATA["SEDATION_0"]; ?> />
+ <input value="1" type="radio" class="formfld" title="-4" alt="-4" name="rad_filter_sens" <?= $DATA["SEDATION_1"]; ?> />
+ <input value="2" type="radio" class="formfld" title="-3" alt="-3" name="rad_filter_sens" <?= $DATA["SEDATION_2"]; ?> />
+ <input value="3" type="radio" class="formfld" title="-2" alt="-2" name="rad_filter_sens" <?= $DATA["SEDATION_3"]; ?> />
+ <input value="4" type="radio" class="formfld" title="-1" alt="-1" name="rad_filter_sens" <?= $DATA["SEDATION_4"]; ?> />
+ <strong style="font-size: larger;">&raquo;</strong>
+ <input value="5" type="radio" class="formfld" title="0" alt="0" name="rad_filter_sens" <?= $DATA["SEDATION_5"]; ?> />
+ <strong style="font-size: larger;">&laquo;</strong>
+ <input value="6" type="radio" class="formfld" title="1" alt="1" name="rad_filter_sens" <?= $DATA["SEDATION_6"]; ?> />
+ <input value="7" type="radio" class="formfld" title="2" alt="2" name="rad_filter_sens" <?= $DATA["SEDATION_7"]; ?> />
+ <input value="8" type="radio" class="formfld" title="3" alt="3" name="rad_filter_sens" <?= $DATA["SEDATION_8"]; ?> />
+ <input value="9" type="radio" class="formfld" title="4" alt="4" name="rad_filter_sens" <?= $DATA["SEDATION_9"]; ?> />
+ <input value="10" type="radio" class="formfld" title="5" alt="5" name="rad_filter_sens" <?= $DATA["SEDATION_10"]; ?> />
+ &nbsp;Assume Good (Fewer in Quarantine)
+ </span>
+ </nobr>
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2" class="list" height="12">&nbsp;</td>
+ </tr>
+ <tr>
+ <td align="left" valign="top" class="listtopic" colspan="2">
+ <strong>Message Handling</strong> &ndash; Configure how SPAM is handled
+ </td>
+ </tr>
+ <tr>
+ <td align="left" valign="top" class="vncell" colspan="2">
+ <p>When a SPAM message is identified:</p>
+ <p>
+ <input value="quarantine" <?= $DATA["S_ACTION_QUARANTINE"]; ?> type="radio" class="formfld" title="Quarantine the message" alt="Quarantine the message" name="rad_ident_action" id="rad_ident_action_one" />
+ <label for="rad_ident_action_one">&nbsp;Quarantine the message</label>
+ <br />
+ <input value="tag" <?= $DATA["S_ACTION_TAG"]; ?> type="radio" class="formfld" title="Tag the Subject header with" alt="Tag the Subject header with" name="rad_ident_action" id="rad_ident_action_two" />
+ <label for="rad_ident_action_two">Tag the Subject header with&nbsp;</label>
+ <input size="35" type="text" class="formfld mail" title="message tag" alt="message tag" value="<?= $DATA["SPAM_SUBJECT"]; ?>" name="msgtag" />
+ <br />
+ <input value="deliver" <?= $DATA["S_ACTION_DELIVER"]; ?> type="radio" class="formfld" title="Deliver the message normally with a X-DSPAM-Result header" alt="Deliver the message normally with a X-DSPAM-Result header" name="rad_ident_action" id="rad_ident_action_three" />
+ <label for="rad_ident_action_three">&nbsp;Deliver the message normally with a X-DSPAM-Result header</label>
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2" class="list" height="12">&nbsp;</td>
+ </tr>
+ <tr>
+ <td align="left" valign="top" class="listtopic" colspan="2">
+ <strong>Features</strong> &ndash; Tuning SPAM filtering
+ </td>
+ </tr>
+ <tr>
+ <td align="left" valign="top" class="vncell" colspan="2">
+ <p>
+ <input <?= $DATA["C_BNR"]; ?> type="checkbox" class="formbtn" title="Enable noise reduction, which usually improves filtering accuracy" alt="Enable noise reduction, which usually improves filtering accuracy" name="chk_feature_nr" id="chk_feature_nr" />
+ <label for="chk_feature_nr">&nbsp;Enable noise reduction, which usually improves filtering accuracy</label>
+ <br />
+ <input <?= $DATA["C_WHITELIST"]; ?> type="checkbox" class="formbtn" title="Enable automatic whitelisting to record frequent correspondence" alt="Enable automatic whitelisting to record frequent correspondence" name="chk_feature_aw" id="chk_feature_aw" />
+ <label for="chk_feature_aw">&nbsp;Enable automatic whitelisting to record frequent correspondence</label>
+ <br />
+ <input <?= $DATA["C_FACTORS"]; ?> type="checkbox" class="formbtn" title="Add the factoring tokens in each email into the message's full headers" alt="Add the factoring tokens in each email into the message's full headers" name="chk_feature_at" id="chk_feature_at" />
+ <label for="chk_feature_at">&nbsp;Add the factoring tokens in each email into the message's full headers</label>
+ <!--
+ <input type="checkbox" class="formbtn" title="Add the factoring tokens in each email into the message's full headers" alt="Add the factoring tokens in each email into the message's full headers" name="chk_feature_at" id="chk_feature_at" />
+ <label for="chk_feature_at">&nbsp;Add the factoring tokens in each email into the message's full headers</label>
+ <br />
+ <input type="checkbox" class="formbtn" title="opt in of DSPAM filtering" alt="opt in of DSPAM filtering" name="chk_feature_optin" id="chk_feature_optin" />
+ <label for="chk_feature_optin">&nbsp;opt in of DSPAM filtering</label>
+ <br />
+ <input type="checkbox" class="formbtn" title="opt out of DSPAM filtering" alt="opt out of DSPAM filtering" name="chk_feature_optout" id="chk_feature_optout" />
+ <label for="chk_feature_optout">&nbsp;opt out of DSPAM filtering</label>
+ -->
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2" class="list" height="12">&nbsp;</td>
+ </tr>
+ <tr>
+ <td class="list">&nbsp;</td>
+ <td class="list">
+ <input id="submitt" name="Submit" type="submit" class="formbtn" value="<?=gettext("Save");?>" />
+ </td>
+ </tr>
+ </table>
+ </div>
+ </td>
+ </tr>
+</table>
+</form>
+<?
+} else {
+?>
+<?php
+ $input_errors[] = "Access to this particular site was denied. You need DSPAM admin access rights to be able to view it.";
+
+ include("head.inc");
+ echo $pfSenseHead->getHTML();
+?>
+<?php include("fbegin.inc");?>
+<?php if ($input_errors) print_input_errors($input_errors);?>
+<?php if ($savemsg) print_info_box($savemsg);?>
+ <body link="#000000" vlink="#000000" alink="#000000">
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td valign="top" class="listtopic">Access denied for: <?=$HTTP_SERVER_VARS['AUTH_USER']?></td>
+ </tr>
+ </table>
+<?php
+} // end of access denied code
+?>
+<?php include("fend.inc"); ?>
+</body>
+</html> \ No newline at end of file
diff --git a/config/dspam/www/dspam-admin-stats.php b/config/dspam/www/dspam-admin-stats.php
new file mode 100644
index 00000000..82b91831
--- /dev/null
+++ b/config/dspam/www/dspam-admin-stats.php
@@ -0,0 +1,123 @@
+<?php
+/* $Id$ */
+/*
+ dspam-train.php
+
+ Copyright (C) 2006 Daniel S. Haischt.
+ All rights reserved.
+*/
+
+$pgtitle = array(gettext("Services"),
+ gettext("DSPAM"),
+ gettext("User Statistics"));
+
+require("guiconfig.inc");
+include("/usr/local/pkg/dspam.inc");
+
+if (isDSPAMAdmin($HTTP_SERVER_VARS['AUTH_USER'])) {
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($input_errors)) {
+ input_errors2Ajax($input_errors);
+ exit;
+ }
+
+ /* if ajax is calling, give them an update message */
+ if(isAjax())
+ print_info_box_np($savemsg);
+
+ include("head.inc");
+ /* put your custom HTML head content here */
+ /* using some of the $pfSenseHead function calls */
+ echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<?php include("fbegin.inc"); ?>
+<form action="dspam-admin-stats.php" method="post" name="iform" id="iform">
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+<p>
+ <span class="vexpl">
+ The following table shows the number of messages processed for each user
+ along with their current preference settings.
+ </span>
+</p>
+<table width="100%" border="0" cellspacing="0" cellpadding="0">
+ <tr>
+ <td>
+<?php
+ $tab_array = array();
+ $tab_array[] = array("System Status", false, "/dspam-admin.php?user={$CURRENT_USER}");
+ $tab_array[] = array("User Statistics", true, "/dspam-admin-stats.php?user={$CURRENT_USER}");
+ $tab_array[] = array("Administration", false, "/dspam-admin-prefs.php?user={$CURRENT_USER}");
+ $tab_array[] = array("Settings", false, "/dspam-settings.php?user={$CURRENT_USER}");
+ $tab_array[] = array("Control Center", false, "/dspam.php?user={$CURRENT_USER}");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <table class="tabcont" align="center" width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td align="left" valign="top" class="listhdrr" colspan="14">Statistical SPAM Protection for...</td>
+ </tr>
+ <tr>
+ <td width="22%" valign="baseline" class="vncell">Username</td>
+ <td width="78%" class="vtable" colspan="13">
+ <strong><?= $CURRENT_USER ?></strong>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="14" class="list" height="12">&nbsp;</td>
+ </tr>
+ <tr>
+ <td align="left" valign="top" class="listtopic">Name</td>
+ <td align="left" valign="top" class="listtopic">Q.Size</td>
+ <td align="left" valign="top" class="listtopic">TP</td>
+ <td align="left" valign="top" class="listtopic">TN</td>
+ <td align="left" valign="top" class="listtopic">FP</td>
+ <td align="left" valign="top" class="listtopic">FN</td>
+ <td align="left" valign="top" class="listtopic">SC</td>
+ <td align="left" valign="top" class="listtopic">IC</td>
+ <td align="left" valign="top" class="listtopic">Mode</td>
+ <td align="left" valign="top" class="listtopic">On Spam</td>
+ <td align="left" valign="top" class="listtopic">BNR</td>
+ <td align="left" valign="top" class="listtopic">Whitelist</td>
+ <td align="left" valign="top" class="listtopic">Sed</td>
+ <td align="left" valign="top" class="listtopic">Sig Loc</td>
+ </tr>
+ <?= $DATA['TABLE']; ?>
+ </table>
+ </div>
+ </td>
+ </tr>
+</table>
+</form>
+<?
+} else {
+?>
+<?php
+ $input_errors[] = "Access to this particular site was denied. You need DSPAM admin access rights to be able to view it.";
+
+ include("head.inc");
+ echo $pfSenseHead->getHTML();
+?>
+<?php include("fbegin.inc");?>
+<?php if ($input_errors) print_input_errors($input_errors);?>
+<?php if ($savemsg) print_info_box($savemsg);?>
+ <body link="#000000" vlink="#000000" alink="#000000">
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td valign="top" class="listtopic">Access denied for: <?=$HTTP_SERVER_VARS['AUTH_USER']?></td>
+ </tr>
+ </table>
+<?php
+} // end of access denied code
+?>
+<?php include("fend.inc"); ?>
+</body>
+</html> \ No newline at end of file
diff --git a/config/dspam/www/dspam-admin.php b/config/dspam/www/dspam-admin.php
new file mode 100644
index 00000000..45b33b55
--- /dev/null
+++ b/config/dspam/www/dspam-admin.php
@@ -0,0 +1,207 @@
+<?php
+/* $Id$ */
+/*
+ dspam-train.php
+
+ Copyright (C) 2006 Daniel S. Haischt.
+ All rights reserved.
+*/
+
+$pgtitle = array(gettext("Services"),
+ gettext("DSPAM"),
+ gettext("System Status"),
+ gettext("Overview"));
+
+require("guiconfig.inc");
+include("/usr/local/pkg/dspam.inc");
+
+if (isDSPAMAdmin($HTTP_SERVER_VARS['AUTH_USER'])) {
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($input_errors)) {
+ input_errors2Ajax($input_errors);
+ exit;
+ }
+
+ /* if ajax is calling, give them an update message */
+ if(isAjax())
+ print_info_box_np($savemsg);
+
+ include("head.inc");
+ /* put your custom HTML head content here */
+ /* using some of the $pfSenseHead function calls */
+ echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<?php include("fbegin.inc"); ?>
+<form action="dspam-admin.php" method="post" name="iform" id="iform">
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+<p>
+ <span class="vexpl">
+ The following graphs and tables summarize the processing done by the filter.
+ </span>
+</p>
+<table width="100%" border="0" cellspacing="0" cellpadding="0">
+ <tr>
+ <td>
+<?php
+ $tab_array = array();
+ $tab_array[] = array("System Status", true, "/dspam-admin.php?user={$CURRENT_USER}");
+ $tab_array[] = array("User Statistics", false, "/dspam-admin-stats.php?user={$CURRENT_USER}");
+ $tab_array[] = array("Administration", false, "/dspam-admin-prefs.php?user={$CURRENT_USER}");
+ $tab_array[] = array("Settings", false, "/dspam-settings.php?user={$CURRENT_USER}");
+ $tab_array[] = array("Control Center", false, "/dspam.php?user={$CURRENT_USER}");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <table class="tabcont" align="center" width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td align="left" valign="top" class="listhdrr" colspan="2">Statistical SPAM Protection for...</td>
+ </tr>
+ <tr>
+ <td width="10%" valign="baseline" class="vncell">Username</td>
+ <td width="90%" class="vtable">
+ <strong><?= $CURRENT_USER ?></strong>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2" class="list" height="12">&nbsp;</td>
+ </tr>
+ <tr>
+ <td colspan="2" align="left" valign="top" class="listtopic">
+ <strong>Overview</strong>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2" align="center" valign="top" class="vncell">
+ <table align="center" width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td align="left" valign="top" class="listhdrr">Messages</td>
+ <td align="left" valign="top" class="listhdrr">Today</td>
+ <td align="left" valign="top" class="listhdrr">This Hour</td>
+ <td align="left" valign="top" class="list">&nbsp;</td>
+ <td align="left" valign="top" class="listhdrr">Status</td>
+ <td align="left" valign="top" class="listhdrr">Current Value</td>
+ </tr>
+ <tr>
+ <td align="left" valign="top" class="listr">Spam</td>
+ <td align="left" valign="top" class="listr"><?= $DATA['SPAM_TODAY']; ?></td>
+ <td align="left" valign="top" class="listr"><?= $DATA['SPAM_THIS_HOUR']; ?></td>
+ <td align="left" valign="top" class="list">&nbsp;</td>
+ <td align="left" valign="top" class="listr">Average message processing time</td>
+ <td align="left" valign="top" class="listr"><?= $DATA['AVG_PROCESSING_TIME']; ?> sec.</td>
+ </tr>
+ <tr>
+ <td align="left" valign="top" class="listr">Good</td>
+ <td align="left" valign="top" class="listr"><?= $DATA['NONSPAM_TODAY']; ?></td>
+ <td align="left" valign="top" class="listr"><?= $DATA['NONSPAM_THIS_HOUR']; ?></td>
+ <td align="left" valign="top" class="list">&nbsp;</td>
+ <td align="left" valign="top" class="listr">Average throughput</td>
+ <td align="left" valign="top" class="listr"><?= $DATA['AVG_MSG_PER_SECOND']; ?> messages/sec.</td>
+ </tr>
+ <tr>
+ <td align="left" valign="top" class="listr">Spam Misses</td>
+ <td align="left" valign="top" class="listr"><?= $DATA['SM_TODAY']; ?></td>
+ <td align="left" valign="top" class="listr"><?= $DATA['SM_THIS_HOUR']; ?></td>
+ <td align="left" valign="top" class="list">&nbsp;</td>
+ <td align="left" valign="top" class="listr">DSPAM instances</td>
+ <td align="left" valign="top" class="listr"><?= $DATA['DSPAM_PROCESSES']; ?> process(es)</td>
+ </tr>
+ <tr>
+ <td align="left" valign="top" class="listr">False Positives</td>
+ <td align="left" valign="top" class="listr"><?= $DATA['FP_TODAY']; ?></td>
+ <td align="left" valign="top" class="listr"><?= $DATA['FP_THIS_HOUR']; ?></td>
+ <td align="left" valign="top" class="list">&nbsp;</td>
+ <td align="left" valign="top" class="listr">System uptime</td>
+ <td align="left" valign="top" class="listr"><?= $DATA['UPTIME']; ?></td>
+ </tr>
+ <tr>
+ <td align="left" valign="top" class="listr">Inoculations</td>
+ <td align="left" valign="top" class="listr"><?= $DATA['INOC_TODAY']; ?></td>
+ <td align="left" valign="top" class="listr"><?= $DATA['INOC_THIS_HOUR']; ?></td>
+ <td align="left" valign="top" class="list">&nbsp;</td>
+ <td align="left" valign="top" class="listr">Mail queue length</td>
+ <td align="left" valign="top" class="listr"><?= $DATA['MAIL_QUEUE']; ?> messages</td>
+ </tr>
+ <tr>
+ <td align="left" valign="top" class="listbgns"><strong>Total</strong></td>
+ <td align="left" valign="top" class="listbgns"><strong><?= $DATA['TOTAL_TODAY']; ?></strong></td>
+ <td align="left" valign="top" class="listbgns"><strong><?= $DATA['TOTAL_THIS_HOUR']; ?></strong></td>
+ <td align="left" valign="top" class="list">&nbsp;</td>
+ <td align="left" valign="top" class="list">&nbsp;</td>
+ <td align="left" valign="top" class="list">&nbsp;</td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2" class="list" height="12">&nbsp;</td>
+ </tr>
+ <tr>
+ <td colspan="2" align="left" valign="top" class="listtopic">
+ <strong>24 Hour Activity</strong> &ndash; 125 SPAM, 601 Good, 2 Spam Misses, 0 False Positives, 2 Inoculations
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2" align="center" valign="top" class="vncell">
+ <?php if(isset($_GET['test'])): ?>
+ <img src="/dspam-admin-graph.php?data=1,2,5,6,2,6,3,1,3,9,5,2,4,8,9,6,9,2,6,8,3,3,5,2_4,22,12,9,11,10,10,8,2,9,9,27,18,26,20,20,11,14,27,69,51,108,86,43_0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0_0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0_0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,2,0,0,0,0_2,8,3,9,7,4,3,2,2,,4,7,6,3,4,6,2,7,4,17,5,3,10,1_10:00pm,11:00pm,12:00am,1:00am,2:00am,3:00am,4:00am,5:00am,6:00am,7:00am,8:00am,9:00am,10:00am,11:00am,12:00pm,1:00pm,2:00pm,3:00pm,4:00pm,5:00pm,6:00pm,7:00pm,8:00pm,9:00pm&x_label=Hour+of+the+day&offset=35" alt="24 Hour Activity" border="0" />
+ <?php else: ?>
+ <img src="/dspam-admin-graph.php?data=<?= $DATA['DATA_DAILY']; ?>&x_label=<?= urlencode("Hour of the day"); ?>&offset=20" alt="24 Hour Activity" border="0" />
+ <?php endif; ?>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2" class="list" height="12">&nbsp;</td>
+ </tr>
+ <tr>
+ <td colspan="2" align="left" valign="top" class="listtopic">
+ <strong>Daily Activity</strong> &ndash; 2457 SPAM, 10772 Good, 35 Spam Misses, 0 False Positives, 33 Inoculations
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2" align="center" valign="top" class="vncell">
+ <?php if(isset($_GET['test'])): ?>
+ <img src="/dspam-admin-graph.php?data=105,98,54,104,85,94,93,103,115,122,109,94,77,103,116,105,112,103,97,83,87,99,97,126,107_368,339,326,395,367,166,176,325,376,382,458,305,149,134,335,396,388,368,403,220,142,534,312,595,600_0,2,0,2,1,3,0,1,4,1,0,0,0,1,2,1,2,1,2,3,4,1,1,2,0_0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0_1,1,2,1,4,1,0,3,1,0,2,0,2,1,2,1,1,5,0,1,0,0,0,2,4_129,142,76,184,139,55,51,94,107,139,168,130,70,63,123,140,118,96,108,88,46,110,133,143,109_5/29/2006,5/30/2006,5/31/2006,6/1/2006,6/2/2006,6/3/2006,6/4/2006,6/5/2006,6/6/2006,6/7/2006,6/8/2006,6/9/2006,6/10/2006,6/11/2006,6/12/2006,6/13/2006,6/14/2006,6/15/2006,6/16/2006,6/17/2006,6/18/2006,6/19/2006,6/20/2006,6/21/2006,6/22/2006&graph=period&x_label=Date&offset=45" border="0" />
+ <?php else: ?>
+ <img src="/dspam-admin-graph.php?data=<?= $DATA['DATA_WEEKLY']; ?>&graph=period&x_label=Date&offset=45" border="0" />
+ <?php endif; ?>
+ </td>
+ </tr>
+ </table>
+ </div>
+ </td>
+ </tr>
+</table>
+</form>
+<?
+} else {
+?>
+<?php
+ $input_errors[] = "Access to this particular site was denied. You need DSPAM admin access rights to be able to view it.";
+
+ include("head.inc");
+ echo $pfSenseHead->getHTML();
+?>
+<?php include("fbegin.inc");?>
+<?php if ($input_errors) print_input_errors($input_errors);?>
+<?php if ($savemsg) print_info_box($savemsg);?>
+ <body link="#000000" vlink="#000000" alink="#000000">
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td valign="top" class="listtopic">Access denied for: <?=$HTTP_SERVER_VARS['AUTH_USER']?></td>
+ </tr>
+ </table>
+<?php
+} // end of access denied code
+?>
+<?php include("fend.inc"); ?>
+</body>
+</html> \ No newline at end of file
diff --git a/config/dspam/www/dspam-analysis-graph.php b/config/dspam/www/dspam-analysis-graph.php
new file mode 100644
index 00000000..67262564
--- /dev/null
+++ b/config/dspam/www/dspam-analysis-graph.php
@@ -0,0 +1,137 @@
+<?php
+/* $Id$ */
+/*
+ dspam-analysis-graph.php
+
+ Copyright (C) 2006 Daniel S. Haischt.
+ All rights reserved.
+*/
+
+/* required because of system_groupmanager.php */
+$pgtitle = array(gettext("Services"),
+ gettext("DSPAM"),
+ gettext("Analysis"),
+ gettext("Graph"));
+
+require_once 'Image/Graph.php';
+require("guiconfig.inc");
+include("/usr/local/pkg/dspam.inc");
+
+if (! $_GET ||
+ strlen($_SERVER['QUERY_STRING']) == 0) {
+ return;
+}
+
+$FORM =& ReadParse($_SERVER['QUERY_STRING']);
+
+list($spam, $nonspam, $period) = split('_', $FORM['data']);
+$spam_day = split(',', $spam);
+$nonspam_day = split(',', $nonspam);
+$period = split(',', $period);
+
+// create the graph
+$Graph =& Image_Graph::factory('graph', array(725, 300));
+
+// add a TrueType font
+$Font =& $Graph->addNew('font', 'Verdana');
+// set the font size to 11 pixels
+$Font->setSize(8);
+
+$Graph->setFont($Font);
+
+// setup the plotarea, legend and their layout
+$Graph->add(
+ Image_Graph::vertical(
+ Image_Graph::factory('title', array('', 12)),
+ Image_Graph::vertical(
+ $Plotarea = Image_Graph::factory('plotarea'),
+ $Legend = Image_Graph::factory('legend'),
+ 88
+ ),
+ 5
+ )
+);
+
+// link the legend with the plotares
+$Legend->setPlotarea($Plotarea);
+
+// create the two datasets
+$i = 0;
+$spamds =& Image_Graph::factory('dataset');
+foreach($spam_day as $el){
+ $spamds->addPoint(strval($period[$i]), intval($el));
+ $i++;
+}
+
+$i = 0;
+$hamds =& Image_Graph::factory('dataset');
+foreach($nonspam_day as $el){
+ $hamds->addPoint(strval($period[$i]), intval($el));
+ $i++;
+}
+
+// set the name/title of each dataset
+$spamds->setName('SPAM');
+$hamds->setName('Good');
+
+// put each dataset in a singel ds array
+$Datasets = array($spamds, $hamds);
+
+// create the plot as line chart using the dataset
+$Plot =& $Plotarea->addNew('Image_Graph_Plot_Line', array($Datasets,'normal'));
+
+// set a line color
+$LineArray =& Image_Graph::factory('Image_Graph_Line_Array');
+$LineArray->addColor('red');
+$LineArray->addColor('green');
+
+// set a standard line style
+$Plot->setLineStyle($LineArray);
+
+/* set axis labels */
+$XAxis =& $Plotarea->getAxis(IMAGE_GRAPH_AXIS_X);
+$XAxis->setTitle("{$FORM['x_label']}");
+$YAxis =& $Plotarea->getAxis(IMAGE_GRAPH_AXIS_Y);
+$YAxis->setTitle('Number of Messages', 'vertical');
+
+// output the Graph
+$Graph->done();
+
+function &ReadParse($URI = "") {
+ if ($URI == "") {
+ return NULL;
+ }
+
+ $pairs = preg_split('/&/', $URI);
+ $FORM = array();
+
+ foreach($pairs as $pair){
+ list($name, $value) = preg_split('/\=/', $pair);
+ $pattern = '/%([a-fA-F0-9][a-fA-F0-9])/';
+
+ $name = preg_replace('/\+/', ' ', $name);
+ $name = preg_replace_callback(
+ $pattern,
+ create_function(
+ '$matches',
+ 'return pack("C", hexdec($matches[1]));'
+ ),
+ $name
+ );
+
+ $value = preg_replace('/\+/', ' ', $value);
+ $value = preg_replace_callback(
+ $pattern,
+ create_function(
+ '$matches',
+ 'return pack("C", hexdec($matches[1]));'
+ ),
+ $value
+ );
+
+ $FORM[$name] = $value;
+ } // end foreach
+
+ return $FORM;
+}
+?>
diff --git a/config/dspam/www/dspam-analysis.php b/config/dspam/www/dspam-analysis.php
new file mode 100644
index 00000000..f80bd54b
--- /dev/null
+++ b/config/dspam/www/dspam-analysis.php
@@ -0,0 +1,147 @@
+<?php
+/* $Id$ */
+/*
+ dspam-analysis.php
+
+ Copyright (C) 2006 Daniel S. Haischt.
+ All rights reserved.
+*/
+
+$pgtitle = array(gettext("Services"),
+ gettext("DSPAM"),
+ gettext("Analysis"),
+ gettext("Overview"));
+
+require("guiconfig.inc");
+include("/usr/local/pkg/dspam.inc");
+
+/* if this is an AJAX caller then handle via JSON */
+if(isAjax() && is_array($input_errors)) {
+ input_errors2Ajax($input_errors);
+ exit;
+}
+
+/* if ajax is calling, give them an update message */
+if(isAjax())
+ print_info_box_np($savemsg);
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+
+ $jscriptstr = <<<EOD
+<script type="text/javascript">
+<!--
+
+EOD;
+
+ $jscriptstr .= getJScriptFunction(0);
+ $jscriptstr .= <<<EOD
+//-->
+</script>
+EOD;
+
+ $pfSenseHead->addScript($jscriptstr);
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<?php include("fbegin.inc"); ?>
+<form action="dspam-analysis.php" method="post" name="iform" id="iform">
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+<p>
+ <span class="vexpl">
+ Graphs showing the number of messages that have been processed are shown below.
+ </span>
+</p>
+<table width="100%" border="0" cellspacing="0" cellpadding="0">
+ <tr>
+ <td>
+<?php
+ $tab_array = array();
+ $tab_array[] = array("Info", false, "/dspam.php?user={$CURRENT_USER}");
+ $tab_array[] = array("Performance", false, "/dspam-perf.php?user={$CURRENT_USER}");
+ $tab_array[] = array("Preferences", false, "/dspam-prefs.php?user={$CURRENT_USER}");
+ $tab_array[] = array("Alerts", false, "/pkg.php?xml=dspam_alerts.xml&user={$CURRENT_USER}");
+ $tab_array[] = array("Quarantine ({$DATA['TOTAL_QUARANTINED_MESSAGES']})", false, "/dspam-quarantine.php?user={$CURRENT_USER}");
+ $tab_array[] = array("Analysis", true, "/dspam-analysis.php?user={$CURRENT_USER}");
+ $tab_array[] = array("History", false, "/dspam-history.php?user={$CURRENT_USER}");
+ $tab_array[] = array("Train Filter", false, "/dspam-train.php?user={$CURRENT_USER}");
+ if (isDSPAMAdmin($HTTP_SERVER_VARS['AUTH_USER'])) {
+ $tab_array[] = array("Admin Suite", false, "/dspam-admin.php");
+ }
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <table class="tabcont" align="center" width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td align="left" valign="top" class="listhdrr" colspan="2">Statistical SPAM Protection for...</td>
+ </tr>
+ <tr>
+ <td width="10%" valign="baseline" class="vncell">Username</td>
+ <td width="90%" class="vtable">
+ <?php if(isset($HTTP_SERVER_VARS['AUTH_USER'])): ?>
+ <input type="text" name="username" id="username" value="<?= $CURRENT_USER ?>" class="formfld user"<?php if (! isDSPAMAdmin($HTTP_SERVER_VARS['AUTH_USER'])) { echo " readonly=\"readonly\""; } ?> />
+ <?php else: ?>
+ <input type="text" name="username" id="username" value="Please provide a username" class="formfld user" onFocus="this.value='';" />
+ <?php endif; ?>
+ &nbsp;
+ <?php
+ if (! isDSPAMAdmin($HTTP_SERVER_VARS['AUTH_USER']))
+ $action = "onClick=\"changeuser();\"";
+ else
+ $action = "onClick=\"document.iform.submit();\"";
+ ?>
+ <input type="button" name="change_user" id="change_user" class="formbtn" value="Change" <?= $action ?> />
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2" class="list" height="12">&nbsp;</td>
+ </tr>
+ <tr>
+ <td align="left" valign="top" class="listtopic" colspan="2">
+ <strong>24 Hour Activity</strong> &ndash; <?= $DATA['TS_DAILY']; ?> SPAM, <?= $DATA['TI_DAILY']; ?> Good
+ </td>
+ </tr>
+ <tr>
+ <td align="center" valign="top" class="vncell" colspan="2">
+ <?php if(isset($_GET['test'])): ?>
+ <img src="/dspam-analysis-graph.php?data=0,0,1,0,1_1,4,0,1,0_4p,6p,7a,11a,2p&x_label=Hour+of+the+day" alt="24 Hour Activity" border="0" />
+ <?php else: ?>
+ <img src="/dspam-analysis-graph.php?data=<?= $DATA['DATA_DAILY']; ?>&x_label=<?= urlencode("Hour of the day"); ?>" alt="24 Hour Activity" border="0" />
+ <?php endif; ?>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2" class="list" height="12">&nbsp;</td>
+ </tr>
+ <tr>
+ <td align="left" valign="top" class="listtopic" colspan="2">
+ <strong>14 Day Activity</strong> &ndash; <?= $DATA['TS_WEEKLY']; ?> SPAM, <?= $DATA['TI_WEEKLY']; ?> Good
+ </td>
+ </tr>
+ <tr>
+ <td align="center" valign="top" class="vncell" colspan="2">
+ <?php if(isset($_GET['test'])): ?>
+ <img src="/dspam-analysis-graph.php?data=1,2,0,2,1,2,2,1,4,0,0,2,0,2_5,2,3,5,12,20,7,9,9,8,7,12,6,1_6/9,6/10,6/11,6/12,6/13,6/14,6/15,6/16,6/17,6/18,6/19,6/20,6/21,6/22&graph=period&x_label=Date" alt="24 Hour Activity" border="0" />
+ <?php else: ?>
+ <img src="/dspam-analysis-graph.php?data=<?= $DATA['DATA_WEEKLY']; ?>&graph=period&x_label=Date" alt="24 Hour Activity" border="0" />
+ <?php endif; ?>
+ </td>
+ </tr>
+ </table>
+ </div>
+ </td>
+ </tr>
+</table>
+</form>
+
+<?php include("fend.inc"); ?>
+</body>
+</html> \ No newline at end of file
diff --git a/config/dspam/www/dspam-hfragment.php b/config/dspam/www/dspam-hfragment.php
new file mode 100644
index 00000000..36152a00
--- /dev/null
+++ b/config/dspam/www/dspam-hfragment.php
@@ -0,0 +1,90 @@
+<?php
+/* $Id$ */
+/*
+ dspam-train.php
+
+ Copyright (C) 2006 Daniel S. Haischt.
+ All rights reserved.
+*/
+
+$pgtitle = array(gettext("Services"),
+ gettext("DSPAM"),
+ gettext("History"),
+ gettext("Fragement"));
+
+require("guiconfig.inc");
+include("/usr/local/pkg/dspam.inc");
+
+/* if this is an AJAX caller then handle via JSON */
+if(isAjax() && is_array($input_errors)) {
+ input_errors2Ajax($input_errors);
+ exit;
+}
+
+/* if ajax is calling, give them an update message */
+if(isAjax())
+ print_info_box_np($savemsg);
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<?php include("fbegin.inc"); ?>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+<table width="100%" border="0" cellspacing="0" cellpadding="0">
+ <tr>
+ <td>
+<?php
+ $tab_array = array();
+ $tab_array[] = array("Info", false, "/dspam.php?{$CURRENT_USER}");
+ $tab_array[] = array("Performance", false, "/dspam-perf.php?user={$CURRENT_USER}");
+ $tab_array[] = array("Preferences", false, "/dspam-prefs.php?user={$CURRENT_USER}");
+ $tab_array[] = array("Alerts", false, "/pkg.php?xml=dspam_alerts.xml&user={$CURRENT_USER}");
+ $tab_array[] = array("Quarantine ({$DATA['TOTAL_QUARANTINED_MESSAGES']})", false, "/dspam-quarantine.php?user={$CURRENT_USER}");
+ $tab_array[] = array("Analysis", false, "/dspam-analysis.php?user={$CURRENT_USER}");
+ $tab_array[] = array("History", true, "/dspam-history.php?user={$CURRENT_USER}");
+ $tab_array[] = array("Train Filter", false, "/dspam-train.php?user={$CURRENT_USER}");
+ if (isDSPAMAdmin($HTTP_SERVER_VARS['AUTH_USER'])) {
+ $tab_array[] = array("Admin Suite", false, "/dspam-admin.php?user={$CURRENT_USER}");
+ }
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <table class="tabcont" align="center" width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td align="left" valign="top" class="list" width="10%">
+ <br />
+ <font color=white><big><?= $DATA['SUBJECT']; ?></big><br />
+ <?= $DATA['FROM']; ?><br />
+ <small><?= $DATA['TIME']; ?> (<?= $DATA['INFO']; ?>)</small></font><br />
+ <br />
+ </td>
+ </tr>
+ <tr>
+ <td class="list" height="12">&nbsp;</td>
+ </tr>
+ <tr>
+ <td align="left" valign="middle" class="list">
+ <pre>
+ <?= $DATA['MESSSAGE']; ?>
+ </pre>
+ </td>
+ </tr>
+ </table>
+ </div>
+ </td>
+ </tr>
+</table>
+
+<?php include("fend.inc"); ?>
+</body>
+</html> \ No newline at end of file
diff --git a/config/dspam/www/dspam-history.php b/config/dspam/www/dspam-history.php
new file mode 100644
index 00000000..cb5e4f2c
--- /dev/null
+++ b/config/dspam/www/dspam-history.php
@@ -0,0 +1,172 @@
+<?php
+/* $Id$ */
+/*
+ dspam-train.php
+
+ Copyright (C) 2006 Daniel S. Haischt.
+ All rights reserved.
+*/
+
+$pgtitle = array(gettext("Services"),
+ gettext("DSPAM"),
+ gettext("History"),
+ gettext("Overview"));
+
+require("guiconfig.inc");
+include("/usr/local/pkg/dspam.inc");
+
+/* if this is an AJAX caller then handle via JSON */
+if(isAjax() && is_array($input_errors)) {
+ input_errors2Ajax($input_errors);
+ exit;
+}
+
+/* if ajax is calling, give them an update message */
+if(isAjax())
+ print_info_box_np($savemsg);
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+
+ $jscriptstr = <<<EOD
+<script type="text/javascript">
+<!--
+
+EOD;
+
+ $jscriptstr .= getJScriptFunction(0);
+ $jscriptstr .= getJScriptFunction(4);
+ $jscriptstr .= <<<EOD
+//-->
+</script>
+EOD;
+
+$pfSenseHead->addScript($jscriptstr);
+$pfSenseHead->addLink("<link rel=\"stylesheet\" type=\"text/css\" href=\"/themes/" . $g['theme'] . "/dspam.css\" media=\"all\" />\n");
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<?php include("fbegin.inc"); ?>
+<form action="dspam-history.php" method="post" name="iform" id="iform">
+<input type="hidden" name="command" value="retrainChecked" />
+<input type="hidden" name="hpage" value="<?= $DATA['HPAGE']; ?>" />
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+<p>
+ <span class="vexpl">
+ The messages that have been processed by the filter are shown below. The
+ most recent messages are shown first. Use the retrain options to correct
+ errors and deliver any false positives that are still in your quarantine.
+ </span>
+</p>
+<table width="100%" border="0" cellspacing="0" cellpadding="0">
+ <tr>
+ <td>
+<?php
+ $tab_array = array();
+ $tab_array[] = array("Info", false, "/dspam.php?user={$CURRENT_USER}");
+ $tab_array[] = array("Performance", false, "/dspam-perf.php?user={$CURRENT_USER}");
+ $tab_array[] = array("Preferences", false, "/dspam-prefs.php?user={$CURRENT_USER}");
+ $tab_array[] = array("Alerts", false, "/pkg.php?xml=dspam_alerts.xml&user={$CURRENT_USER}");
+ $tab_array[] = array("Quarantine ({$DATA['TOTAL_QUARANTINED_MESSAGES']})", false, "/dspam-quarantine.php?user={$CURRENT_USER}");
+ $tab_array[] = array("Analysis", false, "/dspam-analysis.php?user={$CURRENT_USER}");
+ $tab_array[] = array("History", true, "/dspam-history.php?user={$CURRENT_USER}");
+ $tab_array[] = array("Train Filter", false, "/dspam-train.php?user={$CURRENT_USER}");
+ if (isDSPAMAdmin($HTTP_SERVER_VARS['AUTH_USER'])) {
+ $tab_array[] = array("Admin Suite", false, "/dspam-admin.php");
+ }
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <table class="tabcont" align="center" width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td align="left" valign="top" class="listhdrr" colspan="6">Statistical SPAM Protection for...</td>
+ </tr>
+ <tr>
+ <td width="22%" valign="baseline" class="vncell" colspan="2">Username</td>
+ <td width="78%" class="vtable" colspan="4">
+ <?php if(isset($HTTP_SERVER_VARS['AUTH_USER'])): ?>
+ <input type="text" name="username" id="username" value="<?= $CURRENT_USER ?>" class="formfld user"<?php if (! isDSPAMAdmin($HTTP_SERVER_VARS['AUTH_USER'])) { echo " readonly=\"readonly\""; } ?> />
+ <?php else: ?>
+ <input type="text" name="username" id="username" value="Please provide a username" class="formfld user" onFocus="this.value='';" />
+ <?php endif; ?>
+ &nbsp;
+ <?php
+ if (! isDSPAMAdmin($HTTP_SERVER_VARS['AUTH_USER']))
+ $action = "onClick=\"changeuser();\"";
+ else
+ $action = "onClick=\"document.iform.submit();\"";
+ ?>
+ <input type="button" name="change_user" id="change_user" class="formbtn" value="Change" <?= $action ?> />
+ </td>
+ </tr>
+ <tr>
+ <td colspan="6" class="list" height="12">&nbsp;</td>
+ </tr>
+ <tr>
+ <td align="left" valign="middle" class="qnavtdl" colspan="4">
+ <input type="submit" class="formbtn" title="Retrain Checked" value="Retrain Checked" name="retrain_checked" id="retrain_checked_top" />
+ <label for="retrain_checked_top">&nbsp;because those messages have<strong>n't</strong> been correctly classified.</label>
+ </td>
+ <td align="right" valign="middle" class="qnavtdr" colspan="2">
+ <label for="hperpage-top">Records per page:&nbsp;</label>
+ <select class="formselect" id="hperpage-top" name="hperpage" onchange="changeQPerPage(this);">
+ <option value="25"<?php if ($CONFIG['HISTORY_PER_PAGE'] == 25) echo ' selected="selected"'; ?>>25</option>
+ <option value="50"<?php if ($CONFIG['HISTORY_PER_PAGE'] == 50) echo ' selected="selected"'; ?>>50</option>
+ <option value="75"<?php if ($CONFIG['HISTORY_PER_PAGE'] == 75) echo ' selected="selected"'; ?>>75</option>
+ <option value="100"<?php if ($CONFIG['HISTORY_PER_PAGE'] == 100) echo ' selected="selected"'; ?>>100</option>
+ <option value="125"<?php if ($CONFIG['HISTORY_PER_PAGE'] == 125) echo ' selected="selected"'; ?>>125</option>
+ <option value="150"<?php if ($CONFIG['HISTORY_PER_PAGE'] == 150) echo ' selected="selected"'; ?>>150</option>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td class="list" height="12" colspan="6">&nbsp;</td>
+ </tr>
+ <tr>
+ <td align="left" valign="top" class="listtopic" width="10%">Type</td>
+ <td align="left" valign="top" class="listtopic" width="10%">Action</td>
+ <td align="left" valign="top" class="listtopic" width="10%">Day/Time</td>
+ <td align="left" valign="top" class="listtopic" width="25%">From</td>
+ <td align="left" valign="top" class="listtopic" width="25%">Subject</td>
+ <td align="left" valign="top" class="listtopic" width="20%">Additional Info</td>
+ </tr>
+ <?= $DATA['HISTORY']; ?>
+ <?= $DATA['HISTORY_FOOTER']; ?>
+ <tr>
+ <td colspan="6" class="list" height="12">&nbsp;</td>
+ </tr>
+ <tr>
+ <td align="left" valign="middle" class="qnavtdl" colspan="4">
+ <input type="submit" class="formbtn" title="Retrain Checked" value="Retrain Checked" name="retrain_checked" id="retrain_checked_bottom" />
+ <label for="retrain_checked_bottom">&nbsp;because those messages have<strong>n't</strong> correctly been classified.</label>
+ </td>
+ <td align="right" valign="middle" class="qnavtdr" colspan="2">
+ <label for="hperpage-bottom">Records per page:&nbsp;</label>
+ <select class="formselect" id="hperpage-bottom" name="hperpage" onchange="changeQPerPage(this);">
+ <option value="25"<?php if ($CONFIG['HISTORY_PER_PAGE'] == 25) echo ' selected="selected"'; ?>>25</option>
+ <option value="50"<?php if ($CONFIG['HISTORY_PER_PAGE'] == 50) echo ' selected="selected"'; ?>>50</option>
+ <option value="75"<?php if ($CONFIG['HISTORY_PER_PAGE'] == 75) echo ' selected="selected"'; ?>>75</option>
+ <option value="100"<?php if ($CONFIG['HISTORY_PER_PAGE'] == 100) echo ' selected="selected"'; ?>>100</option>
+ <option value="125"<?php if ($CONFIG['HISTORY_PER_PAGE'] == 125) echo ' selected="selected"'; ?>>125</option>
+ <option value="150"<?php if ($CONFIG['HISTORY_PER_PAGE'] == 150) echo ' selected="selected"'; ?>>150</option>
+ </select>
+ </td>
+ </tr>
+ </table>
+ </div>
+ </td>
+ </tr>
+</table>
+</form>
+
+<?php include("fend.inc"); ?>
+</body>
+</html> \ No newline at end of file
diff --git a/config/dspam/www/dspam-perf.php b/config/dspam/www/dspam-perf.php
new file mode 100644
index 00000000..8b69319f
--- /dev/null
+++ b/config/dspam/www/dspam-perf.php
@@ -0,0 +1,222 @@
+<?php
+/* $Id$ */
+/*
+ dspam-train.php
+
+ Copyright (C) 2006 Daniel S. Haischt.
+ All rights reserved.
+*/
+
+$pgtitle = array(gettext("Services"),
+ gettext("DSPAM"),
+ gettext("Performance"));
+
+require("guiconfig.inc");
+include("/usr/local/pkg/dspam.inc");
+
+/* if this is an AJAX caller then handle via JSON */
+if(isAjax() && is_array($input_errors)) {
+ input_errors2Ajax($input_errors);
+ exit;
+}
+
+/* if ajax is calling, give them an update message */
+if(isAjax())
+ print_info_box_np($savemsg);
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+
+ $jscriptstr = <<<EOD
+<script type="text/javascript">
+<!--
+
+EOD;
+
+ $jscriptstr .= getJScriptFunction(0);
+ $jscriptstr .= <<<EOD
+//-->
+</script>
+EOD;
+
+$pfSenseHead->addScript($jscriptstr);
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<?php include("fbegin.inc"); ?>
+<form action="dspam-perf.php" method="post" name="iform" id="iform">
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+<p>
+ <span class="vexpl">
+ If you receive a message in your e-mail application that was not caught by
+ the filter, please forward it to <strong><?= $DATA['SPAM_ALIAS']; ?></strong>
+ so that it can be analyzed and learned as <acronym title="">SPAM</acronym>.
+ This will improve the filter's accuracy in the future.
+ </span>
+</p>
+<table width="100%" border="0" cellspacing="0" cellpadding="0">
+ <tr>
+ <td>
+<?php
+ $tab_array = array();
+ $tab_array[] = array("Info", false, "/dspam.php?user={$CURRENT_USER}");
+ $tab_array[] = array("Performance", true, "/dspam-perf.php?user={$CURRENT_USER}");
+ $tab_array[] = array("Preferences", false, "/dspam-prefs.php?user={$CURRENT_USER}");
+ $tab_array[] = array("Alerts", false, "/pkg.php?xml=dspam_alerts.xml&user={$CURRENT_USER}");
+ $tab_array[] = array("Quarantine ({$DATA['TOTAL_QUARANTINED_MESSAGES']})", false, "/dspam-quarantine.php?user={$CURRENT_USER}");
+ $tab_array[] = array("Analysis", false, "/dspam-analysis.php?user={$CURRENT_USER}");
+ $tab_array[] = array("History", false, "/dspam-history.php?user={$CURRENT_USER}");
+ $tab_array[] = array("Train Filter", false, "/dspam-train.php?user={$CURRENT_USER}");
+ if (isDSPAMAdmin($HTTP_SERVER_VARS['AUTH_USER'])) {
+ $tab_array[] = array("Admin Suite", false, "/dspam-admin.php");
+ }
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <table class="tabcont" align="center" width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td align="left" valign="top" class="listhdrr" colspan="2">Statistical SPAM Protection for...</td>
+ </tr>
+ <tr>
+ <td width="22%" valign="baseline" class="vncell">Username</td>
+ <td width="78%" class="vtable">
+ <?php if(isset($HTTP_SERVER_VARS['AUTH_USER'])): ?>
+ <input type="text" name="username" id="username" value="<?= $CURRENT_USER ?>" class="formfld user"<?php if (! isDSPAMAdmin($HTTP_SERVER_VARS['AUTH_USER'])) { echo " readonly=\"readonly\""; } ?> />
+ <?php else: ?>
+ <input type="text" name="username" id="username" value="Please provide a username" class="formfld user" onFocus="this.value='';" />
+ <?php endif; ?>
+ &nbsp;
+ <?php
+ if (! isDSPAMAdmin($HTTP_SERVER_VARS['AUTH_USER']))
+ $action = "onClick=\"changeuser();\"";
+ else
+ $action = "onClick=\"document.iform.submit();\"";
+ ?>
+ <input type="button" name="change_user" id="change_user" class="formbtn" value="Change" <?= $action ?> />
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2" class="list" height="12">&nbsp;</td>
+ </tr>
+ <tr>
+ <td align="left" valign="top" class="listtopic" colspan="2">
+ <strong>Performance Statistics</strong> &ndash; <?= date("l dS of F Y h:i:s A"); ?>
+ </td>
+ </tr>
+ <tr>
+ <td align="left" valign="top" colspan="2" class="vncell">
+ <table align="center" width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <!- beginn left info pane -->
+ <td align="left" valign="top">
+ <table border="0" cellpadding="0" cellspacing="0" summary="left info pane">
+ <tr>
+ <td align="left" valign="top" class="listhdrr" colspan="2">Metric</td>
+ <td align="left" valign="top" class="listhdrr">Calculated as</td>
+ <td align="left" valign="top" class="list"></td>
+ </tr>
+ <tr>
+ <td align="left" valign="top" class="listr">
+ <nobr>Overall accuracy (since last reset)</nobr>
+ </td>
+ <td align="left" valign="top" class="listr">
+ <strong><?= $DATA['OVERALL_ACCURACY']; ?>%</strong>
+ </td>
+ <td align="left" valign="top" class="listr">(SPAM messages caught + Good messages delivered) / Total number of messages</td>
+ <td align="left" valign="top" class="none">&nbsp;</td>
+ </tr>
+ <tr>
+ <td align="left" valign="top" class="listr">
+ <nobr>Spam identification (since last reset)</nobr>
+ </td>
+ <td align="left" valign="top" class="listr">
+ <strong><?= $DATA['SPAM_ACCURACY']; ?>%</strong>
+ </td>
+ <td align="left" valign="top" class="listr">(Spam catch rate only)</td>
+ <td align="left" valign="top" class="none">&nbsp;</td>
+ </tr>
+ <tr>
+ <td align="left" valign="top" class="listr">
+ <nobr>Spam ratio (of total processed)</nobr>
+ </td>
+ <td align="left" valign="top" class="listr">
+ <strong><?= $DATA['SPAM_RATIO']; ?>%</strong>
+ </td>
+ <td align="left" valign="top" class="listr">Total SPAM messages (both caught & missed) / Total number of messages</td>
+ <td align="left" valign="top" class="none">&nbsp;</td>
+ </tr>
+ </table>
+ </td>
+ <!-- spacer td -->
+ <td align="left" valign="top" class="none">&nbsp;</td>
+ <!-- begin right info pane -->
+ <td align="left" valign="top">
+ <table border="0" cellpadding="0" cellspacing="0" summary="right info pane">
+ <tr id="frheader">
+ <td class="list">&nbsp;</td>
+ <td class="listhdrr">SPAM messages</td>
+ <td class="listhdrr">Good messages</td>
+ </tr>
+ <tr>
+ <td align="left" valign="top" class="listhdrr">Since last reset</td>
+ <td align="left" valign="top" class="listr">
+ <nobr><?= $DATA['TOTAL_SPAM_MISSED']; ?> missed</nobr><br />
+ <nobr><?= $DATA['TOTAL_SPAM_CAUGHT']; ?> caught</nobr><br />
+ <nobr><?= $DATA['SPAM_ACCURACY']; ?>% caught</nobr><br />
+ </td>
+ <td align="left" valign="top" class="listr">
+ <nobr><?= $DATA['TOTAL_NONSPAM_MISSED']; ?> missed</nobr><br />
+ <nobr><?= $DATA['TOTAL_NONSPAM_CAUGHT']; ?> delivered</nobr><br />
+ <nobr><?= $DATA['NONSPAM_ERROR_RATE']; ?>% missed</nobr><br />
+ </td>
+ </tr>
+ <tr>
+ <td align="left" valign="top" class="listhdrr">Total processed by filter</td>
+ <td align="left" valign="top" class="listr">
+ <nobr><?= $DATA['TOTAL_SPAM_LEARNED']; ?> missed</nobr><br />
+ <nobr><?= $DATA['TOTAL_SPAM_SCANNED']; ?> caught</nobr><br />
+ </td>
+ <td align="left" valign="top" class="listr">
+ <nobr><?= $DATA['TOTAL_NONSPAM_LEARNED']; ?> missed</nobr><br />
+ <nobr><?= $DATA['TOTAL_NONSPAM_SCANNED']; ?> delivered</nobr><br />
+ </td>
+ </tr>
+ <tr>
+ <td align="left" valign="top" class="listhdrr">From corpus</td>
+ <td align="left" valign="top" class="listr">
+ <nobr><?= $DATA['TOTAL_SPAM_CORPUSFED']; ?> feed</nobr><br />
+ </td>
+ <td align="left" valign="top" class="listr">
+ <nobr><?= $DATA['TOTAL_NONSPAM_CORPUSFED']; ?> feed</nobr><br />
+ </td>
+ </tr>
+ </table>
+ </td>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td align="left" valign="top" colspan="2">
+ <p>
+ <a href="/dspam-perf.php?user=<?= $CURRENT_USER ?>&command=resetStats">Reset</a>&nbsp;|&nbsp;<a href="/dspam-perf.php?user=<?= $CURRENT_USER ?>&command=tweak">Tweak -1</a>
+ </p>
+ </td>
+ </tr>
+ </table>
+ </div>
+ </td>
+ </tr>
+</table>
+</form>
+
+<?php include("fend.inc"); ?>
+</body>
+</html> \ No newline at end of file
diff --git a/config/dspam/www/dspam-prefs.php b/config/dspam/www/dspam-prefs.php
new file mode 100644
index 00000000..4e6b0f90
--- /dev/null
+++ b/config/dspam/www/dspam-prefs.php
@@ -0,0 +1,234 @@
+<?php
+/* $Id$ */
+/*
+ dspam-train.php
+
+ Copyright (C) 2006 Daniel S. Haischt.
+ All rights reserved.
+*/
+
+$pgtitle = array(gettext("Services"),
+ gettext("DSPAM"),
+ gettext("Preferences"));
+
+require("guiconfig.inc");
+include("/usr/local/pkg/dspam.inc");
+
+/* if this is an AJAX caller then handle via JSON */
+if(isAjax() && is_array($input_errors)) {
+ input_errors2Ajax($input_errors);
+ exit;
+}
+
+/* if ajax is calling, give them an update message */
+if(isAjax())
+ print_info_box_np($savemsg);
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+
+ $jscriptstr = <<<EOD
+<script type="text/javascript">
+<!--
+
+EOD;
+
+ $jscriptstr .= getJScriptFunction(0);
+ $jscriptstr .= <<<EOD
+//-->
+</script>
+EOD;
+
+$pfSenseHead->addScript($jscriptstr);
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<?php include("fbegin.inc"); ?>
+<form action="dspam-prefs.php" method="post" name="iform" id="iform">
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+<p>
+ <span class="vexpl">
+ This page lets you configure how the filter will handle your messages.
+ </span>
+</p>
+<table width="100%" border="0" cellspacing="0" cellpadding="0">
+ <tr>
+ <td>
+<?php
+ $tab_array = array();
+ $tab_array[] = array("Info", false, "/dspam.php?user={$CURRENT_USER}");
+ $tab_array[] = array("Performance", false, "/dspam-perf.php?user={$CURRENT_USER}");
+ $tab_array[] = array("Preferences", true, "/dspam-prefs.php?user={$CURRENT_USER}");
+ $tab_array[] = array("Alerts", false, "/pkg.php?xml=dspam_alerts.xml");
+ $tab_array[] = array("Quarantine ({$DATA['TOTAL_QUARANTINED_MESSAGES']})", false, "/dspam-quarantine.php?user={$CURRENT_USER}");
+ $tab_array[] = array("Analysis", false, "/dspam-analysis.php?user={$CURRENT_USER}");
+ $tab_array[] = array("History", false, "/dspam-history.php?user={$CURRENT_USER}");
+ $tab_array[] = array("Train Filter", false, "/dspam-train.php?user={$CURRENT_USER}");
+ if (isDSPAMAdmin($HTTP_SERVER_VARS['AUTH_USER'])) {
+ $tab_array[] = array("Admin Suite", false, "/dspam-admin.php");
+ }
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <table class="tabcont" align="center" width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td align="left" valign="top" class="listhdrr" colspan="2">Statistical SPAM Protection for...</td>
+ </tr>
+ <tr>
+ <td width="22%" valign="baseline" class="vncell">Username</td>
+ <td width="78%" class="vtable">
+ <?php if(isset($HTTP_SERVER_VARS['AUTH_USER'])): ?>
+ <input type="text" name="username" id="username" value="<?= $CURRENT_USER; ?>" class="formfld user"<?php if (! isDSPAMAdmin($HTTP_SERVER_VARS['AUTH_USER'])) { echo " readonly=\"readonly\""; } ?> />
+ <?php else: ?>
+ <input type="text" name="username" id="username" value="Please provide a username" class="formfld user" onFocus="this.value='';" />
+ <?php endif; ?>
+ &nbsp;
+ <?php
+ if (! isDSPAMAdmin($HTTP_SERVER_VARS['AUTH_USER']))
+ $action = "onClick=\"changeuser();\"";
+ else
+ $action = "onClick=\"document.iform.submit();\"";
+ ?>
+ <input type="button" name="change_user" id="change_user" class="formbtn" value="Change" <?= $action ?> />
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2" class="list" height="12">&nbsp;</td>
+ </tr>
+ <tr>
+ <td align="left" valign="top" class="listtopic" colspan="2">
+ <strong>Training</strong> &ndash; Configure how the filter learns as it processes messages
+ </td>
+ </tr>
+ <tr>
+ <td align="left" valign="top" class="vncell" width="40%">
+ <p>DSPAM should train:</p>
+ <input <?= $DATA["S_TEFT"]; ?> value="TEFT" type="radio" class="formfld" title="On every new message scanned by the filter" alt="On every new message scanned by the filter" name="rad_train" id="rad_train_one" />
+ <label for="rad_train_one">&nbsp;On every new message scanned by the filter (TEFT)</label>
+ <br />
+ <input <?= $DATA["S_TOE"]; ?> value="TOE" type="radio" class="formfld" title="Only when the filter makes a mistake" alt="Only when the filter makes a mistake" name="rad_train" id="rad_train_two" />
+ <label for="rad_train_two">&nbsp;Only when the filter makes a mistake (TOE)</label>
+ <br />
+ <input <?= $DATA["S_TUM"]; ?> value="TUM" type="radio" class="formfld" title=";Only with new data or if the filter makes a mistake" alt=";Only with new data or if the filter makes a mistake" name="rad_train" id="rad_train_three" />
+ <label for="rad_train_three">&nbsp;Only with new data or if the filter makes a mistake (TUM)</label>
+ </td>
+ <td align="left" valign="top" class="vncell" width="60%">
+ <p>When I train DSPAM, I prefer:</p>
+ <input value="message" <?= $DATA["S_LOC_MESSAGE"]; ?> value="message" type="radio" class="formfld" title="To forward my spams (signature appears in message body)" alt="To forward my spams (signature appears in message body)" name="rad_train_action" id="rad_train_action_one" />
+ <label for="rad_train_action_one">&nbsp;To <u>forward</u> my spams (signature appears in message body)</label>
+ <br />
+ <input <?= $DATA["S_LOC_HEADERS"]; ?> value="headers" type="radio" class="formfld" title="To bounce my spams (signature appears in message headers)" alt="To bounce my spams (signature appears in message headers)" name="rad_train_action" id="rad_train_action_two" />
+ <label value="headers" for="rad_train_action_two">&nbsp;To <u>bounce</u> my spams (signature appears in message headers)</label>
+ </td>
+ </tr>
+ <tr>
+ <td align="left" valign="middle" class="vncell" colspan="2">
+ <p>
+ Filter sensitivity <strong>during</strong> the training period:
+ </p>
+ <p align="center">
+ <nobr>
+ <span>
+ Catch SPAM (More in Quarantine)&nbsp;
+ <input value="0" type="radio" class="formfld" title="-5" alt="-5" name="rad_filter_sens" <?= $DATA["SEDATION_0"]; ?> />
+ <input value="1" type="radio" class="formfld" title="-4" alt="-4" name="rad_filter_sens" <?= $DATA["SEDATION_1"]; ?> />
+ <input value="2" type="radio" class="formfld" title="-3" alt="-3" name="rad_filter_sens" <?= $DATA["SEDATION_2"]; ?> />
+ <input value="3" type="radio" class="formfld" title="-2" alt="-2" name="rad_filter_sens" <?= $DATA["SEDATION_3"]; ?> />
+ <input value="4" type="radio" class="formfld" title="-1" alt="-1" name="rad_filter_sens" <?= $DATA["SEDATION_4"]; ?> />
+ <strong style="font-size: larger;">&raquo;</strong>
+ <input value="5" type="radio" class="formfld" title="0" alt="0" name="rad_filter_sens" <?= $DATA["SEDATION_5"]; ?> />
+ <strong style="font-size: larger;">&laquo;</strong>
+ <input value="6" type="radio" class="formfld" title="1" alt="1" name="rad_filter_sens" <?= $DATA["SEDATION_6"]; ?> />
+ <input value="7" type="radio" class="formfld" title="2" alt="2" name="rad_filter_sens" <?= $DATA["SEDATION_7"]; ?> />
+ <input value="8" type="radio" class="formfld" title="3" alt="3" name="rad_filter_sens" <?= $DATA["SEDATION_8"]; ?> />
+ <input value="9" type="radio" class="formfld" title="4" alt="4" name="rad_filter_sens" <?= $DATA["SEDATION_9"]; ?> />
+ <input value="10" type="radio" class="formfld" title="5" alt="5" name="rad_filter_sens" <?= $DATA["SEDATION_10"]; ?> />
+ &nbsp;Assume Good (Fewer in Quarantine)
+ </span>
+ </nobr>
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2" class="list" height="12">&nbsp;</td>
+ </tr>
+ <tr>
+ <td align="left" valign="top" class="listtopic" colspan="2">
+ <strong>Message Handling</strong> &ndash; Configure how SPAM is handled
+ </td>
+ </tr>
+ <tr>
+ <td align="left" valign="top" class="vncell" colspan="2">
+ <p>When a SPAM message is identified:</p>
+ <p>
+ <input value="quarantine" <?= $DATA["S_ACTION_QUARANTINE"]; ?> type="radio" class="formfld" title="Quarantine the message" alt="Quarantine the message" name="rad_ident_action" id="rad_ident_action_one" />
+ <label for="rad_ident_action_one">&nbsp;Quarantine the message</label>
+ <br />
+ <input value="tag" <?= $DATA["S_ACTION_TAG"]; ?> type="radio" class="formfld" title="Tag the Subject header with" alt="Tag the Subject header with" name="rad_ident_action" id="rad_ident_action_two" />
+ <label for="rad_ident_action_two">Tag the Subject header with&nbsp;</label>
+ <input size="35" type="text" class="formfld mail" title="message tag" alt="message tag" value="<?= $DATA["SPAM_SUBJECT"]; ?>" name="msgtag" />
+ <br />
+ <input value="deliver" <?= $DATA["S_ACTION_DELIVER"]; ?> type="radio" class="formfld" title="Deliver the message normally with a X-DSPAM-Result header" alt="Deliver the message normally with a X-DSPAM-Result header" name="rad_ident_action" id="rad_ident_action_three" />
+ <label for="rad_ident_action_three">&nbsp;Deliver the message normally with a X-DSPAM-Result header</label>
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2" class="list" height="12">&nbsp;</td>
+ </tr>
+ <tr>
+ <td align="left" valign="top" class="listtopic" colspan="2">
+ <strong>Features</strong> &ndash; Tuning SPAM filtering
+ </td>
+ </tr>
+ <tr>
+ <td align="left" valign="top" class="vncell" colspan="2">
+ <p>
+ <input <?= $DATA["C_BNR"]; ?> type="checkbox" class="formbtn" title="Enable noise reduction, which usually improves filtering accuracy" alt="Enable noise reduction, which usually improves filtering accuracy" name="chk_feature_nr" id="chk_feature_nr" />
+ <label for="chk_feature_nr">&nbsp;Enable noise reduction, which usually improves filtering accuracy</label>
+ <br />
+ <input <?= $DATA["C_WHITELIST"]; ?> type="checkbox" class="formbtn" title="Enable automatic whitelisting to record frequent correspondence" alt="Enable automatic whitelisting to record frequent correspondence" name="chk_feature_aw" id="chk_feature_aw" />
+ <label for="chk_feature_aw">&nbsp;Enable automatic whitelisting to record frequent correspondence</label>
+ <br />
+ <input <?= $DATA["C_FACTORS"]; ?> type="checkbox" class="formbtn" title="Add the factoring tokens in each email into the message's full headers" alt="Add the factoring tokens in each email into the message's full headers" name="chk_feature_at" id="chk_feature_at" />
+ <label for="chk_feature_at">&nbsp;Add the factoring tokens in each email into the message's full headers</label>
+ <!--
+ <input type="checkbox" class="formbtn" title="Add the factoring tokens in each email into the message's full headers" alt="Add the factoring tokens in each email into the message's full headers" name="chk_feature_at" id="chk_feature_at" />
+ <label for="chk_feature_at">&nbsp;Add the factoring tokens in each email into the message's full headers</label>
+ <br />
+ <input type="checkbox" class="formbtn" title="opt in of DSPAM filtering" alt="opt in of DSPAM filtering" name="chk_feature_optin" id="chk_feature_optin" />
+ <label for="chk_feature_optin">&nbsp;opt in of DSPAM filtering</label>
+ <br />
+ <input type="checkbox" class="formbtn" title="opt out of DSPAM filtering" alt="opt out of DSPAM filtering" name="chk_feature_optout" id="chk_feature_optout" />
+ <label for="chk_feature_optout">&nbsp;opt out of DSPAM filtering</label>
+ -->
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2" class="list" height="12">&nbsp;</td>
+ </tr>
+ <tr>
+ <td class="list">&nbsp;</td>
+ <td class="list">
+ <input id="submitt" name="Submit" type="submit" class="formbtn" value="<?=gettext("Save");?>" />
+ </td>
+ </tr>
+ </table>
+ </div>
+ </td>
+ </tr>
+</table>
+</form>
+
+<?php include("fend.inc"); ?>
+</body>
+</html> \ No newline at end of file
diff --git a/config/dspam/www/dspam-quarantine.php b/config/dspam/www/dspam-quarantine.php
new file mode 100644
index 00000000..bc205a50
--- /dev/null
+++ b/config/dspam/www/dspam-quarantine.php
@@ -0,0 +1,178 @@
+<?php
+/* $Id$ */
+/*
+ dspam-train.php
+
+ Copyright (C) 2006 Daniel S. Haischt.
+ All rights reserved.
+*/
+
+$pgtitle = array(gettext("Services"),
+ gettext("DSPAM"),
+ gettext("Quarantine"),
+ gettext("Overview"));
+
+require("guiconfig.inc");
+include("/usr/local/pkg/dspam.inc");
+
+/* if this is an AJAX caller then handle via JSON */
+if(isAjax() && is_array($input_errors)) {
+ input_errors2Ajax($input_errors);
+ exit;
+}
+
+/* if ajax is calling, give them an update message */
+if(isAjax())
+ print_info_box_np($savemsg);
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+
+ $jscriptstr = <<<EOD
+<script type="text/javascript">
+<!--
+
+EOD;
+
+ $jscriptstr .= getJScriptFunction(0);
+ $jscriptstr .= getJScriptFunction(1);
+ $jscriptstr .= getJScriptFunction(2);
+ $jscriptstr .= getJScriptFunction(3);
+ $jscriptstr .= getJScriptFunction(4);
+ $jscriptstr .= <<<EOD
+//-->
+</script>
+EOD;
+
+$pfSenseHead->addScript($jscriptstr);
+$pfSenseHead->addLink("<link rel=\"stylesheet\" type=\"text/css\" href=\"/themes/" . $g['theme'] . "/dspam.css\" media=\"all\" />\n");
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<?php include("fbegin.inc"); ?>
+<form action="dspam-quarantine.php" method="post" name="iform" id="iform">
+<input type="hidden" name="command" value="processQuarantine" />
+<input type="hidden" name="processAction" value="None" />
+<input type="hidden" name="qpage" value="<?= $DATA['QPAGE']; ?>" />
+<input type="hidden" name="sortby" value="<?= $DATA['SORTBY']; ?>" >
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+<p>
+ <span class="vexpl">
+ The messages below have not been delivered to your normal e-mail application
+ because they are believed to be spam. Click on the Subject line to view the
+ message or choose a sort option to change how messages are sorted. Use the
+ checkboxes and <strong>Deliver Checked</strong> to deliver messages you want
+ to read, or use <strong>Delete All</strong> to empty the quarantine.
+ </span>
+</p>
+<table width="100%" border="0" cellspacing="0" cellpadding="0">
+ <tr>
+ <td>
+<?php
+ $tab_array = array();
+ $tab_array[] = array("Info", false, "/dspam.php?user={$CURRENT_USER}");
+ $tab_array[] = array("Performance", false, "/dspam-perf.php?user={$CURRENT_USER}");
+ $tab_array[] = array("Preferences", false, "/dspam-prefs.php?user={$CURRENT_USER}");
+ $tab_array[] = array("Alerts", false, "/pkg.php?xml=dspam_alerts.xml&user={$CURRENT_USER}");
+ $tab_array[] = array("Quarantine ({$DATA['TOTAL_QUARANTINED_MESSAGES']})", true, "/dspam-quarantine.php?user={$CURRENT_USER}");
+ $tab_array[] = array("Analysis", false, "/dspam-analysis.php?user={$CURRENT_USER}");
+ $tab_array[] = array("History", false, "/dspam-history.php?user={$CURRENT_USER}");
+ $tab_array[] = array("Train Filter", false, "/dspam-train.php?user={$CURRENT_USER}");
+ if (isDSPAMAdmin($HTTP_SERVER_VARS['AUTH_USER'])) {
+ $tab_array[] = array("Admin Suite", false, "/dspam-admin.php");
+ }
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <table class="tabcont" align="center" width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td align="left" valign="top" class="listhdrr" colspan="5">Statistical SPAM Protection for...</td>
+ </tr>
+ <tr>
+ <td width="10%" valign="baseline" class="vncell" colspan="2">Username</td>
+ <td width="90%" class="vtable" colspan="3">
+ <?php if(isset($HTTP_SERVER_VARS['AUTH_USER'])): ?>
+ <input type="text" name="username" id="username" value="<?= $CURRENT_USER ?>" class="formfld user"<?php if (! isDSPAMAdmin($HTTP_SERVER_VARS['AUTH_USER'])) { echo " readonly=\"readonly\""; } ?> />
+ <?php else: ?>
+ <input type="text" name="username" id="username" value="Please provide a username" class="formfld user" onFocus="this.value='';" />
+ <?php endif; ?>
+ &nbsp;
+ <?php
+ if (! isDSPAMAdmin($HTTP_SERVER_VARS['AUTH_USER']))
+ $action = "onClick=\"changeuser();\"";
+ else
+ $action = "onClick=\"document.iform.submit();\"";
+ ?>
+ <input type="button" name="change_user" id="change_user" class="formbtn" value="Change" <?= $action ?> />
+ </td>
+ </tr>
+ <tr>
+ <td colspan="5" class="list" height="12">&nbsp;</td>
+ </tr>
+ <tr>
+ <td align="left" valign="middle" colspan="4" class="qnavtdl">
+ <nobr>
+ <input type="button" class="formbtn" title="Deliver Checked" value="Deliver Checked" name="delichk" id="delichk" onclick="processmsg(0);" />&nbsp;
+ <input type="button" class="formbtn" title="Delete Checked" value="Delete Checked" name="delchk" id="delchk" onclick="processmsg(1);" />&nbsp;
+ <input type="button" class="formbtn" title="Delete All" value="Delete All" name="delall" id="delall" onclick="processmsg(2);" />
+ </nobr>
+ </td>
+ <td align="right" valign="middle" class="qnavtdr">
+ <label for="qperpage-top">Records per page:&nbsp;</label>
+ <select class="formselect" id="qperpage-top" name="qperpage" onchange="changeQPerPage(this);">
+ <option value="25"<?php if ($CONFIG['QUARANTINE_PER_PAGE'] == 25) echo ' selected="selected"'; ?>>25</option>
+ <option value="50"<?php if ($CONFIG['QUARANTINE_PER_PAGE'] == 50) echo ' selected="selected"'; ?>>50</option>
+ <option value="75"<?php if ($CONFIG['QUARANTINE_PER_PAGE'] == 75) echo ' selected="selected"'; ?>>75</option>
+ <option value="100"<?php if ($CONFIG['QUARANTINE_PER_PAGE'] == 100) echo ' selected="selected"'; ?>>100</option>
+ <option value="125"<?php if ($CONFIG['QUARANTINE_PER_PAGE'] == 125) echo ' selected="selected"'; ?>>125</option>
+ <option value="150"<?php if ($CONFIG['QUARANTINE_PER_PAGE'] == 150) echo ' selected="selected"'; ?>>150</option>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="5" class="list" height="12">&nbsp;</td>
+ </tr>
+ <?= $DATA['SORT_SELECTOR']; ?>
+ <?= $DATA['QUARANTINE']; ?>
+ <?= $DATA['QUARANTINE_FOOTER']; ?>
+ <tr>
+ <td colspan="5" class="list" height="12">&nbsp;</td>
+ </tr>
+ <tr>
+ <td align="left" valign="middle" colspan="4" class="qnavtdl">
+ <nobr>
+ <input type="button" class="formbtn" title="Deliver Checked" value="Deliver Checked" name="delichk" id="delichk" onclick="processmsg(0);" />&nbsp;
+ <input type="button" class="formbtn" title="Delete Checked" value="Delete Checked" name="delchk" id="delchk" onclick="processmsg(1);" />&nbsp;
+ <input type="button" class="formbtn" title="Delete All" value="Delete All" name="delall" id="delall" onclick="processmsg(2);" />
+ </nobr>
+ </td>
+ <td align="right" valign="middle" class="qnavtdr">
+ <label for="qperpage-bottom">Records per page:&nbsp;</label>
+ <select class="formselect" id="qperpage-bottom" name="qperpage" onchange="changeQPerPage(this);">
+ <option value="25"<?php if ($CONFIG['QUARANTINE_PER_PAGE'] == 25) echo ' selected="selected"'; ?>>25</option>
+ <option value="50"<?php if ($CONFIG['QUARANTINE_PER_PAGE'] == 50) echo ' selected="selected"'; ?>>50</option>
+ <option value="75"<?php if ($CONFIG['QUARANTINE_PER_PAGE'] == 75) echo ' selected="selected"'; ?>>75</option>
+ <option value="100"<?php if ($CONFIG['QUARANTINE_PER_PAGE'] == 100) echo ' selected="selected"'; ?>>100</option>
+ <option value="125"<?php if ($CONFIG['QUARANTINE_PER_PAGE'] == 125) echo ' selected="selected"'; ?>>125</option>
+ <option value="150"<?php if ($CONFIG['QUARANTINE_PER_PAGE'] == 150) echo ' selected="selected"'; ?>>150</option>
+ </select>
+ </td>
+ </tr>
+ </table>
+ </div>
+ </td>
+ </tr>
+</table>
+</form>
+
+<?php include("fend.inc"); ?>
+</body>
+</html> \ No newline at end of file
diff --git a/config/dspam/www/dspam-settings-algo.php b/config/dspam/www/dspam-settings-algo.php
new file mode 100644
index 00000000..58ffb247
--- /dev/null
+++ b/config/dspam/www/dspam-settings-algo.php
@@ -0,0 +1,204 @@
+<?php
+/* $Id$ */
+/*
+ dspam-settings-algo.php
+
+ Copyright (C) 2006 Daniel S. Haischt.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+$pgtitle = array(gettext("Services"),
+ gettext("DSPAM"),
+ gettext("Advanced Settings"),
+ gettext("Edit Algorithm"));
+
+require("guiconfig.inc");
+include("/usr/local/pkg/dspam.inc");
+
+if (isDSPAMAdmin($HTTP_SERVER_VARS['AUTH_USER'])) {
+
+/*
+ The following code presumes, that the following XML structure exists or
+ if it does not exist, it will be created.
+
+ <algorithm>
+ <name>foo</name>
+ <descr>foo desc</descr>
+ </algorithm>
+ <algorithm>
+ <name>bar</name>
+ <descr>bar desc</descr>
+ </algorithm>
+*/
+
+if (!is_array($config['installedpackages']['dspam']['config'][0]['algorithm'])) {
+ $config['installedpackages']['dspam']['config'][0]['algorithm'] = array();
+}
+
+$t_algos = &$config['installedpackages']['dspam']['config'][0]['algorithm'];
+
+/* ID is only set if the user wants to edit an existing entry */
+$id = $_GET['id'];
+$sectionid = $_GET['sectionid'];
+if (isset($_POST['id']))
+ $id = $_POST['id'];
+if (isset($_POST['sectionid']))
+ $sectionid = $_POST['sectionid'];
+
+if (isset($id) && $t_algos[$id]) {
+ $pconfig['name'] = $t_algos[$id]['name'];
+ $pconfig['descr'] = $t_algos[$id]['descr'];
+} else {
+ $pconfig['name'] = $_GET['aname'];
+ $pconfig['descr'] = $_GET['descr'];
+}
+
+if ($_POST) {
+
+ unset($input_errors);
+ $pconfig = $_POST;
+
+ /* input validation */
+ $reqdfields = explode(" ", "aname");
+ $reqdfieldsn = explode(",", "DSPAM Algorithm Name");
+
+ do_input_validation($_POST, $reqdfields, $reqdfieldsn, &$input_errors);
+
+ /* check for overlaps */
+ foreach ($t_algos as $algo) {
+ if (isset($id) && ($t_algos[$id]) && ($t_algos[$id] === $algo)) {
+ continue;
+ }
+ if ($algo['name'] == $_POST['aname']) {
+ $input_errors[] = gettext("This algorithm name already exists.");
+ break;
+ }
+ }
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($input_errors)) {
+ input_errors2Ajax($input_errors);
+ exit;
+ }
+
+ if (!$input_errors) {
+ $algo = array();
+ $algo['name'] = $_POST['aname'];
+ $algo['descr'] = $_POST['descr'];
+
+ if (isset($id) && $t_algos[$id])
+ $t_algos[$id] = $algo;
+ else
+ $t_algos[] = $algo;
+
+ write_config();
+
+ $retval = 0;
+ config_lock();
+ $retval = dspam_configure();
+ config_unlock();
+
+ $savemsg = get_std_save_message($retval);
+
+ isset($sectionid) ? $header = "dspam-settings.php?sectionid={$sectionid}" : $header = "dspam-settings.php";
+ pfSenseHeader($header);
+ exit;
+ }
+}
+
+/* if ajax is calling, give them an update message */
+if(isAjax())
+ print_info_box_np($savemsg);
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<?php include("fbegin.inc"); ?>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+ <form action="dspam-settings-algo.php" method="post" name="iform" id="iform">
+ <div name="inputerrors" id="inputerrors"></div>
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?=gettext("DSPAM Algorithm Name");?></td>
+ <td width="78%" class="vtable">
+ <!-- <input name="aname" type="text" class="formfld" id="aname" size="30" value="<?=htmlspecialchars($pconfig['name']);?>"> -->
+ <select name="aname" id="aname" class="formselect">
+ <option value="naive" <?php if($pconfig['name'] == "naive") echo('selected=\"selected\"');?>>naive</option>
+ <option value="graham" <?php if($pconfig['name'] == "graham") echo('selected=\"selected\"');?>>graham</option>
+ <option value="burton" <?php if($pconfig['name'] == "burton") echo('selected=\"selected\"');?>>burton</option>
+ <option value="robinson" <?php if($pconfig['name'] == "robinson") echo('selected=\"selected\"');?>>robinson</option>
+ <option value="chi-square" <?php if($pconfig['name'] == "chi-square") echo('selected=\"selected\"');?>>chi-square</option>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("Description");?></td>
+ <td width="78%" class="vtable">
+ <input name="descr" type="text" class="formfld unknown" id="descr" size="40" value="<?=htmlspecialchars($pconfig['descr']);?>">
+ <br> <span class="vexpl"><?=gettext("You may enter a description here
+ for your reference (not parsed).");?></span></td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <input id="submit" name="Submit" type="submit" class="formbtn" value="<?=gettext("Save");?>"> <input id="cancelbutton" class="formbtn" type="button" value="<?=gettext("Cancel");?>" onclick="history.back()">
+ <?php if (isset($id) && $t_algos[$id]): ?>
+ <input name="id" type="hidden" value="<?=$id;?>">
+ <?php endif; ?>
+ <?php if (isset($sectionid)): ?>
+ <input name="sectionid" type="hidden" value="<?=$sectionid;?>">
+ <?php endif; ?>
+ </td>
+ </tr>
+ </table>
+ </form>
+<?
+ } else {
+?>
+<?php
+ $input_errors[] = "Access to this particular site was denied. You need DSPAM admin access rights to be able to view it.";
+
+ include("head.inc");
+ echo $pfSenseHead->getHTML();
+?>
+<?php include("fbegin.inc");?>
+<?php if ($input_errors) print_input_errors($input_errors);?>
+<?php if ($savemsg) print_info_box($savemsg);?>
+ <body link="#000000" vlink="#000000" alink="#000000">
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td valign="top" class="listtopic">Access denied for: <?=$HTTP_SERVER_VARS['AUTH_USER']?></td>
+ </tr>
+ </table>
+<?php
+ } // end of access denied code
+?>
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/dspam/www/dspam-settings-bmta.php b/config/dspam/www/dspam-settings-bmta.php
new file mode 100644
index 00000000..c670085d
--- /dev/null
+++ b/config/dspam/www/dspam-settings-bmta.php
@@ -0,0 +1,202 @@
+<?php
+/* $Id$ */
+/*
+ dspam-settings-feat.php
+
+ Copyright (C) 2006 Daniel S. Haischt.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+$pgtitle = array(gettext("Services"),
+ gettext("DSPAM"),
+ gettext("Advanced Settings"),
+ gettext("Edit Broken MTA Settings"));
+
+require("guiconfig.inc");
+include("/usr/local/pkg/dspam.inc");
+
+if (isDSPAMAdmin($HTTP_SERVER_VARS['AUTH_USER'])) {
+
+/*
+ The following code presumes, that the following XML structure exists or
+ if it does not exist, it will be created.
+
+ <bmta>
+ <name>foo</name>
+ <descr>foo desc</descr>
+ </bmta>
+ <bmta>
+ <name>bar</name>
+ <descr>bar desc</descr>
+ </bmta>
+*/
+
+if (!is_array($config['installedpackages']['dspam']['config'][0]['bmta'])) {
+ $config['installedpackages']['dspam']['config'][0]['bmta'] = array();
+}
+
+$t_bmtas = &$config['installedpackages']['dspam']['config'][0]['bmta'];
+
+/* ID is only set if the user wants to edit an existing entry */
+$id = $_GET['id'];
+$sectionid = $_GET['sectionid'];
+if (isset($_POST['id']))
+ $id = $_POST['id'];
+if (isset($_POST['sectionid']))
+ $sectionid = $_POST['sectionid'];
+
+if (isset($id) && $t_bmtas[$id]) {
+ $pconfig['name'] = $t_bmtas[$id]['name'];
+ $pconfig['descr'] = $t_bmtas[$id]['descr'];
+} else {
+ $pconfig['name'] = $_GET['oname'];
+ $pconfig['descr'] = $_GET['descr'];
+}
+
+if ($_POST) {
+
+ unset($input_errors);
+ $pconfig = $_POST;
+
+ /* input validation */
+ $reqdfields = explode(" ", "oname");
+ $reqdfieldsn = explode(",", "Broken MTA Option Name");
+
+ do_input_validation($_POST, $reqdfields, $reqdfieldsn, &$input_errors);
+
+ /* check for overlaps */
+ foreach ($t_bmtas as $bmta) {
+ if (isset($id) && ($t_bmtas[$id]) && ($t_bmtas[$id] === $bmta)) {
+ continue;
+ }
+ if ($bmta['name'] == $_POST['oname']) {
+ $input_errors[] = gettext("This option name already exists.");
+ break;
+ }
+ }
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($input_errors)) {
+ input_errors2Ajax($input_errors);
+ exit;
+ }
+
+ if (!$input_errors) {
+ $bmta = array();
+ $bmta['name'] = $_POST['oname'];
+ $bmta['descr'] = $_POST['descr'];
+
+ if (isset($id) && $t_bmtas[$id])
+ $t_bmtas[$id] = $bmta;
+ else
+ $t_bmtas[] = $bmta;
+
+ write_config();
+
+ $retval = 0;
+ config_lock();
+ $retval = dspam_configure();
+ config_unlock();
+
+ $savemsg = get_std_save_message($retval);
+
+ isset($sectionid) ? $header = "dspam-settings.php?sectionid={$sectionid}" : $header = "dspam-settings.php";
+ pfSenseHeader($header);
+ exit;
+ }
+}
+
+/* if ajax is calling, give them an update message */
+if(isAjax())
+ print_info_box_np($savemsg);
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<?php include("fbegin.inc"); ?>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+ <form action="dspam-settings-bmta.php" method="post" name="iform" id="iform">
+ <div name="inputerrors" id="inputerrors"></div>
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?=gettext("DSPAM Feature Name");?></td>
+ <td width="78%" class="vtable">
+ <!-- <input name="oname" type="text" class="formfld" id="oname" size="30" value="<?=htmlspecialchars($pconfig['name']);?>"> -->
+ <select name="oname" id="oname" class="formselect">
+ <option value="returnCodes" <?php if($pconfig['name'] == "returnCodes") echo('selected=\"selected\"');?>>returnCodes</option>
+ <option value="case" <?php if($pconfig['name'] == "case") echo('selected=\"selected\"');?>>case</option>
+ <option value="lineStripping" <?php if($pconfig['name'] == "lineStripping") echo('selected=\"selected\"');?>>lineStripping</option>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("Description");?></td>
+ <td width="78%" class="vtable">
+ <input name="descr" type="text" class="formfld unknown" id="descr" size="40" value="<?=htmlspecialchars($pconfig['descr']);?>">
+ <br> <span class="vexpl"><?=gettext("You may enter a description here
+ for your reference (not parsed).");?></span></td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <input id="submit" name="Submit" type="submit" class="formbtn" value="<?=gettext("Save");?>"> <input id="cancelbutton" class="formbtn" type="button" value="<?=gettext("Cancel");?>" onclick="history.back()">
+ <?php if (isset($id) && $t_bmtas[$id]): ?>
+ <input name="id" type="hidden" value="<?=$id;?>">
+ <?php endif; ?>
+ <?php if (isset($sectionid)): ?>
+ <input name="sectionid" type="hidden" value="<?=$sectionid;?>">
+ <?php endif; ?>
+ </td>
+ </tr>
+ </table>
+</form>
+<?
+ } else {
+?>
+<?php
+ $input_errors[] = "Access to this particular site was denied. You need DSPAM admin access rights to be able to view it.";
+
+ include("head.inc");
+ echo $pfSenseHead->getHTML();
+?>
+<?php include("fbegin.inc");?>
+<?php if ($input_errors) print_input_errors($input_errors);?>
+<?php if ($savemsg) print_info_box($savemsg);?>
+ <body link="#000000" vlink="#000000" alink="#000000">
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td valign="top" class="listtopic">Access denied for: <?=$HTTP_SERVER_VARS['AUTH_USER']?></td>
+ </tr>
+ </table>
+<?php
+ } // end of access denied code
+?>
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/dspam/www/dspam-settings-feat.php b/config/dspam/www/dspam-settings-feat.php
new file mode 100644
index 00000000..7805fa43
--- /dev/null
+++ b/config/dspam/www/dspam-settings-feat.php
@@ -0,0 +1,203 @@
+<?php
+/* $Id$ */
+/*
+ dspam-settings-feat.php
+
+ Copyright (C) 2006 Daniel S. Haischt.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+$pgtitle = array(gettext("Services"),
+ gettext("DSPAM"),
+ gettext("Advanced Settings"),
+ gettext("Edit DSPAM Feature"));
+
+require("guiconfig.inc");
+include("/usr/local/pkg/dspam.inc");
+
+if (isDSPAMAdmin($HTTP_SERVER_VARS['AUTH_USER'])) {
+
+/*
+ The following code presumes, that the following XML structure exists or
+ if it does not exist, it will be created.
+
+ <feature>
+ <name>foo</name>
+ <descr>foo desc</descr>
+ </feature>
+ <feature>
+ <name>bar</name>
+ <descr>bar desc</descr>
+ </feature>
+*/
+
+if (!is_array($config['installedpackages']['dspam']['config'][0]['feature'])) {
+ $config['installedpackages']['dspam']['config'][0]['feature'] = array();
+}
+
+$t_features = &$config['installedpackages']['dspam']['config'][0]['feature'];
+
+/* ID is only set if the user wants to edit an existing entry */
+$id = $_GET['id'];
+$sectionid = $_GET['sectionid'];
+if (isset($_POST['id']))
+ $id = $_POST['id'];
+if (isset($_POST['sectionid']))
+ $sectionid = $_POST['sectionid'];
+
+if (isset($id) && $t_features[$id]) {
+ $pconfig['name'] = $t_features[$id]['name'];
+ $pconfig['descr'] = $t_features[$id]['descr'];
+} else {
+ $pconfig['name'] = $_GET['fname'];
+ $pconfig['descr'] = $_GET['descr'];
+}
+
+if ($_POST) {
+
+ unset($input_errors);
+ $pconfig = $_POST;
+
+ /* input validation */
+ $reqdfields = explode(" ", "fname");
+ $reqdfieldsn = explode(",", "DSPAM Feature Name");
+
+ do_input_validation($_POST, $reqdfields, $reqdfieldsn, &$input_errors);
+
+ /* check for overlaps */
+ foreach ($t_features as $feature) {
+ if (isset($id) && ($t_features[$id]) && ($t_features[$id] === $feature)) {
+ continue;
+ }
+ if ($feature['name'] == $_POST['fname']) {
+ $input_errors[] = gettext("This feature name already exists.");
+ break;
+ }
+ }
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($input_errors)) {
+ input_errors2Ajax($input_errors);
+ exit;
+ }
+
+ if (!$input_errors) {
+ $feature = array();
+ $feature['name'] = $_POST['fname'];
+ $feature['descr'] = $_POST['descr'];
+
+ if (isset($id) && $t_features[$id])
+ $t_features[$id] = $feature;
+ else
+ $t_features[] = $feature;
+
+ write_config();
+
+ $retval = 0;
+ config_lock();
+ $retval = dspam_configure();
+ config_unlock();
+
+ $savemsg = get_std_save_message($retval);
+
+ isset($sectionid) ? $header = "dspam-settings.php?sectionid={$sectionid}" : $header = "dspam-settings.php";
+ pfSenseHeader($header);
+ exit;
+ }
+}
+
+/* if ajax is calling, give them an update message */
+if(isAjax())
+ print_info_box_np($savemsg);
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<?php include("fbegin.inc"); ?>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+ <form action="dspam-settings-feat.php" method="post" name="iform" id="iform">
+ <div name="inputerrors" id="inputerrors"></div>
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?=gettext("DSPAM Feature Name");?></td>
+ <td width="78%" class="vtable">
+ <!-- <input name="fname" type="text" class="formfld" id="fname" size="30" value="<?=htmlspecialchars($pconfig['name']);?>"> -->
+ <select name="fname" id="fname" class="formselect">
+ <option value="sbph" <?php if($pconfig['name'] == "sbph") echo('selected=\"selected\"');?>>sbph</option>
+ <option value="noise" <?php if($pconfig['name'] == "noise") echo('selected=\"selected\"');?>>noise</option>
+ <option value="chained" <?php if($pconfig['name'] == "chained") echo('selected=\"selected\"');?>>chained</option>
+ <option value="whitelist" <?php if($pconfig['name'] == "whitelist") echo('selected=\"selected\"');?>>whitelist</option>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("Description");?></td>
+ <td width="78%" class="vtable">
+ <input name="descr" type="text" class="formfld unknown" id="descr" size="40" value="<?=htmlspecialchars($pconfig['descr']);?>">
+ <br> <span class="vexpl"><?=gettext("You may enter a description here
+ for your reference (not parsed).");?></span></td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <input id="submit" name="Submit" type="submit" class="formbtn" value="<?=gettext("Save");?>"> <input id="cancelbutton" class="formbtn" type="button" value="<?=gettext("Cancel");?>" onclick="history.back()">
+ <?php if (isset($id) && $t_features[$id]): ?>
+ <input name="id" type="hidden" value="<?=$id;?>">
+ <?php endif; ?>
+ <?php if (isset($sectionid)): ?>
+ <input name="sectionid" type="hidden" value="<?=$sectionid;?>">
+ <?php endif; ?>
+ </td>
+ </tr>
+ </table>
+</form>
+<?
+ } else {
+?>
+<?php
+ $input_errors[] = "Access to this particular site was denied. You need DSPAM admin access rights to be able to view it.";
+
+ include("head.inc");
+ echo $pfSenseHead->getHTML();
+?>
+<?php include("fbegin.inc");?>
+<?php if ($input_errors) print_input_errors($input_errors);?>
+<?php if ($savemsg) print_info_box($savemsg);?>
+ <body link="#000000" vlink="#000000" alink="#000000">
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td valign="top" class="listtopic">Access denied for: <?=$HTTP_SERVER_VARS['AUTH_USER']?></td>
+ </tr>
+ </table>
+<?php
+ } // end of access denied code
+?>
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/dspam/www/dspam-settings-header.php b/config/dspam/www/dspam-settings-header.php
new file mode 100644
index 00000000..d0a5dd9c
--- /dev/null
+++ b/config/dspam/www/dspam-settings-header.php
@@ -0,0 +1,197 @@
+<?php
+/* $Id$ */
+/*
+ dspam-settings-tuser.php
+
+ Copyright (C) 2006 Daniel S. Haischt.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+$pgtitle = array(gettext("Services"),
+ gettext("DSPAM"),
+ gettext("Advanced Settings"),
+ gettext("Edit Mail Header"));
+
+require("guiconfig.inc");
+include("/usr/local/pkg/dspam.inc");
+
+if (isDSPAMAdmin($HTTP_SERVER_VARS['AUTH_USER'])) {
+
+/*
+ The following code presumes, that the following XML structure exists or
+ if it does not exist, it will be created.
+
+ <header>
+ <name>foo</name>
+ <descr>foo desc</descr>
+ </header>
+ <header>
+ <name>bar</name>
+ <descr>foo desc</descr>
+ </header>
+*/
+
+if (!is_array($config['installedpackages']['dspam']['config'][0]['header'])) {
+ $config['installedpackages']['dspam']['config'][0]['header'] = array();
+}
+
+$t_headers = &$config['installedpackages']['dspam']['config'][0]['header'];
+
+/* ID is only set if the user wants to edit an existing entry */
+$id = $_GET['id'];
+$sectionid = $_GET['sectionid'];
+if (isset($_POST['id']))
+ $id = $_POST['id'];
+if (isset($_POST['sectionid']))
+ $sectionid = $_POST['sectionid'];
+
+if (isset($id) && $t_headers[$id]) {
+ $pconfig['name'] = $t_headers[$id]['name'];
+ $pconfig['descr'] = $t_headers[$id]['descr'];
+} else {
+ $pconfig['name'] = $_GET['hname'];
+ $pconfig['descr'] = $_GET['descr'];
+}
+
+if ($_POST) {
+
+ unset($input_errors);
+ $pconfig = $_POST;
+
+ /* input validation */
+ $reqdfields = explode(" ", "hname");
+ $reqdfieldsn = explode(",", "Header Name");
+
+ do_input_validation($_POST, $reqdfields, $reqdfieldsn, &$input_errors);
+
+ /* check for overlaps */
+ foreach ($t_headers as $header) {
+ if (isset($id) && ($t_headers[$id]) && ($t_headers[$id] === $header)) {
+ continue;
+ }
+ if ($header['name'] == $_POST['hname']) {
+ $input_errors[] = gettext("This header name already exists.");
+ break;
+ }
+ }
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($input_errors)) {
+ input_errors2Ajax($input_errors);
+ exit;
+ }
+
+ if (!$input_errors) {
+ $header = array();
+ $header['name'] = $_POST['hname'];
+ $header['descr'] = $_POST['descr'];
+
+ if (isset($id) && $t_headers[$id])
+ $t_headers[$id] = $header;
+ else
+ $t_headers[] = $header;
+
+ write_config();
+
+ $retval = 0;
+ config_lock();
+ $retval = dspam_configure();
+ config_unlock();
+
+ $savemsg = get_std_save_message($retval);
+
+ isset($sectionid) ? $header = "dspam-settings.php?sectionid={$sectionid}" : $header = "dspam-settings.php";
+ pfSenseHeader($header);
+ exit;
+ }
+}
+
+/* if ajax is calling, give them an update message */
+if(isAjax())
+ print_info_box_np($savemsg);
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<?php include("fbegin.inc"); ?>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+ <form action="dspam-settings-header.php" method="post" name="iform" id="iform">
+ <div name="inputerrors" id="inputerrors"></div>
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?=gettext("Header Name");?></td>
+ <td width="78%" class="vtable">
+ <input name="hname" type="text" class="formfld unknown" id="hname" size="30" value="<?=htmlspecialchars($pconfig['name']);?>">
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("Description");?></td>
+ <td width="78%" class="vtable">
+ <input name="descr" type="text" class="formfld unknown" id="descr" size="40" value="<?=htmlspecialchars($pconfig['descr']);?>">
+ <br> <span class="vexpl"><?=gettext("You may enter a description here
+ for your reference (not parsed).");?></span></td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <input id="submit" name="Submit" type="submit" class="formbtn" value="<?=gettext("Save");?>"> <input id="cancelbutton" class="formbtn" type="button" value="<?=gettext("Cancel");?>" onclick="history.back()">
+ <?php if (isset($id) && $t_headers[$id]): ?>
+ <input name="id" type="hidden" value="<?=$id;?>">
+ <?php endif; ?>
+ <?php if (isset($sectionid)): ?>
+ <input name="sectionid" type="hidden" value="<?=$sectionid;?>">
+ <?php endif; ?>
+ </td>
+ </tr>
+ </table>
+</form>
+<?
+ } else {
+?>
+<?php
+ $input_errors[] = "Access to this particular site was denied. You need DSPAM admin access rights to be able to view it.";
+
+ include("head.inc");
+ echo $pfSenseHead->getHTML();
+?>
+<?php include("fbegin.inc");?>
+<?php if ($input_errors) print_input_errors($input_errors);?>
+<?php if ($savemsg) print_info_box($savemsg);?>
+ <body link="#000000" vlink="#000000" alink="#000000">
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td valign="top" class="listtopic">Access denied for: <?=$HTTP_SERVER_VARS['AUTH_USER']?></td>
+ </tr>
+ </table>
+<?php
+ } // end of access denied code
+?>
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/dspam/www/dspam-settings-overr.php b/config/dspam/www/dspam-settings-overr.php
new file mode 100644
index 00000000..d938b313
--- /dev/null
+++ b/config/dspam/www/dspam-settings-overr.php
@@ -0,0 +1,197 @@
+<?php
+/* $Id$ */
+/*
+ dspam-settings-overr.php
+
+ Copyright (C) 2006 Daniel S. Haischt.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+$pgtitle = array(gettext("Services"),
+ gettext("DSPAM"),
+ gettext("Advanced Settings"),
+ gettext("Edit Override Value"));
+
+require("guiconfig.inc");
+include("/usr/local/pkg/dspam.inc");
+
+if (isDSPAMAdmin($HTTP_SERVER_VARS['AUTH_USER'])) {
+
+/*
+ The following code presumes, that the following XML structure exists or
+ if it does not exist, it will be created.
+
+ <override>
+ <value>foo</value>
+ <descr>foo desc</descr>
+ </override>
+ <override>
+ <value>bar</value>
+ <descr>bar desc</descr>
+ </override>
+*/
+
+if (!is_array($config['installedpackages']['dspam']['config'][0]['override'])) {
+ $config['installedpackages']['dspam']['config'][0]['override'] = array();
+}
+
+$t_overr = &$config['installedpackages']['dspam']['config'][0]['override'];
+
+/* ID is only set if the user wants to edit an existing entry */
+$id = $_GET['id'];
+$sectionid = $_GET['sectionid'];
+if (isset($_POST['id']))
+ $id = $_POST['id'];
+if (isset($_POST['sectionid']))
+ $sectionid = $_POST['sectionid'];
+
+if (isset($id) && $t_overr[$id]) {
+ $pconfig['value'] = $t_overr[$id]['value'];
+ $pconfig['descr'] = $t_overr[$id]['descr'];
+} else {
+ $pconfig['value'] = $_GET['ovalue'];
+ $pconfig['descr'] = $_GET['descr'];
+}
+
+if ($_POST) {
+
+ unset($input_errors);
+ $pconfig = $_POST;
+
+ /* input validation */
+ $reqdfields = explode(" ", "ovalue");
+ $reqdfieldsn = explode(",", "DSPAM Override Value");
+
+ do_input_validation($_POST, $reqdfields, $reqdfieldsn, &$input_errors);
+
+ /* check for overlaps */
+ foreach ($t_overr as $over) {
+ if (isset($id) && ($t_overr[$id]) && ($t_overr[$id] === $over)) {
+ continue;
+ }
+ if ($over['value'] == $_POST['ovalue']) {
+ $input_errors[] = gettext("This override value exists.");
+ break;
+ }
+ }
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($input_errors)) {
+ input_errors2Ajax($input_errors);
+ exit;
+ }
+
+ if (!$input_errors) {
+ $over = array();
+ $over['value'] = $_POST['ovalue'];
+ $over['descr'] = $_POST['descr'];
+
+ if (isset($id) && $t_overr[$id])
+ $t_overr[$id] = $over;
+ else
+ $t_overr[] = $over;
+
+ write_config();
+
+ $retval = 0;
+ config_lock();
+ $retval = dspam_configure();
+ config_unlock();
+
+ $savemsg = get_std_save_message($retval);
+
+ isset($sectionid) ? $header = "dspam-settings.php?sectionid={$sectionid}" : $header = "dspam-settings.php";
+ pfSenseHeader($header);
+ exit;
+ }
+}
+
+/* if ajax is calling, give them an update message */
+if(isAjax())
+ print_info_box_np($savemsg);
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<?php include("fbegin.inc"); ?>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+ <form action="dspam-settings-overr.php" method="post" name="iform" id="iform">
+ <div name="inputerrors" id="inputerrors"></div>
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?=gettext("DSPAM Override Value");?></td>
+ <td width="78%" class="vtable">
+ <input name="ovalue" type="text" class="formfld unknown" id="ovalue" size="30" value="<?=htmlspecialchars($pconfig['value']);?>">
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("Description");?></td>
+ <td width="78%" class="vtable">
+ <input name="descr" type="text" class="formfld unknown" id="descr" size="40" value="<?=htmlspecialchars($pconfig['descr']);?>">
+ <br> <span class="vexpl"><?=gettext("You may enter a description here
+ for your reference (not parsed).");?></span></td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <input id="submit" name="Submit" type="submit" class="formbtn" value="<?=gettext("Save");?>"> <input id="cancelbutton" class="formbtn" type="button" value="<?=gettext("Cancel");?>" onclick="history.back()">
+ <?php if (isset($id) && $t_overr[$id]): ?>
+ <input name="id" type="hidden" value="<?=$id;?>">
+ <?php endif; ?>
+ <?php if (isset($sectionid)): ?>
+ <input name="sectionid" type="hidden" value="<?=$sectionid;?>">
+ <?php endif; ?>
+ </td>
+ </tr>
+ </table>
+</form>
+<?
+ } else {
+?>
+<?php
+ $input_errors[] = "Access to this particular site was denied. You need DSPAM admin access rights to be able to view it.";
+
+ include("head.inc");
+ echo $pfSenseHead->getHTML();
+?>
+<?php include("fbegin.inc");?>
+<?php if ($input_errors) print_input_errors($input_errors);?>
+<?php if ($savemsg) print_info_box($savemsg);?>
+ <body link="#000000" vlink="#000000" alink="#000000">
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td valign="top" class="listtopic">Access denied for: <?=$HTTP_SERVER_VARS['AUTH_USER']?></td>
+ </tr>
+ </table>
+<?php
+ } // end of access denied code
+?>
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/dspam/www/dspam-settings-prefs.php b/config/dspam/www/dspam-settings-prefs.php
new file mode 100644
index 00000000..c30cb7bd
--- /dev/null
+++ b/config/dspam/www/dspam-settings-prefs.php
@@ -0,0 +1,197 @@
+<?php
+/* $Id$ */
+/*
+ dspam-settings-prefs.php
+
+ Copyright (C) 2006 Daniel S. Haischt.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+$pgtitle = array(gettext("Services"),
+ gettext("DSPAM"),
+ gettext("Advanced Settings"),
+ gettext("Edit DSPAM Preferences"));
+
+require("guiconfig.inc");
+include("/usr/local/pkg/dspam.inc");
+
+if (isDSPAMAdmin($HTTP_SERVER_VARS['AUTH_USER'])) {
+
+/*
+ The following code presumes, that the following XML structure exists or
+ if it does not exist, it will be created.
+
+ <preference>
+ <name>foo</name>
+ <descr>foo desc</descr>
+ </preference>
+ <preference>
+ <name>bar</name>
+ <descr>bar desc</descr>
+ </preference>
+*/
+
+if (!is_array($config['installedpackages']['dspam']['config'][0]['preference'])) {
+ $config['installedpackages']['dspam']['config'][0]['preference'] = array();
+}
+
+$t_prefs = &$config['installedpackages']['dspam']['config'][0]['preference'];
+
+/* ID is only set if the user wants to edit an existing entry */
+$id = $_GET['id'];
+$sectionid = $_GET['sectionid'];
+if (isset($_POST['id']))
+ $id = $_POST['id'];
+if (isset($_POST['sectionid']))
+ $sectionid = $_POST['sectionid'];
+
+if (isset($id) && $t_prefs[$id]) {
+ $pconfig['value'] = $t_prefs[$id]['value'];
+ $pconfig['descr'] = $t_prefs[$id]['descr'];
+} else {
+ $pconfig['value'] = $_GET['pvalue'];
+ $pconfig['descr'] = $_GET['descr'];
+}
+
+if ($_POST) {
+
+ unset($input_errors);
+ $pconfig = $_POST;
+
+ /* input validation */
+ $reqdfields = explode(" ", "pvalue");
+ $reqdfieldsn = explode(",", "DSPAM Algorithm Name");
+
+ do_input_validation($_POST, $reqdfields, $reqdfieldsn, &$input_errors);
+
+ /* check for overlaps */
+ foreach ($t_prefs as $pref) {
+ if (isset($id) && ($t_prefs[$id]) && ($t_prefs[$id] === $pref)) {
+ continue;
+ }
+ if ($pref['value'] == $_POST['pvalue']) {
+ $input_errors[] = gettext("This preference value already exists.");
+ break;
+ }
+ }
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($input_errors)) {
+ input_errors2Ajax($input_errors);
+ exit;
+ }
+
+ if (!$input_errors) {
+ $pref = array();
+ $pref['value'] = $_POST['pvalue'];
+ $pref['descr'] = $_POST['descr'];
+
+ if (isset($id) && $t_prefs[$id])
+ $t_prefs[$id] = $pref;
+ else
+ $t_prefs[] = $pref;
+
+ write_config();
+
+ $retval = 0;
+ config_lock();
+ $retval = dspam_configure();
+ config_unlock();
+
+ $savemsg = get_std_save_message($retval);
+
+ isset($sectionid) ? $header = "dspam-settings.php?sectionid={$sectionid}" : $header = "dspam-settings.php";
+ pfSenseHeader($header);
+ exit;
+ }
+}
+
+/* if ajax is calling, give them an update message */
+if(isAjax())
+ print_info_box_np($savemsg);
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<?php include("fbegin.inc"); ?>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+ <form action="dspam-settings-prefs.php" method="post" name="iform" id="iform">
+ <div name="inputerrors" id="inputerrors"></div>
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?=gettext("DSPAM Algorithm Name");?></td>
+ <td width="78%" class="vtable">
+ <input name="pvalue" type="text" class="formfld unknown" id="pvalue" size="30" value="<?=htmlspecialchars($pconfig['value']);?>">
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("Description");?></td>
+ <td width="78%" class="vtable">
+ <input name="descr" type="text" class="formfld unknown" id="descr" size="40" value="<?=htmlspecialchars($pconfig['descr']);?>">
+ <br> <span class="vexpl"><?=gettext("You may enter a description here
+ for your reference (not parsed).");?></span></td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <input id="submit" name="Submit" type="submit" class="formbtn" value="<?=gettext("Save");?>"> <input id="cancelbutton" class="formbtn" type="button" value="<?=gettext("Cancel");?>" onclick="history.back()">
+ <?php if (isset($id) && $t_prefs[$id]): ?>
+ <input name="id" type="hidden" value="<?=$id;?>">
+ <?php endif; ?>
+ <?php if (isset($sectionid)): ?>
+ <input name="sectionid" type="hidden" value="<?=$sectionid;?>">
+ <?php endif; ?>
+ </td>
+ </tr>
+ </table>
+</form>
+<?
+ } else {
+?>
+<?php
+ $input_errors[] = "Access to this particular site was denied. You need DSPAM admin access rights to be able to view it.";
+
+ include("head.inc");
+ echo $pfSenseHead->getHTML();
+?>
+<?php include("fbegin.inc");?>
+<?php if ($input_errors) print_input_errors($input_errors);?>
+<?php if ($savemsg) print_info_box($savemsg);?>
+ <body link="#000000" vlink="#000000" alink="#000000">
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td valign="top" class="listtopic">Access denied for: <?=$HTTP_SERVER_VARS['AUTH_USER']?></td>
+ </tr>
+ </table>
+<?php
+ } // end of access denied code
+?>
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/dspam/www/dspam-settings-spwd.php b/config/dspam/www/dspam-settings-spwd.php
new file mode 100644
index 00000000..7912b0f6
--- /dev/null
+++ b/config/dspam/www/dspam-settings-spwd.php
@@ -0,0 +1,197 @@
+<?php
+/* $Id$ */
+/*
+ dspam-settings-overr.php
+
+ Copyright (C) 2006 Daniel S. Haischt.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+$pgtitle = array(gettext("Services"),
+ gettext("DSPAM"),
+ gettext("Advanced Settings"),
+ gettext("Edit Server Password"));
+
+require("guiconfig.inc");
+include("/usr/local/pkg/dspam.inc");
+
+if (isDSPAMAdmin($HTTP_SERVER_VARS['AUTH_USER'])) {
+
+/*
+ The following code presumes, that the following XML structure exists or
+ if it does not exist, it will be created.
+
+ <server-pwd>
+ <value>foo</value>
+ <descr>foo desc</descr>
+ </server-pwd>
+ <server-pwd>
+ <value>bar</value>
+ <descr>bar desc</descr>
+ </server-pwd>
+*/
+
+if (!is_array($config['installedpackages']['dspam']['config'][0]['server-pwd'])) {
+ $config['installedpackages']['dspam']['config'][0]['server-pwd'] = array();
+}
+
+$t_spwds = &$config['installedpackages']['dspam']['config'][0]['server-pwd'];
+
+/* ID is only set if the user wants to edit an existing entry */
+$id = $_GET['id'];
+$sectionid = $_GET['sectionid'];
+if (isset($_POST['id']))
+ $id = $_POST['id'];
+if (isset($_POST['sectionid']))
+ $sectionid = $_POST['sectionid'];
+
+if (isset($id) && $t_spwds[$id]) {
+ $pconfig['value'] = $t_spwds[$id]['value'];
+ $pconfig['descr'] = $t_spwds[$id]['descr'];
+} else {
+ $pconfig['value'] = $_GET['pwdvalue'];
+ $pconfig['descr'] = $_GET['descr'];
+}
+
+if ($_POST) {
+
+ unset($input_errors);
+ $pconfig = $_POST;
+
+ /* input validation */
+ $reqdfields = explode(" ", "pwdvalue");
+ $reqdfieldsn = explode(",", "Server Password Value");
+
+ do_input_validation($_POST, $reqdfields, $reqdfieldsn, &$input_errors);
+
+ /* check for overlaps */
+ foreach ($t_spwds as $spwd) {
+ if (isset($id) && ($t_spwds[$id]) && ($t_spwds[$id] === $spwd)) {
+ continue;
+ }
+ if ($spwd['value'] == $_POST['pwdvalue']) {
+ $input_errors[] = gettext("This password value already exists.");
+ break;
+ }
+ }
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($input_errors)) {
+ input_errors2Ajax($input_errors);
+ exit;
+ }
+
+ if (!$input_errors) {
+ $pwd = array();
+ $pwd['value'] = $_POST['pwdvalue'];
+ $pwd['descr'] = $_POST['descr'];
+
+ if (isset($id) && $t_spwds[$id])
+ $t_spwds[$id] = $pwd;
+ else
+ $t_spwds[] = $pwd;
+
+ write_config();
+
+ $retval = 0;
+ config_lock();
+ $retval = dspam_configure();
+ config_unlock();
+
+ $savemsg = get_std_save_message($retval);
+
+ isset($sectionid) ? $header = "dspam-settings.php?sectionid={$sectionid}" : $header = "dspam-settings.php";
+ pfSenseHeader($header);
+ exit;
+ }
+}
+
+/* if ajax is calling, give them an update message */
+if(isAjax())
+ print_info_box_np($savemsg);
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<?php include("fbegin.inc"); ?>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+ <form action="dspam-settings-spwd.php" method="post" name="iform" id="iform">
+ <div name="inputerrors" id="inputerrors"></div>
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?=gettext("Server Password Value");?></td>
+ <td width="78%" class="vtable">
+ <input name="pwdvalue" type="text" class="formfld unknown" id="pwdvalue" size="30" value="<?=htmlspecialchars($pconfig['value']);?>">
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("Description");?></td>
+ <td width="78%" class="vtable">
+ <input name="descr" type="text" class="formfld unknown" id="descr" size="40" value="<?=htmlspecialchars($pconfig['descr']);?>">
+ <br> <span class="vexpl"><?=gettext("You may enter a description here
+ for your reference (not parsed).");?></span></td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <input id="submit" name="Submit" type="submit" class="formbtn" value="<?=gettext("Save");?>"> <input id="cancelbutton" class="formbtn" type="button" value="<?=gettext("Cancel");?>" onclick="history.back()">
+ <?php if (isset($id) && $t_spwds[$id]): ?>
+ <input name="id" type="hidden" value="<?=$id;?>">
+ <?php endif; ?>
+ <?php if (isset($sectionid)): ?>
+ <input name="sectionid" type="hidden" value="<?=$sectionid;?>">
+ <?php endif; ?>
+ </td>
+ </tr>
+ </table>
+</form>
+<?
+ } else {
+?>
+<?php
+ $input_errors[] = "Access to this particular site was denied. You need DSPAM admin access rights to be able to view it.";
+
+ include("head.inc");
+ echo $pfSenseHead->getHTML();
+?>
+<?php include("fbegin.inc");?>
+<?php if ($input_errors) print_input_errors($input_errors);?>
+<?php if ($savemsg) print_info_box($savemsg);?>
+ <body link="#000000" vlink="#000000" alink="#000000">
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td valign="top" class="listtopic">Access denied for: <?=$HTTP_SERVER_VARS['AUTH_USER']?></td>
+ </tr>
+ </table>
+<?php
+ } // end of access denied code
+?>
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/dspam/www/dspam-settings-tuser.php b/config/dspam/www/dspam-settings-tuser.php
new file mode 100644
index 00000000..57e9ec71
--- /dev/null
+++ b/config/dspam/www/dspam-settings-tuser.php
@@ -0,0 +1,195 @@
+<?php
+/* $Id$ */
+/*
+ dspam-settings-tuser.php
+
+ Copyright (C) 2006 Daniel S. Haischt.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+$pgtitle = array(gettext("Services"),
+ gettext("DSPAM"),
+ gettext("Advanced Settings"),
+ gettext("Edit UNIX user"));
+
+require("guiconfig.inc");
+include("/usr/local/pkg/dspam.inc");
+
+if (isDSPAMAdmin($HTTP_SERVER_VARS['AUTH_USER'])) {
+
+/*
+ The following code presumes, that the following XML structure exists or
+ if it does not exist, it will be created.
+
+ <tuser>
+ <name>foo</name>
+ </tuser>
+ <tuser>
+ <name>bar</name>
+ </tuser>
+*/
+
+if (!is_array($config['installedpackages']['dspam']['config'][0]['tuser'])) {
+ $config['installedpackages']['dspam']['config'][0]['tuser'] = array();
+}
+
+$t_users = &$config['installedpackages']['dspam']['config'][0]['tuser'];
+
+/* ID is only set if the user wants to edit an existing entry */
+$id = $_GET['id'];
+$sectionid = $_GET['sectionid'];
+if (isset($_POST['id']))
+ $id = $_POST['id'];
+if (isset($_POST['sectionid']))
+ $sectionid = $_POST['sectionid'];
+
+if (isset($id) && $t_users[$id]) {
+ $pconfig['name'] = $t_users[$id]['name'];
+ $pconfig['descr'] = $t_users[$id]['descr'];
+} else {
+ $pconfig['name'] = $_GET['uuname'];
+ $pconfig['descr'] = $_GET['descr'];
+}
+
+if ($_POST) {
+
+ unset($input_errors);
+ $pconfig = $_POST;
+
+ /* input validation */
+ $reqdfields = explode(" ", "uuname");
+ $reqdfieldsn = explode(",", "Unix username");
+
+ do_input_validation($_POST, $reqdfields, $reqdfieldsn, &$input_errors);
+
+ /* check for overlaps */
+ foreach ($t_users as $user) {
+ if (isset($id) && ($t_users[$id]) && ($t_users[$id] === $user)) {
+ continue;
+ }
+ if ($user['name'] == $_POST['uuname']) {
+ $input_errors[] = gettext("This username already exists.");
+ break;
+ }
+ }
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($input_errors)) {
+ input_errors2Ajax($input_errors);
+ exit;
+ }
+
+ if (!$input_errors) {
+ $user = array();
+ $user['name'] = $_POST['uuname'];
+ $user['descr'] = $_POST['descr'];
+
+ if (isset($id) && $t_users[$id])
+ $t_users[$id] = $user;
+ else
+ $t_users[] = $user;
+
+ write_config();
+
+ $retval = 0;
+ config_lock();
+ $retval = dspam_configure();
+ config_unlock();
+
+ $savemsg = get_std_save_message($retval);
+
+ isset($sectionid) ? $header = "dspam-settings.php?sectionid={$sectionid}" : $header = "dspam-settings.php";
+ pfSenseHeader($header);
+ exit;
+ }
+}
+
+/* if ajax is calling, give them an update message */
+if(isAjax())
+ print_info_box_np($savemsg);
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<?php include("fbegin.inc"); ?>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+ <form action="dspam-settings-tuser.php" method="post" name="iform" id="iform">
+ <div name="inputerrors" id="inputerrors"></div>
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?=gettext("UNIX username");?></td>
+ <td width="78%" class="vtable">
+ <input name="uuname" type="text" class="formfld unknown" id="uuname" size="30" value="<?=htmlspecialchars($pconfig['name']);?>">
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("Description");?></td>
+ <td width="78%" class="vtable">
+ <input name="descr" type="text" class="formfld unknown" id="descr" size="40" value="<?=htmlspecialchars($pconfig['descr']);?>">
+ <br> <span class="vexpl"><?=gettext("You may enter a description here
+ for your reference (not parsed).");?></span></td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <input id="submit" name="Submit" type="submit" class="formbtn" value="<?=gettext("Save");?>"> <input id="cancelbutton" class="formbtn" type="button" value="<?=gettext("Cancel");?>" onclick="history.back()">
+ <?php if (isset($id) && $t_users[$id]): ?>
+ <input name="id" type="hidden" value="<?=$id;?>">
+ <?php endif; ?>
+ <?php if (isset($sectionid)): ?>
+ <input name="sectionid" type="hidden" value="<?=$sectionid;?>">
+ <?php endif; ?>
+ </td>
+ </tr>
+ </table>
+</form>
+<?
+ } else {
+?>
+<?php
+ $input_errors[] = "Access to this particular site was denied. You need DSPAM admin access rights to be able to view it.";
+
+ include("head.inc");
+ echo $pfSenseHead->getHTML();
+?>
+<?php include("fbegin.inc");?>
+<?php if ($input_errors) print_input_errors($input_errors);?>
+<?php if ($savemsg) print_info_box($savemsg);?>
+ <body link="#000000" vlink="#000000" alink="#000000">
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td valign="top" class="listtopic">Access denied for: <?=$HTTP_SERVER_VARS['AUTH_USER']?></td>
+ </tr>
+ </table>
+<?php
+ } // end of access denied code
+?>
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/dspam/www/dspam-settings.php b/config/dspam/www/dspam-settings.php
new file mode 100644
index 00000000..05662a6e
--- /dev/null
+++ b/config/dspam/www/dspam-settings.php
@@ -0,0 +1,2955 @@
+<?php
+/* $Id$ */
+/*
+ dspam-settings.php
+ Copyright (C) 2006 Daniel S. Haischt
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+ $pgtitle = array(gettext("Services"),
+ gettext("DSPAM"),
+ gettext("Advanced Settings"),
+ gettext("Overview"));
+
+ require("guiconfig.inc");
+ include("/usr/local/pkg/dspam.inc");
+
+ if (isDSPAMAdmin($HTTP_SERVER_VARS['AUTH_USER'])) {
+
+ $pconfig['sectionid'] = $_GET['sectionid'];
+
+ $pconfig['sdriver'] = $config['installedpackages']['dspam']['config'][0]['storage-driver'];
+ /* ============================================================================================= */
+ /* == MySQL == */
+ /* ============================================================================================= */
+ $pconfig['msqlserver'] = $config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['mysql-server'];
+ $pconfig['msqlport'] = $config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['mysql-port'];
+ $pconfig['msqluser'] = $config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['mysql-user'];
+ $pconfig['msqlpwd'] = $config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['mysql-password'];
+ $pconfig['msqldb'] = $config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['mysql-database'];
+ $pconfig['msqlcomp'] = $config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['mysql-compress'];
+ $pconfig['msqlsuqt'] = $config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['mysql-squote'];
+ $pconfig['msqlccache'] = $config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['mysql-ccache'];
+ $pconfig['msqluid'] = $config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['mysql-uid'];
+ /* ============================================================================================= */
+ /* == SQLite == */
+ /* ============================================================================================= */
+ $pconfig['slitepr'] = $config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['sqlite-pragma'];
+ /* ============================================================================================= */
+ /* == PostgreSQL == */
+ /* ============================================================================================= */
+ $pconfig['pgserver'] = $config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['pgsql-server'];
+ $pconfig['pgport'] = $config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['pgsql-port'];
+ $pconfig['pguser'] = $config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['pgsql-user'];
+ $pconfig['pgpwd'] = $config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['pgsql-password'];
+ $pconfig['pgdb'] = $config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['pgsql-database'];
+ $pconfig['pgccache'] = $config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['pgsql-ccache'];
+ $pconfig['pguid'] = $config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['pgsql-uid'];
+ /* ============================================================================================= */
+ /* == Oracle == */
+ /* ============================================================================================= */
+ $pconfig['oraserver'] = $config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['ora-server'];
+ $pconfig['orauser'] = $config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['ora-user'];
+ $pconfig['orapwd'] = $config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['ora-password'];
+ $pconfig['orasch'] = $config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['ora-schema'];
+ /* ============================================================================================= */
+ /* == Hash == */
+ /* ============================================================================================= */
+ $pconfig['hsrmax'] = $config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['hash-rec-max'];
+ $pconfig['hsatex'] = $config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['hash-auto-ex'];
+ $pconfig['hsmxex'] = $config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['hash-max-ext'];
+ $pconfig['hsexsz'] = $config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['hash-ext-size'];
+ $pconfig['hsmxse'] = $config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['hash-max-seek'];
+ $pconfig['hsccus'] = $config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['hash-co-user'];
+ $pconfig['hscoca'] = $config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['hash-co-cache'];
+ /* ============================================================================================= */
+ /* == Delivery Settings == */
+ /* ============================================================================================= */
+ $pconfig['dagent'] = $config['installedpackages']['dspam']['config'][0]['tdelivery-agent'];
+ $pconfig['dsthinc'] = $config['installedpackages']['dspam']['config'][0]['thin-client'];
+ $pconfig['tcpipdel'] = $config['installedpackages']['dspam']['config'][0]['tcpip-delivery'];
+ $pconfig['dhost'] = $config['installedpackages']['dspam']['config'][0]['tcpip-delivery-host'];
+ $pconfig['dport'] = $config['installedpackages']['dspam']['config'][0]['tcpip-delivery-port'];
+ $pconfig['dident'] = $config['installedpackages']['dspam']['config'][0]['tcpip-delivery-ident'];
+ $pconfig['delproto'] = $config['installedpackages']['dspam']['config'][0]['tcpip-delivery-proto'];
+ $pconfig['onfail'] = $config['installedpackages']['dspam']['config'][0]['delivery-onfail'];
+ /* ============================================================================================= */
+ /* == DSPAM Debugging Options == */
+ /* ============================================================================================= */
+ $pconfig['enabledbg'] = $config['installedpackages']['dspam']['config'][0]['debug-enable'];
+ $pconfig['debug'] = $config['installedpackages']['dspam']['config'][0]['debug-whom'];
+ $pconfig['dopt'] = $config['installedpackages']['dspam']['config'][0]['debug-options'];
+ /* ============================================================================================= */
+ /* == DSPAM Engine Settings == */
+ /* ============================================================================================= */
+ $pconfig['tmode'] = $config['installedpackages']['dspam']['config'][0]['training-mode'];
+ $pconfig['testct'] = $config['installedpackages']['dspam']['config'][0]['test-cond-training'];
+ $pconfig['pvalue'] = $config['installedpackages']['dspam']['config'][0]['pvalue'];
+ $pconfig['ipdrive'] = $config['installedpackages']['dspam']['config'][0]['improbability-drive'];
+ /* ============================================================================================= */
+ /* == LDAP Settings == */
+ /* ============================================================================================= */
+ $pconfig['enableldap'] = $config['installedpackages']['dspam']['config'][0]['ldap-enable'];
+ $pconfig['ldapmode'] = $config['installedpackages']['dspam']['config'][0]['ldap-mode'];
+ $pconfig['ldaphost'] = $config['installedpackages']['dspam']['config'][0]['ldap-host'];
+ $pconfig['ldapfilter'] = $config['installedpackages']['dspam']['config'][0]['ldap-filter'];
+ $pconfig['ldapbase'] = $config['installedpackages']['dspam']['config'][0]['ldap-base'];
+ /* ============================================================================================= */
+ /* == Miscellaneous Settings == */
+ /* ============================================================================================= */
+ $pconfig['foatt'] = $config['installedpackages']['dspam']['config'][0]['failover-attempts'];
+ $pconfig['enablesbl'] = $config['installedpackages']['dspam']['config'][0]['sbl-enable'];
+ $pconfig['sblhost'] = $config['installedpackages']['dspam']['config'][0]['sbl-host'];
+ $pconfig['enablerbl'] = $config['installedpackages']['dspam']['config'][0]['rbl-inoculate'];
+ $pconfig['enablenoti'] = $config['installedpackages']['dspam']['config'][0]['notification-email'];
+ $pconfig['dspamdomain'] = $config['installedpackages']['dspam']['config'][0]['dspam-domain'];
+ $pconfig['dspamcontact'] = $config['installedpackages']['dspam']['config'][0]['dspam-contact'];
+ /* ============================================================================================= */
+ /* == Maintainance Settings == */
+ /* ============================================================================================= */
+ $pconfig['psig'] = $config['installedpackages']['dspam']['config'][0]['purge-signatures'];
+ $pconfig['pneut'] = $config['installedpackages']['dspam']['config'][0]['purge-neutral'];
+ $pconfig['punu'] = $config['installedpackages']['dspam']['config'][0]['purge-unused'];
+ $pconfig['phapa'] = $config['installedpackages']['dspam']['config'][0]['purge-hapaxes'];
+ $pconfig['pones'] = $config['installedpackages']['dspam']['config'][0]['purge-hits-1s'];
+ $pconfig['ponei'] = $config['installedpackages']['dspam']['config'][0]['purge-hits-1i'];
+ /* ============================================================================================= */
+ /* == System Settings == */
+ /* ============================================================================================= */
+ $pconfig['locmx'] = $config['installedpackages']['dspam']['config'][0]['local-mx'];
+ $pconfig['enablesysl'] = $config['installedpackages']['dspam']['config'][0]['system-log'];
+ $pconfig['enableusel'] = $config['installedpackages']['dspam']['config'][0]['user-log'];
+ $pconfig['optinout'] = $config['installedpackages']['dspam']['config'][0]['filter-opt'];
+ $pconfig['enableptoh'] = $config['installedpackages']['dspam']['config'][0]['parse-to-headers'];
+ $pconfig['enablecmop'] = $config['installedpackages']['dspam']['config'][0]['change-mode-on-parse'];
+ $pconfig['enablecuop'] = $config['installedpackages']['dspam']['config'][0]['change-user-on-parse'];
+ $pconfig['enablebmta'] = $config['installedpackages']['dspam']['config'][0]['broken-mta-settings'];
+ $pconfig['maxmsgs'] = $config['installedpackages']['dspam']['config'][0]['max-message-size'];
+ $pconfig['procbias'] = $config['installedpackages']['dspam']['config'][0]['processor-bias'];
+ /* ============================================================================================= */
+ /* == ClamAV Engine Settings == */
+ /* ============================================================================================= */
+ $pconfig['enableclam'] = $config['installedpackages']['dspam']['config'][0]['clamav-enable'];
+ $pconfig['clamport'] = $config['installedpackages']['dspam']['config'][0]['clamav-port'];
+ $pconfig['clamhost'] = $config['installedpackages']['dspam']['config'][0]['clamav-host'];
+ $pconfig['clamresp'] = $config['installedpackages']['dspam']['config'][0]['clamav-response'];
+ /* ============================================================================================= */
+ /* == DSPAM Daemon Settings (Server) == */
+ /* ============================================================================================= */
+ $pconfig['dsport'] = $config['installedpackages']['dspam']['config'][0]['dspam-server-port'];
+ $pconfig['dsqsize'] = $config['installedpackages']['dspam']['config'][0]['dspam-server-queue-size'];
+ $pconfig['dspid'] = $config['installedpackages']['dspam']['config'][0]['dspam-server-pid'];
+ $pconfig['dssmode'] = $config['installedpackages']['dspam']['config'][0]['dspam-server-mode'];
+ $pconfig['serverparam'] = $config['installedpackages']['dspam']['config'][0]['dspam-server-params'];
+ $pconfig['serverid'] = $config['installedpackages']['dspam']['config'][0]['dspam-server-id'];
+ $pconfig['serversock'] = $config['installedpackages']['dspam']['config'][0]['dspam-server-socket'];
+ /* ============================================================================================= */
+ /* == DSPAM Daemon Settings (Client) == */
+ /* ============================================================================================= */
+ $pconfig['enabledsclient'] = $config['installedpackages']['dspam']['config'][0]['dspam-client-enable'];
+ $pconfig['dsclhost'] = $config['installedpackages']['dspam']['config'][0]['dspam-client-host'];
+ $pconfig['dsclport'] = $config['installedpackages']['dspam']['config'][0]['dspam-client-port'];
+ $pconfig['dsclident'] = $config['installedpackages']['dspam']['config'][0]['dspam-client-id'];
+
+ if (!is_array($config['installedpackages']['dspam']['config'][0]['tuser'])) {
+ $config['installedpackages']['dspam']['config'][0]['tuser'] = array();
+ }
+ if (!is_array($config['installedpackages']['dspam']['config'][0]['algorithm'])) {
+ $config['installedpackages']['dspam']['config'][0]['algorithm'] = array();
+ }
+ if (!is_array($config['installedpackages']['dspam']['config'][0]['feature'])) {
+ $config['installedpackages']['dspam']['config'][0]['feature'] = array();
+ }
+ if (!is_array($config['installedpackages']['dspam']['config'][0]['preference'])) {
+ $config['installedpackages']['dspam']['config'][0]['preference'] = array();
+ }
+ if (!is_array($config['installedpackages']['dspam']['config'][0]['override'])) {
+ $config['installedpackages']['dspam']['config'][0]['override'] = array();
+ }
+ if (!is_array($config['installedpackages']['dspam']['config'][0]['header'])) {
+ $config['installedpackages']['dspam']['config'][0]['header'] = array();
+ }
+ if (!is_array($config['installedpackages']['dspam']['config'][0]['bmta'])) {
+ $config['installedpackages']['dspam']['config'][0]['bmta'] = array();
+ }
+
+ $t_users = &$config['installedpackages']['dspam']['config'][0]['tuser'];
+ $t_features = &$config['installedpackages']['dspam']['config'][0]['feature'];
+ $t_algos = &$config['installedpackages']['dspam']['config'][0]['algorithm'];
+ $t_prefs = &$config['installedpackages']['dspam']['config'][0]['preference'];
+ $t_overr = &$config['installedpackages']['dspam']['config'][0]['override'];
+ $t_headers = &$config['installedpackages']['dspam']['config'][0]['header'];
+ $t_bmtas = &$config['installedpackages']['dspam']['config'][0]['bmta'];
+ $t_spwds = &$config['installedpackages']['dspam']['config'][0]['server-pwd'];
+
+if ($_POST) {
+
+ /* hash */
+ $error_bucket = array();
+ /* simple error list */
+ unset($input_errors);
+ $pconfig = $_POST;
+
+ /* input validation */
+ if($_POST['sdriver'] == "mysql") {
+ if (! $_POST['msqlserver'] <> "") {
+ $error_bucket[] = array("error" => "You must specify a valid MySQL server name value.",
+ "field" => "msqlserver");
+ } else {
+ if (strpos($_POST['msqlserver'], '/') === false) {
+ foreach (explode(' ', $_POST['msqlserver']) as $ts) {
+ if (!is_domain($ts)) {
+ $error_bucket[] = array("error" => "A MySQL server name may only contain the characters a-z, 0-9, '-' and '.'.",
+ "field" => "msqlserver");
+ break;
+ }
+ }
+ }
+ }
+ /* if we are going to use a TCP/IP base MySQL connection, a port value is required */
+ if (! is_port($_POST['msqlport']) && strpos($_POST['msqlserver'], '/') === false) {
+ $error_bucket[] = array("error" => "You must specify a valid MySQL port value.",
+ "field" => "msqlport");
+ }
+ if (! $_POST['msqluser'] <> "") {
+ $error_bucket[] = array("error" => "You must specify a valid MySQL username value.",
+ "field" => "msqluser");
+ }
+ if (! $_POST['msqlpwd'] <> "") {
+ $error_bucket[] = array("error" => "You must specify a valid MySQL password value.",
+ "field" => "msqlpwd");
+ }
+ if (! $_POST['msqldb'] <> "") {
+ $error_bucket[] = array("error" => "You must specify a valid MySQL database value.",
+ "field" => "msqldb");
+ }
+ if ($_POST['msqlccache'] && !is_numericint($_POST['msqlccache'])) {
+ $error_bucket[] = array("error" => "You must specify a valid integer value as a connection cache value.",
+ "field" => "msqlccache");
+ }
+ } else if($_POST['sdriver'] == "sqlite") {
+ /* NOP */
+ } else if($_POST['sdriver'] == "bdb") {
+ /* NOP */
+ } else if($_POST['sdriver'] == "pgsql") {
+ if (! $_POST['pgserver'] <> "") {
+ $error_bucket[] = array("error" => "You must specify a valid PostgreSQL server name value.",
+ "field" => "pgserver");
+ } else {
+ foreach (explode(' ', $_POST['pgserver']) as $ts) {
+ if (!is_domain($ts)) {
+ $error_bucket[] = array("error" => "A PostgreSQL server name may only contain the characters a-z, 0-9, '-' and '.'.",
+ "field" => "pgserver");
+ break;
+ }
+ }
+ }
+ if (! is_port($_POST['pgport'])) {
+ $error_bucket[] = array("error" => "You must specify a valid PostgreSQL port value.",
+ "field" => "pgport");
+ }
+ if (! $_POST['pguser'] <> "") {
+ $error_bucket[] = array("error" => "You must specify a valid PostgreSQL username value.",
+ "field" => "pguser");
+ }
+ if (! $_POST['pgpwd'] <> "") {
+ $error_bucket[] = array("error" => "You must specify a valid PostgreSQL password value.",
+ "field" => "pgpwd");
+ }
+ if (! $_POST['pgdb'] <> "") {
+ $error_bucket[] = array("error" => "You must specify a valid PostgreSQL database value.",
+ "field" => "pgdb");
+ }
+ if ($_POST['pgccache'] && !is_numericint($_POST['pgccache'])) {
+ $error_bucket[] = array("error" => "You must specify a valid integer value as a connection cache value.",
+ "field" => "pgccache");
+ }
+ } else if($_POST['sdriver'] == "oracle") {
+ if (! $_POST['oraserver'] <> "") {
+ $error_bucket[] = array("error" => "You must specify a valid Oracle server connection string.",
+ "field" => "oraserver");
+ }
+ if (! $_POST['orauser'] <> "") {
+ $error_bucket[] = array("error" => "You must specify a valid Oracle username value.",
+ "field" => "orauser");
+ }
+ if (! $_POST['orapwd'] <> "") {
+ $error_bucket[] = array("error" => "You must specify a valid Oracle password value.",
+ "field" => "orapwd");
+ }
+ if (! $_POST['orasch'] <> "") {
+ $error_bucket[] = array("error" => "You must specify a valid Oracle schema value.",
+ "field" => "orasch");
+ }
+ } else if($_POST['sdriver'] == "hash") {
+ if ($_POST['hsrmax'] && !is_numericint($_POST['hsrmax'])) {
+ $error_bucket[] = array("error" => "You must specify a valid integer value as a number for the initial records to be created.",
+ "field" => "hsrmax");
+ }
+ if ($_POST['hsmxex'] && !is_numericint($_POST['hsmxex'])) {
+ $error_bucket[] = array("error" => "You must specify a valid integer value as a number for the maximum extends.",
+ "field" => "hsmxex");
+ }
+ if ($_POST['hsexsz'] && !is_numericint($_POST['hsexsz'])) {
+ $error_bucket[] = array("error" => "You must specify a valid integer value as a number for the record size.",
+ "field" => "hsexsz");
+ }
+ if ($_POST['hsmxse'] && !is_numericint($_POST['hsmxse'])) {
+ $error_bucket[] = array("error" => "You must specify a valid integer value as a number for the maximum number of records to seek.",
+ "field" => "hsmxse");
+ }
+ if ($_POST['hscoca'] && !is_numericint($_POST['hscoca'])) {
+ $error_bucket[] = array("error" => "You must specify a valid integer value as a number for hash connection cache.",
+ "field" => "hscoca");
+ }
+ }
+
+ if ($_POST['tcpipdel'] == "yes") {
+ if (! $_POST['dhost'] <> "") {
+ $error_bucket[] = array("error" => "You must specify a valid server name value for the DSPAM deliver host.",
+ "field" => "dhost");
+ } else {
+ foreach (explode(' ', $_POST['dhost']) as $ts) {
+ if (!is_domain($ts)) {
+ $error_bucket[] = array("error" => "A DSPAM delivery host name may only contain the characters a-z, 0-9, '-' and '.'.",
+ "field" => "dhost");
+ break;
+ }
+ }
+ }
+ if (! is_port($_POST['dport'])) {
+ $error_bucket[] = array("error" => "You must specify a valid port value for the DSPAM delivery host.",
+ "field" => "dport");
+ }
+ if (! $_POST['dident'] <> "") {
+ $error_bucket[] = array("error" => "You must specify a valid identification string for the DSPAM delivery host.",
+ "field" => "dident");
+ }
+ }
+
+ if ($_POST['enabledbg'] == "yes") {
+ if (! $_POST['debug'] <> "") {
+ $error_bucket[] = array("error" => "You must specify a non-zero value for the debug parameter.",
+ "field" => "debug");
+ }
+ if (! $_POST['dopt'] <> "") {
+ $error_bucket[] = array("error" => "You must specify a non-zero value for the debug options.",
+ "field" => "dopt");
+ }
+ }
+
+ if ($_POST['enableldap'] == "yes") {
+ if (! $_POST['ldaphost'] <> "") {
+ $error_bucket[] = array("error" => "You must specify a valid server name value for the LDAP host.",
+ "field" => "ldaphost");
+ } else {
+ foreach (explode(' ', $_POST['ldaphost']) as $ts) {
+ if (!is_domain($ts)) {
+ $error_bucket[] = array("error" => "A LDAP host name may only contain the characters a-z, 0-9, '-' and '.'.",
+ "field" => "ldaphost");
+ break;
+ }
+ }
+ }
+ if (! $_POST['ldapfilter'] <> "") {
+ $error_bucket[] = array("error" => "You must specify a non-zero value for the LDAP filter option or you may not be able to get any query result.",
+ "field" => "ldapfilter");
+ }
+ if (! $_POST['ldapbase'] <> "") {
+ $error_bucket[] = array("error" => "You must specify a non-zero value for the LDAP base option or you may not be able to get any query result.",
+ "field" => "ldapbase");
+ }
+ }
+
+ /* misc settings */
+ if ($_POST['foatt'] && !is_numericint($_POST['foatt'])) {
+ $error_bucket[] = array("error" => "You must specify a integer based value for the number of failover attempts.",
+ "field" => "foatt");
+ }
+ if ($_POST['enablesbl'] == "yes") {
+ if (! $_POST['sblhost'] <> "") {
+ $error_bucket[] = array("error" => "You must specify a valid server name value for the SBL host.",
+ "field" => "sblhost");
+ } else {
+ foreach (explode(' ', $_POST['sblhost']) as $ts) {
+ if (!is_domain($ts)) {
+ $error_bucket[] = array("error" => "A SBL host name may only contain the characters a-z, 0-9, '-' and '.'.",
+ "field" => "sblhost");
+ break;
+ }
+ }
+ }
+ }
+ if(isset($_POST['enablenoti'])) {
+ if($_POST['dspamcontact'] == "") {
+ $error_bucket[] = array("error" => "It is necessary to provide a support contact, if you want DSPAM to send notification messages.",
+ "field" => "dspamcontact");
+ }
+ if(empty($_POST['whichdomain'])) {
+ if ($_POST['dspamdomain'] == "") {
+ $error_bucket[] = array("error" => "You must specify a valid domain name that should be used while sending DSPAM related mail messages.",
+ "field" => "dspamdomain");
+ } else {
+ if (!is_domain($_POST['dspamdomain'])) {
+ $error_bucket[] = array("error" => "You must specify a valid domain name that should be used while sending DSPAM related mail messages.",
+ "field" => "dspamdomain");
+ }
+ }
+ }
+ }
+
+ /* Maintanance Settings */
+ if (! $_POST['psig'] || $_POST['psig'] == "") {
+ $error_bucket[] = array("error" => "You must specify a value for the number of signatures to be purged.",
+ "field" => "psig");
+ } else if (! $_POST['psig'] == "off") {
+ if (!is_numericint($_POST['psig'])) {
+ $error_bucket[] = array("error" => "You must specify a valide integer value for the number of signatures to be purged.",
+ "field" => "psig");
+ }
+ }
+ if (! $_POST['pneut'] || $_POST['pneut'] == "") {
+ $error_bucket[] = array("error" => "You must specify a value for the number of neutrals to be purged.",
+ "field" => "pneut");
+ } else if (! $_POST['pneut'] == "off") {
+ if (!is_numericint($_POST['pneut'])) {
+ $error_bucket[] = array("error" => "You must specify a valide integer value for the number of neutrals to be purged.",
+ "field" => "pneut");
+ }
+ }
+ if (! $_POST['punu'] || $_POST['punu'] == "") {
+ $error_bucket[] = array("error" => "You must specify a value for the number of unused tokens to be purged.",
+ "field" => "punu");
+ } else if (! $_POST['punu'] == "off") {
+ if (!is_numericint($_POST['punu'])) {
+ $error_bucket[] = array("error" => "You must specify a valide integer value for the number of unused tokens to be purged.",
+ "field" => "punu");
+ }
+ }
+ if (! $_POST['phapa'] || $_POST['phapa'] == "") {
+ $input_errors[] = "You must specify a value for the number of hapaxes to be purged.";
+ $input_error_fields[] = "phapa";
+ } else if (! $_POST['phapa'] == "off") {
+ if (!is_numericint($_POST['phapa'])) {
+ $error_bucket[] = array("error" => "You must specify a valide integer value for the number of hapaxes to be purged.",
+ "field" => "phapa");
+ }
+ }
+ if (! $_POST['pones'] || $_POST['pones'] == "") {
+ $error_bucket[] = array("error" => "You must specify a value for the number of tokens with only 1 spam hit to be purged.",
+ "field" => "pones");
+ } else if (! $_POST['pones'] == "off") {
+ if (!is_numericint($_POST['pones'])) {
+ $error_bucket[] = array("error" => "You must specify a valide integer value for the number of tokens with only 1 spam hit to be purged.",
+ "field" => "pones");
+ }
+ }
+ if (! $_POST['ponei'] || $_POST['ponei'] == "") {
+ $error_bucket[] = array("error" => "You must specify a value for the number of tokens with only 1 innocent hit to be purged.",
+ "field" => "ponei");
+ } else if (! $_POST['ponei'] == "off") {
+ if (!is_numericint($_POST['ponei'])) {
+ $error_bucket[] = array("error" => "You must specify a valide integer value for the number of tokens with only 1 innocent hit to be purged.",
+ "field" => "ponei");
+ }
+ }
+
+ /* System Settings */
+ if (! is_ipaddr($_POST['locmx'])) {
+ $error_bucket[] = array("error" => "You must specify a valid IP address for the local MX parameter.",
+ "field" => "locmx");
+ }
+ if ($_POST['maxmsgs'] && !is_numericint($_POST['maxmsgs'])) {
+ $error_bucket[] = array("error" => "You must specify a integer based value for the maximum message size.",
+ "field" => "maxmsgs");
+ }
+
+ /* ClamAV Settings */
+ if ($_POST['enableclam'] == "yes") {
+ if (! is_port($_POST['clamport'])) {
+ $error_bucket[] = array("error" => "You must specify a valid port value for the ClamAV host.",
+ "field" => "clamport");
+ }
+ if (! $_POST['clamhost'] <> "") {
+ $error_bucket[] = array("error" => "You must specify a valid server name value for the ClamAV host.",
+ "field" => "clamhost");
+ } else {
+ foreach (explode(' ', $_POST['clamhost']) as $ts) {
+ if (!is_domain($ts)) {
+ $error_bucket[] = array("error" => "A ClamAV host name may only contain the characters a-z, 0-9, '-' and '.'.",
+ "field" => "clamhost");
+ break;
+ }
+ }
+ }
+ }
+
+ /* */
+ /* DSPAM Daemon Settings (Server) */
+ /* */
+
+ /* at least the DSPAM thin client (dspamc)
+ * should force the user to configure the
+ * DSPAM daemon.
+ */
+ if (isset($_POST['dsthinc'])) {
+ if (! is_port($_POST['dsport'])) {
+ $error_bucket[] = array("error" => "You must specify a valid port value for the DSPAM host.",
+ "field" => "dsport");
+ }
+ if ($_POST['dsqsize'] && !is_numericint($_POST['dsqsize'])) {
+ $error_bucket[] = array("error" => "You must specify a valid integer value as a number for the server queue size.",
+ "field" => "dsqsize");
+ }
+ if (! $_POST['dspid'] <> "") {
+ $error_bucket[] = array("error" => "You must specify a valid value as PID file for the DSPAM server.",
+ "field" => "dspid");
+ }
+ if ($_POST['dssmode'] == "standard") {
+ if (! $_POST['serverparam'] <> "") {
+ $error_bucket[] = array("error" => "You must specify some valid parameters to be passed to the LMTP server.",
+ "field" => "serverparam");
+ }
+ if (! $_POST['serverid'] <> "") {
+ $error_bucket[] = array("error" => "You must specify a valid identification string to be passed to the LMTP server.",
+ "field" => "serverid");
+ }
+ if ($_POST['serversock'] && $_POST['serversock'] <> "") {
+ if (strpos($_POST['serversock'], '/') === false) {
+ $error_bucket[] = array("error" => "You must specify a valid value for the location of a Unix domain socket.",
+ "field" => "serversock");
+ }
+ }
+ }
+ }
+
+ /* DSPAM Daemon Settings (Client) */
+ if ($_POST['enabledsclient'] == "yes") {
+ if (! $_POST['dsclhost'] <> "") {
+ $error_bucket[] = array("error" => "You must specify a valid server name value for the DSPAM client host.",
+ "field" => "dsclhost");
+ } else {
+ foreach (explode(' ', $_POST['dsclhost']) as $ts) {
+ if (!is_domain($ts)) {
+ $error_bucket[] = array("error" => "A DSPAM client host name may only contain the characters a-z, 0-9, '-' and '.'.",
+ "field" => "dsclhost");
+ break;
+ }
+ }
+ }
+ if (! is_port($_POST['dsclport'])) {
+ $error_bucket[] = array("error" => "You must specify a valid port value for the DSPAM client host.",
+ "field" => "dsclport");
+ }
+ if (! $_POST['dsclident'] <> "") {
+ $error_bucket[] = array("error" => "You must specify a valid value as identification string for the DSPAM client.",
+ "field" => "dsclident");
+ }
+ }
+
+ if (is_array($error_bucket))
+ foreach($error_bucket as $elem)
+ $input_errors[] =& $elem["error"];
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($input_errors)) {
+ input_errors2Ajax($input_errors);
+ exit;
+ }
+
+ if (!$input_errors) {
+ $config['installedpackages']['dspam']['config'][0]['storage-driver'] = $_POST['sdriver'];
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings']);
+
+ if($_POST['sdriver'] == "mysql") {
+ /* ====================================================================== */
+ /* == String and integer values == */
+ /* ====================================================================== */
+ $config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['mysql-server'] = $_POST['msqlserver'];
+ $config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['mysql-port'] = $_POST['msqlport'];
+ $config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['mysql-user'] = $_POST['msqluser'];
+ $config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['mysql-password'] = $_POST['msqlpwd'];
+ $config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['mysql-database'] = $_POST['msqldb'];
+ $config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['mysql-ccache'] = $_POST['msqlccache'];
+ /* ====================================================================== */
+ /* == Boolean values == */
+ /* ====================================================================== */
+ if($_POST['msqlcomp'] == "yes")
+ $config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['mysql-compress'] = $_POST['msqlcomp'];
+ else
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['mysql-compress']);
+ if($_POST['msqlsuqt'] == "yes")
+ $config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['mysql-squote'] = $_POST['msqlsuqt'];
+ else
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['mysql-squote']);
+ if($_POST['msqluid'] == "yes")
+ $config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['mysql-uid'] = $_POST['msqluid'];
+ else
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['mysql-uid']);
+ } else if($_POST['sdriver'] == "sqlite") {
+ /* ====================================================================== */
+ /* == String and integer values == */
+ /* ====================================================================== */
+ if ($_POST['slitepr'])
+ $config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['sqlite-pragma'] = $_POST['slitepr'];
+ } else if($_POST['sdriver'] == "bdb") {
+ /* NOP */
+ } else if($_POST['sdriver'] == "pgsql") {
+ /* ====================================================================== */
+ /* == String and integer values == */
+ /* ====================================================================== */
+ $config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['pgsql-server'] = $_POST['pgserver'];
+ $config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['pgsql-port'] = $_POST['pgport'];
+ $config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['pgsql-user'] = $_POST['pguser'];
+ $config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['pgsql-password'] = $_POST['pgpwd'];
+ $config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['pgsql-database'] = $_POST['pgdb'];
+ $config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['pgsql-ccache'] = $_POST['pgccache'];
+ /* ====================================================================== */
+ /* == Boolean values == */
+ /* ====================================================================== */
+ if($_POST['pguid'] == "yes")
+ $config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['pgsql-uid'] = $_POST['pguid'];
+ else
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['pgsql-uid']);
+ } else if($_POST['sdriver'] == "oracle") {
+ /* ====================================================================== */
+ /* == String and integer values == */
+ /* ====================================================================== */
+ $config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['ora-server'] = $_POST['oraserver'];
+ $config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['ora-user'] = $_POST['orauser'];
+ $config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['ora-password'] = $_POST['orapwd'];
+ $config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['ora-schema'] = $_POST['orasch'];
+ } else if($_POST['sdriver'] == "hash") {
+ /* ====================================================================== */
+ /* == String and integer values == */
+ /* ====================================================================== */
+ $config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['hash-rec-max'] = $_POST['hsrmax'];
+ $config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['hash-max-ext'] = $_POST['hsmxex'];
+ $config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['hash-ext-size'] = $_POST['hsexsz'];
+ $config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['hash-max-seek'] = $_POST['hsmxse'];
+ $config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['hash-co-user'] = $_POST['hsccus'];
+ $config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['hash-co-cache'] = $_POST['hscoca'];
+ /* ====================================================================== */
+ /* == Boolean values == */
+ /* ====================================================================== */
+ if($_POST['hsatex'] == "yes")
+ $config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['hash-auto-ex'] = $_POST['hsatex'];
+ else
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['hash-auto-ex']);
+ }
+
+ $config['installedpackages']['dspam']['config'][0]['tdelivery-agent'] = $_POST['dagent'];
+ $config['installedpackages']['dspam']['config'][0]['thin-client'] = $_POST['dsthinc'];
+
+ if($_POST['tcpipdel'] == "yes") {
+ $config['installedpackages']['dspam']['config'][0]['tcpip-delivery'] = $_POST['tcpipdel'];
+ $config['installedpackages']['dspam']['config'][0]['tcpip-delivery-host'] = $_POST['dhost'];
+ $config['installedpackages']['dspam']['config'][0]['tcpip-delivery-port'] = $_POST['dport'];
+ $config['installedpackages']['dspam']['config'][0]['tcpip-delivery-ident'] = $_POST['dident'];
+ $config['installedpackages']['dspam']['config'][0]['tcpip-delivery-proto'] = $_POST['delproto'];
+ } else {
+ unset($config['installedpackages']['dspam']['config'][0]['tcpip-delivery']);
+ unset($config['installedpackages']['dspam']['config'][0]['tcpip-delivery-host']);
+ unset($config['installedpackages']['dspam']['config'][0]['tcpip-delivery-port']);
+ unset($config['installedpackages']['dspam']['config'][0]['tcpip-delivery-ident']);
+ unset($config['installedpackages']['dspam']['config'][0]['tcpip-delivery-proto']);
+ }
+
+ $config['installedpackages']['dspam']['config'][0]['delivery-onfail'] = $_POST['onfail'];
+
+ if($_POST['enabledbg'] == "yes") {
+ $config['installedpackages']['dspam']['config'][0]['debug-enable'] = $_POST['enabledbg'];
+ $config['installedpackages']['dspam']['config'][0]['debug-whom'] = $_POST['debug'];
+ $config['installedpackages']['dspam']['config'][0]['debug-options'] = $_POST['dopt'];
+ } else {
+ unset($config['installedpackages']['dspam']['config'][0]['debug-enable']);
+ unset($config['installedpackages']['dspam']['config'][0]['debug-whom']);
+ unset($config['installedpackages']['dspam']['config'][0]['debug-options']);
+ }
+
+ /* DSPAM engine settings */
+ $config['installedpackages']['dspam']['config'][0]['training-mode'] = $_POST['tmode'];
+ if($_POST['testct'] == "yes") {
+ $config['installedpackages']['dspam']['config'][0]['test-cond-training'] = $_POST['testct'];
+ } else {
+ unset($config['installedpackages']['dspam']['config'][0]['test-cond-training']);
+ }
+ $config['installedpackages']['dspam']['config'][0]['pvalue'] = $_POST['pvalue'];
+ if($_POST['ipdrive'] == "yes") {
+ $config['installedpackages']['dspam']['config'][0]['improbability-drive'] = $_POST['ipdrive'];
+ } else {
+ unset($config['installedpackages']['dspam']['config'][0]['improbability-drive']);
+ }
+
+ /* LDAP related settings */
+ if($_POST['enableldap'] == "yes") {
+ $config['installedpackages']['dspam']['config'][0]['ldap-enable'] = $_POST['enableldap'];
+ $config['installedpackages']['dspam']['config'][0]['ldap-mode'] = $_POST['ldapmode'];
+ $config['installedpackages']['dspam']['config'][0]['ldap-host'] = $_POST['ldaphost'];
+ $config['installedpackages']['dspam']['config'][0]['ldap-filter'] = $_POST['ldapfilter'];
+ $config['installedpackages']['dspam']['config'][0]['ldap-base'] = $_POST['ldapbase'];
+ } else {
+ unset($config['installedpackages']['dspam']['config'][0]['ldap-enable']);
+ unset($config['installedpackages']['dspam']['config'][0]['ldap-mode']);
+ unset($config['installedpackages']['dspam']['config'][0]['ldap-host']);
+ unset($config['installedpackages']['dspam']['config'][0]['ldap-filter']);
+ unset($config['installedpackages']['dspam']['config'][0]['ldap-base']);
+ }
+
+ /* misc settings */
+ $config['installedpackages']['dspam']['config'][0]['failover-attempts'] = $_POST['foatt'];
+ if($_POST['enablesbl'] == "yes") {
+ $config['installedpackages']['dspam']['config'][0]['sbl-enable'] = $_POST['enablesbl'];
+ $config['installedpackages']['dspam']['config'][0]['sbl-host'] = $_POST['sblhost'];
+ } else {
+ unset($config['installedpackages']['dspam']['config'][0]['sbl-enable']);
+ unset($config['installedpackages']['dspam']['config'][0]['sbl-host']);
+ }
+ if($_POST['enablerbl'] == "yes") {
+ $config['installedpackages']['dspam']['config'][0]['rbl-inoculate'] = $_POST['enablerbl'];
+ } else {
+ unset($config['installedpackages']['dspam']['config'][0]['rbl-inoculate']);
+ }
+ if($_POST['enablenoti'] == "yes") {
+ $config['installedpackages']['dspam']['config'][0]['notification-email'] = $_POST['enablenoti'];
+ $config['installedpackages']['dspam']['config'][0]['dspam-contact'] = $_POST['dspamcontact'];
+ } else {
+ unset($config['installedpackages']['dspam']['config'][0]['notification-email']);
+ unset($config['installedpackages']['dspam']['config'][0]['dspam-domain']);
+ unset($config['installedpackages']['dspam']['config'][0]['dspam-contact']);
+ }
+ if($_POST['whichdomain'] == "yes") {
+ unset($config['installedpackages']['dspam']['config'][0]['dspam-domain']);
+ } else {
+ $config['installedpackages']['dspam']['config'][0]['dspam-domain'] = $_POST['dspamdomain'];
+ }
+
+ /* Maintainance Settings */
+ $config['installedpackages']['dspam']['config'][0]['purge-signatures'] = $_POST['psig'];
+ $config['installedpackages']['dspam']['config'][0]['purge-neutral'] = $_POST['pneut'];
+ $config['installedpackages']['dspam']['config'][0]['purge-unused'] = $_POST['punu'];
+ $config['installedpackages']['dspam']['config'][0]['purge-hapaxes'] = $_POST['phapa'];
+ $config['installedpackages']['dspam']['config'][0]['purge-hits-1s'] = $_POST['pones'];
+ $config['installedpackages']['dspam']['config'][0]['purge-hits-1i'] = $_POST['ponei'];
+
+ /* System Settings */
+ $config['installedpackages']['dspam']['config'][0]['local-mx'] = $_POST['locmx'];
+ $config['installedpackages']['dspam']['config'][0]['local-mx'] = $_POST['locmx'];
+ if($_POST['enablesysl'] == "yes") {
+ $config['installedpackages']['dspam']['config'][0]['system-log'] = $_POST['enablesysl'];
+ } else {
+ unset($config['installedpackages']['dspam']['config'][0]['system-log']);
+ }
+ if($_POST['enableusel'] == "yes") {
+ $config['installedpackages']['dspam']['config'][0]['user-log'] = $_POST['enableusel'];
+ } else {
+ unset($config['installedpackages']['dspam']['config'][0]['user-log']);
+ }
+ $config['installedpackages']['dspam']['config'][0]['filter-opt'] = $_POST['optinout'];
+ if($_POST['enableptoh'] == "yes") {
+ $config['installedpackages']['dspam']['config'][0]['parse-to-headers'] = $_POST['enableptoh'];
+ } else {
+ unset($config['installedpackages']['dspam']['config'][0]['parse-to-headers']);
+ }
+ if($_POST['enablecmop'] == "yes") {
+ $config['installedpackages']['dspam']['config'][0]['change-mode-on-parse'] = $_POST['enablecmop'];
+ } else {
+ unset($config['installedpackages']['dspam']['config'][0]['change-mode-on-parse']);
+ }
+ if($_POST['enablecuop'] == "yes") {
+ $config['installedpackages']['dspam']['config'][0]['change-user-on-parse'] = $_POST['enablecuop'];
+ } else {
+ unset($config['installedpackages']['dspam']['config'][0]['change-user-on-parse']);
+ }
+ if($_POST['enablecuop'] == "yes") {
+ $config['installedpackages']['dspam']['config'][0]['change-user-on-parse'] = $_POST['enablecuop'];
+ } else {
+ unset($config['installedpackages']['dspam']['config'][0]['change-user-on-parse']);
+ }
+ if($_POST['enablebmta'] == "yes") {
+ $config['installedpackages']['dspam']['config'][0]['broken-mta-settings'] = $_POST['enablebmta'];
+ } else {
+ unset($config['installedpackages']['dspam']['config'][0]['broken-mta-settings']);
+ }
+ $config['installedpackages']['dspam']['config'][0]['max-message-size'] = $_POST['maxmsgs'];
+ if($_POST['procbias'] == "yes") {
+ $config['installedpackages']['dspam']['config'][0]['processor-bias'] = $_POST['procbias'];
+ } else {
+ unset($config['installedpackages']['dspam']['config'][0]['processor-bias']);
+ }
+
+ /* ClamAV related settings */
+ if($_POST['enableclam'] == "yes") {
+ $config['installedpackages']['dspam']['config'][0]['clamav-enable'] = $_POST['enableclam'];
+ $config['installedpackages']['dspam']['config'][0]['clamav-port'] = $_POST['clamport'];
+ $config['installedpackages']['dspam']['config'][0]['clamav-host'] = $_POST['clamhost'];
+ $config['installedpackages']['dspam']['config'][0]['clamav-response'] = $_POST['clamresp'];
+ } else {
+ unset($config['installedpackages']['dspam']['config'][0]['clamav-enable']);
+ unset($config['installedpackages']['dspam']['config'][0]['clamav-port']);
+ unset($config['installedpackages']['dspam']['config'][0]['clamav-host']);
+ unset($config['installedpackages']['dspam']['config'][0]['clamav-response']);
+ }
+
+ /* DSPAM daemon settings */
+ $config['installedpackages']['dspam']['config'][0]['dspam-server-port'] = $_POST['dsport'];
+ $config['installedpackages']['dspam']['config'][0]['dspam-server-queue-size'] = $_POST['dsqsize'];
+ $config['installedpackages']['dspam']['config'][0]['dspam-server-pid'] = $_POST['dspid'];
+ $config['installedpackages']['dspam']['config'][0]['dspam-server-mode'] = $_POST['dssmode'];
+ $config['installedpackages']['dspam']['config'][0]['dspam-server-params'] = $_POST['serverparam'];
+ $config['installedpackages']['dspam']['config'][0]['dspam-server-id'] = $_POST['serverid'];
+ $config['installedpackages']['dspam']['config'][0]['dspam-server-socket'] = $_POST['serversock'];
+
+ /* DSPAM client settings */
+ if($_POST['enabledsclient'] == "yes") {
+ $config['installedpackages']['dspam']['config'][0]['dspam-client-enable'] = $_POST['enabledsclient'];
+ $config['installedpackages']['dspam']['config'][0]['dspam-client-host'] = $_POST['dsclhost'];
+ $config['installedpackages']['dspam']['config'][0]['dspam-client-port'] = $_POST['dsclport'];
+ $config['installedpackages']['dspam']['config'][0]['dspam-client-id'] = $_POST['dsclident'];
+ } else {
+ unset($config['installedpackages']['dspam']['config'][0]['dspam-client-enable']);
+ unset($config['installedpackages']['dspam']['config'][0]['dspam-client-host']);
+ unset($config['installedpackages']['dspam']['config'][0]['dspam-client-port']);
+ unset($config['installedpackages']['dspam']['config'][0]['dspam-client-id']);
+ }
+
+ write_config();
+
+ $retval = 0;
+ conf_mount_rw();
+ config_lock();
+ $retval = dspam_configure();
+ config_unlock();
+ $savemsg = get_std_save_message($retval);
+ conf_mount_ro();
+ }
+}
+
+/* did the user send a request to delete an item? */
+if ($_GET['act'] == "del") {
+ if ($_GET['what'] == "tuser" && $t_users[$_GET['id']]) {
+ unset($t_users[$_GET['id']]);
+ write_config();
+ pfSenseHeader("dspam-settings.php");
+ exit;
+ } else if ($_GET['what'] == "feat" && $t_features[$_GET['id']]) {
+ unset($t_features[$_GET['id']]);
+ write_config();
+ pfSenseHeader("dspam-settings.php");
+ exit;
+ } else if ($_GET['what'] == "algo" && $t_algos[$_GET['id']]) {
+ unset($t_algos[$_GET['id']]);
+ write_config();
+ pfSenseHeader("dspam-settings.php");
+ exit;
+ } else if ($_GET['what'] == "pref" && $t_prefs[$_GET['id']]) {
+ unset($t_prefs[$_GET['id']]);
+ write_config();
+ pfSenseHeader("dspam-settings.php");
+ exit;
+ } else if ($_GET['what'] == "overr" && $t_overr[$_GET['id']]) {
+ unset($t_overr[$_GET['id']]);
+ write_config();
+ pfSenseHeader("dspam-settings.php");
+ exit;
+ } else if ($_GET['what'] == "header" && $t_headers[$_GET['id']]) {
+ unset($t_headers[$_GET['id']]);
+ write_config();
+ pfSenseHeader("dspam-settings.php");
+ exit;
+ } else if ($_GET['what'] == "bmta" && $t_bmtas[$_GET['id']]) {
+ unset($t_bmtas[$_GET['id']]);
+ write_config();
+ pfSenseHeader("dspam-settings.php");
+ exit;
+ } else if ($_GET['what'] == "spwd" && $t_spwds[$_GET['id']]) {
+ unset($t_spwds[$_GET['id']]);
+ write_config();
+ pfSenseHeader("dspam-settings.php");
+ exit;
+ }
+}
+
+ /* if ajax is calling, give them an update message */
+ if(isAjax())
+ print_info_box_np($savemsg);
+
+ include("head.inc");
+ /* put your custom HTML head content here */
+ /* using some of the $pfSenseHead function calls */
+ $jscriptstr = <<<EOD
+<script type="text/javascript">
+<!--
+
+EOD;
+
+ $jscriptstr .= getJScriptFunction(5);
+ if (empty($_POST))
+ $jscriptstr .= getJScriptFunction(6);
+ $jscriptstr .= <<<EOD
+//-->
+</script>
+EOD;
+
+ $pfSenseHead->addScript($jscriptstr);
+ echo $pfSenseHead->getHTML();?>
+
+<body link="#000000" vlink="#000000" alink="#000000" <?php if (empty($_POST)) { echo "onLoad='checkDisabledState(document.iform);'"; } ?>>
+ <?php include("fbegin.inc"); ?>
+ <form action="dspam-settings.php" method="post" name="iform" id="iform">
+ <input type="hidden" name="sectionid" id="sectionid" value="<?=$pconfig['sectionid'];?>" />
+ <?php if ($input_errors) print_input_errors($input_errors); ?>
+ <?php if ($savemsg) print_info_box($savemsg); ?>
+ <p>
+ <span class="vexpl">
+ <span class="red">
+ <strong>Note: </strong>
+ </span>
+ the options on this page are intended for use by advanced users only.
+ Any setting found on this page is directly going into <code>dspam.conf</code>.
+ Make sure you do not mess with settings, you do not understand.
+ </span>
+ </p>
+ <p>
+ <span class="vexpl">If you submit this page, the DSPAM daemon process will be restarted.</span>
+ </p>
+ <br />
+ <table width="99%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td>
+ <?php
+ $tab_array = array();
+ $tab_array[] = array("System Status", false, "/dspam-admin.php");
+ $tab_array[] = array("User Statistics", false, "/dspam-admin-stats.php");
+ $tab_array[] = array("Administration", false, "/dspam-admin-prefs.php");
+ $tab_array[] = array("Settings", true, "/dspam-settings.php");
+ $tab_array[] = array("Control Center", false, "/dspam-perf.php");
+ display_top_tabs($tab_array);
+ ?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <table id="maintable" name="maintable" class="tabcont" width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td>
+ <p><strong>Settings</strong></p>
+ <ul style="font-size:0.95em; font-family:Verdana,Arial,sans-serif">
+ <li><a href="#db" class="redlnk">Database Settings<?php if ($pconfig['sectionid'] == "db") echo '<span class="red">&nbsp;&raquo;last modified&laquo;</span>'; ?></a></li>
+ <li><a href="#del" class="redlnk">Delivery Settings<?php if ($pconfig['sectionid'] == "del") echo '<span class="red">&nbsp;&raquo;last modified&laquo;</span>'; ?></a></li>
+ <li><a href="#priv" class="redlnk">DSPAM Privileges<?php if ($pconfig['sectionid'] == "priv") echo '<span class="red">&nbsp;&raquo;last modified&laquo;</span>'; ?></a></li>
+ <li><a href="#dbg" class="redlnk">DSPAM Debugging Options<?php if ($pconfig['sectionid'] == "dbg") echo '<span class="red">&nbsp;&raquo;last modified&laquo;</span>'; ?></a></li>
+ <li><a href="#eng" class="redlnk">DSPAM Engine Settings<?php if ($pconfig['sectionid'] == "eng") echo '<span class="red">&nbsp;&raquo;last modified&laquo;</span>'; ?></a></li>
+ <?php if (checkForLDAPSupport()): ?>
+ <li><a href="#ldap" class="redlnk">LDAP Settings<?php if ($pconfig['sectionid'] == "ldap") echo '<span class="red">&nbsp;&raquo;last modified&laquo;</span>'; ?></a></li>
+ <?php endif; ?>
+ <li><a href="#misc" class="redlnk">Miscellaneous Settings<?php if ($pconfig['sectionid'] == "misc") echo '<span class="red">&nbsp;&raquo;last modified&laquo;</span>'; ?></a></li>
+ <li><a href="#main" class="redlnk">Maintainance Settings<?php if ($pconfig['sectionid'] == "main") echo '<span class="red">&nbsp;&raquo;last modified&laquo;</span>'; ?></a></li>
+ <li><a href="#sys" class="redlnk">System Settings<?php if ($pconfig['sectionid'] == "sys") echo '<span class="red">&nbsp;&raquo;last modified&laquo;</span>'; ?></a></li>
+ <?php if (checkForClamAVSupport()): ?>
+ <li><a href="#clam" class="redlnk">ClamAV Engine Settings<?php if ($pconfig['sectionid'] == "clam") echo '<span class="red">&nbsp;&raquo;last modified&laquo;</span>'; ?></a></li>
+ <?php endif; ?>
+ <li><a href="#srv" class="redlnk">DSPAM Daemon Settings (Server)<?php if ($pconfig['sectionid'] == "srv") echo '<span class="red">&nbsp;&raquo;last modified&laquo;</span>'; ?></a></li>
+ <li><a href="#cli" class="redlnk">DSPAM Daemon Settings (Client)<?php if ($pconfig['sectionid'] == "cli") echo '<span class="red">&nbsp;&raquo;last modified&laquo;</span>'; ?></a></li>
+ </ul>
+ <br />
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <table id="sortabletable0" name="sortabletable0" width="100%" border="0" cellpadding="10" cellspacing="0">
+ <tr>
+ <td colspan="2" valign="top" class="listtopic"><a name="db" style="visibility: hidden;">&nbsp;</a>Database Settings</td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Storage Driver</td>
+ <td width="78%" class="vtable">
+ <select name="sdriver" onChange="toggleDBSettings();" class="formselect">
+ <?php if (checkForMySQLSupport()): ?>
+ <option value="mysql" <?php if($pconfig['sdriver'] == "mysql") echo('selected="selected"');?>>mysql</option>
+ <?php endif; ?>
+ <?php if (checkForSQLiteSupport()): ?>
+ <option value="sqlite" <?php if($pconfig['sdriver'] == "sqlite") echo('selected="selected"');?>>sqlite</option>
+ <?php endif; ?>
+ <option value="bdb" <?php if($pconfig['sdriver'] == "bdb") echo('selected="selected"');?>>bdb</option>
+ <?php if (checkForPgSQLSupport()): ?>
+ <option value="pgsql" <?php if($pconfig['sdriver'] == "pgsql") echo('selected="selected"');?>>pgsql</option>
+ <?php endif; ?>
+ <option value="oracle" <?php if($pconfig['sdriver'] == "oracle") echo('selected="selected"');?>>oracle</option>
+ <option value="hash" <?php if($pconfig['sdriver'] == "hash") echo('selected="selected"');?>>hash</option>
+ </select>
+ <strong>Specifies the storage driver backend (library) to use.</strong>
+ <p>
+ <span class="vexpl">
+ IMPORTANT: Switching storage drivers requires more than merely changing this option.
+ If you do not wish to lose all of your data, you will need to migrate it to the new
+ backend before making this change.
+ </span>
+ </p>
+ </td>
+ </tr>
+ <?php if ($pconfig['sdriver'] == "mysql" && checkForMySQLSupport()): ?>
+ <tbody id="DBmysql" style="display: table-row-group;">
+ <?php else: ?>
+ <tbody id="DBmysql" style="display: none;">
+ <?php endif; ?>
+ <tr>
+ <td width="22%" valign="top" class="vncell">MySQL Server</td>
+ <td width="78%" class="vtable">
+ <input type="text" size="30" <?= checkForErrorClass("msqlserver", "formfld host"); ?> name="msqlserver" id="msqlserver" value="<?=htmlspecialchars($pconfig['msqlserver']);?>" />
+ <strong>
+ Either a reference to a Unix domain socket or a reference to a specific host.
+ </strong>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">MySQL Port</td>
+ <td width="78%" class="vtable">
+ <input type="text" size="30" <?= checkForErrorClass("msqlport", "formfld unknown"); ?> name="msqlport" id="msqlport" value="<?=htmlspecialchars($pconfig['msqlport']);?>" />
+ <strong>
+ Use this variable if you are going to a MySQL server instance using TCP/IP instead of a socket connection.
+ </strong>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">MySQL User</td>
+ <td width="78%" class="vtable">
+ <input type="text" size="30" <?= checkForErrorClass("msqluser", "formfld user"); ?> name="msqluser" id="msqluser" value="<?=htmlspecialchars($pconfig['msqluser']);?>" <?php if ($_POST && $input_error_fields && in_array("msqluser", $input_error_fields)) echo 'style="background-color: red;" onFocus="this.style.backgroundColor = \'white\';" onBlur="this.style.backgroundColor = \'red\';"'; ?>/>
+ <strong>
+ Username, that will be used to connect to a MySQL server instance.
+ </strong>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">MySQL Password</td>
+ <td width="78%" class="vtable">
+ <input type="text" size="30" <?= checkForErrorClass("msqlpwd", "formfld pwd"); ?> name="msqlpwd" id="msqlpwd" value="<?=htmlspecialchars($pconfig['msqlpwd']);?>" <?php if ($_POST && $input_error_fields && in_array("msqlpwd", $input_error_fields)) echo 'style="background-color: red;" onFocus="this.style.backgroundColor = \'white\';" onBlur="this.style.backgroundColor = \'red\';"'; ?>/>
+ <strong>
+ Password, that will be used to connect to a MySQL server instance.
+ </strong>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">MySQL Database</td>
+ <td width="78%" class="vtable">
+ <input type="text" size="30" <?= checkForErrorClass("msqldb", "formfld unknown"); ?> name="msqldb" id="msqldb" value="<?=htmlspecialchars($pconfig['msqldb']);?>" <?php if ($_POST && $input_error_fields && in_array("msqldb", $input_error_fields)) echo 'style="background-color: red;" onFocus="this.style.backgroundColor = \'white\';" onBlur="this.style.backgroundColor = \'red\';"'; ?>/>
+ <strong>
+ Database name, that contains DSPAM data.
+ </strong>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">MySQL Compress</td>
+ <td width="78%" class="vtable">
+ <input type="checkbox" class="formfld" name="msqlcomp" id="msqlcomp" value="yes" <?php if (isset($pconfig['msqlcomp'])) echo 'checked="checked"'; ?> />
+ <strong>
+ Indicates whether communication data between DSPAM and MySQL should be compressed.
+ </strong>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">MySQL Supress Quote</td>
+ <td width="78%" class="vtable">
+ <input type="checkbox" class="formfld" name="msqlsuqt" id="msqlsuqt" value="yes" <?php if (isset($pconfig['msqlsuqt'])) echo 'checked="checked"'; ?> />
+ <strong>
+ Use this if you have the 4.1 quote bug (see doc/mysql.txt).
+ </strong>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">&nbsp;</td>
+ <td width="78%" class="vtable">
+ <p>
+ <span class="vexpl">
+ If you're running DSPAM in client/server (daemon) mode, uncomment the
+ setting below to override the default connection cache size (the number
+ of connections the server pools between all clients). The connection cache
+ represents the maximum number of database connections *available* and should
+ be set based on the maximum number of concurrent connections you're likely
+ to have. Each connection may be used by only one thread at a time, so all
+ other threads _will block_ until another connection becomes available.
+ </span>
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">MySQL Connection Cache</td>
+ <td width="78%" class="vtable">
+ <input type="text" size="30" <?= checkForErrorClass("msqlccache", "formfld unknown"); ?> name="msqlccache" id="msqlccache" value="<?=htmlspecialchars($pconfig['msqlccache']);?>" <?php if ($_POST && $input_error_fields && in_array("msqlccache", $input_error_fields)) echo 'style="background-color: red;" onFocus="this.style.backgroundColor = \'white\';" onBlur="this.style.backgroundColor = \'red\';"'; ?>/>
+ <strong>
+ Conection cache default set to 10.
+ </strong>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">&nbsp;</td>
+ <td width="78%" class="vtable">
+ <p>
+ <span class="vexpl">
+ MySQL supports the insertion of the user id into the DSPAM
+ signature. This allows you to create one single spam or fp alias
+ (pointing to some arbitrary user), and the uid in the signature will
+ switch to the correct user. Result: you need only one spam alias
+ </span>
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">MySQL UID In Signature</td>
+ <td width="78%" class="vtable">
+ <input type="checkbox" class="formfld" name="msqluid" id="msqluid" value="yes" <?php if (isset($pconfig['msqluid'])) echo 'checked="checked"'; ?> />
+ <strong>
+ Insert user id into the DSPAM signature.
+ </strong>
+ </td>
+ </tr>
+ </tbody>
+ <?php if ($pconfig['sdriver'] == "sqlite" && checkForSQLiteSupport()): ?>
+ <tbody id="DBsqlite" style="display: table-row-group;">
+ <?php else: ?>
+ <tbody id="DBsqlite" style="display: none;">
+ <?php endif; ?>
+ <tr>
+ <td width="22%" valign="top" class="vncell">SQLite Pragma</td>
+ <td width="78%" class="vtable">
+ <input type="text" size="30" <?= checkForErrorClass("slitepr", "formfld unknown"); ?> name="slitepr" id="slitepr" value="<?=htmlspecialchars($pconfig['slitepr']);?>" />
+ <strong>
+ A particular SQLite pragma command to be used.
+ </strong>
+ <p>
+ <span class="vexpl">
+ See: <a href="http://sqlite.org/pragma.html" target="_blank">http://sqlite.org/pragma.html</a>
+ </span>
+ </p>
+ </td>
+ </tr>
+ </tbody>
+ <?php if ($pconfig['sdriver'] == "bdb"): ?>
+ <tbody id="DBbdb" style="display: table-row-group;">
+ <?php else: ?>
+ <tbody id="DBbdb" style="display: none;">
+ <?php endif; ?>
+ <tr>
+ <td width="22%" valign="top" class="vncell">&nbsp;</td>
+ <td width="78%" class="vtable">
+ <strong>
+ Nothing to be configured here !
+ </strong>
+ </td>
+ </tr>
+ </tbody>
+ <?php if ($pconfig['sdriver'] == "pgsql" && checkForPgSQLSupport()): ?>
+ <tbody id="DBpgsql" style="display: table-row-group;">
+ <?php else: ?>
+ <tbody id="DBpgsql" style="display: none;">
+ <?php endif; ?>
+ <tr>
+ <td width="22%" valign="top" class="vncell">PostgreSQL Server</td>
+ <td width="78%" class="vtable">
+ <input type="text" size="30" <?= checkForErrorClass("pgserver", "formfld host"); ?> name="pgserver" id="pgserver" value="<?=htmlspecialchars($pconfig['pgserver']);?>" />
+ <strong>
+ A reference to a specific host that is running a PostgreSQL instance.
+ </strong>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">PostgreSQL Port</td>
+ <td width="78%" class="vtable">
+ <input type="text" size="30" <?= checkForErrorClass("pgport", "formfld unknown"); ?> name="pgport" id="pgport" value="<?=htmlspecialchars($pconfig['pgport']);?>" />
+ <strong>
+ A number that represents the port a specific PostgreSQL instance is listening to.
+ </strong>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">PostgreSQL User</td>
+ <td width="78%" class="vtable">
+ <input type="text" size="30" <?= checkForErrorClass("pguser", "formfld user"); ?> name="pguser" id="pguser" value="<?=htmlspecialchars($pconfig['pguser']);?>" />
+ <strong>
+ Username, that will be used to connect to a PostgreSQL server instance.
+ </strong>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">PostgreSQL Password</td>
+ <td width="78%" class="vtable">
+ <input type="text" size="30" <?= checkForErrorClass("pgpwd", "formfld pwd"); ?> name="pgpwd" id="pgpwd" value="<?=htmlspecialchars($pconfig['pgpwd']);?>"/>
+ <strong>
+ Password, that will be used to connect to a PostgreSQL server instance.
+ </strong>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">PostgreSQL Database</td>
+ <td width="78%" class="vtable">
+ <input type="text" size="30" <?= checkForErrorClass("pgdb", "formfld unknown"); ?> name="pgdb" id="pgdb" value="<?=htmlspecialchars($pconfig['pgdb']);?>" />
+ <strong>
+ Database name, that contains DSPAM data.
+ </strong>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">&nbsp;</td>
+ <td width="78%" class="vtable">
+ <p>
+ <span class="vexpl">
+ If you're running DSPAM in client/server (daemon) mode, uncomment the
+ setting below to override the default connection cache size (the number
+ of connections the server pools between all clients). The connection cache
+ represents the maximum number of database connections *available* and should
+ be set based on the maximum number of concurrent connections you're likely
+ to have. Each connection may be used by only one thread at a time, so all
+ other threads _will block_ until another connection becomes available.
+ </span>
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">PostgreSQL Connection Cache</td>
+ <td width="78%" class="vtable">
+ <input type="text" size="30" <?= checkForErrorClass("pgccache", "formfld unknown"); ?> name="pgccache" id="pgccache" value="<?=htmlspecialchars($pconfig['pgccache']);?>" />
+ <strong>
+ Conection cache default set to 3.
+ </strong>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">&nbsp;</td>
+ <td width="78%" class="vtable">
+ <p>
+ <span class="vexpl">
+ PostgreSQL supports the insertion of the user id into the DSPAM
+ signature. This allows you to create one single spam or fp alias
+ (pointing to some arbitrary user), and the uid in the signature will
+ switch to the correct user. Result: you need only one spam alias
+ </span>
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">PostgreSQL UID In Signature</td>
+ <td width="78%" class="vtable">
+ <input type="checkbox" class="formfld" name="pguid" id="pguid" value="yes" <?php if (isset($pconfig['pguid'])) echo 'checked="checked"'; ?> />
+ <strong>
+ Insert user id into the DSPAM signature.
+ </strong>
+ </td>
+ </tr>
+ </tbody>
+ <?php if ($pconfig['sdriver'] == "oracle"): ?>
+ <tbody id="DBoracle" style="display: table-row-group;">
+ <?php else: ?>
+ <tbody id="DBoracle" style="display: none;">
+ <?php endif; ?>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Attention !</td>
+ <td width="78%" class="vtable">
+ <strong style="color: red;">
+ This feature is currently unsupported !
+ </strong>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Oracle Server</td>
+ <td width="78%" class="vtable">
+ <input type="text" size="30" <?= checkForErrorClass("oraserver", "formfld host"); ?> name="oraserver" id="oraserver" value="<?=htmlspecialchars($pconfig['oraserver']);?>" />
+ <strong>
+ A reference to a specific host that is running an Oracle database instance.
+ </strong>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Oracle User</td>
+ <td width="78%" class="vtable">
+ <input type="text" size="30" <?= checkForErrorClass("orauser", "formfld user"); ?> name="orauser" id="orauser" value="<?=htmlspecialchars($pconfig['orauser']);?>" />
+ <strong>
+ Username, that will be used to connect to a Oracle database server instance.
+ </strong>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Oracle Password</td>
+ <td width="78%" class="vtable">
+ <input type="text" size="30" <?= checkForErrorClass("orapwd", "formfld pwd"); ?> name="orapwd" id="orapwd" value="<?=htmlspecialchars($pconfig['orapwd']);?>" />
+ <strong>
+ Password, that will be used to connect to a Oracle database server instance.
+ </strong>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Oracle Schema</td>
+ <td width="78%" class="vtable">
+ <input type="text" size="30" <?= checkForErrorClass("orasch", "formfld unknown"); ?> name="orasch" id="orasch" value="<?=htmlspecialchars($pconfig['orasch']);?>" />
+ <strong>
+ Schema name, that contains DSPAM data.
+ </strong>
+ </td>
+ </tr>
+ </tbody>
+ <?php if ($pconfig['sdriver'] == "hash"): ?>
+ <tbody id="DBhash" style="display: table-row-group;">
+ <?php else: ?>
+ <tbody id="DBhash" style="display: none;">
+ <?php endif; ?>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Hash Rec Max</td>
+ <td width="78%" class="vtable">
+ <input type="text" size="30" <?= checkForErrorClass("hsrmax", "formfld unknown"); ?> name="hsrmax" id="hsrmax" value="<?=htmlspecialchars($pconfig['hsrmax']);?>" />
+ <strong>
+ Default number of records to create in the initial segment when building hash files.
+ </strong>
+ <p>
+ <span class="vexpl">
+ 100,000 yields files 1.6MB in size, but can fill up fast, so be sure to increase this
+ (to a million or more) if you're not using autoextend.
+ </span>
+ </p>
+ <p>
+ <span class="vexpl">
+ Primes List:
+ <pre>
+53, 97, 193, 389, 769, 1543, 3079, 6151, 12289, 24593, 49157, 98317, 196613,
+393241, 786433, 1572869, 3145739, 6291469, 12582917, 25165843, 50331653,
+100663319, 201326611, 402653189, 805306457, 1610612741, 3221225473,
+4294967291
+ </pre>
+ </span>
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Hash Auto Extend</td>
+ <td width="78%" class="vtable">
+ <input type="checkbox" class="formfld" name="hsatex" id="hsatex" value="yes" <?php if (isset($pconfig['hsatex'])) echo 'checked="checked"'; ?> />
+ <strong>
+ Autoextend hash databases when they fill up. This allows them to continue
+ to train by adding extents (extensions) to the file.
+ </strong>
+ <p>
+ <span class="vexpl">
+ Note: There will be a small delay during the growth process,
+ as everything needs to be closed and remapped.
+ </span>
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Hash Max Extents</td>
+ <td width="78%" class="vtable">
+ <input type="text" size="30" <?= checkForErrorClass("hsmxex", "formfld unknown"); ?> name="hsmxex" id="hsmxex" value="<?=htmlspecialchars($pconfig['hsmxex']);?>" />
+ <strong>
+ The maximum number of extents that may be created in a single hash file.
+ </strong>
+ <p>
+ <span class="vexpl">
+ Note: Set this to zero for unlimited.
+ </span>
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Hash Extent Size</td>
+ <td width="78%" class="vtable">
+ <input type="text" size="30" <?= checkForErrorClass("hsexsz", "formfld unknown"); ?> name="hsexsz" id="hsexsz" value="<?=htmlspecialchars($pconfig['hsexsz']);?>" />
+ <strong>
+ The record size for newly created extents.
+ </strong>
+ <p>
+ <span class="vexpl">
+ Note: Creating this too small could result in many extents
+ being created. Creating this too large could result in
+ excessive disk space usage.
+ </span>
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Hash Max Seek</td>
+ <td width="78%" class="vtable">
+ <input type="text" size="30" <?= checkForErrorClass("hsmxse", "formfld unknown"); ?> name="hsmxse" id="hsmxse" value="<?=htmlspecialchars($pconfig['hsmxse']);?>" />
+ <strong>
+ The maximum number of records to seek to insert a new record
+ before failing or adding a new extent.
+ </strong>
+ <p>
+ <span class="vexpl">
+ Note: Setting this too high will exhaustively scan each segment
+ and kill performance. Typically, a low value is acceptable as
+ even older extents will continue to fill over time.
+ </span>
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Hash Concurrent User</td>
+ <td width="78%" class="vtable">
+ <input type="text" size="30" <?= checkForErrorClass("hsccus", "formfld unknown"); ?> name="hsccus" id="hsccus" value="<?=htmlspecialchars($pconfig['hsccus']);?>" />
+ <strong>
+ If you are using a single, stateful hash database in daemon mode,
+ specifying a concurrent user will cause the user to be permanently
+ mapped into memory and shared via rwlocks.
+ </strong>
+ <p>
+ <span class="vexpl">
+ Note: Leave this field blank, if you do not want to use this option.
+ </span>
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Hash Connection Cache</td>
+ <td width="78%" class="vtable">
+ <input type="text" size="30" <?= checkForErrorClass("hscoca", "formfld unknown"); ?> name="hscoca" id="hscoca" value="<?=htmlspecialchars($pconfig['hscoca']);?>" />
+ <strong>
+ If running in daemon mode, this is the max # of concurrent
+ connections that will be supported.
+ </strong>
+ <p>
+ <span class="vexpl">
+ Note: If you are using HashConcurrentUser, this option is ignored,
+ as all connections are read write locked instead of mutex locked.
+ </span>
+ </p>
+ </td>
+ </tr>
+ </tbody>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <!-- <input name="Submit" type="submit" class="formbtn" value="Save" onclick="enable_change(true)" /> -->
+ <input id="submitt" name="Submit" type="submit" class="formbtn" value="<?=gettext("Save");?>" onclick="document.iform.sectionid.value = 'db';" />
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2" class="list" height="12">&nbsp;</td>
+ </tr>
+ <tr>
+ <td colspan="2" valign="top" class="listtopic"><a name="del" style="visibility: hidden;">&nbsp;</a>Delivery Settings</td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Trusted Delivery Agent</td>
+ <td width="78%" class="vtable">
+ <select name="dagent" class="formselect">
+ <option value="procmail" <?php if($pconfig['dagent'] == "procmail") echo('selected="selected"');?>>procmail</option>
+ <option value="mail" <?php if($pconfig['dagent'] == "mail") echo('selected="selected"');?>>mail</option>
+ <option value="mail.local" <?php if($pconfig['dagent'] == "mail.local") echo('selected="selected"');?>>mail.local</option>
+ <option value="deliver" <?php if($pconfig['dagent'] == "deliver") echo('selected="selected"');?>>deliver</option>
+ <option value="maildrop" <?php if($pconfig['dagent'] == "maildrop") echo('selected="selected"');?>>maildrop</option>
+ <option value="exim" <?php if($pconfig['dagent'] == "exim") echo('selected="selected"');?>>exim</option>
+ </select>
+ <strong>Specifies the local delivery agent DSPAM should call when delivering mail as a trusted user.</strong>
+ <p>
+ <span class="vexpl">
+ Note: Use %u to specify the user DSPAM is processing mail for. It is generally a good idea to
+ allow the MTA to specify the pass-through arguments at run-time, but they may also be specified
+ here.
+ </span>
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">DSPAM Thin Client</td>
+ <td width="78%" class="vtable">
+ <input type="checkbox" name="dsthinc" id="dsthinc" value="yes" <?php if (isset($pconfig['dsthinc'])) echo 'checked="checked"'; ?> />
+ <strong>Use <code>dspamc</code> instead of the <code>dspam</code> binary.</strong>
+ <p>
+ <span class="vexpl">
+ Note: This requires to enable the dspam daemon as well (section: <i>DSPAM Daemon Settings (Server)</i>).
+ </span>
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">TCP/IP Based Delivery</td>
+ <td width="78%" class="vtable">
+ <input type="checkbox" name="tcpipdel" id="tcpipdel" value="yes" <?php if (isset($pconfig['tcpipdel'])) echo 'checked="checked"'; ?> onClick="enable_change(false, 5);" />
+ <strong>Use TCP/IP based delivery.</strong>
+ <p>
+ <span class="vexpl">
+ Note: This option needs to be ticked if you are going to deliver via LMTP or SMTP.
+ </span>
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Deliver Host</td>
+ <td width="78%" class="vtable">
+ <input type="text" size="30" <?= checkForErrorClass("dhost", "formfld host"); ?> name="dhost" id="dhost" value="<?=htmlspecialchars($pconfig['dhost']);?>" <?php if (! isset($pconfig['tcpipdel'])) echo 'disabled="disabled"'; ?> />
+ <strong>Alternatively, you may wish to use SMTP or LMTP delivery to deliver your message to the mail server.</strong>
+ <p>
+ <span class="vexpl">
+ Note: You will need to configure with <code>--enable-daemon</code> to use host delivery,
+ however you do not need to operate in daemon mode. Specify an IP address or UNIX path to a
+ domain socket below as a host.
+ </span>
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Deliver Port</td>
+ <td width="78%" class="vtable">
+ <input type="text" size="30" <?= checkForErrorClass("dport", "formfld unknown"); ?> name="dport" id="dport" value="<?=htmlspecialchars($pconfig['dport']);?>" <?php if (! isset($pconfig['tcpipdel'])) echo 'disabled="disabled"'; ?> />
+ <strong>Port number of a particular host.</strong>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Deliver Ident</td>
+ <td width="78%" class="vtable">
+ <input type="text" size="30" <?= checkForErrorClass("dident", "formfld unknown"); ?> name="dident" id="dident" value="<?=htmlspecialchars($pconfig['dident']);?>" <?php if (! isset($pconfig['tcpipdel'])) echo 'disabled="disabled"'; ?> />
+ <strong>A particular identification string</strong>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">TCP/IP Delivery Protocol</td>
+ <td width="78%" class="vtable">
+ <select name="delproto" class="formselect" <?php if (! isset($pconfig['tcpipdel'])) echo 'disabled="disabled"'; ?>>
+ <option value="smtp" <?php if($pconfig['delproto'] == "smtp") echo('selected="selected"');?>>smtp</option>
+ <option value="lmtp" <?php if($pconfig['delproto'] == "lmtp") echo('selected="selected"');?>>lmtp</option>
+ </select>
+ <strong>A particular protocol typ. Either <acronym title="Simple Mail Transfer Protocol">SMTP</acronym>
+ or <acronym title="Local Mail Transfer Protocol">LMTP</acronym>.</strong>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">On Fail</td>
+ <td width="78%" class="vtable">
+ <select name="onfail" class="formselect">
+ <option value="error" <?php if($pconfig['onfail'] == "error") echo('selected="selected"');?>>error</option>
+ <option value="unlearn" <?php if($pconfig['onfail'] == "unlearn") echo('selected="selected"');?>>unlearn</option>
+ </select>
+ <strong>What to do if local delivery or quarantine should fail.</strong>
+ <p>
+ <span class="vexpl">
+ Note: If set to &quot;unlearn&quot;, DSPAM will unlearn the message prior to exiting with an un
+ successful return code. The default option, &quot;error&quot; will not unlearn the message but
+ return the appropriate error code. The unlearn option is use-ful on some systems where local
+ delivery failures will cause the message to be requeued for delivery, and could result in the
+ message being processed multiple times. During a very large failure, however, this could cause
+ a significant load increase.
+ </span>
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <!-- <input name="Submit" type="submit" class="formbtn" value="Save" onclick="enable_change(true)" /> -->
+ <input id="submitt" name="Submit" type="submit" class="formbtn" value="<?=gettext("Save");?>" onclick="document.iform.sectionid.value = 'del';" />
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2" class="list" height="12">&nbsp;</td>
+ </tr>
+ <tr>
+ <td colspan="2" valign="top" class="listtopic"><a name="priv" style="visibility: hidden;">&nbsp;</a>DSPAM Privileges</td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Trusted Users</td>
+ <td width="78%" class="vtable">
+ <strong>Unix users which are allowed to perform certain actions.</strong>
+ <p>
+ <span class="vexpl">
+ Note: Only the users specified below will be allowed to perform
+ administrative functions in DSPAM such as setting the active user and
+ accessing tools. All other users attempting to run DSPAM will be restricted;
+ their uids will be forced to match the active username and they will not be
+ able to specify delivery agent privileges or use tools.
+ </span>
+ </p>
+ <table class="tabcont" width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td width="55%" class="listhdrr"><?=gettext("UNIX username");?></td>
+ <td width="35%" class="listhdr"><?=gettext("Description");?></td>
+ <td width="10%" class="list"></td>
+ </tr>
+ <?php if(is_array($t_users)): ?>
+ <?php $i = 0; foreach ($t_users as $user): ?>
+ <?php if($user['name'] <> ""): ?>
+
+ <tr>
+ <td class="listlr" ondblclick="document.location='dspam-settings-tuser.php?id=<?=$i;?>&sectionid=priv';">
+ <?=htmlspecialchars($user['name']);?>
+ </td>
+ <td class="listbg" ondblclick="document.location='dspam-settings-tuser.php?id=<?=$i;?>&sectionid=priv';">
+ <font color="#FFFFFF"><?=htmlspecialchars($user['descr']);?>&nbsp;</font>
+ </td>
+ <td valign="middle" nowrap class="list">
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td valign="middle"><a href="dspam-settings-tuser.php?id=<?=$i;?>&sectionid=priv"><img src="./themes/<?= $g['theme']; ?>/images/icons/icon_e.gif" width="17" height="17" border="0"></a></td>
+ <td valign="middle"><a href="dspam-settings.php?act=del&what=tuser&id=<?=$i;?>&sectionid=priv" onclick="return confirm('<?=gettext("Do you really want to delete this mapping?");?>')"><img src="./themes/<?= $g['theme']; ?>/images/icons/icon_x.gif" width="17" height="17" border="0"></a></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+
+ <?php endif; ?>
+ <?php $i++; endforeach; ?>
+ <?php endif; ?>
+ <tr>
+ <td class="list" colspan="3"></td>
+ <td class="list">
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td valign="middle"><a href="dspam-settings-tuser.php?sectionid=priv"><img src="./themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" width="17" height="17" border="0"></a></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <!-- <input name="Submit" type="submit" class="formbtn" value="Save" onclick="enable_change(true)" /> -->
+ <input id="submitt" name="Submit" type="submit" class="formbtn" value="<?=gettext("Save");?>" onclick="document.iform.sectionid.value = 'priv';" />
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2" class="list" height="12">&nbsp;</td>
+ </tr>
+ <tr>
+ <td valign="top" class="listtopic"><a name="dbg" style="visibility: hidden;">&nbsp;</a>DSPAM Debugging Options</td>
+ <td align="right" valign="top" class="listtopic">
+ <input type="checkbox" name="enabledbg" id="enabledbg" value="yes" <?php if (isset($pconfig['enabledbg'])) echo 'checked="checked"'; ?> onClick="enable_change(false, 0);" />
+ <strong>Enable</strong>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Debug</td>
+ <td width="78%" class="vtable">
+ <input type="text" size="30" <?= checkForErrorClass("debug", "formfld unknown"); ?> name="debug" id="debug" value="<?=htmlspecialchars($pconfig['debug']);?>" <?php if (! isset($pconfig['enabledbg'])) echo 'disabled="disabled"'; ?> />
+ <strong>Enables debugging for some or all users.</strong>
+ <p>
+ <span class="vexpl">
+ IMPORTANT: DSPAM must be compiled with debug support in order to use this option.
+ DSPAM should never be running in production with debug active unless you are
+ troubleshooting problems.
+ </span>
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Debug Options</td>
+ <td width="78%" class="vtable">
+ <input type="text" size="30" <?= checkForErrorClass("dopt", "formfld unknown"); ?> name="dopt" id="dopt" value="<?=htmlspecialchars($pconfig['dopt']);?>" <?php if (! isset($pconfig['enabledbg'])) echo 'disabled="disabled"'; ?> />
+ <strong>One or more of: process, classify, spam, fp, inoculation, corpus</strong>
+ <p>
+ <span class="vexpl">
+ <pre>
+process standard message processing
+classify message classification using --classify
+spam error correction of missed spam
+fp error correction of false positives
+inoculation message inoculations (source=inoculation)
+corpus corpusfed messages (source=corpus)
+ </pre>
+ </span>
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <!-- <input name="Submit" type="submit" class="formbtn" value="Save" onclick="enable_change(true)" /> -->
+ <input id="submitt" name="Submit" type="submit" class="formbtn" value="<?=gettext("Save");?>" onclick="document.iform.sectionid.value = 'dbg';" />
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2" class="list" height="12">&nbsp;</td>
+ </tr>
+ <tr>
+ <td colspan="2" valign="top" class="listtopic"><a name="eng" style="visibility: hidden;">&nbsp;</a>DSPAM Engine Settings</td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Training Mode</td>
+ <td width="78%" class="vtable">
+ <select name="tmode" class="formselect">
+ <option value="toe" <?php if($pconfig['tmode'] == "toe") echo('selected="selected"');?>>toe</option>
+ <option value="tum" <?php if($pconfig['tmode'] == "tum") echo('selected="selected"');?>>tum</option>
+ <option value="teft" <?php if($pconfig['tmode'] == "teft") echo('selected="selected"');?>>teft</option>
+ <option value="notrain" <?php if($pconfig['tmode'] == "notrain") echo('selected="selected"');?>>notrain</option>
+ </select>
+ <strong>
+ The default training mode to use for all operations, when one has not been
+ specified on the commandline or in the user's preferences.
+ </strong>
+ <p>
+ <span class="vexpl">
+ Acceptable values are: toe, tum, teft, notrain
+ </span>
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Test Conditional Training</td>
+ <td width="78%" class="vtable">
+ <input name="testct" type="checkbox" id="testct" value="yes" <?php if (isset($pconfig['testct'])) echo 'checked="checked"'; ?> />
+ <strong>
+ By default, dspam will retrain certain errors
+ until the condition is no longer met.
+ </strong>
+ <p>
+ <span class="vexpl">
+ Note: This usually accelerates learning. Some people argue that this can increase
+ the risk of errors, however.
+ </span>
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Features</td>
+ <td width="78%" class="vtable">
+ <strong>
+ Specify features to activate by default; can also be specified
+ on the commandline. See the documentation for a list of available features.
+ If _any_ features are specified on the commandline, these are ignored.
+ </strong>
+ <p>
+ <span class="vexpl">
+ Note: For standard "CRM114" Markovian weighting, use sbph
+ </span>
+ </p>
+ <table class="tabcont" width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td width="55%" class="listhdrr"><?=gettext("DSPAM Feature");?></td>
+ <td width="35%" class="listhdr"><?=gettext("Description");?></td>
+ <td width="10%" class="list"></td>
+ </tr>
+ <?php if(is_array($t_features)): ?>
+ <?php $i = 0; foreach ($t_features as $feature): ?>
+ <?php if($feature['name'] <> ""): ?>
+
+ <tr>
+ <td class="listlr" ondblclick="document.location='dspam-settings-feat.php?id=<?=$i;?>&sectionid=eng';">
+ <?=htmlspecialchars($feature['name']);?>
+ </td>
+ <td class="listbg" ondblclick="document.location='dspam-settings-feat.php?id=<?=$i;?>&sectionid=eng';">
+ <font color="#FFFFFF"><?=htmlspecialchars($feature['descr']);?>&nbsp;</font>
+ </td>
+ <td valign="middle" nowrap class="list">
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td valign="middle"><a href="dspam-settings-feat.php?id=<?=$i;?>&sectionid=eng"><img src="./themes/<?= $g['theme']; ?>/images/icons/icon_e.gif" width="17" height="17" border="0"></a></td>
+ <td valign="middle"><a href="dspam-settings.php?act=del&what=feat&id=<?=$i;?>&sectionid=eng" onclick="return confirm('<?=gettext("Do you really want to delete this mapping?");?>')"><img src="./themes/<?= $g['theme']; ?>/images/icons/icon_x.gif" width="17" height="17" border="0"></a></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+
+ <?php endif; ?>
+ <?php $i++; endforeach; ?>
+ <?php endif; ?>
+ <tr>
+ <td class="list" colspan="3"></td>
+ <td class="list">
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td valign="middle"><a href="dspam-settings-feat.php?sectionid=eng"><img src="./themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" width="17" height="17" border="0"></a></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Algorithms</td>
+ <td width="78%" class="vtable">
+ <strong>
+ Specify the statistical algorithms to use, overriding any
+ defaults configured in the build.
+ </strong>
+ <p>
+ <span class="vexpl">
+ The options are:
+ <pre>
+naive Naive-Bayesian (All Tokens)
+graham Graham-Bayesian ("A Plan for Spam")
+burton Burton-Bayesian (SpamProbe)
+robinson Robinson's Geometric Mean Test (Obsolete)
+chi-square Fisher-Robinson's Chi-Square Algorithm
+ </pre>
+ </span>
+ </p>
+ <p>
+ <span class="vexpl">
+ You may have multiple algorithms active simultaneously, but it is strongly
+ recommended that you group Bayesian algorithms with other Bayesian
+ algorithms, and any use of Chi-Square remain exclusive.
+ </p>
+ <p>
+ <span class="vexpl">
+ NOTE: For standard &quot;CRM114&quot; Markovian weighting, use &lsquo;naive&rsquo;, or consider
+ using &lsquo;burton&rsquo; for slightly better accuracy.
+ </span>
+ </p>
+ <p>
+ <span class="vexpl">
+ Don't mess with this unless you know what you're doing
+ </span>
+ </p>
+ <table class="tabcont" width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td width="55%" class="listhdrr"><?=gettext("DSPAM Algorithm");?></td>
+ <td width="35%" class="listhdr"><?=gettext("Description");?></td>
+ <td width="10%" class="list"></td>
+ </tr>
+ <?php if(is_array($t_algos)): ?>
+ <?php $i = 0; foreach ($t_algos as $algo): ?>
+ <?php if($algo['name'] <> ""): ?>
+
+ <tr>
+ <td class="listlr" ondblclick="document.location='dspam-settings-algo.php?id=<?=$i;?>&sectionid=eng';">
+ <?=htmlspecialchars($algo['name']);?>
+ </td>
+ <td class="listbg" ondblclick="document.location='dspam-settings-algo.php?id=<?=$i;?>&sectionid=eng';">
+ <font color="#FFFFFF"><?=htmlspecialchars($algo['descr']);?>&nbsp;</font>
+ </td>
+ <td valign="middle" nowrap class="list">
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td valign="middle"><a href="dspam-settings-algo.php?id=<?=$i;?>&sectionid=eng"><img src="./themes/<?= $g['theme']; ?>/images/icons/icon_e.gif" width="17" height="17" border="0"></a></td>
+ <td valign="middle"><a href="dspam-settings.php?act=del&what=algo&id=<?=$i;?>&sectionid=eng" onclick="return confirm('<?=gettext("Do you really want to delete this mapping?");?>')"><img src="./themes/<?= $g['theme']; ?>/images/icons/icon_x.gif" width="17" height="17" border="0"></a></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+
+ <?php endif; ?>
+ <?php $i++; endforeach; ?>
+ <?php endif; ?>
+ <tr>
+ <td class="list" colspan="3"></td>
+ <td class="list">
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td valign="middle"><a href="dspam-settings-algo.php?sectionid=eng"><img src="./themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" width="17" height="17" border="0"></a></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">PValue</td>
+ <td width="78%" class="vtable">
+ <select name="pvalue" class="formselect">
+ <option value="graham" <?php if($pconfig['pvalue'] == "toe") echo('selected="selected"');?>>graham</option>
+ <option value="robinson" <?php if($pconfig['pvalue'] == "toe") echo('selected="selected"');?>>robinson</option>
+ <option value="markov" <?php if($pconfig['pvalue'] == "toe") echo('selected="selected"');?>>markov</option>
+ </select>
+ <strong>
+ Specify the technique used for calculating PValues, overriding any defaults
+ configured in the build.
+ </strong>
+ <p>
+ <span class="vexpl">
+ These options are:
+ <pre>
+graham Graham's Technique (&quot;A Plan for Spam&quot;)
+robinson Robinson's Technique
+markov Markovian Weighted Technique
+ </pre>
+ </span>
+ </p>
+ <p>
+ <span class="vexpl">
+ Unlike algorithms, you may only have one of these defined. Use of the
+ chi-square algorithm automatically changes this to robinson.
+ </span>
+ </p>
+ <p>
+ <span class="vexpl">
+ Don't mess with this unless you know what you're doing.
+ </span>
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Improbability Drive</td>
+ <td width="78%" class="vtable">
+ <input name="ipdrive" type="checkbox" id="ipdrive" value="yes" <?php if (isset($pconfig['ipdrive'])) echo 'checked="checked"'; ?> />
+ <strong>
+ Calculate odds-ratios for ham/spam, and add to X-DSPAM-Improbability headers
+ </strong>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Preferences</td>
+ <td width="78%" class="vtable">
+ <strong>
+ Specify any preferences to set by default, unless otherwise
+ overridden by the user (see next section) or a default.prefs file.
+ </strong>
+ <p>
+ <span class="vexpl">
+ Note: If user or default.prefs are found, the user's
+ preferences will override any defaults.
+ </span>
+ </p>
+ <table class="tabcont" width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td width="55%" class="listhdrr"><?=gettext("DSPAM Preference Value");?></td>
+ <td width="35%" class="listhdr"><?=gettext("Description");?></td>
+ <td width="10%" class="list"></td>
+ </tr>
+ <?php if(is_array($t_prefs)): ?>
+ <?php $i = 0; foreach ($t_prefs as $pref): ?>
+ <?php if($pref['value'] <> ""): ?>
+
+ <tr>
+ <td class="listlr" ondblclick="document.location='dspam-settings-prefs.php?id=<?=$i;?>&sectionid=eng';">
+ <?=htmlspecialchars($pref['value']);?>
+ </td>
+ <td class="listbg" ondblclick="document.location='dspam-settings-prefs.php?id=<?=$i;?>&sectionid=eng';">
+ <font color="#FFFFFF"><?=htmlspecialchars($pref['descr']);?>&nbsp;</font>
+ </td>
+ <td valign="middle" nowrap class="list">
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td valign="middle"><a href="dspam-settings-prefs.php?id=<?=$i;?>&sectionid=eng"><img src="./themes/<?= $g['theme']; ?>/images/icons/icon_e.gif" width="17" height="17" border="0"></a></td>
+ <td valign="middle"><a href="dspam-settings.php?act=del&what=pref&id=<?=$i;?>&sectionid=eng" onclick="return confirm('<?=gettext("Do you really want to delete this mapping?");?>')"><img src="./themes/<?= $g['theme']; ?>/images/icons/icon_x.gif" width="17" height="17" border="0"></a></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+
+ <?php endif; ?>
+ <?php $i++; endforeach; ?>
+ <?php endif; ?>
+ <tr>
+ <td class="list" colspan="3"></td>
+ <td class="list">
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td valign="middle"><a href="dspam-settings-prefs.php?sectionid=eng"><img src="./themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" width="17" height="17" border="0"></a></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Overrides</td>
+ <td width="78%" class="vtable">
+ <strong>
+ Specifies the user preferences which may override
+ configuration and commandline defaults.
+ </strong>
+ <p>
+ <span class="vexpl">
+ Note: Any other preferences supplied by an untrusted user will be ignored.
+ </span>
+ </p>
+ <table class="tabcont" width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td width="55%" class="listhdrr"><?=gettext("DSPAM Override Value");?></td>
+ <td width="35%" class="listhdr"><?=gettext("Description");?></td>
+ <td width="10%" class="list"></td>
+ </tr>
+ <?php if(is_array($t_overr)): ?>
+ <?php $i = 0; foreach ($t_overr as $over): ?>
+ <?php if($over['value'] <> ""): ?>
+
+ <tr>
+ <td class="listlr" ondblclick="document.location='dspam-settings-overr.php?id=<?=$i;?>&sectionid=eng';">
+ <?=htmlspecialchars($over['value']);?>
+ </td>
+ <td class="listbg" ondblclick="document.location='dspam-settings-overr.php?id=<?=$i;?>&sectionid=eng';">
+ <font color="#FFFFFF"><?=htmlspecialchars($over['descr']);?>&nbsp;</font>
+ </td>
+ <td valign="middle" nowrap class="list">
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td valign="middle"><a href="dspam-settings-overr.php?id=<?=$i;?>&sectionid=eng"><img src="./themes/<?= $g['theme']; ?>/images/icons/icon_e.gif" width="17" height="17" border="0"></a></td>
+ <td valign="middle"><a href="dspam-settings.php?act=del&what=overr&id=<?=$i;?>&sectionid=eng" onclick="return confirm('<?=gettext("Do you really want to delete this mapping?");?>')"><img src="./themes/<?= $g['theme']; ?>/images/icons/icon_x.gif" width="17" height="17" border="0"></a></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+
+ <?php endif; ?>
+ <?php $i++; endforeach; ?>
+ <?php endif; ?>
+ <tr>
+ <td class="list" colspan="3"></td>
+ <td class="list">
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td valign="middle"><a href="dspam-settings-overr.php?sectionid=eng"><img src="./themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" width="17" height="17" border="0"></a></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <!-- <input name="Submit" type="submit" class="formbtn" value="Save" onclick="enable_change(true)" /> -->
+ <input id="submitt" name="Submit" type="submit" class="formbtn" value="<?=gettext("Save");?>" onclick="document.iform.sectionid.value = 'eng';" />
+ </td>
+ </tr>
+ <?php if (checkForLDAPSupport()): ?>
+ <tr>
+ <td colspan="2" class="list" height="12">&nbsp;</td>
+ </tr>
+ <tr>
+ <td valign="top" class="listtopic"><a name="ldap" style="visibility: hidden;">&nbsp;</a>LDAP Settings</td>
+ <td align="right" valign="top" class="listtopic">
+ <input name="enableldap" type="checkbox" id="enableldap" value="yes" <?php if (isset($pconfig['enableldap'])) echo 'checked="checked"'; ?> onClick="enable_change(false, 1);" />
+ <strong>Enable</strong>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">LDAP Mode</td>
+ <td width="78%" class="vtable">
+ <select name="ldapmode" class="formselect" <?php if (! isset($pconfig['enableldap'])) echo 'disabled="disabled"'; ?>>
+ <option value="verify" selected="selected">verify</option>
+ </select>
+ <strong>
+ Perform various LDAP functions depending on LDAPMode variable.
+ </strong>
+ <p>
+ <span class="vexpl">
+ Note: Presently, the only mode supported is 'verify', which will verify the
+ existence of an unknown user in LDAP prior to creating them as a new user in
+ the system. This is useful on some systems acting as gateway machines.
+ </span>
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">LDAP Host</td>
+ <td width="78%" class="vtable">
+ <input type="text" size="30" <?= checkForErrorClass("hldaphost", "formfld host"); ?> name="ldaphost" id="ldaphost" value="<?=htmlspecialchars($pconfig['ldaphost']);?>" <?php if (! isset($pconfig['enableldap'])) echo 'disabled="disabled"'; ?> />
+ <strong>
+ Hostname of the LDAP directory server.
+ </strong>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">LDAP Filter</td>
+ <td width="78%" class="vtable">
+ <input type="text" size="30" <?= checkForErrorClass("ldapfilter", "formfld unknown"); ?> name="ldapfilter" id="ldapfilter" value="<?=htmlspecialchars($pconfig['ldapfilter']);?>" <?php if (! isset($pconfig['enableldap'])) echo 'disabled="disabled"'; ?> />
+ <strong>
+ A specific query filter, that should be used while querying the LDAP server.
+ </strong>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">LDAP Base</td>
+ <td width="78%" class="vtable">
+ <input type="text" size="30" <?= checkForErrorClass("ldapbase", "formfld unknown"); ?> name="ldapbase" id="ldapbase" value="<?=htmlspecialchars($pconfig['ldapbase']);?>" <?php if (! isset($pconfig['enableldap'])) echo 'disabled="disabled"'; ?> />
+ <strong>
+ A particular distinguish name from where to start LDAP queries.
+ </strong>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <!-- <input name="Submit" type="submit" class="formbtn" value="Save" onclick="enable_change(true)" /> -->
+ <input id="submitt" name="Submit" type="submit" class="formbtn" value="<?=gettext("Save");?>" onclick="document.iform.sectionid.value = 'ldap';" />
+ </td>
+ </tr>
+ <?php endif; ?>
+ <tr>
+ <td colspan="2" class="list" height="12">&nbsp;</td>
+ </tr>
+ <tr>
+ <td colspan="2" valign="top" class="listtopic"><a name="misc" style="visibility: hidden;">&nbsp;</a>Miscellaneous Settings</td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Failover Attempts</td>
+ <td width="78%" class="vtable">
+ <input type="text" size="30"<?= checkForErrorClass("foatt", "formfld unknown"); ?> name="foatt" id="foatt" value="<?=htmlspecialchars($pconfig['foatt']);?>" />
+ <strong>
+ A particular number of attempts.
+ </strong>
+ <p>
+ <span class="vexpl">
+ If the storage fails, the agent will follow each profile's failover up to
+ a maximum number of failover attempts. This should be set to a maximum of
+ the number of profiles you have, otherwise the agent could loop and try
+ the same profile multiple times (unless this is your desired behavior).
+ </span>
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Ignore Headers</td>
+ <td width="78%" class="vtable">
+ <p>
+ <span class="vexpl">
+ If DSPAM is behind other tools which may add a header to
+ incoming emails, it may be beneficial to ignore these headers - especially
+ if they are coming from another spam filter. If you are _not_ using one of
+ these tools, however, leaving the appropriate headers commented out will
+ allow DSPAM to use them as telltale signs of forged email.
+ </span>
+ </p>
+ <table class="tabcont" width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td width="55%" class="listhdrr"><?=gettext("Header Name");?></td>
+ <td width="35%" class="listhdr"><?=gettext("Description");?></td>
+ <td width="10%" class="list"></td>
+ </tr>
+ <?php if(is_array($t_headers)): ?>
+ <?php $i = 0; foreach ($t_headers as $header): ?>
+ <?php if($header['name'] <> ""): ?>
+
+ <tr>
+ <td class="listlr" ondblclick="document.location='dspam-settings-header.php?id=<?=$i;?>&sectionid=misc';">
+ <?=htmlspecialchars($header['name']);?>
+ </td>
+ <td class="listbg" ondblclick="document.location='dspam-settings-header.php?id=<?=$i;?>&sectionid=misc';">
+ <font color="#FFFFFF"><?=htmlspecialchars($header['descr']);?>&nbsp;</font>
+ </td>
+ <td valign="middle" nowrap class="list">
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td valign="middle"><a href="dspam-settings-header.php?id=<?=$i;?>&sectionid=misc"><img src="./themes/<?= $g['theme']; ?>/images/icons/icon_e.gif" width="17" height="17" border="0"></a></td>
+ <td valign="middle"><a href="dspam-settings.php?act=del&what=header&id=<?=$i;?>&sectionid=misc" onclick="return confirm('<?=gettext("Do you really want to delete this mapping?");?>')"><img src="./themes/<?= $g['theme']; ?>/images/icons/icon_x.gif" width="17" height="17" border="0"></a></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+
+ <?php endif; ?>
+ <?php $i++; endforeach; ?>
+ <?php endif; ?>
+ <tr>
+ <td class="list" colspan="3"></td>
+ <td class="list">
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td valign="middle"><a href="dspam-settings-header.php?sectionid=misc"><img src="./themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" width="17" height="17" border="0"></a></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">SBL Lookup</td>
+ <td width="78%" class="vtable">
+ <p>
+ <input type="checkbox" name="enablesbl" id="enablesbl" value="yes" <?php if (isset($pconfig['enablesbl'])) echo 'checked="checked"'; ?> onClick="enable_change(false, 2);" />
+ <strong>
+ Enable checks against a particular <acronym title="Streamlined Blackhole List">SBL</acronym> host.
+ </strong>
+ </p>
+ <p>
+ <input type="text" size="30" c<?= checkForErrorClass("sblhost", "formfld host"); ?> name="sblhost" id="sblhost" value="<?=htmlspecialchars($pconfig['sblhost']);?>" <?php if (! isset($pconfig['enablesbl'])) echo 'disabled="disabled"'; ?> />
+ <strong>
+ A particular SBL hostname.
+ </strong>
+ </p>
+ <p>
+ <span class="vexpl">
+ Perform lookups on streamlined blackhole list servers (see
+ <a href="http://www.nuclearelephant.com/projects/sbl/" target="_blank">http://www.nuclearelephant.com/projects/sbl/</a>).
+ The streamlined blacklist
+ server is machine-automated, unsupervised blacklisting system designed to
+ provide real-time and highly accurate blacklisting based on network spread.
+ When performing a lookup, DSPAM will automatically learn the inbound message
+ as spam if the source IP is listed. Until an official public RABL server is
+ available, this feature is only useful if you are running your own
+ streamlined blackhole list server for internal reporting among multiple mail
+ servers. Provide the name of the lookup zone below to use.
+ </span>
+ </p>
+ <p>
+ <span class="vexpl">
+ This function performs standard reverse-octet.domain lookups, and while it
+ will function with many RBLs, it's strongly discouraged to use those
+ maintained by humans as they're often inaccurate and could hurt filter
+ learning and accuracy.
+ </span>
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">RBL Inoculate</td>
+ <td width="78%" class="vtable">
+ <input name="enablerbl" type="checkbox" id="enablerbl" value="yes" <?php if (isset($pconfig['enablerbl'])) echo 'checked="checked"'; ?> />
+ <strong>
+ Enable <acronym title="Realtime Blackhole List">RBL</acronym> inoculation support.
+ </strong>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Enable Notification</td>
+ <td width="78%" class="vtable">
+ <input name="enablenoti" type="checkbox" id="enablenoti" value="yes" <?php if (isset($pconfig['enablenoti'])) echo 'checked="checked"'; ?> onClick="enable_change(false, 2);" />
+ <strong>
+ Enable the sending of notification emails to users (first message, quarantine full, etc.)
+ </strong>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">DSPAM Support Contact</td>
+ <td width="78%" class="vtable">
+ <input type="text" size="30" <?= checkForErrorClass("dspamcontact", "formfld mail"); ?> name="dspamcontact" id="dspamcontact" value="<?=htmlspecialchars($pconfig['dspamcontact']);?>" <?php if (empty($pconfig['enablenoti'])) echo 'disabled="disabled"'; ?> />
+ <strong>
+ The username of the person who provides DSPAM support for this DSPAM installation
+ </strong>
+ &nbsp;(This is the left most part of an email address before the @ sign).
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Email Domain Name</td>
+ <td width="78%" class="vtable">
+ <input name="whichdomain" type="checkbox" id="whichdomain" value="yes" <?php if (empty($pconfig['dspamdomain'])) echo 'checked="checked"'; if (empty($pconfig['enablenoti'])) echo 'disabled="disabled"'; ?> onClick="toggleDSPAMDomain(false, this);" />
+ <strong>
+ Use global domain settings while trying to send an email message.
+ </strong>
+ </td>
+ </tr>
+ <?php if (isset($pconfig['dspamdomain'])): ?>
+ <tbody id="emailnotitb" style="display: table-row-group;">
+ <?php else: ?>
+ <tbody id="emailnotitb" style="display: none;">
+ <?php endif; ?>
+ <tr>
+ <td width="22%" valign="top" class="vncell">DSPAM Domain Name</td>
+ <td width="78%" class="vtable">
+ <input type="text" size="30" <?= checkForErrorClass("dspamdomain", "formfld url"); ?> name="dspamdomain" id="dspamdomain" value="<?=htmlspecialchars($pconfig['dspamdomain']);?>" />
+ <strong>
+ Use this domain name while trying to send an email message.
+ </strong>
+ </td>
+ </tr>
+ </tbody>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <!-- <input name="Submit" type="submit" class="formbtn" value="Save" onclick="enable_change(true)" /> -->
+ <input id="submitt" name="Submit" type="submit" class="formbtn" value="<?=gettext("Save");?>" onclick="document.iform.sectionid.value = 'misc';" />
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2" class="list" height="12">&nbsp;</td>
+ </tr>
+ <tr>
+ <td colspan="2" valign="top" class="listtopic"><a name="main" style="visibility: hidden;">&nbsp;</a>Maintainance Settings</td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">&nbsp;</td>
+ <td width="78%" class="vtable">
+ <p>
+ <span class="vexpl">
+ Set dspam_clean purge default options, if not
+ otherwise specified on the commandline. You may set some of
+ the below values to <code>off</code>, for instance if you are
+ using a SQL-based database backend for DSPAM. Please consult your
+ DSPAM manual for any details.
+ </span>
+ </p>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Purge Signatures</td>
+ <td width="78%" class="vtable">
+ <input type="text" size="30" <?= checkForErrorClass("psig", "formfld unknown"); ?> name="psig" id="psig" value="<?=htmlspecialchars($pconfig['psig']);?>" />
+ <strong>
+ Purge stale signatures
+ </strong>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Purge Neutral</td>
+ <td width="78%" class="vtable">
+ <input type="text" size="30" <?= checkForErrorClass("pneut", "formfld unknown"); ?> name="pneut" id="pneut" value="<?=htmlspecialchars($pconfig['pneut']);?>" />
+ <strong>
+ Purge tokens with neutralish probabilities
+ </strong>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Purge Unused</td>
+ <td width="78%" class="vtable">
+ <input type="text" size="30" <?= checkForErrorClass("punu", "formfld unknown"); ?> name="punu" id="punu" value="<?=htmlspecialchars($pconfig['punu']);?>" />
+ <strong>
+ Purge unused tokens
+ </strong>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Purge Hapaxes</td>
+ <td width="78%" class="vtable">
+ <input type="text" size="30" <?= checkForErrorClass("phapa", "formfld unknown"); ?> name="phapa" id="phapa" value="<?=htmlspecialchars($pconfig['phapa']);?>" />
+ <strong>
+ Purge tokens with less than 5 hits (hapaxes)
+ </strong>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Purge Hits 1S</td>
+ <td width="78%" class="vtable">
+ <input type="text" size="30" <?= checkForErrorClass("pones", "formfld unknown"); ?> name="pones" id="pones" value="<?=htmlspecialchars($pconfig['pones']);?>" />
+ <strong>
+ Purge tokens with only 1 spam hit
+ </strong>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Purge Hits 1I</td>
+ <td width="78%" class="vtable">
+ <input type="text" size="30" <?= checkForErrorClass("ponei", "formfld unknown"); ?> name="ponei" id="ponei" value="<?=htmlspecialchars($pconfig['ponei']);?>" />
+ <strong>
+ Purge tokens with only 1 innocent hit
+ </strong>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <!-- <input name="Submit" type="submit" class="formbtn" value="Save" onclick="enable_change(true)" /> -->
+ <input id="submitt" name="Submit" type="submit" class="formbtn" value="<?=gettext("Save");?>" onclick="document.iform.sectionid.value = 'main';" />
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2" class="list" height="12">&nbsp;</td>
+ </tr>
+ <tr>
+ <td colspan="2" valign="top" class="listtopic"><a name="sys" style="visibility: hidden;">&nbsp;</a>System Settings</td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Local MX</td>
+ <td width="78%" class="vtable">
+ <input type="text" size="30" <?= checkForErrorClass("locmx", "formfld host"); ?> name="locmx" id="locmx" value="<?=htmlspecialchars($pconfig['locmx']);?>" />
+ <strong>
+ Local Mail Exchangers: Used for source address tracking, tells DSPAM which
+ mail exchangers are local and therefore should be ignored in the Received:
+ header when tracking the source of an email. Note: you should use the address
+ of the host as appears between brackets [ ] in the Received header.
+ </strong>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">&nbsp;</td>
+ <td width="78%" class="vtable">
+ <span class="vexpl">
+ Disabling logging for users will make usage graphs unavailable to
+ them. Disabling system logging will make admin graphs unavailable.
+ </span>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Enable System Log</td>
+ <td width="78%" class="vtable">
+ <input name="enablesysl" type="checkbox" id="enablesysl" value="yes" <?php if (isset($pconfig['enablesysl'])) echo 'checked="checked"'; ?> />
+ <strong>
+ Enable system logging.
+ </strong>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Enable User Log</td>
+ <td width="78%" class="vtable">
+ <input name="enableusel" type="checkbox" id="enableusel" value="yes" <?php if (isset($pconfig['enableusel'])) echo 'checked="checked"'; ?> />
+ <strong>
+ Enable user logging.
+ </strong>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Opt Settings</td>
+ <td width="78%" class="vtable">
+ <select name="optinout" class="formselect">
+ <option value="out" <?php if($pconfig['optinout'] == "out") echo('selected="selected"');?>>out</option>
+ <option value="in" <?php if($pconfig['optinout'] == "in") echo('selected="selected"');?>>in</option>
+ </select>
+ <p>
+ <span class="vexpl">
+ Opt: in or out; determines DSPAM's default filtering behavior. If this value
+ is set to in, users must opt-in to filtering by dropping a .dspam file in
+ <code>/var/dspam/opt-in/user.dspam</code> (or if you have homedirs configured, a .dspam
+ folder in their home directory). The default is opt-out, which means all
+ users will be filtered unless a <code>.nodspam</code> file is dropped in
+ <code>/var/dspam/opt-out/user.nodspam</code>
+ <span class="vexpl">
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">&nbsp;</td>
+ <td width="78%" class="vtable">
+ <span class="vexpl">
+ In lieu of setting up individual aliases for each user,
+ DSPAM can be configured to automatically parse the To: address for spam and
+ false positive forwards. From there, it can be configured to either set the
+ DSPAM user based on the username specified in the header and/or change the
+ training class and source accordingly. The options below can be used to
+ customize most common types of header parsing behavior to avoid the need for
+ multiple aliases, or if using LMTP, aliases entirely..
+ </span>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Parse To Headers</td>
+ <td width="78%" class="vtable">
+ <input name="enableptoh" type="checkbox" id="enableptoh" value="yes" <?php if (isset($pconfig['enableptoh'])) echo 'checked="checked"'; ?> />
+ <strong>
+ Parse the <i>To:</i> headers of an incoming message.
+ </strong>
+ <p>
+ <span class="vexpl">
+ This must be set to &lsquo;on&rsquo; to use either of the following features.
+ </span>
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Change Mode On Parse</td>
+ <td width="78%" class="vtable">
+ <input name="enablecmop" type="checkbox" id="enablecmop" value="yes" <?php if (isset($pconfig['enablecmop'])) echo 'checked="checked"'; ?> />
+ <strong>
+ Automatically change the class (to spam or innocent).
+ </strong>
+ <p>
+ <span class="vexpl">
+ This depends on whether spam- or notspam- was specified, and change
+ the source to &lsquo;error&rsquo;. This is convenient if you're not
+ using aliases at all, but are delivering via LMTP.
+ </span>
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Change User On Parse</td>
+ <td width="78%" class="vtable">
+ <input name="enablecuop" type="checkbox" id="enablecuop" value="yes" <?php if (isset($pconfig['enablecuop'])) echo 'checked="checked"'; ?> />
+ <strong>
+ Automatically change the username to match that specified in the <i>To:</i> header.
+ </strong>
+ <p>
+ <span class="vexpl">
+ For example, <code>spam-bob@domain.tld</code> will set the username
+ to bob, ignoring any --user passed in. This may not always be desirable if
+ you are using virtual email addresses as usernames. Options:
+ on or user take the portion before the @ sign only
+ full take everything after the initial {spam,notspam}-.
+ </span>
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Broken MTA Settings</td>
+ <td width="78%" class="vtable">
+ <input name="enablebmta" type="checkbox" id="enablebmta" value="yes" <?php if (isset($pconfig['enablebmta'])) echo 'checked="checked"'; ?> />
+ <strong>
+ Enable broken MTA settings.
+ </strong>
+ <p>
+ <span class="vexpl">
+ Broken MTA Options: Some MTAs don't support the proper functionality
+ necessary. In these cases you can activate certain features in DSPAM to
+ compensate. &lsquo;returnCodes&rsquo; causes DSPAM to return an exit code of 99 if
+ the message is spam, 0 if not, or a negative code if an error has occured.
+ Specifying &lsquo;case&rsquo; causes DSPAM to force the input usernames to lowercase.
+ Spceifying &lsquo;lineStripping&rsquo; causes DSPAM to strip &circ;M's from messages passed
+ </span>
+ </p>
+ <table class="tabcont" width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td width="55%" class="listhdrr"><?=gettext("Broken MTA Option");?></td>
+ <td width="35%" class="listhdr"><?=gettext("Description");?></td>
+ <td width="10%" class="list"></td>
+ </tr>
+ <?php if(is_array($t_bmtas)): ?>
+ <?php $i = 0; foreach ($t_bmtas as $bmta): ?>
+ <?php if($bmta['name'] <> ""): ?>
+
+ <tr>
+ <td class="listlr" ondblclick="document.location='dspam-settings-bmta.php?id=<?=$i;?>&sectionid=sys';">
+ <?=htmlspecialchars($bmta['name']);?>
+ </td>
+ <td class="listbg" ondblclick="document.location='dspam-settings-bmta.php?id=<?=$i;?>&sectionid=sys';">
+ <font color="#FFFFFF"><?=htmlspecialchars($bmta['descr']);?>&nbsp;</font>
+ </td>
+ <td valign="middle" nowrap class="list">
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td valign="middle"><a href="dspam-settings-bmta.php?id=<?=$i;?>&sectionid=sys"><img src="./themes/<?= $g['theme']; ?>/images/icons/icon_e.gif" width="17" height="17" border="0"></a></td>
+ <td valign="middle"><a href="dspam-settings.php?act=del&what=bmta&id=<?=$i;?>&sectionid=sys" onclick="return confirm('<?=gettext("Do you really want to delete this mapping?");?>')"><img src="./themes/<?= $g['theme']; ?>/images/icons/icon_x.gif" width="17" height="17" border="0"></a></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+
+ <?php endif; ?>
+ <?php $i++; endforeach; ?>
+ <?php endif; ?>
+ <tr>
+ <td class="list" colspan="3"></td>
+ <td class="list">
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td valign="middle"><a href="dspam-settings-bmta.php?sectionid=sys"><img src="./themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" width="17" height="17" border="0"></a></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Max Message Size</td>
+ <td width="78%" class="vtable">
+ <input type="text" size="30" <?= checkForErrorClass("maxmsgs", "formfld unknown"); ?> name="maxmsgs" id="maxmsgs" value="<?=htmlspecialchars($pconfig['maxmsgs']);?>" />
+ <strong>
+ You may specify a maximum message size for DSPAM to process.
+ </strong>
+ <p>
+ <span class="vexpl">
+ If the message is larger than the maximum size, it will be delivered
+ without processing. Value is in bytes.
+ </span>
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Processor Bias</td>
+ <td width="78%" class="vtable">
+ <input type="checkbox" name="procbias" id="procbias" value="yes" <?php if (isset($pconfig['procbias'])) echo 'checked="checked"'; ?> />
+ <strong>
+ Bias causes the filter to lean more toward &lsquo;innocent&rsquo;, and
+ usually greatly reduces false positives. It is the default behavior of
+ most Bayesian filters (including dspam).
+ </strong>
+ <p>
+ <span class="vexpl">
+ Note: You probably DONT want this if you're using Markovian Weighting,
+ unless you are paranoid about false positives.
+ </span>
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <!-- <input name="Submit" type="submit" class="formbtn" value="Save" onclick="enable_change(true)" /> -->
+ <input id="submitt" name="Submit" type="submit" class="formbtn" value="<?=gettext("Save");?>" onclick="document.iform.sectionid.value = 'sys';" />
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2" class="list" height="12">&nbsp;</td>
+ </tr>
+ <?php if (checkForClamAVSupport()): ?>
+ <tr>
+ <td valign="top" class="listtopic"><a name="clam" style="visibility: hidden;">&nbsp;</a>ClamAV Engine Settings</td>
+ <td align="right" valign="top" class="listtopic">
+ <input name="enableclam" type="checkbox" id="enableclam" value="yes" <?php if (isset($pconfig['enableclam'])) echo 'checked="checked"'; ?> onClick="enable_change(false, 3);" />
+ <strong>Enable</strong>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">&nbsp;</td>
+ <td width="78%" class="vtable">
+ <p>
+ <span class="vexpl">
+ If you are running clamd, DSPAM can perform stream-based
+ virus checking using TCP. Uncomment the values below to enable virus
+ checking.
+ </span>
+ </p>
+ <p>
+ <span class="vexpl">
+ ClamAVResponse:
+ <dl>
+ <dt>reject</dt>
+ <dd>(reject or drop the message with a permanent failure)</dd>
+ <dt>accept</dt>
+ <dd>(accept the message and quietly drop the message)</dd>
+ <dt>spam</dt>
+ <dd>(treat as spam and quarantine/tag/whatever)</dd>
+ </dl>
+ </span>
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">ClamAV Port</td>
+ <td width="78%" class="vtable">
+ <p>
+ <input type="text" size="30" <?= checkForErrorClass("clamport", "formfld unknown"); ?> name="clamport" id="clamport" value="<?=htmlspecialchars($pconfig['clamport']);?>" <?php if (! isset($pconfig['enableclam'])) echo 'disabled="disabled"'; ?> />
+ <strong>
+ A number that specifies the port the ClamAV daemon is listening to.
+ </strong>
+ </p>
+ <p>
+ <span class="vexpl">
+ If the message is larger than the maximum size, it will be delivered
+ without processing. Value is in bytes.
+ </span>
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">ClamAV Host</td>
+ <td width="78%" class="vtable">
+ <input type="text" size="30" <?= checkForErrorClass("clamhost", "formfld host"); ?> name="clamhost" id="clamhost" value="<?=htmlspecialchars($pconfig['clamhost']);?>" <?php if (! isset($pconfig['enableclam'])) echo 'disabled="disabled"'; ?> />
+ <strong>
+ An IP address that points to the host the ClamAV daemon is running on.
+ </strong>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">ClamAV Response</td>
+ <td width="78%" class="vtable">
+ <select name="clamresp" class="formselect" <?php if (! isset($pconfig['enableclam'])) echo 'disabled="disabled"'; ?>>
+ <option value="reject" <?php if($pconfig['clamresp'] == "reject") echo('selected="selected"');?>>reject</option>
+ <option value="accept" <?php if($pconfig['clamresp'] == "accept") echo('selected="selected"');?>>accept</option>
+ <option value="spam" <?php if($pconfig['clamresp'] == "spam") echo('selected="selected"');?>>spam</option>
+ </select>
+ <strong>
+ The action that should take place, if ClamAV reports a positive.
+ </strong>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <!-- <input name="Submit" type="submit" class="formbtn" value="Save" onclick="enable_change(true)" /> -->
+ <input id="submitt" name="Submit" type="submit" class="formbtn" value="<?=gettext("Save");?>" onclick="document.iform.sectionid.value = 'clam';" />
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2" class="list" height="12">&nbsp;</td>
+ </tr>
+ <?php endif; ?>
+ <tr>
+ <td colspan="2" valign="top" class="listtopic"><a name="srv" style="visibility: hidden;">&nbsp;</a>DSPAM Daemon Settings (Server)</td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">&nbsp;</td>
+ <td width="78%" class="vtable">
+ <span class="vexpl">
+ If you are running DSPAM as a daemonized server using
+ <code>--daemon</code>, the following parameters will override the default. Use the
+ ServerPass option to set up accounts for each client machine. The DSPAM
+ server will process and deliver the message based on the parameters
+ specified. If you want the client machine to perform delivery, use
+ the <code>--stdout</code> option in conjunction with a local setup.
+ </span>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Server Port</td>
+ <td width="78%" class="vtable">
+ <p>
+ <input type="text" size="30" <?= checkForErrorClass("dsport", "formfld unknown"); ?> name="dsport" id="dsport" value="<?=htmlspecialchars($pconfig['dsport']);?>" />
+ <strong>
+ A number that specifies the port the DSPAM daemon is listening to.
+ </strong>
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Server Queue Size</td>
+ <td width="78%" class="vtable">
+ <p>
+ <input type="text" size="30" <?= checkForErrorClass("dsqsize", "formfld unknown"); ?> name="dsqsize" id="dsqsize" value="<?=htmlspecialchars($pconfig['dsqsize']);?>" />
+ <strong>
+ A number that specifies the server's queue size.
+ </strong>
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Server PID</td>
+ <td width="78%" class="vtable">
+ <p>
+ <input type="text" size="30" <?= checkForErrorClass("dspid", "formfld file"); ?> name="dspid" id="dspid" value="<?=htmlspecialchars($pconfig['dspid']);?>" />
+ <strong>
+ Keep this is sync with <code>/usr/local/etc/rc.d/dspam.rc</code> script.
+ </strong>
+ </p>
+ <p>
+ <span class="vexpl">
+ Note: Don't change this value unless you know what you are doing.
+ </span>
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Server Mode</td>
+ <td width="78%" class="vtable">
+ <p>
+ <select name="dssmode" class="formselect">
+ <option value="dspam" <?php if($pconfig['dssmode'] == "dspam") echo('selected="selected"');?>>dspam</option>
+ <option value="standard" <?php if($pconfig['dssmode'] == "standard") echo('selected="selected"');?>>standard</option>
+ <option value="auto" <?php if($pconfig['dssmode'] == "auto") echo('selected="selected"');?>>auto</option>
+ </select>
+ <strong>
+ Specifies the type of LMTP server to start.
+ </strong>
+ <p>
+ <span class="vexpl">
+ This can be one of:
+ <dl>
+ <dt>dspam</dt>
+ <dd>DSPAM-proprietary DLMTP server, for communicating with dspamc</dd>
+ <dt>standard</dt>
+ <dd>Standard LMTP server, for communicating with Postfix or other MTA</dd>
+ <dt>auto</dt>
+ <dd>Speak both DLMTP and LMTP; auto-detect by ServerPass.IDENT</dd>
+ </dl>
+ </span>
+ </p>
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" rowspan="2" class="vncell">&nbsp;</td>
+ <td width="78%" class="vtable">
+ <p>
+ <span class="vexpl">
+ If supporting DLMTP (dspam) mode, dspam clients will require authentication
+ as they will be passing in parameters. The idents below will be used to
+ determine which clients will be speaking DLMTP, so if you will be using
+ both LMTP and DLMTP from the same host, be sure to use something other
+ than the server's hostname below (which will be sent by the MTA during a
+ standard LMTP LHLO).
+ </span>
+ </p>
+ <table class="tabcont" width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td width="55%" class="listhdrr"><?=gettext("DLMTP Password Value");?></td>
+ <td width="35%" class="listhdr"><?=gettext("Description");?></td>
+ <td width="10%" class="list"></td>
+ </tr>
+ <?php if(is_array($t_spwds)): ?>
+ <?php $i = 0; foreach ($t_spwds as $spwd): ?>
+ <?php if($spwd['value'] <> ""): ?>
+
+ <tr>
+ <td class="listlr" ondblclick="document.location='dspam-settings-spwd.php?id=<?=$i;?>&sectionid=srv';">
+ <?=htmlspecialchars($spwd['value']);?>
+ </td>
+ <td class="listbg" ondblclick="document.location='dspam-settings-spwd.php?id=<?=$i;?>&sectionid=srv';">
+ <font color="#FFFFFF"><?=htmlspecialchars($spwd['descr']);?>&nbsp;</font>
+ </td>
+ <td valign="middle" nowrap class="list">
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td valign="middle"><a href="dspam-settings-spwd.php?id=<?=$i;?>&sectionid=srv"><img src="./themes/<?= $g['theme']; ?>/images/icons/icon_e.gif" width="17" height="17" border="0"></a></td>
+ <td valign="middle"><a href="dspam-settings.php?act=del&what=spwd&id=<?=$i;?>&sectionid=srv" onclick="return confirm('<?=gettext("Do you really want to delete this mapping?");?>')"><img src="./themes/<?= $g['theme']; ?>/images/icons/icon_x.gif" width="17" height="17" border="0"></a></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+
+ <?php endif; ?>
+ <?php $i++; endforeach; ?>
+ <?php endif; ?>
+ <tr>
+ <td class="list" colspan="3"></td>
+ <td class="list">
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td valign="middle"><a href="dspam-settings-spwd.php?sectionid=srv"><img src="./themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" width="17" height="17" border="0"></a></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td width="78%" class="vtable">
+ <p>
+ <span class="vexpl">
+ If supporting standard LMTP mode, server parameters will need to be specified
+ here, as they will not be passed in by the mail server. The ServerIdent
+ specifies the 250 response code ident sent back to connecting clients and
+ should be set to the hostname of your server, or an alias.
+ </span>
+ </p>
+ <p>
+ <span class="vexpl">
+ Note: If you specify <code>--user</code> in ServerParameters, the RCPT TO will be used
+ only for delivery, and not set as the active user for processing.
+ </span>
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Server Parameters</td>
+ <td width="78%" class="vtable">
+ <p>
+ <input type="text" size="30" class="formfld unknown" name="serverparam" id="serverparam" value="<?=htmlspecialchars($pconfig['serverparam']);?>" />
+ <strong>
+ Parameters which will be passed to the LMTP server.
+ </strong>
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Server Ident</td>
+ <td width="78%" class="vtable">
+ <p>
+ <input type="text" size="30" <?= checkForErrorClass("serverid", "formfld host"); ?> name="serverid" id="serverid" value="<?=htmlspecialchars($pconfig['serverid']);?>" />
+ <strong>
+ An identification string which will be used to be passed to the LMTP server.
+ </strong>
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Server Domain Socket Path</td>
+ <td width="78%" class="vtable">
+ <p>
+ <input type="text" size="30" <?= checkForErrorClass("serversock", "formfld file"); ?> name="serversock" id="serversock" value="<?=htmlspecialchars($pconfig['serversock']);?>" />
+ <strong>
+ A local Unix domain socket.
+ </strong>
+ </p>
+ <p>
+ <span class="vexpl">
+ If you wish to use a local domain socket instead of a TCP socket, uncomment
+ the following. It is strongly recommended you use local domain sockets if
+ you are running the client and server on the same machine, as it eliminates
+ much of the bandwidth overhead.
+ </span>
+ </p>
+ <p>
+ <span class="vexpl">
+ Keep this is sync with <code>/usr/local/etc/rd.d/dspam.rc</code> script
+ </span>
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <!-- <input name="Submit" type="submit" class="formbtn" value="Save" onclick="enable_change(true)" /> -->
+ <input id="submitt" name="Submit" type="submit" class="formbtn" value="<?=gettext("Save");?>" onclick="document.iform.sectionid.value = 'srv';" />
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2" class="list" height="12">&nbsp;</td>
+ </tr>
+ <tr>
+ <td valign="top" class="listtopic"><a name="cli" style="visibility: hidden;">&nbsp;</a>DSPAM Daemon Settings (Client)</td>
+ <td align="right" valign="top" class="listtopic">
+ <input name="enabledsclient" type="checkbox" id="enabledsclient" value="yes" <?php if (isset($pconfig['enabledsclient'])) echo 'checked="checked"'; ?> onClick="enable_change(false, 4);" />
+ <strong>Enable</strong>
+ </td>
+ </tr>
+
+ <tr>
+ <td width="22%" valign="top" class="vncell">&nbsp;</td>
+ <td width="78%" class="vtable">
+ <p>
+ <span class="vexpl">
+ If you are running DSPAM in client/server mode, uncomment and
+ set these variables. A ClientHost beginning with a <code>/</code>
+ will be treated as a domain socket.
+ </span>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Client Host</td>
+ <td width="78%" class="vtable">
+ <p>
+ <input type="text" size="30" <?= checkForErrorClass("dsclhost", "formfld host"); ?> name="dsclhost" id="dsclhost" value="<?=htmlspecialchars($pconfig['dsclhost']);?>" <?php if (! isset($pconfig['enabledsclient'])) echo 'disabled="disabled"'; ?> />
+ <strong>
+ A IP address or a Unix domain socket.
+ </strong>
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Client Port</td>
+ <td width="78%" class="vtable">
+ <p>
+ <input type="text" size="30" <?= checkForErrorClass("dsclhost", "formfld host"); ?> name="dsclport" id="dsclport" value="<?=htmlspecialchars($pconfig['dsclport']);?>" <?php if (! isset($pconfig['enabledsclient'])) echo 'disabled="disabled"'; ?> />
+ <strong>
+ Will be only used if this client uses TCP/IP communication.
+ </strong>
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Client Ident</td>
+ <td width="78%" class="vtable">
+ <p>
+ <input type="text" size="30" <?= checkForErrorClass("dsclident", "formfld unknown"); ?> name="dsclident" id="dsclident" value="<?=htmlspecialchars($pconfig['dsclident']);?>" <?php if (! isset($pconfig['enabledsclient'])) echo 'disabled="disabled"'; ?> />
+ <strong>
+ A string that will be used to identify the client against a server.
+ </strong>
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <!-- <input name="Submit" type="submit" class="formbtn" value="Save" onclick="enable_change(true)" /> -->
+ <input id="submitt" name="Submit" type="submit" class="formbtn" value="<?=gettext("Save");?>" onclick="document.iform.sectionid.value = 'cli';" />
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </div>
+ </td>
+ </tr>
+ </table>
+ </form>
+ <br>
+ <?= checkForInputErrors(); ?>
+<?
+ } else {
+?>
+<?php
+ $input_errors[] = "Access to this particular site was denied. You need DSPAM admin access rights to be able to view it.";
+
+ include("head.inc");
+ echo $pfSenseHead->getHTML();
+?>
+<?php include("fbegin.inc");?>
+<?php if ($input_errors) print_input_errors($input_errors);?>
+<?php if ($savemsg) print_info_box($savemsg);?>
+ <body link="#000000" vlink="#000000" alink="#000000">
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td valign="top" class="listtopic">Access denied for: <?=$HTTP_SERVER_VARS['AUTH_USER']?></td>
+ </tr>
+ </table>
+<?php
+ } // end of access denied code
+?>
+<?php include("fend.inc"); ?>
+</body>
+</html> \ No newline at end of file
diff --git a/config/dspam/www/dspam-train.php b/config/dspam/www/dspam-train.php
new file mode 100644
index 00000000..bc0bc087
--- /dev/null
+++ b/config/dspam/www/dspam-train.php
@@ -0,0 +1,284 @@
+<?php
+/* $Id$ */
+/*
+ dspam-train.php
+
+ Copyright (C) 2006 Daniel S. Haischt.
+ All rights reserved.
+*/
+
+$pgtitle = array(gettext("Services"),
+ gettext("DSPAM"),
+ gettext("Train Filter"));
+
+/* omit no-cache headers because it confuses IE with file downloads */
+$omit_nocacheheaders = true;
+require("guiconfig.inc");
+include("/usr/local/pkg/dspam.inc");
+
+function prepare_compressed_mbox_data($type) {
+ global $CURRENT_USER;
+ /* prepare directories */
+ mwexec("mkdir -m 0755 -p /tmp/dspam-data/{$CURRENT_USER}/mbox");
+ mwexec("mkdir -m 0755 -p /tmp/dspam-data/{$CURRENT_USER}/mdir");
+
+ switch ($type) {
+ case 0:
+ move_uploaded_file($_FILES['archfile']['tmp_name'], "/tmp/" . $_FILES['archfile']['name']);
+ mwexec("/usr/local/bin/unzip /tmp/{$_FILES['archfile']['name']} -d /tmp/dspam-data/{$CURRENT_USER}/mbox");
+ unlink("/tmp/{$_FILES['archfile']['name']}");
+ mwexec("/usr/local/bin/mb2md -s /tmp/dspam-data/{$CURRENT_USER}/mbox -R -d /tmp/dspam-data/{$CURRENT_USER}/mdir");
+ break;
+ case 1:
+ move_uploaded_file($_FILES['archfile']['tmp_name'], "/tmp/dspam-data/" . $_SESSION['Username'] . "/mbox/" . $_FILES['archfile']['name']);
+ mwexec("/usr/bin/gunzip /tmp/dspam-data/{$CURRENT_USER}/mbox/{$_FILES['archfile']['name']}");
+ mwexec("/usr/local/bin/mb2md -s /tmp/dspam-data/{$CURRENT_USER}/mbox -R -d /tmp/dspam-data/{$CURRENT_USER}/mdir");
+ break;
+ case 2:
+ move_uploaded_file($_FILES['archfile']['tmp_name'], "/tmp/dspam-data/" . $_SESSION['Username'] . "/mbox/" . $_FILES['archfile']['name']);
+ mwexec("/usr/bin/bunzip2 /tmp/dspam-data/{$CURRENT_USER}/mbox/{$_FILES['archfile']['name']}");
+ mwexec("/usr/local/bin/mb2md -s /tmp/dspam-data/{$CURRENT_USER}/mbox -R -d /tmp/dspam-data/{$CURRENT_USER}/mdir");
+ break;
+ }
+}
+
+function prepare_compressed_mdir_data($type) {
+ global $CURRENT_USER;
+ /* prepare directories */
+ mwexec("mkdir -m 0755 -p /tmp/dspam-data/{$CURRENT_USER}/mdir");
+
+ switch ($type) {
+ case 0:
+ move_uploaded_file($_FILES['archfile']['tmp_name'], "/tmp/" . $_FILES['archfile']['name']);
+ mwexec("/usr/local/bin/unzip /tmp/{$_FILES['archfile']['name']} -d /tmp/dspam-data/{$CURRENT_USER}/mdir");
+ unlink("/tmp/{$_FILES['archfile']['name']}");
+ break;
+ case 1:
+ move_uploaded_file($_FILES['archfile']['tmp_name'], "/tmp/dspam-data/" . $_SESSION['Username'] . "/mdir/" . $_FILES['archfile']['name']);
+ mwexec("/usr/bin/gunzip /tmp/dspam-data/{$CURRENT_USER}/mdir/{$_FILES['archfile']['name']}");
+ break;
+ case 2:
+ move_uploaded_file($_FILES['archfile']['tmp_name'], "/tmp/dspam-data/" . $_SESSION['Username'] . "/mdir/" . $_FILES['archfile']['name']);
+ mwexec("/usr/bin/bunzip2 /tmp/dspam-data/{$CURRENT_USER}/mdir/{$_FILES['archfile']['name']}");
+ break;
+ }
+}
+
+function prepare_compressed_data($type) {
+ if ($_POST['archformat'] == "mbox") {
+ prepare_compressed_mbox_data($type);
+ } else {
+ prepare_compressed_mdir_data($type);
+ }
+}
+
+if ($_POST) {
+ unset($input_errors);
+
+ if(! extension_loaded( 'fileinfo' )) {
+ /* fileinfo pecl extension unavailable? */
+ if(! @dl( 'fileinfo.so' )) {
+ if ($_POST['cotype'] == "zip") {
+ prepare_compressed_data(0);
+ } else if ($_POST['cotype'] == "gzip") {
+ prepare_compressed_data(1);
+ } else if ($_POST['cotype'] == "bzip") {
+ prepare_compressed_data(2);
+ } else {
+ $input_errors[] = "unable to determine compression type.";
+ }
+ } else {
+ if (is_uploaded_file($_FILES['archfile']['tmp_name'])) {
+ $info = finfo_open( FILEINFO_MIME, '/usr/share/misc/magic' );
+ $type = finfo_file( $info, $_FILES['archfile']['tmp_name'] );
+
+ if ($type == "application/x-zip") {
+ prepare_compressed_data(0);
+ } else if ($type == "application/x-gzip") {
+ prepare_compressed_data(1);
+ } else if ($type == "application/x-bzip2") {
+ prepare_compressed_data(2);
+ } else {
+ $input_errors[] = "unable to determine compression type.";
+ }
+ }
+ }
+ }
+
+ /* tell DSPAM to train the messages contained within the maildir */
+ if ($_POST['msgtype'] == "spam") {
+ mwexec("find /tmp/dspam-data/{$CURRENT_USER}/mdir -name '*' -exec /usr/local/bin/dspam_spamfeed {$CURRENT_USER} {} \\;");
+ } else if ($_POST['msgtype'] == "ham") {
+ mwexec("find /tmp/dspam-data/{$CURRENT_USER}/mdir -name '*' -exec /usr/local/bin/dspam_innocentfeed {$CURRENT_USER} {} \\;");
+ mwexec("rm -rf /tmp/dspam-data");
+ }
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($input_errors)) {
+ input_errors2Ajax($input_errors);
+ exit;
+ }
+}
+
+/* if ajax is calling, give them an update message */
+if(isAjax())
+ print_info_box_np($savemsg);
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+ $jscriptstr = <<<EOD
+<script type="text/javascript">
+<!--
+
+EOD;
+
+ $jscriptstr .= getJScriptFunction(0);
+ $jscriptstr .= <<<EOD
+//-->
+</script>
+EOD;
+
+ $pfSenseHead->addScript($jscriptstr);
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<?php include("fbegin.inc"); ?>
+<form action="dspam-train.php" method="post" name="iform" id="iform" enctype="multipart/form-data">
+<input type="hidden" name="MAX_FILE_SIZE" value="<?= (diskfreespace('/') - (10 * pow(10, 6))); ?>">
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+<table width="100%" border="0" cellspacing="0" cellpadding="0">
+ <tr>
+ <td>
+<?php
+ $tab_array = array();
+ $tab_array[] = array("Info", false, "/dspam.php?user={$CURRENT_USER}");
+ $tab_array[] = array("Performance", false, "/dspam-perf.php?user={$CURRENT_USER}");
+ $tab_array[] = array("Preferences", false, "/dspam-prefs.php?user={$CURRENT_USER}");
+ $tab_array[] = array("Alerts", false, "/pkg.php?xml=dspam_alerts.xml&user={$CURRENT_USER}");
+ $tab_array[] = array("Quarantine ({$DATA['TOTAL_QUARANTINED_MESSAGES']})", false, "/dspam-quarantine.php?user={$CURRENT_USER}");
+ $tab_array[] = array("Analysis", false, "/dspam-analysis.php?user={$CURRENT_USER}");
+ $tab_array[] = array("History", false, "/dspam-history.php?user={$CURRENT_USER}");
+ $tab_array[] = array("Train Filter", true, "/dspam-train.php?user={$CURRENT_USER}");
+ if (isDSPAMAdmin($HTTP_SERVER_VARS['AUTH_USER'])) {
+ $tab_array[] = array("Admin Suite", false, "/dspam-admin.php");
+ }
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <table class="tabcont" align="center" width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td align="left" valign="top" class="listhdrr" colspan="2">Statistical SPAM Protection for...</td>
+ </tr>
+ <tr>
+ <td width="22%" valign="baseline" class="vncell">Username</td>
+ <td width="78%" class="vtable">
+ <?php if(isset($HTTP_SERVER_VARS['AUTH_USER'])): ?>
+ <input type="text" name="username" id="username" value="<?= $CURRENT_USER ?>" class="formfld user"<?php if (! isDSPAMAdmin($HTTP_SERVER_VARS['AUTH_USER'])) { echo " readonly=\"readonly\""; } ?> />
+ <?php else: ?>
+ <input type="text" name="username" id="username" value="Please provide a username" class="formfld user" onFocus="this.value='';" />
+ <?php endif; ?>
+ &nbsp;
+ <?php
+ if (! isDSPAMAdmin($HTTP_SERVER_VARS['AUTH_USER']))
+ $action = "onClick=\"changeuser();\"";
+ else
+ $action = "onClick=\"document.iform.submit();\"";
+ ?>
+ <input type="button" name="change_user" id="change_user" class="formbtn" value="Change" <?= $action ?> />
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2" class="list" height="12">&nbsp;</td>
+ </tr>
+ <tr>
+ <td colspan="2" class="listtopic"><?=gettext("Upload Message Archive");?></td>
+ </tr>
+ <tr>
+ <td width="22%" valign="baseline" class="vncell">Archive Type</td>
+ <td width="78%" class="vtable">
+ <?php if($config['installedpackages']['mb2md'] || file_exists('/usr/local/bin/mb2md')): ?>
+ <input type="radio" name="archformat" id="mbxformat" value="mbox" class="formfld" />
+ &nbsp;<a href="http://en.wikipedia.org/wiki/Mbox" target="_blank">Mailbox</a> format (like it is used for example by Mozilla Thunderbird)
+ <br />
+ <?php endif; ?>
+ <input type="radio" name="archformat" id="mdirformat" value="mdir" class="formfld" checked="checked"/>
+ &nbsp;<a href="http://en.wikipedia.org/wiki/Maildir" target="_blank">Maildir</a> format (like it was initially introduced by qmail)
+ <p>
+ <strong>
+ <span class="red"><?=gettext("Note");?>:</span>
+ </strong>
+ <br />
+ <?=gettext("DSPAM is only able to handle Maildir message archives natively. Mailbox message archives need to be converted (the conversion from mbx to maildir will be done on the fly while you are uploading a message archive).");?>
+ <br />
+ </p>
+ </td>
+ </tr>
+ <?php if(! extension_loaded( 'fileinfo' )): ?>
+ <?php if(! @dl( 'fileinfo.so' )): ?>
+ <tr>
+ <td width="22%" valign="baseline" class="vncell">Compression Type</td>
+ <td width="78%" class="vtable">
+ <input type="radio" name="cotype" id="ziptype" value="zip" class="formfld" />
+ &nbsp;Archive was compressed using a ZIP algorithm.
+ <br />
+ <input type="radio" name="cotype" id="gziptype" value="gzip" class="formfld" />
+ &nbsp;Archive was compressed using a GNU ZIP algorithm.
+ <br />
+ <input type="radio" name="cotype" id="bziptype" value="bzip" class="formfld" checked="checked" />
+ &nbsp;Archive was compressed using a bzip2 algorithm
+ <br />
+ </td>
+ </tr>
+ <?php endif; ?>
+ <?php endif; ?>
+ <tr>
+ <td width="22%" valign="baseline" class="vncell">Message Type</td>
+ <td width="78%" class="vtable">
+ <input type="radio" name="msgtype" id="spamtype" value="spam" class="formfld" checked="checked" />
+ &nbsp;Archive to be uploaded contains Spam messages.
+ <br />
+ <input type="radio" name="msgtype" id="hamtype" value="ham" class="formfld" />
+ &nbsp;Archive to be uploaded contains Ham messages.
+ <br />
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="baseline" class="vncell">&nbsp;</td>
+ <td width="78%" class="vtable">
+ <p>
+ <?=gettext("Open a Ham or Spam message archive (please either zip, gzip or bzip your files).");?>
+ </p>
+ <p>
+ <input name="archfile" type="file" class="formfld file" id="archfile" size="40" maxlength="<?= (diskfreespace('/') - (10 * pow(10, 6))); ?>" />
+ </p>
+ <p>
+ <input name="Submit" type="submit" class="formbtn" id="restore" value="<?=gettext("Upload Message Archive");?>" />
+ </p>
+ <p>
+ <strong>
+ <span class="red"><?=gettext("Note");?>:</span>
+ </strong>
+ <br />
+ <?=gettext("It may take a long time until the filter stops training, if you are going to upload a huge archive. Therefore the the allowed filesize to be uploaded has been set to " . ((diskfreespace('/') - (10 * pow(10, 6))) / pow(10, 6)) . " MByte (available space minus 10 MByte).");?>
+ <br />
+ </p>
+ </td>
+ </tr>
+ </table>
+ </div>
+ </td>
+ </tr>
+</table>
+</form>
+
+<?php include("fend.inc"); ?>
+</body>
+</html> \ No newline at end of file
diff --git a/config/dspam/www/dspam-viewmsg.php b/config/dspam/www/dspam-viewmsg.php
new file mode 100644
index 00000000..e56b081f
--- /dev/null
+++ b/config/dspam/www/dspam-viewmsg.php
@@ -0,0 +1,158 @@
+<?php
+/* $Id$ */
+/*
+ dspam-train.php
+
+ Copyright (C) 2006 Daniel S. Haischt.
+ All rights reserved.
+*/
+
+$pgtitle = array(gettext("Services"),
+ gettext("DSPAM"),
+ gettext("Quarantine"),
+ gettext("View Message"));
+
+require("guiconfig.inc");
+include("/usr/local/pkg/dspam.inc");
+
+/* if this is an AJAX caller then handle via JSON */
+if(isAjax() && is_array($input_errors)) {
+ input_errors2Ajax($input_errors);
+ exit;
+}
+
+/* if ajax is calling, give them an update message */
+if(isAjax())
+ print_info_box_np($savemsg);
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+ $jscriptstr = <<<EOD
+<script type="text/javascript">
+<!--
+
+EOD;
+
+ $jscriptstr .= getJScriptFunction(0);
+ $jscriptstr .= <<<EOD
+//-->
+</script>
+EOD;
+
+ $pfSenseHead->addScript($jscriptstr);
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<?php include("fbegin.inc"); ?>
+<form action="dspam-quarantine.php" method="post" name="iform" id="iform">
+<input type="hidden" name="command" value="processFalsePositive" />
+<input type="hidden" name="signatureID" value="<?= $DATA['MESSAGE_ID']; ?>" />
+<input type="hidden" name="qpage" value="<?= $DATA['QPAGE']; ?>" />
+<input type="hidden" name="sortby" value="<?= $DATA['SORTBY']; ?>" >
+<input type="hidden" name="qperpage" value="<?= $CONFIG['QUARANTINE_PER_PAGE']; ?>" >
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+<p>
+ <span class="vexpl">
+ The contents of the message in the quarantine is shown below.
+ </span>
+</p>
+<table width="100%" border="0" cellspacing="0" cellpadding="0">
+ <tr>
+ <td>
+<?php
+ $querystr = "?user=?{$CURRENT_USER}&page={$DATA['QPAGE']}&sortby={$DATA['SORTBY']}&qperpage={$CONFIG['QUARANTINE_PER_PAGE']}";
+
+ $tab_array = array();
+ $tab_array[] = array("Info", false, "/dspam.php?user={$CURRENT_USER}");
+ $tab_array[] = array("Performance", false, "/dspam-perf.php?user={$CURRENT_USER}");
+ $tab_array[] = array("Preferences", false, "/dspam-prefs.php?user={$CURRENT_USER}");
+ $tab_array[] = array("Alerts", false, "/pkg.php?xml=dspam_alerts.xml&user={$CURRENT_USER}");
+ $tab_array[] = array("Quarantine (View)", true, "/dspam-quarantine.php{$querystr}");
+ $tab_array[] = array("Analysis", false, "/dspam-analysis.php?user={$CURRENT_USER}");
+ $tab_array[] = array("History", false, "/dspam-history.php?user={$CURRENT_USER}");
+ $tab_array[] = array("Train Filter", false, "/dspam-train.php?user={$CURRENT_USER}");
+ if (isDSPAMAdmin($HTTP_SERVER_VARS['AUTH_USER'])) {
+ $tab_array[] = array("Admin Suite", false, "/dspam-admin.php");
+ }
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <table class="tabcont" align="center" width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td align="left" valign="top" class="listhdrr" colspan="3">Statistical SPAM Protection for...</td>
+ </tr>
+ <tr>
+ <td width="15%" valign="baseline" class="vncell">Username</td>
+ <td width="85%" class="vtable" colspan="2">
+ <?php if(isset($HTTP_SERVER_VARS['AUTH_USER'])): ?>
+ <input type="text" name="username" id="username" value="<?= $CURRENT_USER ?>" class="formfld user"<?php if (! isDSPAMAdmin($HTTP_SERVER_VARS['AUTH_USER'])) { echo " readonly=\"readonly\""; } ?> />
+ <?php else: ?>
+ <input type="text" name="username" id="username" value="Please provide a username" class="formfld user" onFocus="this.value='';" />
+ <?php endif; ?>
+ &nbsp;
+ <?php
+ if (! isDSPAMAdmin($HTTP_SERVER_VARS['AUTH_USER']))
+ $action = "onClick=\"changeuser();\"";
+ else
+ $action = "onClick=\"document.iform.submit();\"";
+ ?>
+ <input type="button" name="change_user" id="change_user" class="formbtn" value="Change" <?= $action ?> />
+ </td>
+ </tr>
+ <tr>
+ <td class="list" height="12" colspan="3">&nbsp;</td>
+ </tr>
+ <tr>
+ <td align="left" valign="middle" class="qnavtd" colspan="3">
+ <input type="submit" class="formbtn" title="Deliver Message" value="Deliver Message" name="delmsg" id="delmsg" />
+ <label for="delmsg">&nbsp;because it is <strong>not</strong> SPAM</label>
+ </td>
+ </tr>
+ <tr>
+ <td class="list" height="12" colspan="3">&nbsp;</td>
+ </tr>
+ <?php if(! extension_loaded( 'mailparse' ) && $CONFIG['USE_MAILPARSE']): ?>
+ <?php if(! @dl( 'mailparse.so' )): ?>
+ <tr>
+ <td align="left" valign="top" class="listtopic" colspan="3">Mail Message</td>
+ </tr>
+ <tr>
+ <td align="center" valign="top" colspan="3" class="vncell">
+ <textarea rows="36" cols="87" readonly="readonly">
+ <?= $DATA['MESSAGE']; ?>
+ </textarea>
+ </td>
+ </tr>
+ <?php else: ?>
+ <?= getLayoutedMessage($DATA['MESSAGE'], $DATA['MESSAGE_ID'], $DATA['SHOWPART'], $DATA['CONTENT_TYPE']); ?>
+ <?php endif; ?>
+ <?php else: ?>
+ <tr>
+ <td align="left" valign="top" class="listtopic" colspan="3">Mail Message</td>
+ </tr>
+ <tr>
+ <td align="center" valign="top" colspan="3" class="vncell">
+ <textarea rows="36" cols="87" readonly="readonly">
+ <?= $DATA['MESSAGE']; ?>
+ </textarea>
+ </td>
+ </tr>
+ <?php endif; ?>
+ </table>
+ </div>
+ </td>
+ </tr>
+</table>
+</form>
+
+<?php include("fend.inc"); ?>
+</body>
+</html> \ No newline at end of file
diff --git a/config/dspam/www/dspam.php b/config/dspam/www/dspam.php
new file mode 100644
index 00000000..1f2d7df7
--- /dev/null
+++ b/config/dspam/www/dspam.php
@@ -0,0 +1,264 @@
+<?php
+/* $Id$ */
+/*
+ dspam.php
+
+ Copyright (C) 2006 Daniel S. Haischt.
+ All rights reserved.
+*/
+
+$pgtitle = array(gettext("Services"),
+ gettext("DSPAM"),
+ gettext("Overview"));
+
+require("guiconfig.inc");
+include("/usr/local/pkg/dspam.inc");
+
+if ($_POST) {
+ unset($input_errors);
+
+ if (is_uploaded_file($_FILES['nionelic']['tmp_name'])) {
+ conf_mount_rw();
+ config_lock();
+ move_uploaded_file($_FILES['nionelic']['tmp_name'], "{$g['conf_path']}/{$_FILES['nionelic']['name']}");
+ chmod("{$g['conf_path']}/{$_FILES['nionelic']['name']}", 0400);
+ config_unlock();
+ conf_mount_ro();
+ }
+ if (is_uploaded_file($_FILES['nionelicchk']['tmp_name'])) {
+ conf_mount_rw();
+ config_lock();
+ move_uploaded_file($_FILES['nionelicchk']['tmp_name'], "{$g['conf_path']}/{$_FILES['nionelicchk']['name']}");
+ chmod("{$g['conf_path']}/{$_FILES['nionelicchk']['name']}", 0400);
+ config_unlock();
+ conf_mount_ro();
+ }
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($input_errors)) {
+ input_errors2Ajax($input_errors);
+ exit;
+ }
+}
+
+/* if ajax is calling, give them an update message */
+if(isAjax())
+ print_info_box_np($savemsg);
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+ $jscriptstr = <<<EOD
+<script type="text/javascript">
+<!--
+
+EOD;
+
+ $jscriptstr .= getJScriptFunction(0);
+ $jscriptstr .= <<<EOD
+//-->
+</script>
+EOD;
+
+ $pfSenseHead->addScript($jscriptstr);
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<?php include("fbegin.inc"); ?>
+<form action="dspam.php" method="post" name="iform" id="iform" enctype="multipart/form-data">
+<input type="hidden" name="MAX_FILE_SIZE" value="<?= (diskfreespace('/') - (10 * pow(10, 6))); ?>">
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+<table width="100%" border="0" cellspacing="0" cellpadding="0">
+ <tr>
+ <td>
+<?php
+ $tab_array = array();
+ $tab_array[] = array("Info", true, "/dspam.php?user={$CURRENT_USER}");
+ $tab_array[] = array("Performance", false, "/dspam-perf.php?user={$CURRENT_USER}");
+ $tab_array[] = array("Preferences", false, "/dspam-prefs.php?user={$CURRENT_USER}");
+ $tab_array[] = array("Alerts", false, "/pkg.php?xml=dspam_alerts.xml&user={$CURRENT_USER}");
+ $tab_array[] = array("Quarantine ({$DATA['TOTAL_QUARANTINED_MESSAGES']})", false, "/dspam-quarantine.php?user={$CURRENT_USER}");
+ $tab_array[] = array("Analysis", false, "/dspam-analysis.php?user={$CURRENT_USER}");
+ $tab_array[] = array("History", false, "/dspam-history.php?user={$CURRENT_USER}");
+ $tab_array[] = array("Train Filter", false, "/dspam-train.php?user={$CURRENT_USER}");
+ if (isDSPAMAdmin($HTTP_SERVER_VARS['AUTH_USER'])) {
+ $tab_array[] = array("Admin Suite", false, "/dspam-admin.php");
+ }
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <table class="tabcont" align="center" width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td align="left" valign="top" class="listhdrr" colspan="2">Statistical SPAM Protection for...</td>
+ </tr>
+ <tr>
+ <td width="22%" valign="baseline" class="vncell">Username</td>
+ <td width="78%" class="vtable">
+ <?php if(isset($HTTP_SERVER_VARS['AUTH_USER'])): ?>
+ <input type="text" name="username" id="username" value="<?= $CURRENT_USER ?>" class="formfld user"<?php if (! isDSPAMAdmin($HTTP_SERVER_VARS['AUTH_USER'])) { echo " readonly=\"readonly\""; } ?> />
+ <?php else: ?>
+ <input type="text" name="username" id="username" value="Please provide a username" class="formfld user" onFocus="this.value='';" />
+ <?php endif; ?>
+ &nbsp;
+ <?php
+ if (! isDSPAMAdmin($HTTP_SERVER_VARS['AUTH_USER']))
+ $action = "onClick=\"changeuser();\"";
+ else
+ $action = "onClick=\"document.iform.submit();\"";
+ ?>
+ <input type="button" name="change_user" id="change_user" class="formbtn" value="Change" <?= $action ?> />
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2" class="list" height="12">&nbsp;</td>
+ </tr>
+ <tr>
+ <td colspan="2" class="listtopic"><?=gettext("DSPAM Software Details");?></td>
+ </tr>
+ <tr>
+ <td width="22%" valign="baseline" class="vncell">DSPAM Version</td>
+ <td width="78%" class="vtable"><?= $DATA['DSPAM_VERSION']; ?></td>
+ </tr>
+ <tr>
+ <td width="22%" valign="baseline" class="vncell">DSPAM Copyright</td>
+ <td width="78%" class="vtable"><?= $DATA['DSPAM_COPYRIGHT']; ?></td>
+ </tr>
+ <tr>
+ <td width="22%" valign="baseline" class="vncell">DSPAM Copyright Text</td>
+ <td width="78%" class="vtable"><?= $DATA['DSPAM_COPYRIGHT_TEXT']; ?></td>
+ </tr>
+ <tr>
+ <td width="22%" valign="baseline" class="vncell">DSPAM Website</td>
+ <td width="78%" class="vtable">
+ <a href="<?= $DATA['DSPAM_WEBSITE']; ?>" target="_blank"><?= $DATA['DSPAM_WEBSITE']; ?></a>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="baseline" class="vncell">DSPAM Configure Args</td>
+ <td width="78%" class="vtable">
+ <code style="font-size: small;"><?= $DATA['DSPAM_CONFIGURE_ARGS']; ?></code>
+ </td>
+ </tr>
+ <?php if($CONFIG['OPENSOURCE'] == false): ?>
+ <tr>
+ <td colspan="2" class="list" height="12">&nbsp;</td>
+ </tr>
+ <tr>
+ <td colspan="2" class="listtopic"><?=gettext("Ni-ONE License Information");?></td>
+ </tr>
+ <tr>
+ <td width="22%" valign="baseline" class="vncell">License User</td>
+ <td width="78%" class="vtable"><?= $DATA['OWNER']; ?></td>
+ </tr>
+ <tr>
+ <td width="22%" valign="baseline" class="vncell">Company</td>
+ <td width="78%" class="vtable"><?= $DATA['COMPANY']; ?></td>
+ </tr>
+ <tr>
+ <td width="22%" valign="baseline" class="vncell">License Key</td>
+ <td width="78%" class="vtable"><?= $DATA['LICENSE_KEY']; ?></td>
+ </tr>
+ <tr>
+ <td width="22%" valign="baseline" class="vncell">License Validity</td>
+ <td width="78%" class="vtable">
+ <?= $DATA['LICENSE_VALIDITY']; ?>
+ <?php if(strpos($DATA['LICENSE_VALIDITY'], "expired") !== false && isDSPAMAdmin($HTTP_SERVER_VARS['AUTH_USER'])): ?>
+ &nbsp;<a href="http://www.niefert.net/nione.php?customer<?= $DATA['LICENSE_KEY']; ?>" target="_blank">Renew License</a>
+ <?php endif; ?>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="baseline" class="vncell">Purchase Date</td>
+ <td width="78%" class="vtable"><?= $DATA['PURCHASE_DATE']; ?></td>
+ </tr>
+ <tr>
+ <td width="22%" valign="baseline" class="vncell">Expiry Date</td>
+ <td width="78%" class="vtable"><?= $DATA['EXPIRY_DATE']; ?></td>
+ </tr>
+ <tr>
+ <td width="22%" valign="baseline" class="vncell">Ni-ONE Website</td>
+ <td width="78%" class="vtable">
+ <a href="http://www.niefert.net/nione.php" target="_blank">http://www.niefert.net/nione.php</a>
+ </td>
+ </tr>
+ <?php if($DATA['LICENSE_VALIDITY'] == "valide"): ?>
+ <tr>
+ <td width="22%" valign="baseline" class="vncell">Support Request</td>
+ <td width="78%" class="vtable">
+ <a href="http://www.niefert.net/nione.php?supportreq=true&amp;customer=<?= $DATA['LICENSE_KEY']; ?>" target="_blank">Issue a support request</a>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="baseline" class="vncell">Ni-ONE Customer Forum</td>
+ <td width="78%" class="vtable">
+ <a href="http://www.niefert.net/nione-forum.php?customer=<?= $DATA['LICENSE_KEY']; ?>" target="_blank">Visit Ni-ONE Customer Forum</a>
+ </td>
+ </tr>
+ <?php endif; ?>
+ <?php if(strpos($DATA['LICENSE_VALIDITY'], "found") !== false && isDSPAMAdmin($HTTP_SERVER_VARS['AUTH_USER'])): ?>
+ <tr>
+ <td width="22%" valign="baseline" class="vncell">License File (nione.lic)</td>
+ <td width="78%" class="vtable">
+ <input type="file" name="nionelic" id="nionelic" class="formfld file" size="50" maxlength="100" />
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="baseline" class="vncell">License Checksum (nione.lic.sha1)</td>
+ <td width="78%" class="vtable">
+ <input type="file" name="nionelicchk" id="nionelicchk" class="formfld file" size="50" maxlength="100" />
+ </td>
+ </tr>
+ <?php endif; ?>
+ <?php if($DATA['LICENSE_VALIDITY'] == "valide"): ?>
+ <tr>
+ <td width="22%" valign="baseline" class="vncell">License Disclaimer</td>
+ <td width="78%" class="vtable">
+ <p>
+ The Ni-ONE appliance solution is based on open source software. Hence you
+ are allowed to use the corresponding software components (i.e. DSPAM and
+ its dependencies) under the terms of the accompanying open source license.
+ </p>
+ <p>
+ The Ni-ONE license provides 1<sup>st</sup> class priority support for a period
+ of one year starting from the day you did purchase a valide license option. If the
+ license is marked as <i>expired</i>, you may consider to purchase a renewal license
+ option using the <i>renew license</i> button that will be provided by the web
+ interface in such circumstances.
+ </p>
+ </td>
+ </tr>
+ <?php endif; ?>
+ <?php if(strpos($DATA['LICENSE_VALIDITY'], "found") !== false && isDSPAMAdmin($HTTP_SERVER_VARS['AUTH_USER'])): ?>
+ <tr>
+ <td width="22%" valign="baseline">&nbsp;</td>
+ <td width="78%">
+ <input name="Submit" type="submit" class="formbtn" id="restore" value="<?=gettext("Upload License");?>" />
+ <p>
+ <strong>
+ <span class="red"><?=gettext("Note");?>:</span>
+ </strong>
+ <br />
+ <?=gettext("You may have to hit the reload button of your browser after uploading your license files to be able to see the license data.");?>
+ <br />
+ </p>
+ </td>
+ </tr>
+ <?php endif; ?>
+ <?php endif; ?>
+ </table>
+ </div>
+ </td>
+ </tr>
+</table>
+</form>
+
+<?php include("fend.inc"); ?>
+</body>
+</html> \ No newline at end of file
diff --git a/config/dspam/www/themes/metallic/dspam.css b/config/dspam/www/themes/metallic/dspam.css
new file mode 100644
index 00000000..5b39ba32
--- /dev/null
+++ b/config/dspam/www/themes/metallic/dspam.css
@@ -0,0 +1,115 @@
+.qrowEven {
+ background-color: #DDDDDD;
+ padding-right: 20px;
+ padding-left: 8px;
+ border-bottom: 1px solid #999999;
+}
+.qrowOdd {
+ background-color: #FFFFFF;
+ padding-right: 20px;
+ padding-left: 8px;
+ border-bottom: 1px solid #999999;
+}
+.qrowAlert {
+ background-color: yellow;
+ padding-right: 20px;
+ padding-left: 8px;
+ border-bottom: 1px solid #999999;
+}
+.qrowHighlight {
+ background-color: white;
+ font-weight: bold;
+ padding-right: 20px;
+ padding-left: 8px;
+ border-bottom: 1px solid #999999;
+}
+.qrowDivider {
+ padding-right: 20px;
+ padding-left: 8px;
+ border-left: 1px solid black;
+ border-bottom: 1px solid #999999;
+}
+
+.innocent {color: limegreen; background-color: green;}
+.whitelisted {color: magenta; background-color: purple;}
+.spam {color: red; background-color: darkred;}
+.false {color: white; font-weight: bold; background-color: green;}
+.missed {color: white; font-weight: bold; background-color: darkred;}
+.inoculation {color: dodgerblue; background-color: darkblue;}
+.corpus {color: black; background-color: white;}
+.relay {color: white; background-color: #994400;}
+.low {color: darkblue; font-weight: bold;}
+.medium {color: steelblue; font-weight: bold;}
+.high {color: darkorange; font-weight: bold;}
+
+.small { font-size: 9px;}
+.hollow { border: 0px; }
+
+.qnavtd {
+ border: 1px solid #CCCCCC;
+}
+.qnavtdl {
+ border-top: 1px solid #CCCCCC;
+ border-bottom: 1px solid #CCCCCC;
+ border-left: 1px solid #CCCCCC;
+}
+.qnavtdr {
+ border-top: 1px solid #CCCCCC;
+ border-bottom: 1px solid #CCCCCC;
+ border-right: 1px solid #CCCCCC;
+}
+.qnavbtnhl {
+ font-size: 9px !important;
+ border-right: 1px solid #FF7F7F;
+ border-bottom: 1px solid #FF7F7F;
+ border-left: 1px solid #5F0000;
+ border-top: 1px solid #5F0000;
+ padding-left: 3px;
+ padding-right: 3px;
+ padding-bottom: 2px;
+ padding-top: 2px;
+ background-color: #FF7F7F;
+}
+.qnavbtn {
+ font-size: 9px !important;
+ border-right: 1px solid #FF7F7F;
+ border-bottom: 1px solid #FF7F7F;
+ border-left: 1px solid #5F0000;
+ border-top: 1px solid #5F0000;
+ padding-left: 3px;
+ padding-right: 3px;
+ padding-bottom: 2px;
+ padding-top: 2px;
+ background-color: #507DCD;
+ cursor: pointer;
+}
+.qnavbtn a:link {
+ font-size: 9px !important;
+ font-weight: bold;
+ color: #FFFFFF;
+ text-decoration:none;
+}
+.qnavbtn a:visited {
+ font-size: 9px !important;
+ font-weight: bold;
+ color: #FFFFFF;
+ text-decoration:none;
+}
+.qnavbtn a:focus {
+ font-size: 9px !important;
+ font-weight: bold;
+ color: #FFFFFF;
+ text-decoration:underline;
+}
+.qnavbtn a:hover {
+ font-size: 9px !important;
+ font-weight: bold;
+ color: #FFFFFF;
+ text-decoration:none;
+}
+.qnavbtn a:active {
+ font-size: 9px !important;
+ font-weight: bold;
+ color: #FFFFFF;
+ text-decoration:underline;
+} \ No newline at end of file
diff --git a/config/dspam/www/wizards/dspam-lda-proxy.png b/config/dspam/www/wizards/dspam-lda-proxy.png
new file mode 100644
index 00000000..7a4565ec
--- /dev/null
+++ b/config/dspam/www/wizards/dspam-lda-proxy.png
Binary files differ
diff --git a/config/dspam/www/wizards/dspam-pop-proxy.png b/config/dspam/www/wizards/dspam-pop-proxy.png
new file mode 100644
index 00000000..fa373385
--- /dev/null
+++ b/config/dspam/www/wizards/dspam-pop-proxy.png
Binary files differ
diff --git a/config/dspam/www/wizards/dspam-smtp-relay.png b/config/dspam/www/wizards/dspam-smtp-relay.png
new file mode 100644
index 00000000..07f554c8
--- /dev/null
+++ b/config/dspam/www/wizards/dspam-smtp-relay.png
Binary files differ
diff --git a/config/dspam/www/wizards/dspam_wizard.xml b/config/dspam/www/wizards/dspam_wizard.xml
new file mode 100644
index 00000000..4ac96a4c
--- /dev/null
+++ b/config/dspam/www/wizards/dspam_wizard.xml
@@ -0,0 +1,1848 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<pfsensewizard>
+<!--
+ Tags which can be used to exec arbitrary PHP code:
+
+ <stepsubmitbeforesave />
+ <stepsubmitphpaction />
+ <stepbeforeformdisplay />
+ <formvalidate />
+ <disableallfieldsbydefault />
+ <stepafterformdisplay />
+ <javascriptafterformdisplay />
+-->
+<copyright>
+<![CDATA[
+/*
+ dspam_wizard.xml
+ part of pfSense (http://www.pfsense.org/)
+
+ Copyright (C) 2006 Daniel S. Haischt
+ All rights reserved.
+*/
+]]>
+</copyright>
+<totalsteps>15</totalsteps>
+<title>Services: DSPAM: DSPAM Wizard</title>
+<step>
+ <id>1</id>
+ <includefile>dspam.inc</includefile>
+ <title>DSPAM Setup Wizard</title>
+ <disableheader>true</disableheader>
+ <description>This wizard will guide you through the initial configuration of the DSPAM filter.</description>
+ <fields>
+ <field>
+ <name>Next</name>
+ <type>submit</type>
+ </field>
+ </fields>
+</step>
+<step>
+ <id>2</id>
+ <includefile>dspam.inc</includefile>
+ <title>DSPAM Profile Selection</title>
+ <disableheader>true</disableheader>
+ <description>DSPAM can be used in different network environment. Hence we are providing three distinct profiles to suit different DSPAM use cases. Please select a particular profile from the below profile selection.</description>
+ <fields>
+ <field>
+ <name>dspamprofile</name>
+ <type>radio</type>
+ <bindstofield>installedpackages->dspam->config->0->dspam-profile</bindstofield>
+ <description>
+ &lt;center&gt;
+ &lt;p&gt;
+When your mail server gets ready to deliver mail to a user's mailbox it calls
+a delivery agent of some sort. On most UNIX systems, this is procmail, maildrop,
+mail.local, or a similar tool. When used as a delivery proxy, the DSPAM agent
+is called in place of your existing agent - or better put, it can masquerade
+as the local delivery agent. DSPAM then processes the message and will call
+the /real/ delivery agent to pass the good mail into the user's mailbox,
+quarantining the bad mail. DSPAM can optionally tag and deliver both spam
+and legitimate mail.
+ &lt;/p&gt;
+ &lt;p&gt;
+In the diagram below, MTA refers to Mail Transfer Agent, or your mail server
+software: Postfix, Sendmail, Exim, etc. LDA refers to the Local Delivery
+Agent: Procmail, Maildrop, etc..
+ &lt;/p&gt;
+ &lt;/center&gt;
+ </description>
+ <value>lda</value>
+ <dontdisplayname />
+ <typehint>&lt;center&gt;&lt;img src=&quot;/wizards/dspam-lda-proxy.png&quot; alt=&quot;DSPAM acts as a LDA proxy&quot; border=&quot;0&quot; /&gt;&lt;/center&gt;</typehint>
+ </field>
+ <field>
+ <name>dspamprofile</name>
+ <type>radio</type>
+ <bindstofield>installedpackages->dspam->config->0->dspam-profile</bindstofield>
+ <description>
+ &lt;center&gt;
+If you don't want to tinker with your existing mail server setup, DSPAM can
+be combined with one of a few open source programs designed to act as a POP3
+proxy. This means spam is filtered whenever the user checks their mail,
+rather than when it is delivered. The benefit to this is that you can set up
+a small machine on your network that will connect to your existing mail server,
+so no integration is needed. It also allows your users to arbitarily point their
+mail client at it if they desire filtering. The drawback to this approach is
+that the POP3 protocol has no way to tell the mail client that a message is
+spam, and so the user will have to download the spam (tagged, of course).
+ &lt;/center&gt;
+ </description>
+ <value>pop</value>
+ <dontdisplayname />
+ <typehint>&lt;center&gt;&lt;img src=&quot;/wizards/dspam-pop-proxy.png&quot; alt=&quot;DSPAM will be invoked by a POP3 proxy&quot; border=&quot;0&quot; /&gt;&lt;/center&gt;</typehint>
+ </field>
+ <field>
+ <name>dspamprofile</name>
+ <type>radio</type>
+ <bindstofield>installedpackages->dspam->config->0->dspam-profile</bindstofield>
+ <description>
+ &lt;center&gt;
+Newer versions of DSPAM have seen features that allow it to function more
+easily as an SMTP relay. An SMTP relay sits in front of your existing mail
+server (requiring no integration). To use an SMTP relay, the MX records for
+your domains are repointed to the relay machine running DSPAM. DSPAM then
+relays the good (and optionally bad) mail to the existing SMTP server. This
+allows you to use DSPAM with even a Windows-based destination mail server
+as no integration is necessary. See doc/relay.txt for one example of how to
+do this with Postfix.
+ &lt;/center&gt;
+ </description>
+ <value>smtp</value>
+ <dontdisplayname />
+ <typehint>&lt;center&gt;&lt;img src=&quot;/wizards/dspam-smtp-relay.png&quot; alt=&quot;DSPAM acts as a SMTP realy&quot; border=&quot;0&quot; /&gt;&lt;/center&gt;</typehint>
+ </field>
+ <field>
+ <name>Next</name>
+ <type>submit</type>
+ </field>
+ </fields>
+ <stepsubmitphpaction>
+ <![CDATA[
+ if($_POST['dspamprofile'] != "") {
+
+ /* set default trusted users */
+ $config['installedpackages']['dspam']['config'][0]['tuser'][0]['name'] = "root";
+ $config['installedpackages']['dspam']['config'][0]['tuser'][0]['descr'] = "desc";
+ $config['installedpackages']['dspam']['config'][0]['tuser'][1]['name'] = "mail";
+ $config['installedpackages']['dspam']['config'][0]['tuser'][1]['descr'] = "desc";
+ $config['installedpackages']['dspam']['config'][0]['tuser'][2]['name'] = "mailnull";
+ $config['installedpackages']['dspam']['config'][0]['tuser'][2]['descr'] = "desc";
+ $config['installedpackages']['dspam']['config'][0]['tuser'][3]['name'] = "smmsp";
+ $config['installedpackages']['dspam']['config'][0]['tuser'][3]['descr'] = "desc";
+ $config['installedpackages']['dspam']['config'][0]['tuser'][4]['name'] = "daemon";
+ $config['installedpackages']['dspam']['config'][0]['tuser'][4]['descr'] = "desc";
+ /* set default features */
+ $config['installedpackages']['dspam']['config'][0]['feature'][0]['name'] = "chained";
+ $config['installedpackages']['dspam']['config'][0]['feature'][0]['descr'] = "desc";
+ $config['installedpackages']['dspam']['config'][0]['feature'][1]['name'] = "whitelist";
+ $config['installedpackages']['dspam']['config'][0]['feature'][1]['descr'] = "desc";
+ /* set default algorithms */
+ $config['installedpackages']['dspam']['config'][0]['algorithm'][0]['name'] = "graham";
+ $config['installedpackages']['dspam']['config'][0]['algorithm'][0]['descr'] = "desc";
+ $config['installedpackages']['dspam']['config'][0]['algorithm'][1]['name'] = "burton";
+ $config['installedpackages']['dspam']['config'][0]['algorithm'][1]['descr'] = "desc";
+ /* set default prefs */
+ $config['installedpackages']['dspam']['config'][0]['preference'][0]['value'] = "\"spamAction=quarantine\"";
+ $config['installedpackages']['dspam']['config'][0]['preference'][0]['descr'] = "desc";
+ $config['installedpackages']['dspam']['config'][0]['preference'][1]['value'] = "\"signatureLocation=message\"";
+ $config['installedpackages']['dspam']['config'][0]['preference'][1]['descr'] = "desc";
+ $config['installedpackages']['dspam']['config'][0]['preference'][2]['value'] = "\"showFactors=on\"";
+ $config['installedpackages']['dspam']['config'][0]['preference'][2]['descr'] = "desc";
+ /* set default overrides */
+ $config['installedpackages']['dspam']['config'][0]['override'][0]['value'] = "trainingMode";
+ $config['installedpackages']['dspam']['config'][0]['override'][0]['descr'] = "desc";
+ $config['installedpackages']['dspam']['config'][0]['override'][1]['value'] = "spamAction spamSubject";
+ $config['installedpackages']['dspam']['config'][0]['override'][1]['descr'] = "desc";
+ $config['installedpackages']['dspam']['config'][0]['override'][2]['value'] = "statisticalSedation";
+ $config['installedpackages']['dspam']['config'][0]['override'][2]['descr'] = "desc";
+ $config['installedpackages']['dspam']['config'][0]['override'][3]['value'] = "enableBNR";
+ $config['installedpackages']['dspam']['config'][0]['override'][3]['descr'] = "desc";
+ $config['installedpackages']['dspam']['config'][0]['override'][4]['value'] = "enableWhitelist";
+ $config['installedpackages']['dspam']['config'][0]['override'][4]['descr'] = "desc";
+ $config['installedpackages']['dspam']['config'][0]['override'][5]['value'] = "signatureLocation";
+ $config['installedpackages']['dspam']['config'][0]['override'][5]['descr'] = "desc";
+ $config['installedpackages']['dspam']['config'][0]['override'][6]['value'] = "showFactors";
+ $config['installedpackages']['dspam']['config'][0]['override'][6]['descr'] = "desc";
+ $config['installedpackages']['dspam']['config'][0]['override'][7]['value'] = "optIn optOut";
+ $config['installedpackages']['dspam']['config'][0]['override'][7]['descr'] = "desc";
+ $config['installedpackages']['dspam']['config'][0]['override'][8]['value'] = "whitelistThreshold";
+ $config['installedpackages']['dspam']['config'][0]['override'][8]['descr'] = "desc";
+
+ if($_POST['dspamprofile'] == "lda" || $_POST['dspamprofile'] == "pop") {
+ $config['installedpackages']['dspam']['config'][0]['tdelivery-agent'] = "mail";
+ /* TCP/IP based deliver is not needed */
+ unset($config['installedpackages']['dspam']['config'][0]['tcpip-delivery']);
+ unset($config['installedpackages']['dspam']['config'][0]['tcpip-delivery-host']);
+ unset($config['installedpackages']['dspam']['config'][0]['tcpip-delivery-port']);
+ unset($config['installedpackages']['dspam']['config'][0]['tcpip-delivery-ident']);
+ unset($config['installedpackages']['dspam']['config'][0]['tcpip-delivery-proto']);
+ $config['installedpackages']['dspam']['config'][0]['delivery-onfail'] = "error";
+
+ /* We will asume that the user is going to use the dspam and not the dspamc
+ * binary. Hence we are unsetting server/client settings.
+ */
+ unset($config['installedpackages']['dspam']['config'][0]['dspam-server-port']);
+ unset($config['installedpackages']['dspam']['config'][0]['dspam-server-queue-size']);
+ unset($config['installedpackages']['dspam']['config'][0]['dspam-server-pid']);
+ unset($config['installedpackages']['dspam']['config'][0]['dspam-server-mode']);
+ unset($config['installedpackages']['dspam']['config'][0]['dspam-server-params']);
+ unset($config['installedpackages']['dspam']['config'][0]['dspam-server-id']);
+ unset($config['installedpackages']['dspam']['config'][0]['dspam-server-socket']);
+ /* Client */
+ unset($config['installedpackages']['dspam']['config'][0]['dspam-client-enable']);
+ unset($config['installedpackages']['dspam']['config'][0]['dspam-client-host']);
+ unset($config['installedpackages']['dspam']['config'][0]['dspam-client-port']);
+ unset($config['installedpackages']['dspam']['config'][0]['dspam-client-id']);
+ } else if($_POST['dspamprofile'] == "smtp") {
+ /* TCP/IP based deliver is not needed */
+ $config['installedpackages']['dspam']['config'][0]['tcpip-delivery'] = "on";
+ $config['installedpackages']['dspam']['config'][0]['tcpip-delivery-host'] = "127.0.0.1";
+ $config['installedpackages']['dspam']['config'][0]['tcpip-delivery-port'] = "25";
+ $config['installedpackages']['dspam']['config'][0]['tcpip-delivery-ident'] = "localhost";
+ $config['installedpackages']['dspam']['config'][0]['tcpip-delivery-proto'] = "smtp";
+ $config['installedpackages']['dspam']['config'][0]['delivery-onfail'] = "error";
+
+ /* We will asume that the user is going to use the dspam and not the dspamc
+ * binary. Hence we are unsetting server/client settings.
+ */
+ $config['installedpackages']['dspam']['config'][0]['dspam-server-port'] = "24";
+ $config['installedpackages']['dspam']['config'][0]['dspam-server-queue-size'] = "32";
+ $config['installedpackages']['dspam']['config'][0]['dspam-server-pid'] = "/var/run/dspam/dspam.pid";
+ $config['installedpackages']['dspam']['config'][0]['dspam-server-mode'] = "standard";
+ $config['installedpackages']['dspam']['config'][0]['dspam-server-params'] = "--deliver=innocent -d %u";
+ $config['installedpackages']['dspam']['config'][0]['dspam-server-id'] = "localhost";
+ $config['installedpackages']['dspam']['config'][0]['dspam-server-socket'] = "/var/run/dspam/dspam.sock";
+ /* server passwords */
+ $config['installedpackages']['dspam']['config'][0]['server-pwd'][0]['value'] = "secret";
+ $config['installedpackages']['dspam']['config'][0]['server-pwd'][0]['descr'] = "desc";
+ $config['installedpackages']['dspam']['config'][0]['server-pwd'][1]['value'] = "password";
+ $config['installedpackages']['dspam']['config'][0]['server-pwd'][1]['descr'] = "desc";
+ /* Client */
+ $config['installedpackages']['dspam']['config'][0]['dspam-client-enable'] = "on";
+ $config['installedpackages']['dspam']['config'][0]['dspam-client-host'] = "/tmp/dspam.sock";
+ $config['installedpackages']['dspam']['config'][0]['dspam-client-port'] = "24";
+ $config['installedpackages']['dspam']['config'][0]['dspam-client-id'] = "secret@Relay1";
+ }
+
+ write_config();
+ }
+ ]]>
+ </stepsubmitphpaction>
+</step>
+<step>
+ <id>3</id>
+ <includefile>dspam.inc</includefile>
+ <title>Database Settings</title>
+ <description>
+ On this screen you will set the storage driver type that will be used to store
+ DSPAM tokens. After having completed this wizard you have to configure the
+ database that you did select herein.
+ </description>
+ <fields>
+ <field>
+ <name>storagedriver</name>
+ <type>select</type>
+ <bindstofield>installedpackages->dspam->config->0->storage-driver</bindstofield>
+ <description>Specifies the storage driver backend (library) to use.</description>
+ <default_value>mysql</default_value>
+ <onchange>toggleDBSettings();</onchange>
+ <size>1</size>
+ <options>
+ <option>
+ <name>mysql</name>
+ <value>mysql</value>
+ </option>
+ <option>
+ <name>sqlite</name>
+ <value>sqlite</value>
+ </option>
+ <option>
+ <name>bdb</name>
+ <value>bdb</value>
+ </option>
+ <option>
+ <name>pgsql</name>
+ <value>pgsql</value>
+ </option>
+ <option>
+ <name>oracle</name>
+ <value>oracle</value>
+ </option>
+ <option>
+ <name>hash</name>
+ <value>hash</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <name>msqlserver</name>
+ <type>input</type>
+ <bindstofield>installedpackages->dspam->config->0->dbsettings->0->mysql-server</bindstofield>
+ <description>Either a reference to a Unix domain socket or a reference to a specific host.</description>
+ <default_value>/tmp/mysql.sock</default_value>
+ <validate>^[a-z0-9.|/]+$</validate>
+ <message>Server name field is invalid</message>
+ <required />
+ </field>
+ <field>
+ <name>msqlport</name>
+ <type>input</type>
+ <bindstofield>installedpackages->dspam->config->0->dbsettings->0->mysql-port</bindstofield>
+ <description>Use this variable if you are going to a MySQL server instance using TCP/IP instead of a socket connection.</description>
+ <default_value>3306</default_value>
+ <validate>^[0-9]+$</validate>
+ <message>Port field is invalid</message>
+ <required />
+ </field>
+ <field>
+ <name>msqluser</name>
+ <type>input</type>
+ <bindstofield>installedpackages->dspam->config->0->dbsettings->0->mysql-user</bindstofield>
+ <description>Username, that will be used to connect to a MySQL server instance.</description>
+ <default_value>dspam</default_value>
+ <required />
+ </field>
+ <field>
+ <name>msqlpwd</name>
+ <type>input</type>
+ <bindstofield>installedpackages->dspam->config->0->dbsettings->0->mysql-password</bindstofield>
+ <description>Password, that will be used to connect to a MySQL server instance.</description>
+ <default_value>dspam</default_value>
+ <required />
+ </field>
+ <field>
+ <name>msqldb</name>
+ <type>input</type>
+ <bindstofield>installedpackages->dspam->config->0->dbsettings->0->mysql-database</bindstofield>
+ <description>Database name, that contains DSPAM data.</description>
+ <default_value>dspam</default_value>
+ <required />
+ </field>
+ <field>
+ <name>msqlcomp</name>
+ <type>checkbox</type>
+ <bindstofield>installedpackages->dspam->config->0->dbsettings->0->mysql-compress</bindstofield>
+ <description>Indicates whether communication data between DSPAM and MySQL should be compressed.</description>
+ <default_value>on</default_value>
+ </field>
+ <field>
+ <name>msqlsuqt</name>
+ <type>checkbox</type>
+ <bindstofield>installedpackages->dspam->config->0->dbsettings->0->mysql-squote</bindstofield>
+ <description>Use this if you have the 4.1 quote bug (see doc/mysql.txt).</description>
+ </field>
+ <field>
+ <name>msqlccache</name>
+ <type>input</type>
+ <bindstofield>installedpackages->dspam->config->0->dbsettings->0->mysql-ccache</bindstofield>
+ <description>Conection cache default set to 10.</description>
+ <default_value>10</default_value>
+ <validate>^[0-9]+$</validate>
+ <message>Connection cache field is invalid</message>
+ <required />
+ </field>
+ <field>
+ <name>msqluid</name>
+ <type>checkbox</type>
+ <bindstofield>installedpackages->dspam->config->0->dbsettings->0->mysql-uid</bindstofield>
+ <description>Insert user id into the DSPAM signature.</description>
+ <default_value>on</default_value>
+ </field>
+ <field>
+ <name>slitepr</name>
+ <type>input</type>
+ <bindstofield>installedpackages->dspam->config->0->dbsettings->0->sqlite-pragma</bindstofield>
+ <description>A particular SQLite pragma command to be used.</description>
+ </field>
+ <field>
+ <name>pgserver</name>
+ <type>input</type>
+ <bindstofield>installedpackages->dspam->config->0->dbsettings->0->pgsql-server</bindstofield>
+ <description>A reference to a specific host that is running a PostgreSQL instance.</description>
+ <default_value>127.0.0.1</default_value>
+ <validate>^[a-z0-9.|-]+$</validate>
+ <message>Server name field is invalid</message>
+ <required />
+ </field>
+ <field>
+ <name>pgport</name>
+ <type>input</type>
+ <bindstofield>installedpackages->dspam->config->0->dbsettings->0->pgsql-port</bindstofield>
+ <description>A number that represents the port a specific PostgreSQL instance is listening to.</description>
+ <default_value>5432</default_value>
+ <validate>^[0-9]+$</validate>
+ <message>Port field is invalid</message>
+ <required />
+ </field>
+ <field>
+ <name>pguser</name>
+ <type>input</type>
+ <bindstofield>installedpackages->dspam->config->0->dbsettings->0->pgsql-user</bindstofield>
+ <description>Username, that will be used to connect to a PostgreSQL server instance.</description>
+ <default_value>dspam</default_value>
+ <required />
+ </field>
+ <field>
+ <name>pgpwd</name>
+ <type>input</type>
+ <bindstofield>installedpackages->dspam->config->0->dbsettings->0->pgsql-password</bindstofield>
+ <description>Password, that will be used to connect to a PostgreSQL server instance.</description>
+ <default_value>dspam</default_value>
+ <required />
+ </field>
+ <field>
+ <name>pgdb</name>
+ <type>input</type>
+ <bindstofield>installedpackages->dspam->config->0->dbsettings->0->pgsql-database</bindstofield>
+ <description>Database name, that contains DSPAM data.</description>
+ <default_value>dspam</default_value>
+ <required />
+ </field>
+ <field>
+ <name>pgccache</name>
+ <type>input</type>
+ <bindstofield>installedpackages->dspam->config->0->dbsettings->0->pgsql-ccache</bindstofield>
+ <description>Conection cache default set to 3.</description>
+ <default_value>3</default_value>
+ <validate>^[0-9]+$</validate>
+ <message>Connection cache field is invalid</message>
+ <required />
+ </field>
+ <field>
+ <name>pguid</name>
+ <type>checkbox</type>
+ <bindstofield>installedpackages->dspam->config->0->dbsettings->0->pgsql-uid</bindstofield>
+ <description>Insert user id into the DSPAM signature.</description>
+ <default_value>on</default_value>
+ </field>
+ <field>
+ <name>oraserver</name>
+ <type>input</type>
+ <bindstofield>installedpackages->dspam->config->0->dbsettings->0->ora-server</bindstofield>
+ <description>A reference to a specific host that is running an Oracle database instance.</description>
+ <size>50</size>
+ <default_value>&quot;(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=127.0.0.1)(PORT=1521))(CONNECT_DATA=(SID=PROD)))&quot;</default_value>
+ <required />
+ </field>
+ <field>
+ <name>orauser</name>
+ <type>input</type>
+ <bindstofield>installedpackages->dspam->config->0->dbsettings->0->ora-user</bindstofield>
+ <description>Username, that will be used to connect to a Oracle database server instance.</description>
+ <default_value>dspam</default_value>
+ <required />
+ </field>
+ <field>
+ <name>orapwd</name>
+ <type>input</type>
+ <bindstofield>installedpackages->dspam->config->0->dbsettings->0->ora-password</bindstofield>
+ <description>Password, that will be used to connect to a Oracle database server instance.</description>
+ <default_value>dspam</default_value>
+ <required />
+ </field>
+ <field>
+ <name>orasch</name>
+ <type>input</type>
+ <bindstofield>installedpackages->dspam->config->0->dbsettings->0->ora-schema</bindstofield>
+ <description>Schema name, that contains DSPAM data.</description>
+ <default_value>dspam</default_value>
+ <required />
+ </field>
+ <field>
+ <name>hsrmax</name>
+ <type>input</type>
+ <bindstofield>installedpackages->dspam->config->0->dbsettings->0->hash-rec-max</bindstofield>
+ <description>Default number of records to create in the initial segment when building hash files.</description>
+ <default_value>98317</default_value>
+ <validate>^[0-9]+$</validate>
+ <message>Default number of record field is invalid</message>
+ <required />
+ </field>
+ <field>
+ <name>hsatex</name>
+ <type>checkbox</type>
+ <bindstofield>installedpackages->dspam->config->0->dbsettings->0->hash-auto-ex</bindstofield>
+ <description>Autoextend hash databases when they fill up. This allows them to continue to train by adding extents (extensions) to the file.</description>
+ <default_value>on</default_value>
+ <required />
+ </field>
+ <field>
+ <name>hsmxex</name>
+ <type>input</type>
+ <bindstofield>installedpackages->dspam->config->0->dbsettings->0->hash-max-ext</bindstofield>
+ <description>The maximum number of extents that may be created in a single hash file.</description>
+ <default_value>0</default_value>
+ <validate>^[0-9]+$</validate>
+ <message>Default number of record field is invalid</message>
+ <required />
+ </field>
+ <field>
+ <name>hsexsz</name>
+ <type>input</type>
+ <bindstofield>installedpackages->dspam->config->0->dbsettings->0->hash-ext-size</bindstofield>
+ <description>The record size for newly created extents.</description>
+ <default_value>49157</default_value>
+ <validate>^[0-9]+$</validate>
+ <message>Default number of record field is invalid</message>
+ <required />
+ </field>
+ <field>
+ <name>hsmxse</name>
+ <type>input</type>
+ <bindstofield>installedpackages->dspam->config->0->dbsettings->0->hash-max-seek</bindstofield>
+ <description>The maximum number of records to seek to insert a new record before failing or adding a new extent.</description>
+ <default_value>100</default_value>
+ <validate>^[0-9]+$</validate>
+ <message>Default number of record field is invalid</message>
+ <required />
+ </field>
+ <field>
+ <name>hsccus</name>
+ <type>input</type>
+ <bindstofield>installedpackages->dspam->config->0->dbsettings->0->hash-co-user</bindstofield>
+ <description>If you are using a single, stateful hash database in daemon mode, specifying a concurrent user will cause the user to be permanently mapped into memory and shared via rwlocks.</description>
+ <default_value>user</default_value>
+ <required />
+ </field>
+ <field>
+ <name>hscoca</name>
+ <type>input</type>
+ <bindstofield>installedpackages->dspam->config->0->dbsettings->0->hash-co-cache</bindstofield>
+ <description>If running in daemon mode, this is the max # of concurrent connections that will be supported.</description>
+ <default_value>10</default_value>
+ <validate>^[0-9]+$</validate>
+ <message>Default number of record field is invalid</message>
+ <required />
+ </field>
+ <field>
+ <name>Next</name>
+ <type>submit</type>
+ </field>
+ </fields>
+ <stepsubmitphpaction>
+ <![CDATA[
+ if ($_POST['storagedriver'] == "mysql") {
+ /* ============================================================================================= */
+ /* == SQLite == */
+ /* ============================================================================================= */
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['sqlite-pragma']);
+ /* ============================================================================================= */
+ /* == PostgreSQL == */
+ /* ============================================================================================= */
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['pgsql-server']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['pgsql-port']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['pgsql-user']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['pgsql-password']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['pgsql-database']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['pgsql-ccache']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['pgsql-uid']);
+ /* ============================================================================================= */
+ /* == Oracle == */
+ /* ============================================================================================= */
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['ora-server']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['ora-user']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['ora-password']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['ora-schema']);
+ /* ============================================================================================= */
+ /* == Hash == */
+ /* ============================================================================================= */
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['hash-rec-max']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['hash-auto-ex']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['hash-max-ext']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['hash-ext-size']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['hash-max-seek']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['hash-co-user']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['hash-co-cache']);
+ } else if ($_POST['storagedriver'] == "sqlite") {
+ /* ============================================================================================= */
+ /* == MySQL == */
+ /* ============================================================================================= */
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['mysql-server']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['mysql-port']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['mysql-user']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['mysql-password']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['mysql-database']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['mysql-compress']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['mysql-squote']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['mysql-ccache']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['mysql-uid']);
+ /* ============================================================================================= */
+ /* == PostgreSQL == */
+ /* ============================================================================================= */
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['pgsql-server']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['pgsql-port']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['pgsql-user']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['pgsql-password']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['pgsql-database']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['pgsql-ccache']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['pgsql-uid']);
+ /* ============================================================================================= */
+ /* == Oracle == */
+ /* ============================================================================================= */
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['ora-server']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['ora-user']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['ora-password']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['ora-schema']);
+ /* ============================================================================================= */
+ /* == Hash == */
+ /* ============================================================================================= */
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['hash-rec-max']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['hash-auto-ex']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['hash-max-ext']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['hash-ext-size']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['hash-max-seek']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['hash-co-user']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['hash-co-cache']);
+ } else if ($_POST['storagedriver'] == "bdb") {
+ /* NOP */
+ } else if ($_POST['storagedriver'] == "pgsql") {
+ /* ============================================================================================= */
+ /* == MySQL == */
+ /* ============================================================================================= */
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['mysql-server']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['mysql-port']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['mysql-user']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['mysql-password']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['mysql-database']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['mysql-compress']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['mysql-squote']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['mysql-ccache']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['mysql-uid']);
+ /* ============================================================================================= */
+ /* == SQLite == */
+ /* ============================================================================================= */
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['sqlite-pragma']);
+ /* ============================================================================================= */
+ /* == Oracle == */
+ /* ============================================================================================= */
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['ora-server']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['ora-user']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['ora-password']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['ora-schema']);
+ /* ============================================================================================= */
+ /* == Hash == */
+ /* ============================================================================================= */
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['hash-rec-max']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['hash-auto-ex']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['hash-max-ext']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['hash-ext-size']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['hash-max-seek']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['hash-co-user']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['hash-co-cache']);
+ } else if ($_POST['storagedriver'] == "oracle") {
+ /* ============================================================================================= */
+ /* == MySQL == */
+ /* ============================================================================================= */
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['mysql-server']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['mysql-port']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['mysql-user']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['mysql-password']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['mysql-database']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['mysql-compress']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['mysql-squote']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['mysql-ccache']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['mysql-uid']);
+ /* ============================================================================================= */
+ /* == SQLite == */
+ /* ============================================================================================= */
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['sqlite-pragma']);
+ /* ============================================================================================= */
+ /* == PostgreSQL == */
+ /* ============================================================================================= */
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['pgsql-server']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['pgsql-port']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['pgsql-user']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['pgsql-password']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['pgsql-database']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['pgsql-ccache']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['pgsql-uid']);
+ /* ============================================================================================= */
+ /* == Hash == */
+ /* ============================================================================================= */
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['hash-rec-max']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['hash-auto-ex']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['hash-max-ext']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['hash-ext-size']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['hash-max-seek']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['hash-co-user']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['hash-co-cache']);
+ } else if ($_POST['storagedriver'] == "hash") {
+ /* ============================================================================================= */
+ /* == MySQL == */
+ /* ============================================================================================= */
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['mysql-server']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['mysql-port']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['mysql-user']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['mysql-password']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['mysql-database']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['mysql-compress']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['mysql-squote']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['mysql-ccache']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['mysql-uid']);
+ /* ============================================================================================= */
+ /* == SQLite == */
+ /* ============================================================================================= */
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['sqlite-pragma']);
+ /* ============================================================================================= */
+ /* == PostgreSQL == */
+ /* ============================================================================================= */
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['pgsql-server']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['pgsql-port']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['pgsql-user']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['pgsql-password']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['pgsql-database']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['pgsql-ccache']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['pgsql-uid']);
+ /* ============================================================================================= */
+ /* == Oracle == */
+ /* ============================================================================================= */
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['ora-server']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['ora-user']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['ora-password']);
+ unset($config['installedpackages']['dspam']['config'][0]['dbsettings'][0]['ora-schema']);
+ }
+ ]]>
+ </stepsubmitphpaction>
+ <javascriptafterformdisplay>
+ <![CDATA[
+ function toggleDBSettings(idx) {
+ if (idx)
+ idx = idx;
+ else
+ idx = document.iform.storagedriver.selectedIndex;
+
+ switch (idx) {
+ case 0: /* mysql */
+ /* mysql specifics */
+ trNode = document.iform.msqlserver.parentNode.parentNode;
+ trNode.style.display = "table-row";
+ trNode = document.iform.msqlport.parentNode.parentNode;
+ trNode.style.display = "table-row";
+ trNode = document.iform.msqluser.parentNode.parentNode;
+ trNode.style.display = "table-row";
+ trNode = document.iform.msqlpwd.parentNode.parentNode;
+ trNode.style.display = "table-row";
+ trNode = document.iform.msqldb.parentNode.parentNode;
+ trNode.style.display = "table-row";
+ trNode = document.iform.msqlcomp.parentNode.parentNode;
+ trNode.style.display = "table-row";
+ trNode = document.iform.msqlsuqt.parentNode.parentNode;
+ trNode.style.display = "table-row";
+ trNode = document.iform.msqlccache.parentNode.parentNode;
+ trNode.style.display = "table-row";
+ trNode = document.iform.msqluid.parentNode.parentNode;
+ trNode.style.display = "table-row";
+ /* sqlite specifics */
+ trNode = document.iform.slitepr.parentNode.parentNode;
+ trNode.style.display = "none";
+ /* pgsql specifics */
+ trNode = document.iform.pgserver.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.pgport.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.pguser.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.pgpwd.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.pgdb.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.pgccache.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.pguid.parentNode.parentNode;
+ trNode.style.display = "none";
+ /* oracle specifics */
+ trNode = document.iform.oraserver.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.orauser.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.orapwd.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.orasch.parentNode.parentNode;
+ trNode.style.display = "none";
+ /* hash specifics */
+ trNode = document.iform.hsrmax.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.hsatex.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.hsmxex.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.hsexsz.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.hsmxse.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.hsccus.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.hscoca.parentNode.parentNode;
+ trNode.style.display = "none";
+ break;
+ case 1: /* sqlite */
+ /* mysql specifics */
+ trNode = document.iform.msqlserver.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.msqlport.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.msqluser.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.msqlpwd.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.msqldb.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.msqlcomp.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.msqlsuqt.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.msqlccache.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.msqluid.parentNode.parentNode;
+ trNode.style.display = "none";
+ /* sqlite specifics */
+ trNode = document.iform.slitepr.parentNode.parentNode;
+ trNode.style.display = "table-row";
+ /* pgsql specifics */
+ trNode = document.iform.pgserver.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.pgport.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.pguser.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.pgpwd.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.pgdb.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.pgccache.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.pguid.parentNode.parentNode;
+ trNode.style.display = "none";
+ /* oracle specifics */
+ trNode = document.iform.oraserver.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.orauser.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.orapwd.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.orasch.parentNode.parentNode;
+ trNode.style.display = "none";
+ /* hash specifics */
+ trNode = document.iform.hsrmax.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.hsatex.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.hsmxex.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.hsexsz.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.hsmxse.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.hsccus.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.hscoca.parentNode.parentNode;
+ trNode.style.display = "none";
+ break;
+ case 2: /* bdb */
+ /* mysql specifics */
+ trNode = document.iform.msqlserver.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.msqlport.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.msqluser.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.msqlpwd.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.msqldb.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.msqlcomp.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.msqlsuqt.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.msqlccache.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.msqluid.parentNode.parentNode;
+ trNode.style.display = "none";
+ /* sqlite specifics */
+ trNode = document.iform.slitepr.parentNode.parentNode;
+ trNode.style.display = "none";
+ /* pgsql specifics */
+ trNode = document.iform.pgserver.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.pgport.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.pguser.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.pgpwd.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.pgdb.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.pgccache.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.pguid.parentNode.parentNode;
+ trNode.style.display = "none";
+ /* oracle specifics */
+ trNode = document.iform.oraserver.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.orauser.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.orapwd.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.orasch.parentNode.parentNode;
+ trNode.style.display = "none";
+ /* hash specifics */
+ trNode = document.iform.hsrmax.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.hsatex.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.hsmxex.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.hsexsz.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.hsmxse.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.hsccus.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.hscoca.parentNode.parentNode;
+ trNode.style.display = "none";
+ break;
+ case 3: /* pgsql */
+ /* mysql specifics */
+ trNode = document.iform.msqlserver.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.msqlport.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.msqluser.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.msqlpwd.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.msqldb.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.msqlcomp.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.msqlsuqt.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.msqlccache.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.msqluid.parentNode.parentNode;
+ trNode.style.display = "none";
+ /* sqlite specifics */
+ trNode = document.iform.slitepr.parentNode.parentNode;
+ trNode.style.display = "none";
+ /* pgsql specifics */
+ trNode = document.iform.pgserver.parentNode.parentNode;
+ trNode.style.display = "table-row";
+ trNode = document.iform.pgport.parentNode.parentNode;
+ trNode.style.display = "table-row";
+ trNode = document.iform.pguser.parentNode.parentNode;
+ trNode.style.display = "table-row";
+ trNode = document.iform.pgpwd.parentNode.parentNode;
+ trNode.style.display = "table-row";
+ trNode = document.iform.pgdb.parentNode.parentNode;
+ trNode.style.display = "table-row";
+ trNode = document.iform.pgccache.parentNode.parentNode;
+ trNode.style.display = "table-row";
+ trNode = document.iform.pguid.parentNode.parentNode;
+ trNode.style.display = "table-row";
+ /* oracle specifics */
+ trNode = document.iform.oraserver.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.orauser.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.orapwd.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.orasch.parentNode.parentNode;
+ trNode.style.display = "none";
+ /* hash specifics */
+ trNode = document.iform.hsrmax.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.hsatex.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.hsmxex.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.hsexsz.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.hsmxse.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.hsccus.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.hscoca.parentNode.parentNode;
+ trNode.style.display = "none";
+ break;
+ case 4: /* oracle */
+ /* mysql specifics */
+ trNode = document.iform.msqlserver.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.msqlport.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.msqluser.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.msqlpwd.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.msqldb.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.msqlcomp.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.msqlsuqt.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.msqlccache.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.msqluid.parentNode.parentNode;
+ trNode.style.display = "none";
+ /* sqlite specifics */
+ trNode = document.iform.slitepr.parentNode.parentNode;
+ trNode.style.display = "none";
+ /* pgsql specifics */
+ trNode = document.iform.pgserver.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.pgport.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.pguser.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.pgpwd.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.pgdb.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.pgccache.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.pguid.parentNode.parentNode;
+ trNode.style.display = "none";
+ /* oracle specifics */
+ trNode = document.iform.oraserver.parentNode.parentNode;
+ trNode.style.display = "table-row";
+ trNode = document.iform.orauser.parentNode.parentNode;
+ trNode.style.display = "table-row";
+ trNode = document.iform.orapwd.parentNode.parentNode;
+ trNode.style.display = "table-row";
+ trNode = document.iform.orasch.parentNode.parentNode;
+ trNode.style.display = "table-row";
+ /* hash specifics */
+ trNode = document.iform.hsrmax.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.hsatex.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.hsmxex.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.hsexsz.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.hsmxse.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.hsccus.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.hscoca.parentNode.parentNode;
+ trNode.style.display = "none";
+ break;
+ case 5: /* hash */
+ /* mysql specifics */
+ trNode = document.iform.msqlserver.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.msqlport.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.msqluser.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.msqlpwd.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.msqldb.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.msqlcomp.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.msqlsuqt.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.msqlccache.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.msqluid.parentNode.parentNode;
+ trNode.style.display = "none";
+ /* sqlite specifics */
+ trNode = document.iform.slitepr.parentNode.parentNode;
+ trNode.style.display = "none";
+ /* pgsql specifics */
+ trNode = document.iform.pgserver.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.pgport.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.pguser.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.pgpwd.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.pgdb.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.pgccache.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.pguid.parentNode.parentNode;
+ trNode.style.display = "none";
+ /* oracle specifics */
+ trNode = document.iform.oraserver.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.orauser.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.orapwd.parentNode.parentNode;
+ trNode.style.display = "none";
+ trNode = document.iform.orasch.parentNode.parentNode;
+ trNode.style.display = "none";
+ /* hash specifics */
+ trNode = document.iform.hsrmax.parentNode.parentNode;
+ trNode.style.display = "table-row";
+ trNode = document.iform.hsatex.parentNode.parentNode;
+ trNode.style.display = "table-row";
+ trNode = document.iform.hsmxex.parentNode.parentNode;
+ trNode.style.display = "table-row";
+ trNode = document.iform.hsexsz.parentNode.parentNode;
+ trNode.style.display = "table-row";
+ trNode = document.iform.hsmxse.parentNode.parentNode;
+ trNode.style.display = "table-row";
+ trNode = document.iform.hsccus.parentNode.parentNode;
+ trNode.style.display = "table-row";
+ trNode = document.iform.hscoca.parentNode.parentNode;
+ trNode.style.display = "table-row";
+ break;
+ }
+ }
+
+ toggleDBSettings(0);
+ ]]>
+ </javascriptafterformdisplay>
+</step>
+<step>
+ <id>4</id>
+ <includefile>dspam.inc</includefile>
+ <title>Delivery Settings</title>
+ <description>
+ On this page you will specify how DSPAM should deliver email messages to
+ their final destination. This could be either a local delivery method or
+ a TCP/IP based delivery method.
+ </description>
+ <fields>
+ <field>
+ <name>dagent</name>
+ <description>Specifies the local delivery agent DSPAM should call when delivering mail as a trusted user.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>procmail</name>
+ <value>procmail</value>
+ </option>
+ <option>
+ <name>mail</name>
+ <value>mail</value>
+ </option>
+ <option>
+ <name>mail.local</name>
+ <value>mail.local</value>
+ </option>
+ <option>
+ <name>deliver</name>
+ <value>deliver</value>
+ </option>
+ <option>
+ <name>maildrop</name>
+ <value>maildrop</value>
+ </option>
+ <option>
+ <name>exim</name>
+ <value>exim</value>
+ </option>
+ </options>
+ <bindstofield>installedpackages->dspam->config->0->tdelivery-agent</bindstofield>
+ </field>
+ <field>
+ <donotdisable>true</donotdisable>
+ <name>dspamc</name>
+ <description>Use &lt;code&gt;dspamc&lt;/code&gt; instead of &lt;code&gt;dspam&lt;/code&gt; to locally deliver mails from the MTA to the user's mailbox (this pulls in DSPAM client/server settings).</description>
+ <type>checkbox</type>
+ <bindstofield>installedpackages->dspam->config->0->thin-client</bindstofield>
+ </field>
+ <field>
+ <donotdisable>true</donotdisable>
+ <name>tcpipdel</name>
+ <description>Use TCP/IP based delivery. This option needs to be ticked if you are going to deliver via LMTP or SMTP.</description>
+ <type>checkbox</type>
+ <bindstofield>installedpackages->dspam->config->0->tcpip-delivery</bindstofield>
+ <enablefields>dhost,dport,dident,delproto</enablefields>
+ </field>
+ <field>
+ <name>dhost</name>
+ <type>input</type>
+ <donotdisable>false</donotdisable>
+ <bindstofield>installedpackages->dspam->config->0->tcpip-delivery-host</bindstofield>
+ <description>Alternatively, you may wish to use SMTP or LMTP delivery to deliver your message to the mail server.</description>
+ <validate>^[a-z0-9.|-]+$</validate>
+ <message>Host name field is invalid</message>
+ </field>
+ <field>
+ <name>dport</name>
+ <type>input</type>
+ <bindstofield>installedpackages->dspam->config->0->tcpip-delivery-port</bindstofield>
+ <description>Port number of a particular host.</description>
+ <validate>^[0-9]+$</validate>
+ <message>Port field is invalid</message>
+ </field>
+ <field>
+ <name>dident</name>
+ <type>input</type>
+ <bindstofield>installedpackages->dspam->config->0->tcpip-delivery-ident</bindstofield>
+ <description>A particular identification string.</description>
+ </field>
+ <field>
+ <name>delproto</name>
+ <description>A particular protocol typ. Either SMTP or LMTP.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>ltmp</name>
+ <value>lmtp</value>
+ </option>
+ <option>
+ <name>smtp</name>
+ <value>smtp</value>
+ </option>
+ </options>
+ <bindstofield>installedpackages->dspam->config->0->tcpip-delivery-proto</bindstofield>
+ </field>
+ <field>
+ <name>onfail</name>
+ <description>What to do if local delivery or quarantine should fail.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>error</name>
+ <value>error</value>
+ </option>
+ <option>
+ <name>unlearn</name>
+ <value>unlearn</value>
+ </option>
+ </options>
+ <bindstofield>installedpackages->dspam->config->0->delivery-onfail</bindstofield>
+ </field>
+ <field>
+ <name>Next</name>
+ <type>submit</type>
+ </field>
+ </fields>
+ <stepsubmitphpaction>
+ <![CDATA[
+ if($_POST['dspamc'] != "") {
+ /* DSPAM server settings */
+ $config['installedpackages']['dspam']['config'][0]['dspam-server-port'] = "24";
+ $config['installedpackages']['dspam']['config'][0]['dspam-server-queue-size'] = "32";
+ $config['installedpackages']['dspam']['config'][0]['dspam-server-pid'] = "/var/run/dspam/dspam.pid";
+ $config['installedpackages']['dspam']['config'][0]['dspam-server-mode'] = "auto";
+ $config['installedpackages']['dspam']['config'][0]['dspam-server-params'] = "--deliver=innocent -d %u";
+ $config['installedpackages']['dspam']['config'][0]['dspam-server-id'] = "abysseleven.abyssworld.de";
+ $config['installedpackages']['dspam']['config'][0]['dspam-server-socket'] = "/var/run/dspam/dspam.sock";
+
+ /* server passwords */
+ $config['installedpackages']['dspam']['config'][0]['server-pwd'][0]['value'] = "secret";
+ $config['installedpackages']['dspam']['config'][0]['server-pwd'][0]['descr'] = "desc";
+ $config['installedpackages']['dspam']['config'][0]['server-pwd'][1]['value'] = "password";
+ $config['installedpackages']['dspam']['config'][0]['server-pwd'][1]['descr'] = "desc";
+
+ /* DSPAM client settings */
+ $config['installedpackages']['dspam']['config'][0]['dspam-client-enable'] = "on";
+ $config['installedpackages']['dspam']['config'][0]['dspam-client-host'] = "/tmp/dspam.sock";
+ $config['installedpackages']['dspam']['config'][0]['dspam-client-port'] = "24";
+ $config['installedpackages']['dspam']['config'][0]['dspam-client-id'] = "secret@Relay1";
+ write_config();
+ }
+ ]]>
+ </stepsubmitphpaction>
+</step>
+<step>
+ <id>5</id>
+ <includefile>dspam.inc</includefile>
+ <title> DSPAM Debugging Options</title>
+ <description>
+ Usually the DSPAM binary that ships with pfSense does not contain debugging symbols.
+ Hence it makes little sense to enable debugging options. If you are quite certain that
+ your DSPAM distribution comes with debugging enabled you may tweak the below debugging
+ options.
+ </description>
+ <fields>
+ <field>
+ <donotdisable>true</donotdisable>
+ <name>enabledbg</name>
+ <description>Enable debugging.</description>
+ <type>checkbox</type>
+ <bindstofield>installedpackages->dspam->config->0->debug-enable</bindstofield>
+ <enablefields>debug,dopt</enablefields>
+ </field>
+ <field>
+ <name>debug</name>
+ <type>input</type>
+ <bindstofield>installedpackages->dspam->config->0->debug-whom</bindstofield>
+ <description>Enables debugging for some or all users.</description>
+ </field>
+ <field>
+ <name>dopt</name>
+ <type>input</type>
+ <bindstofield>installedpackages->dspam->config->0->debug-options</bindstofield>
+ <description>One or more of: process, classify, spam, fp, inoculation, corpus</description>
+ </field>
+ <field>
+ <name>Next</name>
+ <type>submit</type>
+ </field>
+ </fields>
+</step>
+<step>
+ <id>6</id>
+ <includefile>dspam.inc</includefile>
+ <title>DSPAM Engine Settings</title>
+ <description>
+ On this page you will find some specific options required to operate the DSPAM engine. Please
+ consult your &lt;code&gt;dspam.conf&lt;/code&gt; for a detailed explanation of each option.
+ If you are unsure about the meaning of a particular option, please use the default values.
+ </description>
+ <fields>
+ <field>
+ <name>tmode</name>
+ <description>
+ The default training mode to use for all operations, when one has not
+ been specified on the commandline or in the user's preferences (default: teft).
+ </description>
+ <type>select</type>
+ <default_value>teft</default_value>
+ <options>
+ <option>
+ <name>toe</name>
+ <value>toe</value>
+ </option>
+ <option>
+ <name>tum</name>
+ <value>tum</value>
+ </option>
+ <option>
+ <name>teft</name>
+ <value>teft</value>
+ </option>
+ <option>
+ <name>notrain</name>
+ <value>notrain</value>
+ </option>
+ </options>
+ <bindstofield>installedpackages->dspam->config->0->training-mode</bindstofield>
+ </field>
+ <field>
+ <donotdisable>true</donotdisable>
+ <name>testct</name>
+ <default_value>on</default_value>
+ <description>
+ By default, dspam will retrain certain errors until the condition is
+ no longer met (default: enabled).
+ </description>
+ <type>checkbox</type>
+ <bindstofield>installedpackages->dspam->config->0->test-cond-training</bindstofield>
+ </field>
+ <field>
+ <name>pvalue</name>
+ <description>
+ Specify the technique used for calculating PValues, overriding any
+ defaults configured in the build (default: graham).
+ </description>
+ <type>select</type>
+ <default_value>teft</default_value>
+ <options>
+ <option>
+ <name>graham</name>
+ <value>graham</value>
+ </option>
+ <option>
+ <name>robinson</name>
+ <value>robinso</value>
+ </option>
+ <option>
+ <name>markov</name>
+ <value>markov</value>
+ </option>
+ </options>
+ <bindstofield>installedpackages->dspam->config->0->pvalue</bindstofield>
+ </field>
+ <field>
+ <donotdisable>true</donotdisable>
+ <name>ipdrive</name>
+ <default_value>on</default_value>
+ <description>
+ Calculate odds-ratios for ham/spam, and add to X-DSPAM-Improbability
+ headers (default: disabled).
+ </description>
+ <type>checkbox</type>
+ <bindstofield>installedpackages->dspam->config->0->improbability-drive</bindstofield>
+ </field>
+ <field>
+ <name>Next</name>
+ <type>submit</type>
+ </field>
+ </fields>
+</step>
+<step>
+ <id>7</id>
+ <includefile>dspam.inc</includefile>
+ <title>LDAP Settings</title>
+ <description>
+ DSPAM comes with the ability to verify users agains user records stored within a LDAP directory.
+ If using this option, it would be for example possible to verify mail users against Windows
+ user entries stored within an Active Directory. Please consider this feature as somewhat experimental.
+ </description>
+ <fields>
+ <field>
+ <donotdisable>true</donotdisable>
+ <name>enableldap</name>
+ <description>Enable checks against a LDAP directory.</description>
+ <type>checkbox</type>
+ <bindstofield>installedpackages->dspam->config->0->ldap-enable</bindstofield>
+ <enablefields>ldapmode,ldaphost,ldapfilter,ldapbase</enablefields>
+ </field>
+ <field>
+ <name>ldapmode</name>
+ <description>
+ Perform various LDAP functions depending on LDAPMode variable.
+ </description>
+ <type>select</type>
+ <default_value>verify</default_value>
+ <options>
+ <option>
+ <name>verify</name>
+ <value>verify</value>
+ </option>
+ </options>
+ <bindstofield>installedpackages->dspam->config->0->ldap-mode</bindstofield>
+ </field>
+ <field>
+ <name>ldaphost</name>
+ <type>input</type>
+ <bindstofield>installedpackages->dspam->config->0->ldap-host</bindstofield>
+ <description>Hostname of the LDAP directory server.</description>
+ </field>
+ <field>
+ <name>ldapfilter</name>
+ <type>input</type>
+ <bindstofield>installedpackages->dspam->config->0->ldap-filter</bindstofield>
+ <description>A specific query filter, that should be used while querying the LDAP server.</description>
+ </field>
+ <field>
+ <name>ldapbase</name>
+ <type>input</type>
+ <bindstofield>installedpackages->dspam->config->0->ldap-base</bindstofield>
+ <description>A particular distinguish name from where to start LDAP queries.</description>
+ </field>
+ <field>
+ <name>Next</name>
+ <type>submit</type>
+ </field>
+ </fields>
+</step>
+<step>
+ <id>8</id>
+ <includefile>dspam.inc</includefile>
+ <title>Miscellaneous Settings</title>
+ <description>
+ On this page we will give you an opertunity to fine-tune the DSPAM engine. As mentioned earlier,
+ if you are unsure about the meaning of a particular option, use its default value.
+ </description>
+ <fields>
+ <field>
+ <name>foatt</name>
+ <type>input</type>
+ <bindstofield>installedpackages->dspam->config->0->failover-attempts</bindstofield>
+ <description>A particular number of attempts (default: 1).</description>
+ </field>
+ <field>
+ <donotdisable>true</donotdisable>
+ <name>enablesbl</name>
+ <description>Enable checks against a particular SBL host (default: disabled).</description>
+ <type>checkbox</type>
+ <bindstofield>installedpackages->dspam->config->0->sbl-enable</bindstofield>
+ <enablefields>sblhost</enablefields>
+ </field>
+ <field>
+ <name>sblhost</name>
+ <type>input</type>
+ <bindstofield>installedpackages->dspam->config->0->sbl-host</bindstofield>
+ <description>A particular SBL hostname (default: none).</description>
+ <size>30</size>
+ </field>
+ <field>
+ <donotdisable>true</donotdisable>
+ <name>enablerbl</name>
+ <description>Enable RBL inoculation support (default: disabled).</description>
+ <type>checkbox</type>
+ <bindstofield>installedpackages->dspam->config->0->rbl-inoculate</bindstofield>
+ </field>
+ <field>
+ <donotdisable>true</donotdisable>
+ <name>enablenoti</name>
+ <description>Enable the sending of notification emails to users (first message, quarantine full, etc. default: disabled).</description>
+ <type>checkbox</type>
+ <bindstofield>installedpackages->dspam->config->0->notification-email</bindstofield>
+ </field>
+ <field>
+ <name>Next</name>
+ <type>submit</type>
+ </field>
+ </fields>
+</step>
+<step>
+ <id>9</id>
+ <includefile>dspam.inc</includefile>
+ <title>Maintainance Settings</title>
+ <description>
+ DSPAM stores token data etc. in some kind of a database (e.g. a RDBMS or flat files).
+ Over time, this token data may consume lots of space. Hence it makes sense to run
+ certain routines to clean up unused data.
+ </description>
+ <fields>
+ <field>
+ <name>psig</name>
+ <type>input</type>
+ <bindstofield>installedpackages->dspam->config->0->purge-signatures</bindstofield>
+ <description>Purge stale signatures (default: 14).</description>
+ </field>
+ <field>
+ <name>pneut</name>
+ <type>input</type>
+ <bindstofield>installedpackages->dspam->config->0->purge-neutral</bindstofield>
+ <description>Purge tokens with neutralish probabilities (default: 90).</description>
+ </field>
+ <field>
+ <name>punu</name>
+ <type>input</type>
+ <bindstofield>installedpackages->dspam->config->0->purge-unused</bindstofield>
+ <description>Purge unused tokens (default: 90).</description>
+ </field>
+ <field>
+ <name>phapa</name>
+ <type>input</type>
+ <bindstofield>installedpackages->dspam->config->0->purge-hapaxes</bindstofield>
+ <description> Purge tokens with less than 5 hits (hapaxes - default: 30).</description>
+ </field>
+ <field>
+ <name>pones</name>
+ <type>input</type>
+ <bindstofield>installedpackages->dspam->config->0->purge-hits-1s</bindstofield>
+ <description>Purge tokens with only 1 spam hit (default: 15).</description>
+ </field>
+ <field>
+ <name>ponei</name>
+ <type>input</type>
+ <bindstofield>installedpackages->dspam->config->0->purge-hits-1i</bindstofield>
+ <description> Purge tokens with only 1 innocent hit (default: 15).</description>
+ </field>
+ <field>
+ <name>Next</name>
+ <type>submit</type>
+ </field>
+ </fields>
+</step>
+<step>
+ <id>10</id>
+ <includefile>dspam.inc</includefile>
+ <title>System Settings</title>
+ <description>
+ This page contains additional settings related to the DSPAM system such as logging,
+ message processing behaviour et cetera.
+ </description>
+ <fields>
+ <field>
+ <name>locmx</name>
+ <type>input</type>
+ <bindstofield>installedpackages->dspam->config->0->local-mx</bindstofield>
+ <description>
+ Local Mail Exchangers: Used for source address tracking, tells DSPAM
+ which mail exchangers are local and therefore should be ignored in the
+ Received: header when tracking the source of an email. Note: you should
+ use the address of the host as appears between brackets [ ] in the
+ Received header (default: 127.0.0.1).
+ </description>
+ </field>
+ <field>
+ <donotdisable>true</donotdisable>
+ <name>enablesysl</name>
+ <description>Enable system logging (default: enabled).</description>
+ <type>checkbox</type>
+ <bindstofield>installedpackages->dspam->config->0->system-log</bindstofield>
+ </field>
+ <field>
+ <donotdisable>true</donotdisable>
+ <name>enableusel</name>
+ <description>Enable per user logging (default: enabled).</description>
+ <type>checkbox</type>
+ <bindstofield>installedpackages->dspam->config->0->user-log</bindstofield>
+ </field>
+ <field>
+ <name>optinout</name>
+ <description>
+ Opt: in or out; determines DSPAM's default filtering behavior (default: out).
+ </description>
+ <type>select</type>
+ <default_value>out</default_value>
+ <options>
+ <option>
+ <name>out</name>
+ <value>out</value>
+ </option>
+ <option>
+ <name>in</name>
+ <value>in</value>
+ </option>
+ </options>
+ <bindstofield>installedpackages->dspam->config->0->filter-opt</bindstofield>
+ </field>
+ <field>
+ <donotdisable>true</donotdisable>
+ <name>enableptoh</name>
+ <description>Parse the To: headers of an incoming message. (default: disabled).</description>
+ <type>checkbox</type>
+ <bindstofield>installedpackages->dspam->config->0->parse-to-headers</bindstofield>
+ </field>
+ <field>
+ <donotdisable>true</donotdisable>
+ <name>enablecmop</name>
+ <description>Automatically change the class (to spam or innocent - default: disabled).</description>
+ <type>checkbox</type>
+ <bindstofield>installedpackages->dspam->config->0->change-mode-on-parse</bindstofield>
+ </field>
+ <field>
+ <donotdisable>true</donotdisable>
+ <name>enablecuop</name>
+ <description>Automatically change the username to match that specified in the To: header (default: enabled).</description>
+ <type>checkbox</type>
+ <bindstofield>installedpackages->dspam->config->0->change-user-on-parse</bindstofield>
+ </field>
+ <field>
+ <name>maxmsgs</name>
+ <type>input</type>
+ <bindstofield>installedpackages->dspam->config->0->max-message-size</bindstofield>
+ <description>
+ You may specify a maximum message size in bytes for DSPAM to process. (default: 307200).
+ </description>
+ </field>
+ <field>
+ <donotdisable>true</donotdisable>
+ <name>procbias</name>
+ <description>
+ Bias causes the filter to lean more toward &quot;innocent&quot;, and usually
+ greatly reduces false positives. It is the default behavior of most
+ Bayesian filters, including dspam (default: enabled).
+ </description>
+ <type>checkbox</type>
+ <bindstofield>installedpackages->dspam->config->0->processor-bias</bindstofield>
+ </field>
+ <field>
+ <name>Next</name>
+ <type>submit</type>
+ </field>
+ </fields>
+</step>
+<step>
+ <id>11</id>
+ <includefile>dspam.inc</includefile>
+ <title>ClamAV Engine Settings</title>
+ <description>
+ DSPAM comes with an additional feature which allows to scan mail messages
+ for malicious code (i.e. virii). If you require messages not only to be
+ classified as Spam/Ham but additionally to be scanned for virii, enable
+ to appropriate option below.
+ </description>
+ <fields>
+ <field>
+ <donotdisable>true</donotdisable>
+ <name>enableclam</name>
+ <description>Enable ClamAV Engine (default: disabled).</description>
+ <type>checkbox</type>
+ <bindstofield>installedpackages->dspam->config->0->clamav-enable</bindstofield>
+ <enablefields>clamport,clamhost,clamresp</enablefields>
+ </field>
+ <field>
+ <name>clamport</name>
+ <type>input</type>
+ <bindstofield>installedpackages->dspam->config->0->clamav-port</bindstofield>
+ <description>A number that specifies the port the ClamAV daemon is listening to (default: none).</description>
+ </field>
+ <field>
+ <name>clamhost</name>
+ <type>input</type>
+ <bindstofield>installedpackages->dspam->config->0->clamav-host</bindstofield>
+ <description>An IP address that points to the host the ClamAV daemon is running on (default: none).</description>
+ </field>
+ <field>
+ <name>clamresp</name>
+ <description>The action that should take place, if ClamAV reports a positive (default: none).</description>
+ <type>select</type>
+ <default_value>accept</default_value>
+ <options>
+ <option>
+ <name>reject</name>
+ <value>reject</value>
+ </option>
+ <option>
+ <name>accept</name>
+ <value>accept</value>
+ </option>
+ <option>
+ <name>spam</name>
+ <value>spam</value>
+ </option>
+ </options>
+ <bindstofield>installedpackages->dspam->config->0->clamav-response</bindstofield>
+ </field>
+ <field>
+ <name>Next</name>
+ <type>submit</type>
+ </field>
+ </fields>
+</step>
+<step>
+ <id>12</id>
+ <includefile>dspam.inc</includefile>
+ <title>DSPAM Daemon Settings (Server)</title>
+ <description>
+ DSPAM can be either invoked per message (i.e. a thread per message) or it
+ can be run as a daemon in the background. The latter option enables DSPAM
+ to maintain database connection pools which may increase overall performance.
+ Based on the profile, that you did choose initially, some of the below options
+ may be already set.
+ </description>
+ <fields>
+ <field>
+ <name>dsport</name>
+ <type>input</type>
+ <bindstofield>installedpackages->dspam->config->0->dspam-server-port</bindstofield>
+ <description>A number that specifies the port the DSPAM daemon is listening to (default: none).</description>
+ </field>
+ <field>
+ <name>dsqsize</name>
+ <type>input</type>
+ <bindstofield>installedpackages->dspam->config->0->dspam-server-queue-size</bindstofield>
+ <description>A number that specifies the server's queue size (default: none).</description>
+ </field>
+ <field>
+ <name>dspid</name>
+ <type>input</type>
+ <bindstofield>installedpackages->dspam->config->0->dspam-server-pid</bindstofield>
+ <description> Keep this is sync with &lt;code&gt;/usr/local/etc/rc.d/dspam.rc&lt;/code&gt; script (default: none).</description>
+ <size>40</size>
+ </field>
+ <field>
+ <name>dssmode</name>
+ <description>Specifies the type of LMTP server to start. (default: none).</description>
+ <type>select</type>
+ <default_value>auto</default_value>
+ <options>
+ <option>
+ <name>dspam</name>
+ <value>dspam</value>
+ </option>
+ <option>
+ <name>standard</name>
+ <value>standard</value>
+ </option>
+ <option>
+ <name>auto</name>
+ <value>auto</value>
+ </option>
+ </options>
+ <bindstofield>installedpackages->dspam->config->0->dspam-server-mode</bindstofield>
+ </field>
+ <field>
+ <name>serverparam</name>
+ <type>input</type>
+ <bindstofield>installedpackages->dspam->config->0->dspam-server-params</bindstofield>
+ <description>Parameters which will be passed to the LMTP server (default: none).</description>
+ </field>
+ <field>
+ <name>serverid</name>
+ <type>input</type>
+ <bindstofield>installedpackages->dspam->config->0->dspam-server-id</bindstofield>
+ <description>An identification string which will be used to be passed to the LMTP server (default: none).</description>
+ </field>
+ <field>
+ <name>serversock</name>
+ <type>input</type>
+ <bindstofield>installedpackages->dspam->config->0->dspam-server-socket</bindstofield>
+ <description>A local Unix domain socket (default: none).</description>
+ <size>40</size>
+ </field>
+ <field>
+ <name>Next</name>
+ <type>submit</type>
+ </field>
+ </fields>
+</step>
+<step>
+ <id>13</id>
+ <includefile>dspam.inc</includefile>
+ <title>DSPAM Daemon Settings (Client)</title>
+ <description>
+ If you did configure DSPAM to run in dspam mode, it is required to configure
+ client settings because DSPAM needs for example to authenticate against its
+ server counterpart.
+ </description>
+ <fields>
+ <field>
+ <donotdisable>true</donotdisable>
+ <name>enabledsclient</name>
+ <description>Run DSPAM in client mode (default: disabled).</description>
+ <type>checkbox</type>
+ <bindstofield>installedpackages->dspam->config->0->dspam-client-enable</bindstofield>
+ <enablefields>dsclhost,dsclport,dsclident</enablefields>
+ </field>
+ <field>
+ <name>dsclhost</name>
+ <type>input</type>
+ <bindstofield>installedpackages->dspam->config->0->dspam-client-host</bindstofield>
+ <description>An IP address or a Unix domain socket (default: none).</description>
+ </field>
+ <field>
+ <name>dsclport</name>
+ <type>input</type>
+ <bindstofield>installedpackages->dspam->config->0->dspam-client-port</bindstofield>
+ <description>Will be only used if this client uses TCP/IP communication (default: none).</description>
+ </field>
+ <field>
+ <name>dsclident</name>
+ <type>input</type>
+ <bindstofield>installedpackages->dspam->config->0->dspam-client-id</bindstofield>
+ <description>A string that will be used to identify the client against a server. (default: none).</description>
+ <size>40</size>
+ </field>
+ <field>
+ <name>Next</name>
+ <type>submit</type>
+ </field>
+ </fields>
+</step>
+<step>
+ <id>14</id>
+ <includefile>dspam.inc</includefile>
+ <title>Reload configuration</title>
+ <disableheader>true</disableheader>
+ <description>Click 'Reload' to reload the DSPAM daemon with new changes.</description>
+ <fields>
+ <field>
+ <name>Reload</name>
+ <type>submit</type>
+ </field>
+ </fields>
+</step>
+<step>
+ <id>15</id>
+ <includefile>dspam.inc</includefile>
+ <title>Reload in progress</title>
+ <description>
+ A reload is now in progress. Please wait.
+ &lt;br /&gt;&#160;&lt;br /&gt;
+ The system will automatically try to access DSPAM settings in 120 page seconds.
+ &lt;br /&gt;&#160;&lt;br /&gt;
+ You can click on the icon above to access the site more quickly.
+ </description>
+ <javascriptafterformdisplay>
+ <![CDATA[
+ Effect.Pulsate('wzd_step_title', { duration: 10});
+ window.setTimeout('window.location.href = "/dspam-settings.php"', 120000);
+ ]]>
+ </javascriptafterformdisplay>
+ <stepafterformdisplay>
+ <![CDATA[
+ dspam_configure();
+ mwexec("/usr/local/etc/rc.d/spamd.sh stop");
+ mwexec("/usr/local/etc/rc.d/spamd.sh start");
+ ]]>
+ </stepafterformdisplay>
+</step>
+</pfsensewizard>
diff --git a/config/dyntables/pkg/dyntables.inc b/config/dyntables/pkg/dyntables.inc
new file mode 100644
index 00000000..97e8a422
--- /dev/null
+++ b/config/dyntables/pkg/dyntables.inc
@@ -0,0 +1,117 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ dyntables.inc
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+require_once("dyntables_classdefs.inc");
+
+function syncPackageDyntables() {
+
+}
+
+function installPackageDyntables() {
+ /* move temp files */
+ @rename('/usr/local/www/diag_dhcp_leases.php', '/usr/local/pkg/diag_dhcp_leases.php.org');
+ @rename('/usr/local/pkg/dyntables.js', '/usr/local/www/javascript/dyntables.js');
+ @rename('/usr/local/pkg/diag_dhcp_leases.php', '/usr/local/www/diag_dhcp_leases.php');
+}
+
+function deinstallPackageDyntables() {
+ /* move backup files */
+ @unlink('/usr/local/www/diag_dhcp_leases.php');
+ @unlink('/usr/local/www/javascript/dyntables.js');
+ @rename('/usr/local/pkg/diag_dhcp_leases.php.org', '/usr/local/www/diag_dhcp_leases.php');
+}
+
+function checkForExtension($alertClass) {
+ if(! extension_loaded( 'json' )) {
+ if(! @dl( 'json.so' )) {
+ return openNoExtDialog($alertClass);
+ }
+ }
+}
+
+/**
+ * openNoExtDialog()
+ *
+ * @param mixed $effectClass
+ * @return
+ */
+function openNoExtDialog($effectClass) {
+ $alertMessage = gettext("PHP extension json.so was not found or could not be loaded. Please check you PHP installation.");
+ $dialogScript = "
+ <script type='text/javascript'>
+ var anchor = document.getElementById('popupanchor');
+
+ function openNoExtDialog(html) {
+ var effect = new PopupEffect(html, {className: '${effectClass}'});
+ Dialog.alert('${alertMessage}',{className:'alphacube', top:150, width:400, height:null, showEffect:effect.show.bind(effect), hideEffect:effect.hide.bind(effect)});
+ }
+
+ openNoExtDialog(anchor);
+ </script>
+ ";
+
+ return $dialogScript;
+}
+
+/**
+* getWindowJSScriptRefs()
+*
+* @return an array of &lt;script /&gt; elements
+*/
+function getWindowJSScriptRefs(){
+ $result = array('<script type="text/javascript" src="/javascript/windows-js/javascript/window.js"></script>',
+ '<script type="text/javascript" src="/javascript/windows-js/javascript/window_effects.js"></script>',
+ '<script type="text/javascript" src="/javascript/windows-js/javascript/debug.js"></script>');
+
+ return $result;
+}
+
+/**
+* getWindowJSStyleRefs()
+*
+* @return an array of &lt;style /&gt; tags
+*/
+function getWindowJSStyleRefs(){
+ $result = array('<link href="/javascript/windows-js/themes/default.css" rel="stylesheet" type="text/css" />',
+ '<link href="/javascript/windows-js/themes/alert.css" rel="stylesheet" type="text/css" />',
+ '<link href="/javascript/windows-js/themes/alphacube.css" rel="stylesheet" type="text/css" />');
+
+ return $result;
+}
+
+?> \ No newline at end of file
diff --git a/config/dyntables/pkg/dyntables.xml b/config/dyntables/pkg/dyntables.xml
new file mode 100644
index 00000000..8a249966
--- /dev/null
+++ b/config/dyntables/pkg/dyntables.xml
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ dyntables.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>
+ This package adds dynamic reloading support of table data to
+ various pfSense web pages. Reloading table data is done using
+ Ajax.
+ </description>
+ <requirements>
+ This package is supposed to be run on RELENG based pfSense systems.
+ </requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>dyntables</name>
+ <version>1.0</version>
+ <title>System: Dynamic Tables</title>
+ <include_file>/usr/local/pkg/dyntables.inc</include_file>
+ <!-- Menu is where this packages menu will appear -->
+ <!--
+ <menu>
+ <name>Menu Name</name>
+ <section>Menu Section</section>
+ <url>/phpfile.php</url>
+ </menu>
+ -->
+ <!--
+ <service>
+ <name>yourservice</name>
+ <rcfile>/usr/local/etc/rc.d/yourservice.sh</rcfile>
+ </service>
+ -->
+ <tabs />
+ <!--
+ configpath gets expanded out automatically and config items
+ will be stored in that location
+ -->
+ <configpath>['installedpackages']['dyntables']['config']</configpath>
+ <!--
+ |
+ | PHP files (user management)
+ |
+ -->
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/dyntables/www/php/diag_dhcp_leases.php</item>
+ </additional_files_needed>
+ <!--
+ |
+ | JavaScript files (*.js and *.inc.)
+ |
+ -->
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/dyntables/www/js/dyntables.js</item>
+ </additional_files_needed>
+ <!--
+ |
+ | Include files (class defs etc.)
+ |
+ -->
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/dyntables/pkg/dyntables.inc</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/dyntables/pkg/dyntables_classdefs.inc</item>
+ </additional_files_needed>
+ <!--
+ |
+ | Binary files
+ |
+ -->
+ <additional_files_needed>
+ <prefix>/usr/local/lib/php/extensions/no-debug-non-zts-20020429/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/dyntables/bin/json.so</item>
+ </additional_files_needed>
+ <!--
+ fields gets invoked when the user adds or edits a item. The following items
+ will be parsed and rendered for the user as a gui with input, and selectboxes.
+ -->
+ <!--
+ Arbitrary PHP Code, that gets executed if a certain event gets triggered.
+ -->
+ <custom_php_resync_config_command>
+ syncPackageDyntables();
+ </custom_php_resync_config_command>
+ <custom_php_install_command>
+ installPackageDyntables();
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ deinstallPackageDyntables();
+ </custom_php_deinstall_command>
+</packagegui>
diff --git a/config/dyntables/pkg/dyntables_classdefs.inc b/config/dyntables/pkg/dyntables_classdefs.inc
new file mode 100644
index 00000000..696170d1
--- /dev/null
+++ b/config/dyntables/pkg/dyntables_classdefs.inc
@@ -0,0 +1,146 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ classdefs.inc
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+if (! class_exists("Object")) {
+ class Object {
+ function Object() {
+ $args = func_get_args();
+ if (method_exists($this, '__destruct')) {
+ register_shutdown_function(array(&$this, '__destruct'));
+ }
+ call_user_func_array(array(&$this, '__construct'), $args);
+ }
+
+ function __construct() {
+ }
+ }
+}
+
+class Column extends Object {
+ var $defaultClass = "listhdrr";
+ var $class = null;
+ var $name = null;
+ var $sortID = null;
+
+ function __construct($name) {
+ // Perform object initialization here.
+ parent::__construct();
+ $this->name = $name;
+ }
+
+ function setClass($class) {
+ $this->class = $class;
+ }
+
+ function getClass() {
+ return $this->class;
+ }
+
+ function setSortID($id) {
+ $this->sortID = $id;
+ }
+
+ function getSortID() {
+ return $this->sortID;
+ }
+
+ function toHTML() {
+ global $_GET;
+
+ $classString = $this->class != null ? $this->class : $this->defaultClass;
+ $allString = isset($_GET['all']) ? ", {$_GET['all']}" : "";
+ return "<td class='{$classString}'><a id='{$this->sortID}' href='#' onclick='sortTable(this{$allString});'>{$this->name}</a></td>";
+ }
+}
+
+class Table extends Object {
+ var $columns = null;
+ var $data = null;
+
+ function __construct() {
+ // Perform object initialization here.
+ parent::__construct();
+ $this->columns = array();
+ $this->data = array();
+ }
+
+ function addColumn($column, $id = null, $class = null) {
+ $column = new Column($column);
+
+ if ($id != null) {
+ $column->setSortID($id);
+ }
+ if ($class != null) {
+ $column->setClass($class);
+ }
+
+ $this->columns[] = $column;
+ }
+
+ function addDataSet($dataSet) {
+ if (is_array($dataSet)) {
+ if (count($dataSet) == count($this->columns)) {
+ $this->data[] = $dataSet;
+ } else {
+ trigger_error("Dataset does not match column size.");
+ }
+ } else {
+ trigger_error("Adding non arrays as datasets to a table is not supported.");
+ }
+ }
+
+ function setData(&$data) {
+ $this->data = $data;
+ }
+
+ function getData() {
+ return $this->data;
+ }
+
+ function getColumnHTML() {
+ $htmlString = "";
+
+ foreach($this->columns as $column) {
+ $htmlString .= $column->toHtml();
+ }
+
+ return "<tr>{$htmlString}</tr>";
+ }
+}
+
+?> \ No newline at end of file
diff --git a/config/dyntables/www/js/dyntables.js b/config/dyntables/www/js/dyntables.js
new file mode 100644
index 00000000..0e90a3c1
--- /dev/null
+++ b/config/dyntables/www/js/dyntables.js
@@ -0,0 +1,287 @@
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng_wizard.js
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+function openInfoDialog() {
+ Dialog.info("Reloading table data ...",
+ {className:"alphacube", width:200, height:75, top:100, showProgress: true});
+}
+
+/**
+ *
+ * @access public
+ * @return void
+ **/
+function getFirstTD(node, index){
+ var firstTD = node.childNodes[index];
+
+ if (firstTD.tagName == 'TD') {
+ return firstTD;
+ } else {
+ return getFirstTD(node, ++index);
+ }
+}
+
+/**
+ *
+ * @access public
+ * @return void
+ **/
+function getTableRow(nodes, index){
+ var row = nodes[index];
+
+ if (row.tagName == 'TR') {
+ return row;
+ } else {
+ return getTableRow(nodes, ++index);
+ }
+}
+
+/**
+ *
+ * @access public
+ * @return void
+ **/
+function emtyDhcpLeaseTable(table) {
+ var tbody = table.childNodes[1];
+ var trNodes = tbody.childNodes;
+
+ for (i = 0; i < trNodes.length; i++) {
+ var currentRow = getTableRow(trNodes, i);
+ var firstTd = getFirstTD(currentRow, 0);
+ var classAttrib = firstTd.className;
+
+ if (classAttrib == 'listhdrr') {
+ continue;
+ } else if (currentRow.tagName == 'TR') {
+ tbody.removeChild(currentRow);
+ }
+ }
+}
+
+/**
+ * TODO: data[if], $fspans, $fspane,
+ *
+ **/
+function dhcpLeaseTableToHTML(table, json, theme) {
+ var tbody = table.childNodes[1];
+
+ if (json && json.length > 0) {
+ for (i = 0; i < json.length; i++) {
+ /* text nodes */
+ var newActTxt = document.createTextNode(json[i]['act']);
+ var newEndTxt = document.createTextNode(json[i]['end']);
+ var newStartTxt = document.createTextNode(json[i]['start']);
+ var newHostnameTxt = document.createTextNode(json[i]['hostname']);
+ var newIPTxt = document.createTextNode(json[i]['ip']);
+ var newMACTxt = document.createTextNode(json[i]['mac']);
+ var newOnlineTxt = document.createTextNode(json[i]['online']);
+ var newTypeTxt = document.createTextNode(json[i]['type']);
+
+ var newTR = document.createElement("tr");
+ var newTRIdAttrib = document.createAttribute("id");
+ newTRIdAttrib.nodeValue = "dhcpRow" + i;
+ newTR.setAttributeNode(newTRIdAttrib);
+
+ /* IP td element */
+ var newIPTD = document.createElement("td");
+ /* TD attributes */
+ var newIPTDClassAttrib = document.createAttribute("class");
+ newIPTDClassAttrib.nodeValue = "listlr";
+ /* assign attribs */
+ newIPTD.setAttributeNode(newIPTDClassAttrib);
+
+ /* MAC td element */
+ var newMACTD = document.createElement("td");
+ /* TD attributes */
+ var newMACTDClassAttrib = document.createAttribute("class");
+ newMACTDClassAttrib.nodeValue = "listr";
+ /* assign attribs */
+ newMACTD.setAttributeNode(newMACTDClassAttrib);
+
+ /* Hostname td element */
+ var newHostnameTD = document.createElement("td");
+ /* TD attributes */
+ var newHostnameTDClassAttrib = document.createAttribute("class");
+ newHostnameTDClassAttrib.nodeValue = "listr";
+ /* assign attribs */
+ newHostnameTD.setAttributeNode(newHostnameTDClassAttrib);
+
+ /* Start td element */
+ var newStartTD = document.createElement("td");
+ /* TD attributes */
+ var newStartTDClassAttrib = document.createAttribute("class");
+ newStartTDClassAttrib.nodeValue = "listr";
+ /* assign attribs */
+ newStartTD.setAttributeNode(newStartTDClassAttrib);
+
+ /* End td element */
+ var newEndTD = document.createElement("td");
+ /* TD attributes */
+ var newEndTDClassAttrib = document.createAttribute("class");
+ newEndTDClassAttrib.nodeValue = "listr";
+ /* assign attribs */
+ newEndTD.setAttributeNode(newEndTDClassAttrib);
+
+ /* Online td element */
+ var newOnlineTD = document.createElement("td");
+ /* TD attributes */
+ var newOnlineTDClassAttrib = document.createAttribute("class");
+ newOnlineTDClassAttrib.nodeValue = "listr";
+ /* assign attribs */
+ newOnlineTD.setAttributeNode(newOnlineTDClassAttrib);
+
+ /* Lease td element */
+ var newLeaseTD = document.createElement("td");
+ /* TD attributes */
+ var newLeaseTDClassAttrib = document.createAttribute("class");
+ newLeaseTDClassAttrib.nodeValue = "listr";
+ /* assign attribs */
+ newLeaseTD.setAttributeNode(newLeaseTDClassAttrib);
+
+ /* Mapping td element */
+ var newMappingTD = document.createElement("td");
+ /* TD attributes */
+ var newMappingTDClassAttrib = document.createAttribute("class");
+ newMappingTDClassAttrib.nodeValue = "list";
+ var newMappingTDValignAttrib = document.createAttribute("valign");
+ newMappingTDValignAttrib.nodeValue = "middle";
+ /* assign attribs */
+ newMappingTD.setAttributeNode(newMappingTDClassAttrib);
+ newMappingTD.setAttributeNode(newMappingTDValignAttrib);
+
+ /* WOL td element */
+ var newWOLTD = document.createElement("td");
+ /* TD attributes */
+ var newWOLTDValignAttrib = document.createAttribute("valign");
+ newWOLTDValignAttrib.nodeValue = "middle";
+ /* assign attribs */
+ newWOLTD.setAttributeNode(newWOLTDValignAttrib);
+
+ /* Mapping anchor */
+ var newMappingAnchor = document.createElement("a");
+ /* Anchor attribs */
+ var newMappingAnchorHrefAttrib = document.createAttribute("href");
+ newMappingAnchorHrefAttrib.nodeValue = "services_dhcp_edit.php?if=lan&mac=" + json[i]['mac'] + "&hostname=" + json[i]['hostname'];
+ /* assign attribs */
+ newMappingAnchor.setAttributeNode(newMappingAnchorHrefAttrib);
+
+ /* Mapping button */
+ var newMappingButton = document.createElement("img");
+ /* Button attribs */
+ var newMappingButtonSrcAttrib = document.createAttribute("src");
+ newMappingButtonSrcAttrib.nodeValue = "/themes/" + theme + "/images/icons/icon_plus.gif";
+ var newMappingButtonWidthAttrib = document.createAttribute("width");
+ newMappingButtonWidthAttrib.nodeValue = "17";
+ var newMappingButtonHeightAttrib = document.createAttribute("height");
+ newMappingButtonHeightAttrib.nodeValue = "17";
+ var newMappingButtonBorderAttrib = document.createAttribute("border");
+ newMappingButtonBorderAttrib.nodeValue = "0";
+ var newMappingButtonTitleAttrib = document.createAttribute("title");
+ newMappingButtonTitleAttrib.nodeValue = "add a static mapping for this MAC address";
+ var newMappingButtonAltAttrib = document.createAttribute("alt");
+ newMappingButtonAltAttrib.nodeValue = "add a static mapping for this MAC address";
+ /* assign attribs */
+ newMappingButton.setAttributeNode(newMappingButtonSrcAttrib);
+ newMappingButton.setAttributeNode(newMappingButtonWidthAttrib);
+ newMappingButton.setAttributeNode(newMappingButtonHeightAttrib);
+ newMappingButton.setAttributeNode(newMappingButtonBorderAttrib);
+ newMappingButton.setAttributeNode(newMappingButtonTitleAttrib);
+ newMappingButton.setAttributeNode(newMappingButtonAltAttrib);
+
+ /* WOL anchor */
+ var newWOLAnchor = document.createElement("a");
+ /* Anchor attribs */
+ var newWOLAnchorHrefAttrib = document.createAttribute("href");
+ newWOLAnchorHrefAttrib.nodeValue = "services_wol_edit.php?if=lan&mac=" + json[i]['mac'] + "&descr=pfSense";
+ /* assign attribs */
+ newWOLAnchor.setAttributeNode(newWOLAnchorHrefAttrib);
+
+ /* WOL button */
+ var newWOLButton = document.createElement("img");
+ /* Button attribs */
+ var newWOLButtonSrcAttrib = document.createAttribute("src");
+ newWOLButtonSrcAttrib.nodeValue = "/themes/" + theme + "/images/icons/icon_wol_all.gif";
+ var newWOLButtonWidthAttrib = document.createAttribute("width");
+ newWOLButtonWidthAttrib.nodeValue = "17";
+ var newWOLButtonHeightAttrib = document.createAttribute("height");
+ newWOLButtonHeightAttrib.nodeValue = "17";
+ var newWOLButtonBorderAttrib = document.createAttribute("border");
+ newWOLButtonBorderAttrib.nodeValue = "0";
+ var newWOLButtonTitleAttrib = document.createAttribute("title");
+ newWOLButtonTitleAttrib.nodeValue = "add a Wake on Lan mapping for this MAC address";
+ var newWOLButtonAltAttrib = document.createAttribute("alt");
+ newWOLButtonAltAttrib.nodeValue = "add a Wake on Lan mapping for this MAC address";
+ /* assign attribs */
+ newWOLButton.setAttributeNode(newWOLButtonSrcAttrib);
+ newWOLButton.setAttributeNode(newWOLButtonWidthAttrib);
+ newWOLButton.setAttributeNode(newWOLButtonHeightAttrib);
+ newWOLButton.setAttributeNode(newWOLButtonBorderAttrib);
+ newWOLButton.setAttributeNode(newWOLButtonTitleAttrib);
+ newWOLButton.setAttributeNode(newWOLButtonAltAttrib);
+
+ /* assign buttons to anchor elements */
+ newMappingAnchor.appendChild(newMappingButton);
+ newWOLAnchor.appendChild(newWOLButton);
+
+ /* assign anchors to TD elements */
+ newMappingTD.appendChild(newMappingAnchor);
+ newWOLTD.appendChild(newWOLAnchor);
+
+ /* assign text nodes to TD elements */
+ newIPTD.appendChild(newIPTxt);
+ newMACTD.appendChild(newMACTxt);
+ newHostnameTD.appendChild(newHostnameTxt);
+ newStartTD.appendChild(newStartTxt);
+ newEndTD.appendChild(newEndTxt);
+ newOnlineTD.appendChild(newOnlineTxt);
+ newLeaseTD.appendChild(newActTxt);
+
+ /* populate table body */
+ newTR.appendChild(newIPTD);
+ newTR.appendChild(newMACTD);
+ newTR.appendChild(newHostnameTD);
+ newTR.appendChild(newStartTD);
+ newTR.appendChild(newEndTD);
+ newTR.appendChild(newOnlineTD);
+ newTR.appendChild(newLeaseTD);
+ newTR.appendChild(newMappingTD);
+ newTR.appendChild(newWOLTD);
+
+ tbody.appendChild(newTR);
+ }
+ }
+} \ No newline at end of file
diff --git a/config/dyntables/www/php/diag_dhcp_leases.php b/config/dyntables/www/php/diag_dhcp_leases.php
new file mode 100644
index 00000000..4ff8e241
--- /dev/null
+++ b/config/dyntables/www/php/diag_dhcp_leases.php
@@ -0,0 +1,440 @@
+<?php
+/* $Id$ */
+/*
+ diag_dhcp_leases.php
+ Copyright (C) 2004 Scott Ullrich
+ All rights reserved.
+
+ originially part of m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require("guiconfig.inc");
+require("dyntables.inc");
+
+/* ========================================================================== */
+/* ======================= NON GUI RELATED FUNCTIONS ======================== */
+/* ========================================================================== */
+
+function leasecmp($a, $b) {
+ return strcmp($a[$_GET['order']], $b[$_GET['order']]);
+}
+
+function adjust_gmt($dt) {
+ $ts = strtotime($dt . " GMT");
+ return strftime("%Y/%m/%d %H:%M:%S", $ts);
+}
+
+function remove_duplicate($array, $field)
+{
+ foreach ($array as $sub)
+ $cmp[] = $sub[$field];
+ $unique = array_unique($cmp);
+ foreach ($unique as $k => $rien)
+ $new[] = $array[$k];
+ return $new;
+}
+
+$leasesfile = "{$g['dhcpd_chroot_path']}/var/db/dhcpd.leases";
+$awk = "/usr/bin/awk";
+/* this pattern sticks comments into a single array item */
+$cleanpattern = "'{ gsub(\"#.*\", \"\");} { gsub(\";\", \"\"); print;}'";
+/* We then split the leases file by } */
+$splitpattern = "'BEGIN { RS=\"}\";} {for (i=1; i<=NF; i++) printf \"%s \", \$i; printf \"}\\n\";}'";
+
+/* stuff the leases file in a proper format into a array by line */
+exec("cat {$leasesfile} | {$awk} {$cleanpattern} | {$awk} {$splitpattern}", $leases_content);
+$leases_count = count($leases_content);
+
+$pools = array();
+$leases = array();
+$i = 0;
+$l = 0;
+$p = 0;
+
+// Put everything together again
+while($i < $leases_count) {
+ /* split the line by space */
+ $data = explode(" ", $leases_content[$i]);
+ /* walk the fields */
+ $f = 0;
+ $fcount = count($data);
+ /* with less then 20 fields there is nothing useful */
+ if($fcount < 20) {
+ $i++;
+ continue;
+ }
+ while($f < $fcount) {
+ switch($data[$f]) {
+ case "failover":
+ $pools[$p]['name'] = $data[$f+2];
+ $pools[$p]['mystate'] = $data[$f+7];
+ $pools[$p]['peerstate'] = $data[$f+14];
+ $pools[$p]['mydate'] = $data[$f+10];
+ $pools[$p]['mydate'] .= " " . $data[$f+11];
+ $pools[$p]['peerdate'] = $data[$f+17];
+ $pools[$p]['peerdate'] .= " " . $data[$f+18];
+ $p++;
+ $i++;
+ continue 3;
+ case "lease":
+ $leases[$l]['ip'] = $data[$f+1];
+ $leases[$l]['type'] = "dynamic";
+ $f = $f+2;
+ break;
+ case "starts":
+ $leases[$l]['start'] = $data[$f+2];
+ $leases[$l]['start'] .= " " . $data[$f+3];
+ $f = $f+3;
+ break;
+ case "ends":
+ $leases[$l]['end'] = $data[$f+2];
+ $leases[$l]['end'] .= " " . $data[$f+3];
+ $f = $f+3;
+ break;
+ case "tstp":
+ $f = $f+3;
+ break;
+ case "tsfp":
+ $f = $f+3;
+ break;
+ case "atsfp":
+ $f = $f+3;
+ break;
+ case "cltt":
+ $f = $f+3;
+ break;
+ case "binding":
+ switch($data[$f+2]) {
+ case "active":
+ $leases[$l]['act'] = "active";
+ break;
+ case "free":
+ $leases[$l]['act'] = "expired";
+ $leases[$l]['online'] = "offline";
+ break;
+ case "backup":
+ $leases[$l]['act'] = "reserved";
+ $leases[$l]['online'] = "offline";
+ break;
+ }
+ $f = $f+1;
+ break;
+ case "next":
+ /* skip the next binding statement */
+ $f = $f+3;
+ break;
+ case "hardware":
+ $leases[$l]['mac'] = $data[$f+2];
+ /* check if it's online and the lease is active */
+ if($leases[$l]['act'] == "active") {
+ $online = exec("/usr/sbin/arp -an |/usr/bin/awk '/{$leases[$l]['ip']}/ {print}'|wc -l");
+ if ($online == 1) {
+ $leases[$l]['online'] = 'online';
+ } else {
+ $leases[$l]['online'] = 'offline';
+ }
+ }
+ $f = $f+2;
+ break;
+ case "client-hostname":
+ if($data[$f+1] <> "") {
+ $leases[$l]['hostname'] = preg_replace('/"/','',$data[$f+1]);
+ } else {
+ $hostname = gethostbyaddr($leases[$l]['ip']);
+ if($hostname <> "") {
+ $leases[$l]['hostname'] = $hostname;
+ }
+ }
+ $f = $f+1;
+ break;
+ case "uid":
+ $f = $f+1;
+ break;
+ }
+ $f++;
+ }
+ $l++;
+ $i++;
+}
+
+/* remove duplicate items by mac address */
+if(count($leases) > 0) {
+ $leases = remove_duplicate($leases,"ip");
+}
+
+if(count($pools) > 0) {
+ $pools = remove_duplicate($pools,"name");
+ asort($pools);
+}
+
+foreach($config['interfaces'] as $ifname => $ifarr) {
+ if (is_array($config['dhcpd'][$ifname]['staticmap'])) {
+ foreach($config['dhcpd'][$ifname]['staticmap'] as $static) {
+ $slease = array();
+ $slease['ip'] = $static['ipaddr'];
+ $slease['type'] = "static";
+ $slease['mac'] = $static['mac'];
+ $slease['start'] = gmdate("M d Y H:i:s", time());
+ $slease['end'] = gmdate("M d Y H:i:s", time());
+ $slease['end'] = gmdate("M d Y H:i:s", strtotime('+5 minutes'));
+ $slease['hostname'] = $static['hostname'];
+ $slease['act'] = "static";
+ $online = exec("/usr/sbin/arp -an |/usr/bin/grep {$slease['mac']}| /usr/bin/wc -l|/usr/bin/awk '{print $1;}'");
+ if ($online == 1) {
+ $slease['online'] = 'online';
+ } else {
+ $slease['online'] = 'offline';
+ }
+ $leases[] = $slease;
+ }
+ }
+}
+
+/* ========================================================================== */
+/* ====================== PROCESS POST AND GET VARS ========================= */
+/* ========================================================================== */
+
+if ($_GET['order']) {
+ usort($leases, "leasecmp");
+} else if ($_GET['refresh']) {
+ dl( 'json.so' );
+ echo json_encode($leases);
+ exit;
+}
+
+/* ========================================================================== */
+/* =================== GUI RELATED FUNCTIONS AND STUFF ====================== */
+/* ========================================================================== */
+
+$pgtitle = "Diagnostics: DHCP leases";
+
+$effectStyle = '
+ <style type="text/css">
+ .popup_dialog {
+ background: #000000;
+ opacity: 0.2;
+ }
+ </style>
+';
+
+include("head.inc");
+
+// add extra stuff to HTML head
+if (isset($pfSenseHead)) {
+ $pfSenseHead->setCloseHead(false);
+ print($pfSenseHead->getHTML());
+} else {
+ $closehead = false;
+}
+
+$scriptaculousRefs = '
+ <script type="text/javascript" src="/javascript/scriptaculous/prototype.js"></script>
+ <script type="text/javascript" src="/javascript/scriptaculous/scriptaculous.js"></script>
+';
+
+$ajaxRequest = "
+<script type='text/javascript' src='/javascript/dyntables.js'></script>
+<script type='text/javascript'>
+<!--
+ function refreshTable(column, all) {
+ var myAjax = new Ajax.Request(
+ '{$_SERVER['SCRIPT_NAME']}',
+ {
+ method: 'get',
+ parameters: { refresh: 'true' },
+ onLoading: openInfoDialog,
+ onSuccess: function(transport) {
+ var json = transport.responseText.evalJSON();
+ var table = document.getElementById('sortabletable');
+
+ emtyDhcpLeaseTable(table);
+ dhcpLeaseTableToHTML(table, json, '{$g['theme']}');
+ Dialog.closeInfo();
+ }
+ });
+ }
+//-->
+</script>
+";
+
+print($ajaxRequest);
+print($scriptaculousRefs);
+
+foreach(getWindowJSScriptRefs() as $jscript){
+ print("{$jscript}\n");
+}
+
+foreach(getWindowJSStyleRefs() as $style){
+ print("{$style}\n");
+}
+
+print($effectStyle);
+
+?>
+<script type="text/javascript" src="/javascript/sorttable.js"></script>
+</head>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<?php include("fbegin.inc"); ?>
+<p class="pgtitle"><?=$pgtitle?></p>
+<?php
+/* only print pool status when we have one */
+if(count($pools) > 0) {
+?>
+<table class="sortable" id="sortabletable" name="sortabletable" width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="listhdrr">Failover Group</a></td>
+ <td class="listhdrr">My State</a></td>
+ <td class="listhdrr">Since</a></td>
+ <td class="listhdrr">Peer State</a></td>
+ <td class="listhdrr">Since</a></td>
+ </tr>
+<?php
+foreach ($pools as $data) {
+ echo "<tr>\n";
+ echo "<td class=\"listlr\">{$fspans}{$data['name']}{$fspane}&nbsp;</td>\n";
+ echo "<td class=\"listr\">{$fspans}{$data['mystate']}{$fspane}&nbsp;</td>\n";
+ echo "<td class=\"listr\">{$fspans}" . adjust_gmt($data['mydate']) . "{$fspane}&nbsp;</td>\n";
+ echo "<td class=\"listr\">{$fspans}{$data['peerstate']}{$fspane}&nbsp;</td>\n";
+ echo "<td class=\"listr\">{$fspans}" . adjust_gmt($data['peerdate']) . "{$fspane}&nbsp;</td>\n";
+ echo "<td class=\"list\" valign=\"middle\" width=\"17\">&nbsp;</td>\n";
+ echo "<td class=\"list\" valign=\"middle\" width=\"17\">&nbsp;</td>\n";
+ echo "</tr>\n";
+}
+
+?>
+</table>
+
+<?php
+/* only print pool status when we have one */
+}
+
+$table = new Table();
+
+// assemble columns
+$table->addColumn("IP address", "ip");
+$table->addColumn("MAC address", "mac");
+$table->addColumn("Hostname", "hostname");
+$table->addColumn("Start", "start");
+$table->addColumn("End", "end");
+$table->addColumn("Online", "online");
+$table->addColumn("Lease Type", "act", "listhdr");
+
+// populate table data
+$table->setData($leases);
+
+?>
+
+<p>
+
+<table class="sortable" id="sortabletable" name="sortabletable" width="100%" border="0" cellpadding="0" cellspacing="0">
+<?= $table->getColumnHTML(); ?>
+<?php
+foreach ($table->getData() as $data) {
+ if (($data['act'] == "active") || ($data['act'] == "static") || ($_GET['all'] == 1)) {
+ if ($data['act'] != "active" && $data['act'] != "static") {
+ $fspans = "<span class=\"gray\">";
+ $fspane = "</span>";
+ } else {
+ $fspans = $fspane = "";
+ }
+ $lip = ip2long($data['ip']);
+ if ($data['act'] == "static") {
+ foreach ($config['dhcpd'] as $dhcpif => $dhcpifconf) {
+ if(is_array($dhcpifconf['staticmap'])) {
+ foreach ($dhcpifconf['staticmap'] as $staticent) {
+ if ($data['ip'] == $staticent['ipaddr']) {
+ $data['if'] = $dhcpif;
+ break;
+ }
+ }
+ }
+ /* exit as soon as we have an interface */
+ if ($data['if'] != "")
+ break;
+ }
+ } else {
+ foreach ($config['dhcpd'] as $dhcpif => $dhcpifconf) {
+ if (($lip >= ip2long($dhcpifconf['range']['from'])) && ($lip <= ip2long($dhcpifconf['range']['to']))) {
+ $data['if'] = $dhcpif;
+ break;
+ }
+ }
+ }
+ echo "<tr>\n";
+ echo "<td class=\"listlr\">{$fspans}{$data['ip']}{$fspane}&nbsp;</td>\n";
+ if ($data['online'] != "online") {
+ echo "<td class=\"listr\">{$fspans}<a href=\"services_wol.php?if={$data['if']}&mac={$data['mac']}\" title=\"send Wake on Lan packet to mac\">{$data['mac']}</a>{$fspane}&nbsp;</td>\n";
+ } else {
+ echo "<td class=\"listr\">{$fspans}{$data['mac']}{$fspane}&nbsp;</td>\n";
+ }
+ echo "<td class=\"listr\">{$fspans}{$data['hostname']}{$fspane}&nbsp;</td>\n";
+ echo "<td class=\"listr\">{$fspans}" . adjust_gmt($data['start']) . "{$fspane}&nbsp;</td>\n";
+ echo "<td class=\"listr\">{$fspans}" . adjust_gmt($data['end']) . "{$fspane}&nbsp;</td>\n";
+ echo "<td class=\"listr\">{$fspans}{$data['online']}{$fspane}&nbsp;</td>\n";
+ echo "<td class=\"listr\">{$fspans}{$data['act']}{$fspane}&nbsp;</td>\n";
+
+ if ($data['type'] == "dynamic") {
+ echo "<td class=\"list\" valign=\"middle\"><a href=\"services_dhcp_edit.php?if={$data['if']}&mac={$data['mac']}&hostname={$data['hostname']}\">";
+ echo "<img src=\"/themes/{$g['theme']}/images/icons/icon_plus.gif\" width=\"17\" height=\"17\" border=\"0\" title=\"add a static mapping for this MAC address\"></a></td>\n";
+ } else {
+ echo "<td class=\"list\" valign=\"middle\">";
+ echo "<img src=\"/themes/{$g['theme']}/images/icons/icon_plus_mo.gif\" width=\"17\" height=\"17\" border=\"0\"></td>\n";
+ }
+
+ echo "<td valign=\"middle\"><a href=\"services_wol_edit.php?if={$data['if']}&mac={$data['mac']}&descr={$data['hostname']}\">";
+ echo "<img src=\"/themes/{$g['theme']}/images/icons/icon_wol_all.gif\" width=\"17\" height=\"17\" border=\"0\" title=\"add a Wake on Lan mapping for this MAC address\"></a></td>\n";
+ echo "</tr>\n";
+ }
+}
+
+?>
+</table>
+<p>
+<form action="diag_dhcp_leases.php" method="GET">
+<input type="hidden" name="order" value="<?=$_GET['order'];?>">
+<?php if ($_GET['all']): ?>
+<input type="hidden" name="all" value="0">
+<input type="submit" class="formbtn" value="Show active and static leases only">
+<?php else: ?>
+<input type="hidden" name="all" value="1">
+<input type="submit" class="formbtn" value="Show all configured leases">
+<?php endif; ?>
+</form>
+<?php if($leases == 0): ?>
+<p><strong>No leases file found. Is the DHCP server active?</strong></p>
+<?php endif; ?>
+
+<div id="popupanchor">&#160;</div>
+<?= checkForExtension("popup_dialog"); ?>
+<?php include("fend.inc"); ?>
+<script type="text/javascript">
+<!--
+ window.setInterval("refreshTable()", 20000);
+//-->
+</script>
+</body>
+</html>
diff --git a/config/freenas/bin/ext2fs.ko b/config/freenas/bin/ext2fs.ko
new file mode 100644
index 00000000..042b4bb8
--- /dev/null
+++ b/config/freenas/bin/ext2fs.ko
Binary files differ
diff --git a/config/freenas/bin/geom_concat.ko b/config/freenas/bin/geom_concat.ko
new file mode 100644
index 00000000..f1c40215
--- /dev/null
+++ b/config/freenas/bin/geom_concat.ko
Binary files differ
diff --git a/config/freenas/bin/geom_gpt.ko b/config/freenas/bin/geom_gpt.ko
new file mode 100644
index 00000000..308b017b
--- /dev/null
+++ b/config/freenas/bin/geom_gpt.ko
Binary files differ
diff --git a/config/freenas/bin/geom_mirror.ko b/config/freenas/bin/geom_mirror.ko
new file mode 100644
index 00000000..50a5f5ac
--- /dev/null
+++ b/config/freenas/bin/geom_mirror.ko
Binary files differ
diff --git a/config/freenas/bin/geom_stripe.ko b/config/freenas/bin/geom_stripe.ko
new file mode 100644
index 00000000..dd8e6a4d
--- /dev/null
+++ b/config/freenas/bin/geom_stripe.ko
Binary files differ
diff --git a/config/freenas/bin/geom_vinum.ko b/config/freenas/bin/geom_vinum.ko
new file mode 100644
index 00000000..c550fc83
--- /dev/null
+++ b/config/freenas/bin/geom_vinum.ko
Binary files differ
diff --git a/config/freenas/bin/iscontrol b/config/freenas/bin/iscontrol
new file mode 100644
index 00000000..f2e3f409
--- /dev/null
+++ b/config/freenas/bin/iscontrol
Binary files differ
diff --git a/config/freenas/bin/iscsi_initiator.ko b/config/freenas/bin/iscsi_initiator.ko
new file mode 100644
index 00000000..94a07423
--- /dev/null
+++ b/config/freenas/bin/iscsi_initiator.ko
Binary files differ
diff --git a/config/freenas/bin/kernel.gz b/config/freenas/bin/kernel.gz
new file mode 100644
index 00000000..9d9eb3f2
--- /dev/null
+++ b/config/freenas/bin/kernel.gz
Binary files differ
diff --git a/config/freenas/bin/mountd b/config/freenas/bin/mountd
new file mode 100644
index 00000000..55682c7b
--- /dev/null
+++ b/config/freenas/bin/mountd
Binary files differ
diff --git a/config/freenas/bin/nfsd b/config/freenas/bin/nfsd
new file mode 100644
index 00000000..311f1fca
--- /dev/null
+++ b/config/freenas/bin/nfsd
Binary files differ
diff --git a/config/freenas/bin/ntfs.ko b/config/freenas/bin/ntfs.ko
new file mode 100644
index 00000000..1e923dac
--- /dev/null
+++ b/config/freenas/bin/ntfs.ko
Binary files differ
diff --git a/config/freenas/bin/rpc.lockd b/config/freenas/bin/rpc.lockd
new file mode 100644
index 00000000..906a8641
--- /dev/null
+++ b/config/freenas/bin/rpc.lockd
Binary files differ
diff --git a/config/freenas/bin/rpc.statd b/config/freenas/bin/rpc.statd
new file mode 100644
index 00000000..c630a05a
--- /dev/null
+++ b/config/freenas/bin/rpc.statd
Binary files differ
diff --git a/config/freenas/bin/rpcbind b/config/freenas/bin/rpcbind
new file mode 100644
index 00000000..882d9c4d
--- /dev/null
+++ b/config/freenas/bin/rpcbind
Binary files differ
diff --git a/config/freenas/conf.default/config.xml b/config/freenas/conf.default/config.xml
new file mode 100644
index 00000000..74ed6186
--- /dev/null
+++ b/config/freenas/conf.default/config.xml
@@ -0,0 +1,179 @@
+<?xml version="1.0"?>
+<!-- FreeNAS default system configuration -->
+<freenas>
+ <version>1.1</version>
+ <lastchange/>
+ <system>
+ <hostname>freenas</hostname>
+ <domain>local</domain>
+ <dnsserver/>
+ <dnsallowoverride/>
+ <username>admin</username>
+ <password>$1$KLfrklGE$9mMLCl/tNeqZJzdCJw6Gb0</password>
+ <timezone>Etc/UTC</timezone>
+ <time-update-interval>300</time-update-interval>
+ <timeservers>pool.ntp.org</timeservers>
+ <webgui>
+ <protocol>http</protocol>
+ <!--
+ <port></port>
+ <certificate></certificate>
+ <private-key></private-key>
+ <noassigninterfaces/>
+ <expanddiags/>
+ <noantilockout></noantilockout>
+ -->
+ </webgui>
+ <!-- <disableconsolemenu/> -->
+ <!-- <disablefirmwarecheck/> -->
+ <!-- <shellcmd></shellcmd> -->
+ <!-- <earlyshellcmd></earlyshellcmd> -->
+ <!-- <harddiskstandby></harddiskstandby> -->
+ <!-- <polling/> -->
+ </system>
+ <interfaces>
+ <lan>
+ <if>sis0</if>
+ <ipaddr>192.168.1.250</ipaddr>
+ <subnet>24</subnet>
+ <media/>
+ <mediaopt/>
+ <!--
+ <wireless>
+ *see below (opt[n])*
+ </wireless>
+ -->
+ </lan>
+ <!--
+ <opt[n]>
+ <enable/>
+ <descr></descr>
+ <if></if>
+ <ipaddr></ipaddr>
+ <subnet></subnet>
+ <media></media>
+ <mediaopt></mediaopt>
+ <bridge>lan|wan|opt[n]</bridge>
+ <wireless>
+ <standard>11a|11b|11g</standard>
+ <mode>hostap *or* bss *or* ibss</mode>
+ <ssid></ssid>
+ <channel></channel>
+ <wep>
+ <enable/>
+ <key>
+ <txkey/>
+ <value></value>
+ </key>
+ </wep>
+ </wireless>
+ </opt[n]>
+ -->
+ </interfaces>
+ <!--
+ <vlans>
+ <vlan>
+ <tag></tag>
+ <if></if>
+ <descr></descr>
+ </vlan>
+ </vlans>
+ -->
+ <staticroutes>
+ <!--
+ <route>
+ <interface>lan|opt[n]|pptp</interface>
+ <network>xxx.xxx.xxx.xxx/xx</network>
+ <gateway>xxx.xxx.xxx.xxx</gateway>
+ <descr></descr>
+ </route>
+ -->
+ </staticroutes>
+ <disks>
+ <!--
+ <disk>
+ <device>xxx</device>
+ <type>IDE|SCSI</type>
+ <position>master|slave|number</position>
+ <desc>xxx</desc>
+ <status>ok|new|missing</status>
+ </disk>
+ -->
+
+ </disks>
+ <mounts>
+ <!--
+ <mount>
+ <device>xxx</device>
+ <fstype>msdosfs|ufs|ntfs|etc...</fstype>
+ <options>xxx</options>
+ </mount>
+ -->
+ </mounts>
+ <samba>
+ <!-- <enable/> -->
+ <netbiosname>freenas</netbiosname>
+ <workgroup>WORKGROUP</workgroup>
+ <serverdesc>FreeNAS Server</serverdesc>
+ <security>share</security>
+ <localmaster>yes</localmaster>
+ </samba>
+ <ftp>
+ <!-- <enable/> -->
+ <numberclients>5</numberclients>
+ <maxconperip>2</maxconperip>
+ <timeout>300</timeout>
+ <port>21</port>
+ <anonymous>yes</anonymous>
+ <localuser>yes</localuser>
+ <pasv_max_port>0</pasv_max_port>
+ <pasv_min_port>0</pasv_min_port>
+ </ftp>
+ <afp>
+ <!-- <enable/> -->
+ </afp>
+ <rsyncd>
+ <!-- <enable/> -->
+ <readonly>no</readonly>
+ <port>873</port>
+ </rsyncd>
+ <sshd>
+ <!-- <enable/> -->
+ <port>22</port>
+ </sshd>
+
+ <nfs>
+ <!-- <enable/> -->
+ </nfs>
+ <snmpd>
+ <!-- <enable/> -->
+ <syslocation/>
+ <syscontact/>
+ <rocommunity>public</rocommunity>
+ </snmpd>
+ <diag>
+ <ipv6nat>
+ <!-- <enable/> -->
+ <ipaddr/>
+ </ipv6nat>
+ <!-- <ipfstatentries></ipfstatentries> -->
+ </diag>
+ <bridge>
+ <!-- <filteringbridge/> -->
+ </bridge>
+ <syslog>
+ <!--
+ <reverse/>
+ <enable/>
+ <remoteserver>xxx.xxx.xxx.xxx</remoteserver>
+ <system/>
+ <nologdefaultblock/>
+ <resolve/>
+ -->
+ </syslog>
+ <access>
+ <userid>1002</userid>
+ <groupid>1002</groupid>
+ </access>
+
+</freenas> \ No newline at end of file
diff --git a/config/freenas/conf.kernel/pfSense.6.freenas b/config/freenas/conf.kernel/pfSense.6.freenas
new file mode 100644
index 00000000..aee11302
--- /dev/null
+++ b/config/freenas/conf.kernel/pfSense.6.freenas
@@ -0,0 +1,433 @@
+#
+# GENERIC -- Generic kernel configuration file for FreeBSD/i386
+#
+# For more information on this file, please read the handbook section on
+# Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD: src/sys/i386/conf/GENERIC,v 1.429.2.7.2.2 2006/05/01 00:15:12 scottl Exp $
+
+machine i386
+cpu I486_CPU
+cpu I586_CPU
+cpu I686_CPU
+ident pfSense
+
+# To statically compile in device wiring instead of /boot/device.hints
+#hints "GENERIC.hints" # Default places to look for devices.
+
+makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
+
+#FREENAS ADD lines:
+options NO_SWAPPING
+options HZ=1000
+
+#options SCHED_ULE # ULE scheduler
+options SCHED_4BSD # 4BSD scheduler
+options PREEMPTION # Enable kernel thread preemption
+options INET # InterNETworking
+options INET6 # IPv6 communications protocols
+options FFS # Berkeley Fast Filesystem
+options SOFTUPDATES # Enable FFS soft updates support
+options UFS_ACL # Support for access control lists
+options UFS_DIRHASH # Improve performance on big directories
+options MD_ROOT # MD is a potential root device
+options NFSCLIENT # Network Filesystem Client
+options NFSSERVER # Network Filesystem Server
+options NFS_ROOT # NFS usable as /, requires NFSCLIENT
+options MSDOSFS # MSDOS Filesystem
+options MSDOSFS_LARGE # MSDOS Filesystem for FAT32 > 128GB
+options CD9660 # ISO 9660 Filesystem
+options PROCFS # Process filesystem (requires PSEUDOFS)
+options PSEUDOFS # Pseudo-filesystem framework
+options GEOM_GPT # GUID Partition Tables.
+options COMPAT_43 # Compatible with BSD 4.3 [KEEP THIS!]
+options COMPAT_FREEBSD4 # Compatible with FreeBSD4
+options COMPAT_FREEBSD5 # Compatible with FreeBSD5
+options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI
+options KTRACE # ktrace(1) support
+options SYSVSHM # SYSV-style shared memory
+options SYSVMSG # SYSV-style message queues
+options SYSVSEM # SYSV-style semaphores
+options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions
+options KBD_INSTALL_CDEV # install a CDEV entry in /dev
+options AHC_REG_PRETTY_PRINT # Print register bitfields in debug
+ # output. Adds ~128k to driver.
+options AHD_REG_PRETTY_PRINT # Print register bitfields in debug
+ # output. Adds ~215k to driver.
+options ADAPTIVE_GIANT # Giant mutex is adaptive.
+
+#FreeNAS include ACPI in the kernel:
+device acpi # acpi -- Advanced Configuration and Power Management support
+
+device apic # I/O APIC
+
+# Bus support.
+device eisa
+device pci
+
+# Floppy drives
+device fdc
+
+# ATA and ATAPI devices
+device ata
+device atadisk # ATA disk drives
+device ataraid # ATA RAID drives
+device atapicd # ATAPI CDROM drives
+device atapifd # ATAPI floppy drives
+#device atapifd # ATAPI floppy drives
+device atapist # ATAPI tape drives
+options ATA_STATIC_ID # Static device numbering
+
+# SCSI Controllers
+device ahb # EISA AHA1742 family
+device ahc # AHA2940 and onboard AIC7xxx devices
+device ahd # AHA39320/29320 and onboard AIC79xx devices
+device amd # AMD 53C974 (Tekram DC-390(T))
+device isp # Qlogic family
+device ispfw # Firmware for QLogic HBAs- normally a module
+device mpt # LSI-Logic MPT-Fusion
+#device ncr # NCR/Symbios Logic
+device sym # NCR/Symbios Logic (newer chipsets + those of `ncr')
+device trm # Tekram DC395U/UW/F DC315U adapters
+
+device adv # Advansys SCSI adapters
+device adw # Advansys wide SCSI adapters
+device aha # Adaptec 154x SCSI adapters
+device aic # Adaptec 15[012]x SCSI adapters, AIC-6[23]60.
+device bt # Buslogic/Mylex MultiMaster SCSI adapters
+
+device ncv # NCR 53C500
+device nsp # Workbit Ninja SCSI-3
+device stg # TMC 18C30/18C50
+
+#FREENAS ADD SPECIAL DRIVERSAdding special IOI-A100U2W drivers:
+device ihb # IOI-A100U2W drivers
+
+# SCSI peripherals
+device scbus # SCSI bus (required for SCSI)
+device ch # SCSI media changers
+device da # Direct Access (disks)
+device sa # Sequential Access (tape etc)
+device cd # CD
+device pass # Passthrough device (direct SCSI access)
+device ses # SCSI Environmental Services (and SAF-TE)
+
+# RAID controllers interfaced to the SCSI subsystem
+device amr # AMI MegaRAID
+device arcmsr # Areca SATA II RAID
+device asr # DPT SmartRAID V, VI and Adaptec SCSI RAID
+device ciss # Compaq Smart RAID 5*
+device dpt # DPT Smartcache III, IV - See NOTES for options
+device hptmv # Highpoint RocketRAID 182x
+device rr232x # Highpoint RocketRAID 232x
+device iir # Intel Integrated RAID
+device ips # IBM (Adaptec) ServeRAID
+device mly # Mylex AcceleRAID/eXtremeRAID
+device twa # 3ware 9000 series PATA/SATA RAID
+
+# RAID controllers
+device aac # Adaptec FSA RAID
+device aacp # SCSI passthrough for aac (requires CAM)
+device ida # Compaq Smart RAID
+device mfi # LSI MegaRAID SAS
+device mlx # Mylex DAC960 family
+device pst # Promise Supertrak SX6000
+device twe # 3ware ATA RAID
+
+# atkbdc0 controls both the keyboard and the PS/2 mouse
+device atkbdc # AT keyboard controller
+device atkbd # AT keyboard
+device psm # PS/2 mouse
+
+device kbdmux # keyboard multiplexer
+
+device vga # VGA video card driver
+
+device splash # Splash screen and screen saver support
+
+# syscons is the default console driver, resembling an SCO console
+device sc
+
+# Enable this for the pcvt (VT220 compatible) console driver
+#device vt
+#options XSERVER # support for X server on a vt console
+#options FAT_CURSOR # start with block cursor
+
+device agp # support several AGP chipsets
+
+# Power management support (see NOTES for more options)
+#device apm
+# Add suspend/resume support for the i8254.
+device pmtimer
+
+# PCCARD (PCMCIA) support
+# PCMCIA and cardbus bridge support
+device cbb # cardbus (yenta) bridge
+device pccard # PC Card (16-bit) bus
+device cardbus # CardBus (32-bit) bus
+
+# Serial (COM) ports
+device sio # 8250, 16[45]50 based serial ports
+
+# Parallel port
+device ppc
+device ppbus # Parallel port bus (required)
+device lpt # Printer
+device ppi # Parallel port interface device
+#device vpo # Requires scbus and da
+
+# If you've got a "dumb" serial or parallel PCI card that is
+# supported by the puc(4) glue driver, uncomment the following
+# line to enable it (connects to the sio and/or ppc drivers):
+#device puc
+
+# PCI Ethernet NICs.
+device de # DEC/Intel DC21x4x (``Tulip'')
+device em # Intel PRO/1000 adapter Gigabit Ethernet Card
+device ixgb # Intel PRO/10GbE Ethernet Card
+device txp # 3Com 3cR990 (``Typhoon'')
+device vx # 3Com 3c590, 3c595 (``Vortex'')
+
+# PCI Ethernet NICs that use the common MII bus controller code.
+# NOTE: Be sure to keep the 'device miibus' line in order to use these NICs!
+device miibus # MII bus support
+device bce # Broadcom BCM5706/BCM5708 Gigabit Ethernet
+device bfe # Broadcom BCM440x 10/100 Ethernet
+device bge # Broadcom BCM570xx Gigabit Ethernet
+device dc # DEC/Intel 21143 and various workalikes
+device fxp # Intel EtherExpress PRO/100B (82557, 82558)
+device lge # Level 1 LXT1001 gigabit Ethernet
+device nge # NatSemi DP83820 gigabit Ethernet
+device nve # nVidia nForce MCP on-board Ethernet Networking
+device pcn # AMD Am79C97x PCI 10/100(precedence over 'lnc')
+device re # RealTek 8139C+/8169/8169S/8110S
+device rl # RealTek 8129/8139
+device sf # Adaptec AIC-6915 (``Starfire'')
+device sis # Silicon Integrated Systems SiS 900/SiS 7016
+device sk # SysKonnect SK-984x & SK-982x gigabit Ethernet
+device ste # Sundance ST201 (D-Link DFE-550TX)
+device ti # Alteon Networks Tigon I/II gigabit Ethernet
+device tl # Texas Instruments ThunderLAN
+device tx # SMC EtherPower II (83c170 ``EPIC'')
+device vge # VIA VT612x gigabit Ethernet
+device vr # VIA Rhine, Rhine II
+device wb # Winbond W89C840F
+device xl # 3Com 3c90x (``Boomerang'', ``Cyclone'')
+
+# ISA Ethernet NICs. pccard NICs included.
+device cs # Crystal Semiconductor CS89x0 NIC
+# 'device ed' requires 'device miibus'
+device ed # NE[12]000, SMC Ultra, 3c503, DS8390 cards
+device ex # Intel EtherExpress Pro/10 and Pro/10+
+device ep # Etherlink III based cards
+device fe # Fujitsu MB8696x based cards
+device ie # EtherExpress 8/16, 3C507, StarLAN 10 etc.
+device le # NE2100, NE32-VL Lance Ethernet cards
+device sn # SMC's 9000 series of Ethernet chips
+device xe # Xircom pccard Ethernet
+
+# Wireless NIC cards
+device wlan # 802.11 support
+device an # Aironet 4500/4800 802.11 wireless NICs.
+device awi # BayStack 660 and others
+device ral # Ralink Technology RT2500 wireless NICs.
+device wi # WaveLAN/Intersil/Symbol 802.11 wireless NICs.
+#device wl # Older non 802.11 Wavelan wireless NIC.
+
+# Pseudo devices.
+device loop # Network loopback
+device random # Entropy device
+device ether # Ethernet support
+device sl # Kernel SLIP
+device ppp # Kernel PPP
+device tun # Packet tunnel.
+device pty # Pseudo-ttys (telnet etc)
+device md # Memory "disks"
+device gif # IPv6 and IPv4 tunneling
+device faith # IPv6-to-IPv4 relaying (translation)
+
+# The `bpf' device enables the Berkeley Packet Filter.
+# Be aware of the administrative consequences of enabling this!
+# Note that 'bpf' is required for DHCP.
+device bpf # Berkeley packet filter
+
+# USB support
+device uhci # UHCI PCI->USB interface
+device ohci # OHCI PCI->USB interface
+device ehci # EHCI PCI->USB interface (USB 2.0)
+device usb # USB Bus (required)
+#device udbp # USB Double Bulk Pipe devices
+device ugen # Generic
+device uhid # "Human Interface Devices"
+device ukbd # Keyboard
+device ulpt # Printer
+device umass # Disks/Mass storage - Requires scbus and da
+device ums # Mouse
+device ural # Ralink Technology RT2500USB wireless NICs
+device urio # Diamond Rio 500 MP3 player
+device uscanner # Scanners
+# USB Ethernet, requires miibus
+device aue # ADMtek USB Ethernet
+device axe # ASIX Electronics USB Ethernet
+device cdce # Generic USB over Ethernet
+device cue # CATC USB Ethernet
+device kue # Kawasaki LSI USB Ethernet
+device rue # RealTek RTL8150 USB Ethernet
+
+# FireWire support
+device firewire # FireWire bus code
+device sbp # SCSI over FireWire (Requires scbus and da)
+device fwe # Ethernet over FireWire (non-standard!)
+device fwip
+
+# pfSense addons
+
+# Wireless NIC cards
+device wlan # 802.11 support
+device wlan_wep
+device wlan_ccmp
+device wlan_tkip
+device wlan_xauth
+device wlan_acl
+device ath
+device ath_rate_sample
+device ath_hal
+device an # Aironet 4500/4800 802.11 wireless NICs.
+device awi # BayStack 660 and others
+device iwi # Intel PRO/Wireless 2200BG
+device ipw
+device ral # Ralink Technology RT2500 wireless NICs.
+device wi # WaveLAN/Intersil/Symbol 802.11 wireless NICs.
+device wl # Older non 802.11 Wavelan wireless NIC.
+
+options COMPAT_FREEBSD5
+
+options UNIONFS # Union filesystem
+
+device bktr
+
+#options IPFIREWALL
+#options DUMMYNET
+#options IPDIVERT
+options IPFIREWALL_DEFAULT_TO_ACCEPT
+options IPFIREWALL_FORWARD
+options IPFIREWALL_VERBOSE
+options IPFIREWALL_VERBOSE_LIMIT
+
+device carp
+device pf
+device pflog
+device pfsync
+device vlan
+device gre
+
+options IPSTEALTH
+options TCP_DROP_SYNFIN #drop TCP packets with SYN+FIN
+options GEOM_UZIP
+options GEOM_LABEL
+
+options INCLUDE_CONFIG_FILE
+
+#options BRIDGE
+options NETGRAPH #netgraph(4) system
+options NETGRAPH_ASYNC
+options NETGRAPH_BPF
+options NETGRAPH_BRIDGE
+options NETGRAPH_CISCO
+options NETGRAPH_ECHO
+options NETGRAPH_ETHER
+options NETGRAPH_FRAME_RELAY
+options NETGRAPH_HOLE
+options NETGRAPH_IFACE
+options NETGRAPH_KSOCKET
+
+options NETGRAPH_LMI
+options NETGRAPH_MPPC_ENCRYPTION
+options NETGRAPH_ONE2MANY
+options NETGRAPH_PPP
+options NETGRAPH_PPPOE
+options NETGRAPH_PPTPGRE
+options NETGRAPH_RFC1490
+options NETGRAPH_SOCKET
+options NETGRAPH_TEE
+options NETGRAPH_TTY
+options NETGRAPH_UI
+options NETGRAPH_VJC
+
+device ubsa
+device ucom
+
+options FAST_IPSEC
+#options IPSEC_NAT_T
+device enc
+
+device crypto # core crypto support
+device cryptodev # /dev/crypto for access to h/w
+device rndtest # FIPS 140-2 entropy tester
+device hifn # Hifn 7951, 7781, etc.
+options HIFN_DEBUG # enable debugging support: hw.hifn.debug
+options HIFN_RNDTEST # enable rndtest support
+device ubsec # Broadcom 5501, 5601, 58xx
+
+options ALTQ
+options ALTQ_CBQ
+options ALTQ_RED
+options ALTQ_RIO
+options ALTQ_HFSC
+options ALTQ_PRIQ
+options ALTQ_NOPCC # Required for SMP builds !!
+
+
+# Bridging
+device if_bridge
+
+options MSGMNB=8192 # max # of bytes in a queue
+options MSGMNI=40 # number of message queue identifiers
+options MSGSEG=512 # number of message segments per queue
+options MSGSSZ=32 # size of a message segment
+options MSGTQL=2048 # max messages in system
+
+device tap
+device hme
+
+# Needed for FreeSBIE 2
+options NULLFS
+
+# Kbdmux
+device kbdmux
+
+device speaker
+
+options DEVICE_POLLING
+
+options ZERO_COPY_SOCKETS
+
+#device natpt
+
+device bce # Broadcom BCM5706/BCM5708 Gigabit Ethernet
+
+options TCP_SIGNATURE
+
+# To make an SMP kernel, the next two lines are needed
+options SMP # Symmetric MultiProcessor Kernel
+device apic # I/O APIC
+
+# Allow gmirror to function
+options GEOM_MIRROR
+options GEOM_MBR
+
+options PREEMPTION
+
+
diff --git a/config/freenas/diffs/netatalk-2.0.3-afpd-zeroconf.patch b/config/freenas/diffs/netatalk-2.0.3-afpd-zeroconf.patch
new file mode 100644
index 00000000..74ee8795
--- /dev/null
+++ b/config/freenas/diffs/netatalk-2.0.3-afpd-zeroconf.patch
@@ -0,0 +1,1386 @@
+? etc/afpd/afp_avahi.c
+? etc/afpd/afp_avahi.c.org
+? etc/afpd/afp_avahi.h
+? etc/afpd/afp_avahi.h.org
+? etc/afpd/afp_bonjour.c
+? etc/afpd/afp_bonjour.c.org
+? etc/afpd/afp_bonjour.h
+? etc/afpd/afp_bonjour.h.org
+? etc/afpd/afp_howl.c
+? etc/afpd/afp_howl.c.org
+? etc/afpd/afp_howl.h
+? etc/afpd/afp_howl.h.org
+? etc/afpd/afp_zeroconf.c
+? etc/afpd/afp_zeroconf.c.org
+? etc/afpd/afp_zeroconf.h
+? etc/afpd/afp_zeroconf.h.org
+? macros/zeroconf.m4
+? macros/zeroconf.m4.org
+Index: configure.in
+===================================================================
+RCS file: /cvsroot/netatalk/netatalk/configure.in,v
+retrieving revision 1.203
+diff -u -r1.203 configure.in
+--- configure.in 28 Apr 2005 20:49:17 -0000 1.203
++++ configure.in 5 May 2006 10:46:30 -0000
+@@ -398,6 +398,9 @@
+ dnl Check for optional server location protocol support (used by MacOS X)
+ NETATALK_SRVLOC
+
++dnl Check for optional Zeroconf support
++NETATALK_ZEROCONF
++
+ dnl Check for PAM libs
+ netatalk_cv_use_pam=no
+ AC_PATH_PAM([
+Index: config/afpd.conf.tmpl
+===================================================================
+RCS file: /cvsroot/netatalk/netatalk/config/afpd.conf.tmpl,v
+retrieving revision 1.16
+diff -u -r1.16 afpd.conf.tmpl
+--- config/afpd.conf.tmpl 28 Apr 2005 20:49:20 -0000 1.16
++++ config/afpd.conf.tmpl 5 May 2006 10:46:31 -0000
+@@ -51,6 +51,8 @@
+ # empty string.
+ # -noslp Don't register this server with the Service
+ # Location Protocol.
++# -nozeroconf Don't register this server with the Multicats
++# DNS Protocol.
+ #
+ #
+ # Authentication Methods:
+Index: contrib/a2boot/Makefile.am
+===================================================================
+RCS file: /cvsroot/netatalk/netatalk/contrib/a2boot/Makefile.am,v
+retrieving revision 1.5
+diff -u -r1.5 Makefile.am
+--- contrib/a2boot/Makefile.am 28 Apr 2005 20:49:21 -0000 1.5
++++ contrib/a2boot/Makefile.am 5 May 2006 10:46:32 -0000
+@@ -10,7 +10,7 @@
+ EXTRA_DIST = COPYRIGHT VERSION
+
+ CFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/sys \
+- @CFLAGS@ @SLP_CFLAGS@ \
++ @CFLAGS@ @SLP_CFLAGS@ @ZEROCONF_CFLAGS@ \
+ -D_PATH_A_GS_BLOCKS=\"$(PKGCONFDIR)/a2boot/ProDOS16\ Boot\ Blocks\" \
+ -D_PATH_A_2E_BLOCKS=\"$(PKGCONFDIR)/a2boot/Apple\ :2f:2fe\ Boot\ Blocks\" \
+ -D_PATH_P16_IMAGE=\"$(PKGCONFDIR)/a2boot/ProDOS16\ Image\"
+Index: etc/afpd/Makefile.am
+===================================================================
+RCS file: /cvsroot/netatalk/netatalk/etc/afpd/Makefile.am,v
+retrieving revision 1.38
+diff -u -r1.38 Makefile.am
+--- etc/afpd/Makefile.am 30 Apr 2005 21:33:41 -0000 1.38
++++ etc/afpd/Makefile.am 5 May 2006 10:46:33 -0000
+@@ -8,19 +8,21 @@
+ file.c enumerate.c desktop.c filedir.c fork.c appl.c gettok.c \
+ mangle.c status.c afp_options.c afp_asp.c afp_dsi.c messages.c \
+ afp_config.c nfsquota.c quota.c uam.c afs.c uid.c afp_util.c \
+- catsearch.c afprun.c
++ catsearch.c afprun.c \
++ afp_zeroconf.c afp_avahi.c afp_bonjour.c afp_howl.c
+
+ afpd_LDADD = $(top_builddir)/libatalk/cnid/libcnid.la $(top_builddir)/libatalk/libatalk.la
+ afpd_LDFLAGS = -export-dynamic
+
+ noinst_HEADERS = auth.h afp_config.h desktop.h directory.h file.h \
+ filedir.h fork.h globals.h icon.h mangle.h misc.h status.h switch.h \
+- uam_auth.h uid.h unix.h volume.h
++ uam_auth.h uid.h unix.h volume.h \
++ afp_zeroconf.h afp_avahi.h afp_bonjour.h afp_howl.h
+
+-LIBS = @LIBS@ @PAM_LIBS@ @QUOTA_LIBS@ @SLP_LIBS@ @WRAP_LIBS@
++LIBS = @LIBS@ @PAM_LIBS@ @QUOTA_LIBS@ @SLP_LIBS@ @ZEROCONF_LIBS@ @WRAP_LIBS@
+
+ CFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/sys \
+- @CFLAGS@ @SLP_CFLAGS@ \
++ @CFLAGS@ @SLP_CFLAGS@ @ZEROCONF_CFLAGS@ \
+ -D_PATH_AFPDDEFVOL=\"$(pkgconfdir)/AppleVolumes.default\" \
+ -D_PATH_AFPDSYSVOL=\"$(pkgconfdir)/AppleVolumes.system\" \
+ -D_PATH_AFPDPWFILE=\"$(pkgconfdir)/afppasswd\" \
+Index: etc/afpd/afp_config.c
+===================================================================
+RCS file: /cvsroot/netatalk/netatalk/etc/afpd/afp_config.c,v
+retrieving revision 1.23
+diff -u -r1.23 afp_config.c
+--- etc/afpd/afp_config.c 28 Apr 2005 20:49:39 -0000 1.23
++++ etc/afpd/afp_config.c 5 May 2006 10:46:35 -0000
+@@ -50,6 +50,9 @@
+ #ifdef USE_SRVLOC
+ #include <slp.h>
+ #endif /* USE_SRVLOC */
++#ifdef USE_ZEROCONF
++#include "afp_zeroconf.h"
++#endif /* USE_ZEROCONF */
+
+ #include "globals.h"
+ #include "afp_config.h"
+@@ -154,9 +157,9 @@
+ }
+ #endif /* USE_SRVLOC */
+
+-#ifdef USE_SRVLOC
+ static void dsi_cleanup(const AFPConfig *config)
+ {
++#ifdef USE_SRVLOC
+ SLPError err;
+ SLPError callbackerr;
+ SLPHandle hslp;
+@@ -189,8 +192,16 @@
+ srvloc_dereg_err:
+ dsi->srvloc_url[0] = '\0';
+ SLPClose(hslp);
+-}
++#elif defined (USE_ZEROCONF)
++ DSI *dsi = (DSI *)config->obj.handle;
++
++ /* Do nothing if we didn't register. */
++ if (!dsi || dsi->zeroconf_registered == 0)
++ return;
++
++ zeroconf_deregister();
+ #endif /* USE_SRVLOC */
++}
+
+ #ifndef NO_DDP
+ static void asp_cleanup(const AFPConfig *config)
+@@ -355,6 +366,10 @@
+ struct servent *afpovertcp;
+ int afp_port = 548;
+ char *srvloc_hostname, *hostname;
++#elif defined (USE_ZEROCONF)
++ struct servent *afpovertcp;
++ int afp_port = 548;
++ char *hostname = NULL;
+ #endif /* USE_SRVLOC */
+
+ if ((config = (AFPConfig *) calloc(1, sizeof(AFPConfig))) == NULL) {
+@@ -449,6 +464,36 @@
+ }
+ #endif /* USE_SRVLOC */
+
++#ifdef USE_ZEROCONF
++ dsi->zeroconf_registered = 0; /* Mark that we haven't registered. */
++
++ if (!(options->flags & OPTION_NOZEROCONF)) {
++ /* XXX We don't want to tack on the port number if we don't have to.
++ * Why?
++ * Well, this seems to break MacOS < 10. If the user _really_ wants to
++ * use a non-default port, they can, but be aware, this server might
++ * not show up int the Network Browser.
++ */
++ afpovertcp = getservbyname("afpovertcp", "tcp");
++ if (afpovertcp != NULL) {
++ afp_port = ntohs(afpovertcp->s_port);
++ }
++
++ /* If specified use the FQDN to register with srvloc, otherwise use IP. */
++ p = NULL;
++ if (options->fqdn) {
++ hostname = options->fqdn;
++ p = strchr(hostname, ':');
++ }
++ else
++ hostname = inet_ntoa(dsi->server.sin_addr);
++
++ if (!(options->flags & OPTION_NOSLP)) {
++ zeroconf_register(afp_port, hostname);
++ dsi->zeroconf_registered = 1; /* Mark that we have registered. */
++ }
++ }
++#endif /* USE_ZEROCONF */
+
+ config->fd = dsi->serversock;
+ config->obj.handle = dsi;
+@@ -469,6 +514,9 @@
+ #ifdef USE_SRVLOC
+ config->server_cleanup = dsi_cleanup;
+ #endif
++#ifdef USE_ZEROCONF
++ config->server_cleanup = dsi_cleanup;
++#endif
+ return config;
+ }
+
+Index: etc/afpd/afp_options.c
+===================================================================
+RCS file: /cvsroot/netatalk/netatalk/etc/afpd/afp_options.c,v
+retrieving revision 1.35
+diff -u -r1.35 afp_options.c
+--- etc/afpd/afp_options.c 28 Apr 2005 20:49:39 -0000 1.35
++++ etc/afpd/afp_options.c 5 May 2006 10:46:39 -0000
+@@ -202,10 +202,15 @@
+ /* parse toggles */
+ if (strstr(buf, " -nodebug"))
+ options->flags &= ~OPTION_DEBUG;
++
+ #ifdef USE_SRVLOC
+ if (strstr(buf, " -noslp"))
+ options->flags |= OPTION_NOSLP;
+ #endif /* USE_SRVLOC */
++#ifdef USE_ZEROCONF
++ if (strstr(buf, " -nozeroconf"))
++ options->flags |= OPTION_NOZEROCONF;
++#endif
+
+ if (strstr(buf, " -nouservolfirst"))
+ options->flags &= ~OPTION_USERVOLFIRST;
+@@ -578,6 +583,12 @@
+ puts( "No" );
+ #endif
+
++#ifdef USE_ZEROCONF
++ puts( "Yes" );
++#else
++ puts( "No" );
++#endif
++
+ printf( " TCP wrappers support:\t" );
+ #ifdef TCPWRAP
+ puts( "Yes" );
+Index: etc/afpd/globals.h
+===================================================================
+RCS file: /cvsroot/netatalk/netatalk/etc/afpd/globals.h,v
+retrieving revision 1.21
+diff -u -r1.21 globals.h
+--- etc/afpd/globals.h 28 Apr 2005 20:49:43 -0000 1.21
++++ etc/afpd/globals.h 5 May 2006 10:46:39 -0000
+@@ -40,6 +40,7 @@
+ #define OPTION_CUSTOMICON (1 << 4)
+ #define OPTION_NOSLP (1 << 5)
+ #define OPTION_ANNOUNCESSH (1 << 6)
++#define OPTION_NOZEROCONF (1 << 7)
+
+ #ifdef FORCE_UIDGID
+ /* set up a structure for this */
+Index: include/atalk/dsi.h
+===================================================================
+RCS file: /cvsroot/netatalk/netatalk/include/atalk/dsi.h,v
+retrieving revision 1.6
+diff -u -r1.6 dsi.h
+--- include/atalk/dsi.h 3 May 2005 14:55:12 -0000 1.6
++++ include/atalk/dsi.h 5 May 2006 10:46:41 -0000
+@@ -85,6 +85,10 @@
+ char srvloc_url[512];
+ #endif
+
++#ifdef USE_ZEROCONF
++ int zeroconf_registered;
++#endif
++
+ /* buffer for OSX deadlock */
+ int noblocking;
+ char *buffer;
+Index: macros/summary.m4
+===================================================================
+RCS file: /cvsroot/netatalk/netatalk/macros/summary.m4,v
+retrieving revision 1.2
+diff -u -r1.2 summary.m4
+--- macros/summary.m4 28 Apr 2005 20:50:05 -0000 1.2
++++ macros/summary.m4 5 May 2006 10:46:46 -0000
+@@ -44,6 +44,7 @@
+ AC_MSG_RESULT([ Options:])
+ AC_MSG_RESULT([ CUPS support: $netatalk_cv_use_cups])
+ AC_MSG_RESULT([ SLP support: $netatalk_cv_srvloc])
++ AC_MSG_RESULT([ Zeroconf support: $netatalk_cv_zeroconf])
+ AC_MSG_RESULT([ tcp wrapper support: $netatalk_cv_tcpwrap])
+ dnl if test x"$netatalk_cv_linux_sendfile" != x; then
+ dnl AC_MSG_RESULT([ Linux sendfile support: $netatalk_cv_linux_sendfile])
+Index: man/man5/afpd.conf.5.tmpl
+===================================================================
+RCS file: /cvsroot/netatalk/netatalk/man/man5/afpd.conf.5.tmpl,v
+retrieving revision 1.4
+diff -u -r1.4 afpd.conf.5.tmpl
+--- man/man5/afpd.conf.5.tmpl 28 Apr 2005 20:50:06 -0000 1.4
++++ man/man5/afpd.conf.5.tmpl 5 May 2006 10:46:48 -0000
+@@ -210,6 +210,9 @@
+ Protocol (if SLP support was compiled in). This is useful if you are
+ running multiple servers and want one to be hidden, perhaps because
+ it is advertised elsewhere, ie. by a SLP Directory Agent.
++\-noslp
++Do not register this server using the Multicast DNS
++Protocol (if Zeroconf support was compiled in).
+ .SH "MISCELLANEOUS OPTIONS"
+ .TP
+ \-admingroup \fI[group]\fR
+--- etc/afpd/afp_avahi.c.org 2006-04-21 10:29:22.000000000 +0200
++++ etc/afpd/afp_avahi.c 2006-04-22 08:34:34.000000000 +0200
+@@ -0,0 +1,500 @@
++/* -*- Mode: C; tab-width: 2; indent-tabs-mode: t; c-basic-offset: 2 -*- */
++/*
++ * Author: Daniel S. Haischt <me@daniel.stefan.haischt.name>
++ * Purpose: Avahi based Zeroconf support
++ * Docs: http://avahi.org/download/doxygen/
++ *
++ */
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif
++
++#ifdef HAVE_AVAHI
++
++#include "afp_avahi.h"
++
++static void publish_reply(AvahiEntryGroup *g,
++ AvahiEntryGroupState state,
++ void *userdata);
++
++/*
++ * This function tries to register the AFP DNS
++ * SRV service type.
++ */
++static void register_stuff(struct context *ctx) {
++ char r[128];
++ int ret;
++
++ assert(ctx->client);
++
++ if (!ctx->group) {
++
++ if (!(ctx->group = avahi_entry_group_new(ctx->client,
++ publish_reply,
++ ctx))) {
++ LOG(log_error,
++ logtype_afpd,
++ "Failed to create entry group: %s\n",
++ avahi_strerror(avahi_client_errno(ctx->client)));
++ goto fail;
++ }
++
++ }
++
++ LOG(log_info, logtype_afpd, "Adding service '%s'\n", ctx->name);
++
++ if (avahi_entry_group_is_empty(ctx->group)) {
++ /* Register our service */
++
++ if (avahi_entry_group_add_service(ctx->group,
++ AVAHI_IF_UNSPEC,
++ AVAHI_PROTO_UNSPEC,
++ 0,
++ ctx->name,
++ AFP_DNS_SERVICE_TYPE,
++ NULL,
++ NULL,
++ ctx->port,
++ NULL) < 0) {
++ LOG(log_error,
++ logtype_afpd,
++ "Failed to add service: %s\n",
++ avahi_strerror(avahi_client_errno(ctx->client)));
++ goto fail;
++ }
++
++ if (avahi_entry_group_commit(ctx->group) < 0) {
++ LOG(log_error,
++ logtype_afpd,
++ "Failed to commit entry group: %s\n",
++ avahi_strerror(avahi_client_errno(ctx->client)));
++ goto fail;
++ }
++ }
++
++ return;
++
++ fail:
++ avahi_client_free (ctx->client);
++#ifndef HAVE_AVAHI_THREADED_POLL
++ avahi_simple_poll_quit(ctx->simple_poll);
++#else
++ avahi_threaded_poll_quit(ctx->threaded_poll);
++#endif
++}
++
++/* Called when publishing of service data completes */
++static void publish_reply(AvahiEntryGroup *g,
++ AvahiEntryGroupState state,
++ AVAHI_GCC_UNUSED void *userdata)
++{
++ struct context *ctx = userdata;
++
++ assert(g == ctx->group);
++
++ switch (state) {
++
++ case AVAHI_ENTRY_GROUP_ESTABLISHED :
++ /* The entry group has been established successfully */
++ break;
++
++ case AVAHI_ENTRY_GROUP_COLLISION: {
++ char *n;
++
++ /* Pick a new name for our service */
++
++ n = avahi_alternative_service_name(ctx->name);
++ assert(n);
++
++ avahi_free(ctx->name);
++ ctx->name = n;
++
++ register_stuff(ctx);
++ break;
++ }
++
++ case AVAHI_ENTRY_GROUP_FAILURE: {
++ LOG(log_error,
++ logtype_afpd,
++ "Failed to register service: %s\n",
++ avahi_strerror(avahi_client_errno(ctx->client)));
++ avahi_client_free (avahi_entry_group_get_client(g));
++#ifndef HAVE_AVAHI_THREADED_POLL
++ avahi_simple_poll_quit(ctx->simple_poll);
++#else
++ avahi_threaded_poll_quit(ctx->threaded_poll);
++#endif
++ break;
++ }
++
++ case AVAHI_ENTRY_GROUP_UNCOMMITED:
++ case AVAHI_ENTRY_GROUP_REGISTERING:
++ ;
++ }
++}
++
++static void client_callback(AvahiClient *client,
++ AvahiClientState state,
++ void *userdata)
++{
++ struct context *ctx = userdata;
++
++ ctx->client = client;
++
++ switch (state) {
++
++ case AVAHI_CLIENT_S_RUNNING:
++
++ /* The server has startup successfully and registered its host
++ * name on the network, so it's time to create our services */
++ if (!ctx->group)
++ register_stuff(ctx);
++ break;
++
++ case AVAHI_CLIENT_S_COLLISION:
++
++ if (ctx->group)
++ avahi_entry_group_reset(ctx->group);
++ break;
++
++ case AVAHI_CLIENT_FAILURE: {
++
++ if (avahi_client_errno(client) == AVAHI_ERR_DISCONNECTED) {
++ int error;
++
++ avahi_client_free(ctx->client);
++ ctx->client = NULL;
++ ctx->group = NULL;
++
++ /* Reconnect to the server */
++
++#ifndef HAVE_AVAHI_THREADED_POLL
++ if (!(ctx->client = avahi_client_new(avahi_simple_poll_get(ctx->simple_poll),
++#else
++ if (!(ctx->client = avahi_client_new(avahi_threaded_poll_get(ctx->threaded_poll),
++#endif
++ AVAHI_CLIENT_NO_FAIL,
++ client_callback,
++ ctx,
++ &error))) {
++
++ LOG(log_error,
++ logtype_afpd,
++ "Failed to contact server: %s\n",
++ avahi_strerror(error));
++
++ avahi_client_free (ctx->client);
++#ifndef HAVE_AVAHI_THREADED_POLL
++ avahi_simple_poll_quit(ctx->simple_poll);
++#else
++ avahi_threaded_poll_quit(ctx->threaded_poll);
++#endif
++ }
++
++ } else {
++ LOG(log_error,
++ logtype_afpd,
++ "Client failure: %s\n",
++ avahi_strerror(avahi_client_errno(client)));
++
++ avahi_client_free (ctx->client);
++#ifndef HAVE_AVAHI_THREADED_POLL
++ avahi_simple_poll_quit(ctx->simple_poll);
++#else
++ avahi_threaded_poll_quit(ctx->threaded_poll);
++#endif
++ }
++
++ break;
++ }
++
++ case AVAHI_CLIENT_S_REGISTERING:
++ case AVAHI_CLIENT_CONNECTING:
++ ;
++ }
++}
++
++static void* thread(void *userdata) {
++#ifndef HAVE_AVAHI_THREADED_POLL
++ struct context *ctx = userdata;
++ sigset_t mask;
++ int r;
++
++ /* Make sure that signals are delivered to the main thread */
++ sigfillset(&mask);
++ pthread_sigmask(SIG_BLOCK, &mask, NULL);
++
++ pthread_mutex_lock(&ctx->mutex);
++
++ /* Run the main loop */
++ LOG(log_info, logtype_afpd, "Starting avahi loop...");
++ r = avahi_simple_poll_loop(ctx->simple_poll);
++
++ /* Cleanup some stuff */
++ if (ctx->client)
++ avahi_client_free(ctx->client);
++ ctx->client = NULL;
++ ctx->group = NULL;
++
++ pthread_mutex_unlock(&ctx->mutex);
++#endif
++ return NULL;
++}
++
++static int poll_func(struct pollfd *ufds,
++ unsigned int nfds,
++ int timeout,
++ void *userdata) {
++#ifndef HAVE_AVAHI_THREADED_POLL
++ pthread_mutex_t *mutex = userdata;
++ int r;
++
++ /* Before entering poll() we unlock the mutex, so that
++ * avahi_simple_poll_quit() can succeed from another thread. */
++
++ pthread_mutex_unlock(mutex);
++ r = poll(ufds, nfds, timeout);
++ pthread_mutex_lock(mutex);
++
++ return r;
++#else
++ return 0;
++#endif
++}
++
++/*
++ * Tries to setup the Zeroconf thread and any
++ * neccessary config setting.
++ */
++void* av_zeroconf_setup(unsigned long port, const char *name) {
++ struct context *ctx = NULL;
++
++ /* default service name, if there's none in
++ * the config file.
++ */
++ char service[256] = "AFP Server on ";
++ int error, ret;
++
++ /* initialize the struct that holds our
++ * config settings.
++ */
++ ctx = malloc(sizeof(struct context));
++ assert(ctx);
++ ctx->client = NULL;
++ ctx->group = NULL;
++#ifndef HAVE_AVAHI_THREADED_POLL
++ ctx->simple_poll = NULL;
++ pthread_mutex_init(&ctx->mutex, NULL);
++#else
++ ctx->threaded_poll = NULL;
++#endif
++ ctx->thread_running = 0;
++
++ LOG(log_info,
++ logtype_afpd,
++ "Setting port for Zeroconf service to: %i.\n",
++ port);
++ ctx->port = port;
++
++ /* Prepare service name */
++ if (!name) {
++ LOG(log_info,
++ logtype_afpd,
++ "Assigning default service name.\n");
++ gethostname(service+14, sizeof(service)-15);
++ service[sizeof(service)-1] = 0;
++
++ ctx->name = strdup(service);
++ }
++ else {
++ ctx->name = strdup(name);
++ }
++
++ assert(ctx->name);
++
++/* first of all we need to initialize our threading env */
++#ifdef HAVE_AVAHI_THREADED_POLL
++ if (!(ctx->threaded_poll = avahi_threaded_poll_new())) {
++ goto fail;
++ }
++#else
++ if (!(ctx->simple_poll = avahi_simple_poll_new())) {
++ LOG(log_error,
++ logtype_afpd,
++ "Failed to create event loop object.\n");
++ goto fail;
++ }
++
++ avahi_simple_poll_set_func(ctx->simple_poll, poll_func, &ctx->mutex);
++#endif
++
++/* now we need to acquire a client */
++#ifdef HAVE_AVAHI_THREADED_POLL
++ if (!(ctx->client = avahi_client_new(avahi_threaded_poll_get(ctx->threaded_poll),
++ AVAHI_CLIENT_NO_FAIL,
++ client_callback,
++ ctx,
++ &error))) {
++ LOG(log_error,
++ logtype_afpd,
++ "Failed to create client object: %s\n",
++ avahi_strerror(avahi_client_errno(ctx->client)));
++ goto fail;
++ }
++#else
++ if (!(ctx->client = avahi_client_new(avahi_simple_poll_get(ctx->simple_poll),
++ AVAHI_CLIENT_NO_FAIL,
++ client_callback,
++ ctx,
++ &error))) {
++ LOG(log_error,
++ logtype_afpd,
++ "Failed to create client object: %s\n",
++ avahi_strerror(avahi_client_errno(ctx->client)));
++ goto fail;
++ }
++#endif
++
++ return ctx;
++
++fail:
++
++ if (ctx)
++ av_zeroconf_unregister(ctx);
++
++ return NULL;
++}
++
++/*
++ * This function finally runs the loop impl.
++ */
++int av_zeroconf_run(void *u) {
++ struct context *ctx = u;
++ int ret;
++
++#ifdef HAVE_AVAHI_THREADED_POLL
++ /* Finally, start the event loop thread */
++ if (avahi_threaded_poll_start(ctx->threaded_poll) < 0) {
++ LOG(log_error,
++ logtype_afpd,
++ "Failed to create thread: %s\n",
++ avahi_strerror(avahi_client_errno(ctx->client)));
++ goto fail;
++ } else {
++ LOG(log_info, logtype_afpd, "Successfully started avahi loop.\n");
++ }
++#else
++ /* Create the mDNS event handler */
++ if ((ret = pthread_create(&ctx->thread_id, NULL, thread, ctx)) < 0) {
++ LOG(log_error,
++ logtype_afpd,
++ "Failed to create thread: %s\n", strerror(ret));
++ goto fail;
++ } else {
++ LOG(log_info, logtype_afpd, "Successfully started avahi loop.\n");
++ }
++#endif
++
++ ctx->thread_running = 1;
++
++ return 0;
++
++fail:
++
++ if (ctx)
++ av_zeroconf_unregister(ctx);
++
++ return -1;
++}
++
++/*
++ * Used to lock access to the loop.
++ * Currently unused.
++ */
++void av_zeroconf_lock(void *u) {
++#ifdef HAVE_AVAHI_THREADED_POLL
++ struct context *ctx = u;
++
++ avahi_threaded_poll_lock(ctx->threaded_poll);
++#endif
++}
++
++/*
++ * Used to unlock access to the loop.
++ * Currently unused.
++ */
++void av_zeroconf_unlock(void *u) {
++#ifdef HAVE_AVAHI_THREADED_POLL
++ struct context *ctx = u;
++
++ avahi_threaded_poll_unlock(ctx->threaded_poll);
++#endif
++}
++
++/*
++ * Tries to shutdown this loop impl.
++ * Call this function from outside this thread.
++ */
++void av_zeroconf_shutdown(void *u) {
++ struct context *ctx = u;
++
++ /* Call this when the app shuts down */
++#ifdef HAVE_AVAHI_THREADED_POLL
++ avahi_threaded_poll_stop(ctx->threaded_poll);
++ avahi_free(ctx->name);
++ avahi_client_free(ctx->client);
++ avahi_threaded_poll_free(ctx->threaded_poll);
++#else
++ av_zeroconf_unregister(ctx);
++#endif
++}
++
++/*
++ * Tries to shutdown this loop impl.
++ * Call this function from inside this thread.
++ */
++int av_zeroconf_unregister(void *u) {
++ struct context *ctx = u;
++
++ if (ctx->thread_running) {
++#ifndef HAVE_AVAHI_THREADED_POLL
++ pthread_mutex_lock(&ctx->mutex);
++ avahi_simple_poll_quit(ctx->simple_poll);
++ pthread_mutex_unlock(&ctx->mutex);
++
++ pthread_join(ctx->thread_id, NULL);
++#else
++ /* First, block the event loop */
++ avahi_threaded_poll_lock(ctx->threaded_poll);
++
++ /* Than, do your stuff */
++ avahi_threaded_poll_quit(ctx->threaded_poll);
++
++ /* Finally, unblock the event loop */
++ avahi_threaded_poll_unlock(ctx->threaded_poll);
++#endif
++ ctx->thread_running = 0;
++ }
++
++ avahi_free(ctx->name);
++
++ if (ctx->client)
++ avahi_client_free(ctx->client);
++
++#ifndef HAVE_AVAHI_THREADED_POLL
++ if (ctx->simple_poll)
++ avahi_simple_poll_free(ctx->simple_poll);
++
++ pthread_mutex_destroy(&ctx->mutex);
++#else
++ if (ctx->threaded_poll)
++ avahi_threaded_poll_free(ctx->threaded_poll);
++#endif
++
++ free(ctx);
++
++ return 0;
++}
++
++#endif /* USE_AVAHI */
+--- etc/afpd/afp_avahi.h.org 2006-04-21 10:29:23.000000000 +0200
++++ etc/afpd/afp_avahi.h 2006-04-22 07:40:05.000000000 +0200
+@@ -0,0 +1,58 @@
++/* -*- Mode: C; tab-width: 2; indent-tabs-mode: t; c-basic-offset: 2 -*- */
++/*
++ * Author: Daniel S. Haischt <me@daniel.stefan.haischt.name>
++ * Purpose: Avahi based Zeroconf support
++ * Docs: http://avahi.org/download/doxygen/
++ *
++ */
++
++#ifndef AFPD_AVAHI_H
++#define AFPD_AVAHI_H
++
++#include <stdlib.h>
++#include <assert.h>
++#include <string.h>
++
++#include <avahi-client/client.h>
++#include <avahi-client/publish.h>
++
++#include <avahi-common/alternative.h>
++
++#ifndef HAVE_AVAHI_THREADED_POLL
++#include <avahi-common/simple-watch.h>
++#include <signal.h> /* SIG_BLOCK */
++#else
++#include <avahi-common/thread-watch.h>
++#endif
++
++#include <avahi-common/malloc.h>
++#include <avahi-common/error.h>
++
++#include <atalk/logger.h>
++
++#define AFP_DNS_SERVICE_TYPE "_afpovertcp._tcp"
++
++struct context {
++ int thread_running;
++ pthread_t thread_id;
++ pthread_mutex_t mutex;
++ char *name;
++#ifndef HAVE_AVAHI_THREADED_POLL
++ AvahiSimplePoll *simple_poll;
++#else
++ AvahiThreadedPoll *threaded_poll;
++#endif
++ AvahiClient *client;
++ AvahiEntryGroup *group;
++ unsigned long port;
++};
++
++/* prototype definitions */
++void* av_zeroconf_setup(unsigned long, const char *);
++int av_zeroconf_run(void*);
++int av_zeroconf_unregister(void*);
++void av_zeroconf_shutdown(void*);
++void av_zeroconf_lock(void *);
++void av_zeroconf_unlock(void *);
++
++#endif /* AFPD_AVAHI_H */
+--- etc/afpd/afp_bonjour.h.org 2006-04-21 10:29:30.000000000 +0200
++++ etc/afpd/afp_bonjour.h 2006-04-21 07:37:05.000000000 +0200
+@@ -0,0 +1,27 @@
++/* -*- Mode: C; tab-width: 2; indent-tabs-mode: t; c-basic-offset: 2 -*- */
++/*
++ * Author: Daniel S. Haischt <me@daniel.stefan.haischt.name>
++ * Purpose: Bonjour based Zeroconf support
++ * Docs: http://developer.apple.com/documentation/Networking/Reference/DNSServiceDiscovery_CRef/dns_sd/
++ *
++ */
++
++#ifndef AFPD_BONJOUR_H
++#define AFPD_BONJOUR_H
++
++#include <stdlib.h>
++#include <assert.h>
++#include <string.h>
++
++#include <dns_sd.h> /* DNSServiceRegister(), DNSServiceDiscoveryDeallocate() */
++
++#include <atalk/logger.h>
++
++#define AFP_DNS_SERVICE_TYPE "_afpovertcp._tcp"
++
++/* prototype definitions */
++void* bo_zeroconf_setup(unsigned long, const char *);
++int bo_zeroconf_unregister(void);
++int bo_zeroconf_run(void);
++
++#endif /* AFPD_BONJOUR_H */
+--- etc/afpd/afp_bonjour.c.org 2006-04-21 10:29:28.000000000 +0200
++++ etc/afpd/afp_bonjour.c 2006-04-21 09:45:13.000000000 +0200
+@@ -0,0 +1,112 @@
++/* -*- Mode: C; tab-width: 2; indent-tabs-mode: t; c-basic-offset: 2 -*- */
++/*
++ * Author: Daniel S. Haischt <me@daniel.stefan.haischt.name>
++ * Purpose: Bonjour based Zeroconf support
++ * Docs: http://developer.apple.com/documentation/Networking/Reference/DNSServiceDiscovery_CRef/dns_sd/
++ *
++ */
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif
++
++#ifdef HAVE_BONJOUR
++
++#include "afp_bonjour.h"
++
++DNSServiceRef publish_session = NULL;
++
++static void DNSSD_API
++publish_reply(DNSServiceRef,
++ const DNSServiceFlags,
++ DNSServiceErrorType,
++ const char *,
++ const char *,
++ const char *,
++ void *);
++
++static void DNSSD_API
++publish_reply (DNSServiceRef sdRef,
++ const DNSServiceFlags flags,
++ DNSServiceErrorType errorCode,
++ const char *name,
++ const char *regtype,
++ const char *domain,
++ void *context)
++{
++}
++
++void* bo_zeroconf_setup(unsigned long port, const char *name) {
++ DNSServiceErrorType err;
++ char service[256] = "AFP Server on ";
++
++ /* Prepare service name */
++ if (!name) {
++ LOG(log_info, logtype_afpd,, "Assigning default service name.\n");
++ gethostname(service+14, sizeof(service)-15);
++ service[sizeof(service)-1] = 0;
++
++ name = strdup(service);
++ }
++
++ assert(name);
++ assert(port);
++
++ err = DNSServiceRegister (&publish_session,
++ 0, /* flags */
++ 0, /* interface; 0 for all */
++ name, /* name */
++ AFP_DNS_SERVICE_TYPE, /* type */
++ NULL, /* domain */
++ NULL, /* hostname */
++ htons (port), /* port in network byte order */
++ 0, /* text record length */
++ NULL, /* text record */
++ publish_reply, /* callback */
++ NULL); /* context */
++
++ if (err == kDNSServiceErr_NoError) {
++ LOG(log_info, logtype_afpd, "Adding service '%s'\n", name);
++ } else {
++ LOG(log_error, logtype_afpd, "Adding service '%s' failed\n", name);
++ bo_zeroconf_unregister();
++ }
++}
++
++int bo_zeroconf_run(void) {
++ fd_set set;
++ int fd;
++ struct timeval timeout;
++
++ /* Initialize the file descriptor set. */
++ FD_ZERO (&set);
++ FD_SET (fd, &set);
++
++ /* Initialize the timeout data structure. */
++ /* TODO: Should the value for sec be configurable? */
++ timeout.tv_sec = 10;
++ timeout.tv_usec = 0;
++
++ if (publish_session != NULL) {
++ fd = DNSServiceRefSockFD(publish_session);
++
++ if (select(FD_SETSIZE,
++ &set, NULL, NULL,
++ &timeout) > 0) {
++ DNSServiceProcessResult(publish_session);
++ }
++ }
++
++ return 0;
++}
++
++int bo_zeroconf_unregister(void) {
++ if (publish_session != NULL) {
++ DNSServiceRefDeallocate(publish_session);
++ publish_session = NULL;
++ }
++
++ return 0;
++}
++
++#endif /* HAVE_BONJOUR */
+--- etc/afpd/afp_howl.c.org 2006-04-21 10:29:34.000000000 +0200
++++ etc/afpd/afp_howl.c 2006-04-21 09:46:11.000000000 +0200
+@@ -0,0 +1,92 @@
++/* -*- Mode: C; tab-width: 2; indent-tabs-mode: t; c-basic-offset: 2 -*- */
++/*
++ * Author: Daniel S. Haischt <me@daniel.stefan.haischt.name>
++ * Purpose: Howl based Zeroconf support
++ * Doc: http://www.porchdogsoft.com/products/howl/docs/
++ *
++ */
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif
++
++#ifdef HAVE_HOWL
++
++#include "afp_howl.h"
++
++sw_discovery discovery = NULL;
++
++static sw_result HOWL_API publish_reply(sw_discovery,
++ sw_discovery_oid,
++ sw_discovery_publish_status,
++ sw_opaque);
++
++static sw_result HOWL_API publish_reply(sw_discovery discovery,
++ sw_discovery_oid oid,
++ sw_discovery_publish_status status,
++ sw_opaque extra) {
++ static sw_string
++ status_text[] =
++ {
++ "Started",
++ "Stopped",
++ "Name Collision",
++ "Invalid"
++ };
++
++ LOG(log_info, logtype_afpd, "publish reply: %s\n", status_text[status]);
++ return SW_OKAY;
++}
++
++void* ho_zeroconf_setup(unsigned long port, const char *name) {
++ sw_result result;
++ sw_discovery_publish_id id;
++ char service[256] = "AFP Server on ";
++
++ if (sw_discovery_init (&discovery) != SW_OKAY) {
++ LOG(log_error,
++ logtype_afpd,
++ "AFPD could not be started. \nTry running mDNSResponder.");
++ return;
++ }
++
++ /* Prepare service name */
++ if (!name) {
++ LOG(log_info, logtype_afpd, "Assigning default service name.\n");
++ gethostname(service+14, sizeof(service)-15);
++ service[sizeof(service)-1] = 0;
++
++ name = strdup(service);
++ }
++
++ assert(name);
++
++ if (!(result = sw_discovery_publish (discovery,
++ 0,
++ name,
++ AFP_DNS_SERVICE_TYPE,
++ NULL,
++ NULL,
++ port,
++ NULL,
++ 0,
++ publish_reply,
++ NULL,
++ &id)) != SW_OKAY) {
++ LOG(log_info, logtype_afpd, "Adding service '%s'\n", name);
++ } else {
++ LOG(log_error, logtype_afpd, "Adding service '%s' failed\n", name);
++ ho_zeroconf_unregister();
++ }
++}
++
++void* ho_zeroconf_run(void) {
++ sw_discovery_run(discovery);
++}
++
++void* ho_zeroconf_unregister(void) {
++ sw_discovery_stop_run(discovery);
++ sw_discovery_fina(discovery);
++}
++
++#endif /* USE_HOWL */
+--- etc/afpd/afp_howl.h.org 2006-04-21 10:29:33.000000000 +0200
++++ etc/afpd/afp_howl.h 2006-04-21 07:37:11.000000000 +0200
+@@ -0,0 +1,27 @@
++/* -*- Mode: C; tab-width: 2; indent-tabs-mode: t; c-basic-offset: 2 -*- */
++/*
++ * Author: Daniel S. Haischt <me@daniel.stefan.haischt.name>
++ * Purpose: Howl based Zeroconf support
++ * Doc: http://www.porchdogsoft.com/products/howl/docs/
++ *
++ */
++
++#ifndef AFPD_HOWL_H
++#define AFPD_HOWL_H
++
++#include <stdlib.h>
++#include <assert.h>
++#include <string.h>
++
++#include <howl.h>
++
++#include <atalk/logger.h>
++
++#define NTP_DNS_SERVICE_TYPE "_afpovertcp._tcp"
++
++/* prototype definitions */
++void* ho_zeroconf_setup(unsigned long, const char *);
++void* ho_zeroconf_unregister(void);
++void* ho_zeroconf_run(void);
++
++#endif /* AFPD_HOWL_H */
+--- etc/afpd/afp_zeroconf.h.org 2006-04-21 10:29:39.000000000 +0200
++++ etc/afpd/afp_zeroconf.h 2006-04-21 11:39:20.000000000 +0200
+@@ -0,0 +1,40 @@
++/* -*- Mode: C; tab-width: 2; indent-tabs-mode: t; c-basic-offset: 2 -*- */
++/*
++ * Author: Daniel S. Haischt <me@daniel.stefan.haischt.name>
++ * Purpose: Zeroconf facade, that abstracts access to a
++ * particular Zeroconf implementation
++ * Doc: http://www.dns-sd.org/
++ *
++ */
++
++#ifndef AFPD_ZEROCONF_H
++#define AFPD_ZEROCONF_H
++
++#include <netinet/in.h> /* htons() */
++#include <atalk/logger.h>
++
++# ifdef HAVE_BONJOUR
++# include "afp_bonjour.h"
++# elif defined (HAVE_HOWL)
++# include "afp_howl.h"
++# elif defined (HAVE_AVAHI)
++# include "afp_avahi.h"
++# endif
++
++#define AFP_PORT 548
++
++/*
++ * Prototype Definitions
++ */
++
++/*
++ * registers the ntpd service with a particular Zerconf implemenation.
++ */
++void zeroconf_register(int port, char *hostname);
++
++/*
++ * de-registers the ntpd service with a particular Zerconf implemenation.
++ */
++void zeroconf_deregister(void);
++
++#endif AFPD_ZEROCONF_H
+--- etc/afpd/afp_zeroconf.c.org 2006-04-21 10:29:38.000000000 +0200
++++ etc/afpd/afp_zeroconf.c 2006-04-21 13:12:38.000000000 +0200
+@@ -0,0 +1,97 @@
++/* -*- Mode: C; tab-width: 2; indent-tabs-mode: t; c-basic-offset: 2 -*- */
++/*
++ * Author: Daniel S. Haischt <me@daniel.stefan.haischt.name>
++ * Purpose: Zeroconf facade, that abstracts access to a
++ * particular Zeroconf implementation
++ * Doc: http://www.dns-sd.org/
++ *
++ */
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif
++
++#include "afp_zeroconf.h"
++
++/*
++ * Global Definitions
++ */
++#ifdef HAVE_AVAHI
++struct context *ctx = NULL;
++#endif
++
++/*
++ * Functions (actually they are just facades)
++ */
++void zeroconf_register(int port, char *hostname)
++{
++#ifdef HAVE_BONJOUR
++ LOG(log_info,
++ logtype_afpd,
++ "Attempting to register with mDNS using Apple's Bonjour\n");
++ if (hostname && strlen(hostname) > 0 && port)
++ {
++ bo_zeroconf_setup(port, hostname);
++ }
++ else if (hostname && strlen(hostname) > 0)
++ {
++ bo_zeroconf_setup(AFP_PORT, hostname);
++ }
++ else
++ {
++ bo_zeroconf_setup(AFP_PORT, NULL);
++ }
++ bo_zeroconf_run();
++#elif defined (HAVE_HOWL)
++ LOG(log_info,
++ logtype_afpd,
++ "Attempting to register with mDNS using Porchdog's Howl\n");
++ if (hostname && strlen(hostname) > 0 && port)
++ {
++ ho_zeroconf_setup(port, hostname);
++ }
++ else if (hostname && strlen(hostname) > 0)
++ {
++ ho_zeroconf_setup(AFP_PORT, hostname);
++ }
++ else
++ {
++ ho_zeroconf_setup(AFP_PORT, NULL);
++ }
++ bo_zeroconf_run();
++#elif defined (HAVE_AVAHI)
++ LOG(log_info, logtype_afpd, "Attempting to register with mDNS using Avahi\n");
++ if (hostname && strlen(hostname) > 0 && port)
++ {
++ ctx = av_zeroconf_setup(port, hostname);
++ }
++ else if (hostname && strlen(hostname) > 0)
++ {
++ ctx = av_zeroconf_setup(AFP_PORT, hostname);
++ }
++ else
++ {
++ ctx = av_zeroconf_setup(AFP_PORT, NULL);
++ }
++ av_zeroconf_run(ctx);
++#endif
++}
++
++void zeroconf_deregister(void)
++{
++#ifdef HAVE_BONJOUR
++ LOG(log_error,
++ logtype_afpd,
++ "Attempting to de-register mDNS using Apple's Bonjour\n");
++ bo_zeroconf_unregister();
++#elif defined (HAVE_HOWL)
++ LOG(log_error,
++ logtype_afpd,
++ "Attempting to de-register mDNS using Porchdog's Howl\n");
++ ho_zeroconf_unregister();
++#elif defined (HAVE_AVAHI)
++ LOG(log_error, logtype_afpd, "Attempting to de-register mDNS using Avahi\n");
++ if (ctx)
++ av_zeroconf_shutdown(ctx);
++#endif
++}
+--- macros/zeroconf.m4.org 2006-04-21 10:29:51.000000000 +0200
++++ macros/zeroconf.m4 2006-04-22 07:26:56.000000000 +0200
+@@ -0,0 +1,101 @@
++dnl Check for optional Zeroconf support
++
++dnl $Id$
++
++AC_DEFUN([NETATALK_ZEROCONF], [
++
++ ZEROCONF_LIBS=""
++ ZEROCONF_CFLAGS=""
++ found_zeroconf=no
++ zeroconf_dir=""
++
++ AC_ARG_ENABLE(zeroconf,
++ [ --enable-zeroconf[[=DIR]] enable Zeroconf support [[auto]]],
++ [zeroconf=$enableval],
++ [zeroconf=try]
++ )
++
++ dnl make sure atalk_libname is defined beforehand
++ [[ -n "$atalk_libname" ]] || AC_MSG_ERROR([internal error, atalk_libname undefined])
++
++ if test "x$zeroconf" != "xno"; then
++
++ savedcppflags="$CPPFLAGS"
++ savedldflags="$LDFLAGS"
++
++ if test "x$zeroconf" = "xyes" -o "x$zeroconf" = "xtry"; then
++ zeroconf_dir="/usr"
++ else
++ zeroconf_dir="$zeroconf"
++ fi
++
++ # mDNS support using Apple's Bonjour
++ AC_CHECK_HEADER(dns_sd.h,
++ [AC_CHECK_LIB(dns_sd,
++ DNSServiceRegister,
++ [AC_DEFINE(USE_ZEROCONF, 1,
++ [Use DNS-SD registration])])])
++ case "$ac_cv_lib_dns_sd_DNSServiceRegister" in
++ yes)
++ ZEROCONF_LIBS="-L$zeroconf_dir/lib -ldns_sd"
++ ZEROCONF_LIBS="-I$zeroconf_dir/include"
++ AC_DEFINE(HAVE_BONJOUR, 1, [Use Bonjour/DNS-SD registration])
++ found_zeroconf=yes
++ ;;
++ esac
++ # mDNS support using Porchdog's Howl
++ AC_CHECK_HEADER(howl.h,
++ [AC_CHECK_LIB(howl,
++ sw_discovery_publish,
++ [AC_DEFINE(USE_ZEROCONF, 1,
++ [Use DNS-SD registration])])])
++ case "$ac_cv_lib_howl_sw_discovery_publish" in
++ yes)
++ PKG_CHECK_MODULES(HOWL, [ howl >= 1.0.0 ])
++ ZEROCONF_LIBS="$HOWL_LIBS"
++ ZEROCONF_CFLAGS="$HOWL_CFLAGS"
++ AC_DEFINE(HAVE_HOWL, 1, [Use Howl/DNS-SD registration])
++ found_zeroconf=yes
++ ;;
++ esac
++ # mDNS support using Avahi
++ AC_CHECK_HEADER(avahi-client/client.h,
++ [AC_CHECK_LIB(avahi-client,
++ avahi_client_new,
++ [AC_DEFINE(USE_ZEROCONF, 1,
++ [Use DNS-SD registration])])])
++ case "$ac_cv_lib_avahi_client_avahi_client_new" in
++ yes)
++ PKG_CHECK_MODULES(AVAHI, [ avahi-client >= 0.6 ])
++ PKG_CHECK_MODULES(AVAHI_TPOLL, [ avahi-client >= 0.6.4 ],
++ [AC_DEFINE(HAVE_AVAHI_THREADED_POLL, 1, [Uses Avahis threaded poll implementation])],
++ [AC_MSG_WARN(This Avahi implementation is not supporting threaded poll objects. Maybe this is not what you want.)])
++ ZEROCONF_LIBS="$AVAHI_LIBS"
++ ZEROCONF_CFLAGS="$AVAHI_CFLAGS"
++ AC_DEFINE(HAVE_AVAHI, 1, [Use Avahi/DNS-SD registration])
++ found_zeroconf=yes
++ ;;
++ esac
++
++ CPPFLAGS="$savedcppflags"
++ LDFLAGS="$savedldflags"
++ fi
++
++ netatalk_cv_zeroconf=no
++ AC_MSG_CHECKING([whether to enable Zerconf support])
++ if test "x$found_zeroconf" = "xyes"; then
++ AC_MSG_RESULT([yes])
++ AC_DEFINE(USE_ZEROCONF, 1, [Define to enable Zeroconf support])
++ netatalk_cv_zeroconf=yes
++ else
++ AC_MSG_RESULT([no])
++ if test "x$zeroconf" != "xno" -a "x$zeroconf" != "xtry"; then
++ AC_MSG_ERROR([Zeroconf installation not found])
++ fi
++ fi
++
++ LIB_REMOVE_USR_LIB(ZEROCONF_LIBS)
++ CFLAGS_REMOVE_USR_INCLUDE(ZEROCONF_CFLAGS)
++ AC_SUBST(ZEROCONF_LIBS)
++ AC_SUBST(ZEROCONF_CFLAGS)
++])
diff --git a/config/freenas/doc/README.txt b/config/freenas/doc/README.txt
new file mode 100644
index 00000000..8183022f
--- /dev/null
+++ b/config/freenas/doc/README.txt
@@ -0,0 +1,52 @@
+FreeNAS Port for pfSense
+=~=~=~=~=~=~=~=~=~=~=~=~
+
+This is a port of the FreeNAS PHP sources to pfSense.
+It is based on FreeNAS 0.68 and was tested on pfSense
+HEAD.
+
+*** NOTES ***
+
+You should be aware that this package installes a custom
+kernel and some additional kernel modules.
+
+YOU NEED TO REBOOT YOUR pfSense SYSTEM AFTER HAVING INSTALLED
+THIS PACKAGE!!!
+
+Additionally, if you are going to enable the FTP service, you
+need to disable the FTP helper on each interface.
+
+Maintainer:
+-----------
+
+Daniel S. Haischt <me@daniel.stefan.haischt.name>
+
+Dependencies:
+-------------
+
+* ataidle-0.9
+* avahi+libdns-0.6.12
+* pkgconfig-0.20
+* perl-5.8.8
+* libiconv-1.9.2_2
+* libxml2-2.6.26
+* libdaemon-0.10_1
+* gettext-0.14.5_2
+* glib-2.10.3
+* expat-2.0.0_1
+* dbus-0.62
+* wzdftpd-0.7.2_1
+* e2fsprogs-1.39_1
+* smartmontools-5.36
+* aaccli-1.0
+* rsync-2.6.8_2
+* scponly-4.6_1
+* unison-2.13.16_1
+* cracklib-2.7_2
+* samba-3.0.23,1
+* db44-4.4.20.2
+* popt-1.7_1
+* cyrus-sasl-2.1.22
+* openldap-sasl-client-2.3.24
+* netatalk-2.0.3_3,1
+* pam_ldap-1.8.2 \ No newline at end of file
diff --git a/config/freenas/pkg/freenas.inc b/config/freenas/pkg/freenas.inc
new file mode 100644
index 00000000..b87ebfe6
--- /dev/null
+++ b/config/freenas/pkg/freenas.inc
@@ -0,0 +1,297 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ freenas.inc
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+require_once("freenas_config.inc");
+
+function sync_package_freenas() {
+}
+
+function oninstall_copy_kernel_binaries($action = "install") {
+ $binaries = array();
+ $binaries[] = array("source" => "/usr/local/pkg/iscsi_initiator.ko",
+ "target" => "/boot/kernel/iscsi_initiator.ko",
+ "backup" => false);
+ $binaries[] = array("source" => "/usr/local/pkg/ext2fs.ko",
+ "target" => "/boot/kernel/ext2fs.ko",
+ "backup" => false);
+ $binaries[] = array("source" => "/usr/local/pkg/geom_concat.ko",
+ "target" => "/boot/kernel/geom_concat.ko",
+ "backup" => false);
+ $binaries[] = array("source" => "/usr/local/pkg/geom_gpt.ko",
+ "target" => "/boot/kernel/geom_gpt.ko",
+ "backup" => false);
+ $binaries[] = array("source" => "/usr/local/pkg/geom_mirror.ko",
+ "target" => "/boot/kernel/geom_mirror.ko",
+ "backup" => false);
+ $binaries[] = array("source" => "/usr/local/pkg/geom_stripe.ko",
+ "target" => "/boot/kernel/geom_stripe.ko",
+ "backup" => false);
+ $binaries[] = array("source" => "/usr/local/pkg/geom_vinum.ko",
+ "target" => "/boot/kernel/geom_vinum.ko",
+ "backup" => false);
+ $binaries[] = array("source" => "/usr/local/pkg/ntfs.ko",
+ "target" => "/boot/kernel/ntfs.ko",
+ "backup" => false);
+ $binaries[] = array("source" => "/usr/local/pkg/kernel.gz",
+ "target" => "/boot/kernel/kernel.gz",
+ "backup" => true);
+
+ if ($action == "install") {
+ while (list(, $val) = each($binaries)) {
+ $static_output .= "FreeNAS: Moving binary file... ";
+ update_output_window($static_output);
+ if ($val['backup'] && file_exists($val['target']))
+ rename($val['target'], "{$val['target']}.org");
+ rename($val['source'], $val['target']);
+ $static_output .= "done.\n";
+ update_output_window($static_output);
+ }
+ } else if ($action == "deinstall") {
+ while (list($source, $target) = each($binaries)) {
+ $static_output .= "FreeNAS: Removing binary file... ";
+ update_output_window($static_output);
+ unlink($target);
+ $static_output .= "done.\n";
+ update_output_window($static_output);
+ }
+ }
+}
+
+function remove_package_contents($pkg = "") {
+ if ($pkg == "") { return; }
+
+ $pd = popen("pkg_info -rf {$pkg}", "r");
+
+ if (! pd) { return; }
+
+ while (! feof($pd)) {
+ $buffer = fgets($pd, 4096);
+
+ if (strpos($buffer, "File:") !== false) {
+ $file = trim(str_replace("File:", "", $buffer));
+
+ if (strpos($file, "man/") !== false) {
+ unlink_if_exists("/usr/local/{$file}");
+ } else if (strpos($file, "share/doc/") !== false) {
+ unlink_if_exists("/usr/local/{$file}");
+ } else if (strpos($file, "share/aclocal/") !== false) {
+ unlink_if_exists("/usr/local/{$file}");
+ } else if (strpos($file, "include/") !== false) {
+ unlink_if_exists("/usr/local/{$file}");
+ } else if (strpos($file, "libdata/pkgconfig/") !== false) {
+ unlink_if_exists("/usr/local/{$file}");
+ } else if (strpos($file, "info/") !== false) {
+ unlink_if_exists("/usr/local/{$file}");
+ } else if (strpos($file, "etc/rc.d/") !== false) {
+ unlink_if_exists("/usr/local/{$file}");
+ } else if (strpos($file, "etc/") !== false) {
+ if (strpos($file, ".dist") !== false ||
+ strpos($file, ".sample") !== false ||
+ strpos($file, ".example") !== false ||
+ strpos($file, ".default") !== false ||
+ strpos($file, ".sh") !== false) {
+ unlink_if_exists("/usr/local/{$file}");
+ }
+ } else if (strpos($file, "share/examples/") !== false) {
+ unlink_if_exists("/usr/local/{$file}");
+ }
+
+ /* What about locales? */
+ /*
+ } else if (strpos($file, "share/local/") !== false) {
+ unlink_if_exists("/usr/local/{$file}");
+ }
+ */
+ }
+ }
+
+ fclose ($pd);
+}
+
+function adjust_package_contents() {
+ remove_package_contents("avahi+libdns-0.6.12");
+ remove_package_contents("ataidle-0.9");
+ remove_package_contents("perl-5.8.8");
+ remove_package_contents("libiconv-1.9.2_2");
+ remove_package_contents("libxml2-2.6.26");
+ remove_package_contents("gettext-0.14.5_2");
+ remove_package_contents("glib-2.10.3");
+ remove_package_contents("expat-2.0.0_1");
+ remove_package_contents("wzdftpd-0.7.2_1");
+ remove_package_contents("e2fsprogs-1.39_1");
+ remove_package_contents("smartmontools-5.36");
+ remove_package_contents("aaccli-1.0");
+ remove_package_contents("rsync-2.6.8_2");
+ remove_package_contents("scponly-4.6_1");
+ remove_package_contents("cracklib-2.7_2");
+ remove_package_contents("samba-3.0.23,1");
+ remove_package_contents("netatalk-2.0.3_3,1");
+ remove_package_contents("pam_ldap-1.8.2");
+}
+
+function oninstall_copy_misc_binaries($action = "install") {
+ $binaries = array();
+ $binaries[] = array("source" => "/usr/local/pkg/iscontrol",
+ "target" => "/usr/local/sbin/iscontrol");
+ $binaries[] = array("source" => "/usr/local/pkg/nfsd",
+ "target" => "/usr/sbin/nfsd");
+ $binaries[] = array("source" => "/usr/local/pkg/nfsd",
+ "target" => "/usr/sbin/mountd");
+ $binaries[] = array("source" => "/usr/local/pkg/rpcbind",
+ "target" => "/usr/sbin/rpcbind");
+ $binaries[] = array("source" => "/usr/local/pkg/rpc.lockd",
+ "target" => "/usr/sbin/rpc.lockd");
+ $binaries[] = array("source" => "/usr/local/pkg/rpc.lockd",
+ "target" => "/usr/sbin/rpc.lockd");
+
+ if ($action == "install") {
+ while (list(, $val) = each($binaries)) {
+ $static_output .= "FreeNAS: Installing binary file... ";
+ update_output_window($static_output);
+ mwexec("install -s {$source} ${target}");
+ $static_output .= "done.\n";
+ update_output_window($static_output);
+ }
+ } else if ($action == "deinstall") {
+ while (list($val['source'], $val['target']) = each($binaries)) {
+ $static_output .= "FreeNAS: Removing binary file... ";
+ update_output_window($static_output);
+ unlink($target);
+ $static_output .= "done.\n";
+ update_output_window($static_output);
+ }
+ }
+}
+
+function oninstall_setup_config() {
+ global $config;
+
+ $config['system']['zeroconf_disable'] = "yes";
+
+ $freenas_config =& $config['installedpackages']['freenas']['config'][0];
+
+ if (!is_array($freenas_config['disks']))
+ $freenas_config['disks'] = array();
+ if (!is_array($freenas_config['mounts']))
+ $freenas_config['mounts'] = array();
+
+ if (!is_array($freenas_config['samba']))
+ $freenas_config['samba'] = array();
+ $freenas_config['samba']['netbiosname'] = "freenas";
+ $freenas_config['samba']['workgroup'] = "WORKGROUP";
+ $freenas_config['samba']['serverdesc'] = "pfSense Server";
+ $freenas_config['samba']['security'] = "share";
+ $freenas_config['samba']['localmaster'] = "yes";
+
+ if (!is_array($freenas_config['ftp']))
+ $freenas_config['ftp'] = array();
+ $freenas_config['ftp']['numberclients'] = "5";
+ $freenas_config['ftp']['maxconperip'] = "2";
+ $freenas_config['ftp']['timeout'] = "300";
+ $freenas_config['ftp']['port'] = "21";
+ $freenas_config['ftp']['anonymous'] = "yes";
+ $freenas_config['ftp']['pasv_max_port'] = "0";
+ $freenas_config['ftp']['pasv_min_port'] = "0";
+
+ if (!is_array($freenas_config['afp']))
+ $freenas_config['afp'] = array();
+
+ if (!is_array($freenas_config['rsyncd']))
+ $freenas_config['rsyncd'] = array();
+ $freenas_config['rsyncd']['readonly'] = "no";
+ $freenas_config['rsyncd']['port'] = "873";
+
+ if (!is_array($freenas_config['nfs']))
+ $freenas_config['nfs'] = array();
+}
+
+function custom_php_install_command() {
+ global $g;
+
+ oninstall_copy_kernel_binaries();
+ oninstall_copy_misc_binaries();
+ adjust_package_contents();
+ oninstall_setup_config();
+
+ if (! file_exists("/usr/local/etc/rc.d"))
+ mwexec("mkdir -p /usr/local/etc/rc.d");
+
+ if (! file_exists("{$g['varrun_path']}/dbus"))
+ mkdir("{$g['varrun_path']}/dbus");
+
+ if (! file_exists("{$g['varrun_path']}/avahi-daemon"))
+ mkdir("{$g['varrun_path']}/avahi-daemon");
+
+ rename("/usr/local/pkg/rc.freenas", "/usr/local/etc/rc.d/freenas.sh");
+ chmod ("/usr/local/etc/rc.d/freenas.sh", 0755);
+
+ mwexec("ln -s /usr/local/etc/uams/uams_passwd.so /usr/local/etc/uams/uams_clrtxt.so");
+ mwexec("ln -s /usr/local/etc/uams/uams_dhx_passwd.so /usr/local/etc/uams/uams_dhx.so");
+ /* hack cause I linked netatalk against db44 instead of db42 */
+ mwexec("ln -s /usr/local/lib/libdb-4.4.so.0 /usr/local/lib/libdb-4.2.so.2");
+}
+
+function custom_php_deinstall_command() {
+ global $config, $g;
+
+ oninstall_copy_kernel_binaries("deinstall");
+ oninstall_copy_misc_binaries("deinstall");
+
+ if (! file_exists("/usr/local/etc/rc.d"))
+ mwexec("rm -rf /usr/local/etc/rc.d");
+
+ if (! file_exists("{$g['varrun_path']}/dbus"))
+ mwexec("rm -rf {$g['varrun_path']}/dbus");
+
+ if (! file_exists("{$g['varrun_path']}/avahi-daemon"))
+ mwexec("rm -rf {$g['varrun_path']}/avahi-daemon");
+
+ unlink_if_exists("/usr/local/etc/uams/uams_clrtxt.so");
+ unlink_if_exists("/usr/local/etc/uams/uams_dhx.so");
+ unlink_if_exists("/usr/local/etc/rc.d/freenas.sh");
+ unlink_if_exists("/usr/local/lib/libdb-4.2.so.2");
+
+ unset($config['installedpackages']['freenas']);
+ write_config();
+ conf_mount_ro();
+}
+?>
diff --git a/config/freenas/pkg/freenas.xml b/config/freenas/pkg/freenas.xml
new file mode 100644
index 00000000..edac8085
--- /dev/null
+++ b/config/freenas/pkg/freenas.xml
@@ -0,0 +1,570 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>freenas</name>
+ <version>1.0</version>
+ <title>System: Disks: Management</title>
+ <include_file>/usr/local/pkg/freenas.inc</include_file>
+ <!-- Menu is where this packages menu will appear -->
+ <menu>
+ <name>Disks</name>
+ <section>System</section>
+ <url>/disks_manage.php</url>
+ </menu>
+ <menu>
+ <name>RAID</name>
+ <section>System</section>
+ <url>/disks_raid_gmirror.php</url>
+ </menu>
+ <menu>
+ <name>Mounts</name>
+ <section>System</section>
+ <url>/disks_mount.php</url>
+ </menu>
+ <menu>
+ <name>FreeNAS Infos</name>
+ <section>Diagnostics</section>
+ <url>/diag_disk_infos.php</url>
+ </menu>
+ <menu>
+ <name>FreeNAS Logs</name>
+ <section>Diagnostics</section>
+ <url>/diag_fn_logs_samba.php</url>
+ </menu>
+ <menu>
+ <name>Disk Status</name>
+ <section>Status</section>
+ <url>/status_disks.php</url>
+ </menu>
+ <menu>
+ <name>AFP</name>
+ <section>Services</section>
+ <url>/services_afp.php</url>
+ </menu>
+ <menu>
+ <name>FTP</name>
+ <section>Services</section>
+ <url>/services_ftp.php</url>
+ </menu>
+ <menu>
+ <name>NFS</name>
+ <section>Services</section>
+ <url>/services_nfs.php</url>
+ </menu>
+ <menu>
+ <name>Rsync</name>
+ <section>Services</section>
+ <url>/services_rsyncd.php</url>
+ </menu>
+ <menu>
+ <name>Samba</name>
+ <section>Services</section>
+ <url>/services_samba.php</url>
+ </menu>
+ <menu>
+ <name>Unison</name>
+ <section>Services</section>
+ <url>/services_unison.php</url>
+ </menu>
+ <!--
+ <service>
+ <name>dspam</name>
+ <rcfile>/usr/local/etc/rc.d/dspam.sh</rcfile>
+ </service>
+ -->
+ <tabs />
+ <!--
+ configpath gets expanded out automatically and config items
+ will be stored in that location
+ -->
+ <configpath>['installedpackages']['freenas']['config']</configpath>
+ <!-- PHP files (disk management) -->
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/www/disks_manage.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/www/disks_manage_edit.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/www/disks_manage_init.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/www/disks_manage_iscsi.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/www/disks_manage_tools.php</item>
+ </additional_files_needed>
+ <!-- PHP files (RAID management) -->
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/www/disks_raid_gmirror.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/www/disks_raid_gmirror_edit.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/www/disks_raid_gmirror_infos.php</item>
+ </additional_files_needed>
+ <!--
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/www/disks_raid_gmirror_init.php</item>
+ </additional_files_needed>
+ -->
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/www/disks_raid_gmirror_tools.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/www/disks_raid_gvinum.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/www/disks_raid_gvinum_edit.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/www/disks_raid_gvinum_infos.php</item>
+ </additional_files_needed>
+ <!--
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/www/disks_raid_gvinum_init.php</item>
+ </additional_files_needed>
+ -->
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/www/disks_raid_gvinum_tools.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/www/disks_raid_gconcat.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/www/disks_raid_gconcat_edit.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/www/disks_raid_gconcat_infos.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/www/disks_raid_gconcat_tools.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/www/disks_raid_gstripe.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/www/disks_raid_gstripe_edit.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/www/disks_raid_gstripe_infos.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/www/disks_raid_gstripe_tools.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/www/disks_raid_graid5.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/www/disks_raid_graid5_edit.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/www/disks_raid_graid5_infos.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/www/disks_raid_graid5_tools.php</item>
+ </additional_files_needed>
+ <!-- PHP files (mount management) -->
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/www/disks_mount.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/www/disks_mount_edit.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/www/disks_mount_tools.php</item>
+ </additional_files_needed>
+ <!-- PHP files (diagnostics) -->
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/www/diag_ad_infos.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/www/diag_ataidle_infos.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/www/diag_disk_infos.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/www/diag_iscsi_infos.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/www/diag_mounts_infos.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/www/diag_part_infos.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/www/diag_raid_infos.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/www/diag_smart_infos.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/www/diag_space_infos.php</item>
+ </additional_files_needed>
+ <!-- PHP files (logs) -->
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/www/diag_fn_logs_daemon.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/www/diag_fn_logs_ftp.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/www/diag_fn_logs_rsyncd.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/www/diag_fn_logs_samba.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/www/diag_fn_logs_settings.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/www/diag_fn_logs_smartd.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/www/diag_fn_logs_sshd.php</item>
+ </additional_files_needed>
+ <!-- PHP files (services) -->
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/www/services_afp.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/www/services_ftp.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/www/services_nfs.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/www/services_nfs_export.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/www/services_nfs_export_edit.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/www/services_rsyncd.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/www/services_rsyncd_client.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/www/services_rsyncd_local.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/www/services_samba.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/www/services_samba_share.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/www/services_samba_edit.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/www/services_unison.php</item>
+ </additional_files_needed>
+ <!-- PHP files (misc) -->
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/www/status_disks.php</item>
+ </additional_files_needed>
+ <!-- package files -->
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/pkg/freenas.inc</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/pkg/freenas_disks.inc</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/pkg/freenas_config.inc</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/pkg/freenas_functions.inc</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/pkg/freenas_guiconfig.inc</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/pkg/freenas_services.inc</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/pkg/freenas_utils.inc</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/pkg/freenas_system.inc</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/pkg/rc.freenas</item>
+ </additional_files_needed>
+ <!-- kernel binaries -->
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/bin/iscsi_initiator.ko</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/bin/ext2fs.ko</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/bin/geom_concat.ko</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/bin/geom_gpt.ko</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/bin/geom_mirror.ko</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/bin/geom_stripe.ko</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/bin/geom_vinum.ko</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/bin/kernel.gz</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/bin/ntfs.ko</item>
+ </additional_files_needed>
+ <!-- misc binaries -->
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/bin/iscontrol</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/bin/mountd</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/bin/nfsd</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/bin/rpcbind</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/bin/rpc.lockd</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freenas/bin/rpc.statd</item>
+ </additional_files_needed>
+ <!--
+ fields gets invoked when the user adds or edits a item. The following items
+ will be parsed and rendered for the user as a gui with input, and selectboxes.
+ -->
+ <!--
+ Arbitrary PHP Code, that gets executed if a certain event gets triggered.
+ -->
+ <custom_php_resync_config_command>
+ sync_package_freenas();
+ </custom_php_resync_config_command>
+ <custom_php_install_command>
+ custom_php_install_command();
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ custom_php_deinstall_command();
+ </custom_php_deinstall_command>
+</packagegui>
diff --git a/config/freenas/pkg/freenas_config.inc b/config/freenas/pkg/freenas_config.inc
new file mode 100644
index 00000000..fc139228
--- /dev/null
+++ b/config/freenas/pkg/freenas_config.inc
@@ -0,0 +1,45 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ freenas_config.inc
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+$GLOBALS['custom_listtags'] = array("disk", "mount", "vdisk");
+
+?> \ No newline at end of file
diff --git a/config/freenas/pkg/freenas_disks.inc b/config/freenas/pkg/freenas_disks.inc
new file mode 100644
index 00000000..0946164f
--- /dev/null
+++ b/config/freenas/pkg/freenas_disks.inc
@@ -0,0 +1,1256 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ freenas_disks.inc
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+/* include all configuration functions */
+require_once("functions.inc");
+require_once("freenas_functions.inc");
+
+$freenas_config =& $config['installedpackages']['freenas']['config'][0];
+
+/* Mount all configured disks */
+function disks_mount_all() {
+ global $freenas_config, $g;
+
+ if ($g['booting'])
+ echo "Mounting Partitions... ";
+
+ /* For each device configured: */
+ if (is_array($freenas_config['mounts']['mount'])) {
+ foreach ($freenas_config['mounts']['mount'] as $mountent) {
+ /* Advanced Umount filesystem if not booting mode (mount edition) */
+ if (!$g['booting'])
+ disks_umount_adv($mountent);
+
+ /* mount filesystem */
+ disks_mount($mountent);
+ } // end foreach
+ } // end if
+
+ if ($g['booting'])
+ echo "done\n";
+
+ return 0;
+}
+
+/* Mount using the configured mount given in parameter
+ * Return 0 if sucessful, 1 if error
+ */
+function disks_mount($mount) {
+ global $freenas_config, $g;
+
+ /* Create one directory for each device under mnt */
+
+ $mountname=escapeshellcmd($mount['sharename']);
+
+ @mkdir ("/mnt/$mountname",0777);
+
+ /* mount the filesystems */
+ $devname=escapeshellcmd($mount['fullname']);
+
+ /* check the fileystem only if there is a problem*/
+ /* This part is too stupid: I must read the FreBSD
+ * start script for use the same intelligent method
+ * for checking hard drive
+ */
+ switch ($mount['fstype']) {
+ case "ufs":
+ if (mwexec("/sbin/mount -t ufs -o acls $devname /mnt/$mountname") == 0) {
+ /* Change this directory into 777 mode */
+ mwexec("/bin/chmod 777 /mnt/$mountname");
+ $result = 0;
+ } else {
+ /* If it's NOK, Check filesystem and do a fsck, answer Yes to all question*/
+ mwexec("/sbin/fsck -y -t ufs $devname");
+
+ /* Re-try to mount the partition */
+ if (mwexec("/sbin/mount -t ufs -o acls $devname /mnt/$mountname") == 0) {
+ /* Change this directory into 777 mode */
+ mwexec("/bin/chmod 777 /mnt/$mountname");
+ $result = 0;
+ } else {
+ /* Not OK, remove the directory, prevent writing on RAM disk*/
+ @rmdir ("/mnt/$mountname");
+ $result = 1;
+ } // end if
+ } // end if
+ break;
+ case "msdosfs":
+ if (mwexec("/sbin/mount_msdosfs -u ftp -g ftp -m 777 $devname /mnt/$mountname") == 0) {
+ $result = 0;
+ } else {
+ exec("/sbin/fsck -y -t msdosfs {$devname}");
+
+ if (mwexec("/sbin/mount_msdosfs -u ftp -g ftp -m 777 $devname /mnt/$mountname") == 0) {
+ $result = 0;
+ } else {
+ /* Not OK, remove the directory, prevent writing on RAM disk*/
+ @rmdir ("/mnt/$mountname");
+ $result = 1;
+ }
+ }
+ break;
+ case "ntfs":
+ if (mwexec("/sbin/mount_ntfs -u ftp -g ftp -m 777 $devname /mnt/$mountname") == 0) {
+ $result = 0;
+ } else {
+ /* Not OK, remove the directory, prevent writing on RAM disk */
+ @rmdir ("/mnt/$mountname");
+ $result = 1;
+ }
+ break;
+ case "ext2fs":
+ if (mwexec("/sbin/mount_ext2fs $devname /mnt/$mountname") == 0) {
+ /* Change this directory into 777 mode */
+ mwexec("/bin/chmod 777 /mnt/$mountname");
+ $result = 0;
+ } else {
+ exec("/usr/local/sbin/e2fsck -f -p {$devname}");
+
+ if (mwexec("/sbin/mount_ext2fs $devname /mnt/$mountname") == 0) {
+ /* Change this directory into 777 mode */
+ mwexec("/bin/chmod 777 /mnt/$mountname");
+ $result = 0;
+ } else {
+ /* Not OK, remove the directory, prevent writing on RAM */
+ @rmdir ("/mnt/$mountname");
+ $result= 1;
+ }
+ }
+ break;
+ } // end switch
+
+ return $result;
+}
+
+/* Mount using fullname (/dev/ad0s1) given in parameter*/
+function disks_mount_fullname($fullname) {
+ global $freenas_config;
+
+ if (is_array($freenas_config['mounts']['mount'])) {
+ /* Search the mount list for given disk and partition */
+ foreach($freenas_config['mounts']['mount'] as $mountk => $mountv) {
+ if($mountv['fullname'] == $fullname) {
+ $mount = $mountv;
+ }
+ }
+ }
+
+ if($mount) {
+ $result= disks_mount($mount);
+ } else {
+ $result=0;
+ }
+
+ return $result;
+}
+
+/* Umount the specified configured mount point
+ * Return 0 is successfull, 1 if error
+ */
+function disks_umount($mount) {
+ global $freenas_config, $g;
+
+ /* Umout the specified mount point */
+ /* The $mount variable is the all config table for the mount point*/
+ $mountname=escapeshellcmd($mount['sharename']);
+
+ if (mwexec("/sbin/umount /mnt/$mountname") == 0) {
+ if (@rmdir ("/mnt/$mountname")) {
+ return 0;
+ } else {
+ return 1;
+ }
+ } else {
+ return 1;
+ }
+}
+
+/* Advanced unmount the specified mount point without using the sharename value
+ * Used when changing the 'sharename': Need to umount the old unknow sharename
+ * Return 0 if successful, 1 if error
+ */
+function disks_umount_fullname($fullname) {
+ global $freenas_config;
+
+ /* Search the mount list for given fullname */
+ foreach($freenas_config['mounts']['mount'] as $mountk => $mountv) {
+ if (strcmp($mountv['fullname'],$fullname) == 0) {
+ $mount = $mountv;
+ }
+ }
+
+ if($mount) {
+ $result = disks_umount($mount);
+ } else {
+ $result= 1;
+ }
+
+ return $result;
+}
+
+/* Advanced unmount the specified mount point without using the sharename value
+ * Used when changing the 'sharename': Need to umount the old unknow sharename
+ * Return 0 if successful, 1 if error
+ */
+function disks_umount_adv($mount)
+{
+ $fulname="{$mount['fullname']}";
+
+ // get the mount list
+ $detmount = get_mounts_list();
+
+ //Look for the mount point in all mounted point
+ foreach ($detmount as $detmountk => $detmountv) {
+ // If we found the mount point on the device
+ if (strcmp($detmountv['fullname'],$fullname) == 0) {
+ $mountname="{$detmountv['mp']}";
+ }
+ }
+
+ if ($mountname) {
+ exec("/sbin/umount $mountname");
+ @rmdir ("$mountname");
+ return 0;
+ } else {
+ $result = 1;
+ }
+
+ return $result;
+}
+
+function disks_mount_status($mount) {
+ // This option check if the mount are mounted
+ global $freenas_config, $g;
+ $detmount = get_mounts_list();
+ $status="ERROR";
+
+ // Recreate the full system name device+s+partition number
+ /* mount the filesystems */
+ $mountpart="{$mount['partition']}";
+
+ if ((strcmp($mountpart,"gvinum") == 0) || (strcmp($mountpart,"gmirror") == 0)) {
+ $complete = "{$mount['mdisk']}";
+ } else {
+ $complete = "{$mount['mdisk']}{$mount['partition']}";
+ }
+
+ //echo "debug, display complete: $complete <br>";
+
+ foreach ($detmount as $detmountk => $detmountv) {
+ //echo "debug, display detmountv[mdisk]: {$detmountv['mdisk']} <br>";
+
+ if (strcmp($detmountv['mdisk'],$complete) == 0) {
+ $status="OK";
+ return $status;
+ }
+ }
+
+ return $status;
+}
+
+/* This option check if this fullname (/dev/ad0s1) is mounted
+ * Return 0 if not, 1 if yes
+ */
+function disks_check_mount_fullname($fullname) {
+ $detmount = get_mounts_list();
+ $status=0;
+ //print_r($detmount);
+
+ foreach ($detmount as $detmountk => $detmountv) {
+ if (strpos($detmountv['fullname'],$fullname) !== false) {
+ $status=1;
+ break;
+ }
+ }
+
+ return $status;
+}
+
+/* This option check if the configured mount is mounted. */
+function disks_check_mount($mount)
+{
+ return disks_check_mount_fullname($mount['fullname']);
+}
+
+/* This function check if the disk is mounted
+ * Return 0 if not, 1 if yes
+ */
+function disks_check_mount_disk($disk) {
+ $detmount = get_mounts_list();
+ $status=0;
+
+ foreach ($detmount as $detmountk => $detmountv) {
+ /* Must found the $disk (ad0) in result $mdisk (ad0s1) */
+ // strpos will return 0 (found at position 0) if found, must check the 'false' value
+ if (strpos($detmountv['mdisk'], $disk) !== false ) {
+ $status=1;
+ break;
+ }
+}
+return $status;
+}
+
+/* This option check if the configured disk is online (detected by the system)
+ * Result: "MISSING", disk don't detected by OS
+ * Result: "ONLINE", disk is online
+ * Result: "CHANGED", disk have changed (be replaced ?)
+ */
+function disks_status($diskname) {
+ // This option check if the configured disk is online
+ global $freenas_config, $g;
+ $detectedlist = get_physical_disks_list();
+ $status="MISSING";
+
+ foreach ($detectedlist as $detecteddisk => $detecteddiskv) {
+ if ($detecteddisk == $diskname['name']) {
+ $status="ONLINE";
+ if (($detecteddiskv['size'] != $diskname['size']) || ($detecteddiskv['desc'] != $diskname['desc'])) {
+ $status="CHANGED";
+ }
+ break;
+ }
+ }
+
+ return $status;
+}
+
+function disks_addfstab($cfgdev,$cfgtype) {
+ global $freenas_config, $g;
+
+ /* Open or create fstab in RW */
+ $fd = fopen("{$g['etc_path']}/fstab", "w");
+
+ if ( $fd ) {
+ /* check for the precence of dev */
+ /* ADD (check if it's ADD line or replace) the line for the dev */
+ $fstab = "/dev/$cfgdev /mnt/$cfgdev $cfgtype rw 1 1\n";
+
+ /* write out an fstab */
+ fwrite($fd, $fstab);
+
+ /* close file */
+ fclose($fd);
+ } else {
+ die( "fopen failed for {$g['etc_path']}/fstab" ) ;
+ }
+}
+
+function disks_umount_all() {
+ global $freenas_config, $g;
+
+ /* Sync disks*/
+ mwexec("/bin/sync");
+
+ if (is_array($freenas_config['mounts']['mount'])) {
+ foreach ($freenas_config['mounts']['mount'] as $mountent) {
+ /* Umount filesystem */
+ disks_umount($mountent);
+ }
+ }
+
+ return 0;
+}
+
+/* Configure, create and start gvinum volume */
+function disks_raid_gvinum_configure() {
+ global $freenas_config, $g;
+
+ /* Generate the raid.conf file */
+ if ($freenas_config['gvinum']['vdisk']) {
+
+ foreach ($freenas_config['gvinum']['vdisk'] as $a_raid_conf) {
+ if (file_exists($g['varrun_path'] . "/raid.conf.dirty") &&
+ !in_array("{$a_raid_conf['name']}\n", file($g['varrun_path'] . "/raid.conf.dirty"))) { continue; }
+
+ /* generate raid.conf */
+ $fd = fopen("{$g['varetc_path']}/raid-{$a_raid_conf['name']}.conf", "w");
+ if (!$fd) {
+ printf("Error: cannot open raid.conf in services_raid_configure().\n");
+ return 1;
+ }
+
+ $raidconf="";
+ foreach ($a_raid_conf['diskr'] as $diskrk => $diskrv) {
+ $raidconf .= <<<EOD
+drive disk_{$diskrv} device {$diskrv}
+
+EOD;
+ } // end foreach
+
+ $raidconf .= <<<EOD
+volume {$a_raid_conf['name']}
+
+EOD;
+
+ switch ($a_raid_conf['type']) {
+ case "0":
+ $raidconf .= <<<EOD
+plex org striped 256k
+
+EOD;
+
+ foreach ($a_raid_conf['diskr'] as $diskrk => $diskrv) {
+ /* Get the disksize */
+ $disksize=get_disks_size($diskrv);
+ /* Remove the ending 'B' in 'MB' */
+ $disksize=rtrim($disksize, 'B');
+ /*
+ $raidconf .= <<<EOD
+sd length {$disksize} drive disk_{$diskrv}
+
+EOD;
+*/
+
+ $raidconf .= <<<EOD
+sd length 0 drive disk_{$diskrv}
+
+EOD;
+
+ } // end foreach
+ break;
+ case "1":
+ foreach ($a_raid_conf['diskr'] as $diskrk => $diskrv) {
+ $raidconf .= <<<EOD
+plex org concat
+
+EOD;
+
+ /* Get the disksize */
+ $disksize=get_disks_size($diskrv);
+ /* Remove the ending 'B' in 'MB' */
+ $disksize=rtrim($disksize, 'B');
+ /*
+ $raidconf .= <<<EOD
+sd length {$disksize} drive disk_{$diskrv}
+
+EOD;
+*/
+ $raidconf .= <<<EOD
+sd length 0 drive disk_{$diskrv}
+
+EOD;
+
+ } // end foreach
+ break;
+ case "5":
+ $raidconf .= <<<EOD
+plex org raid5 256k
+
+EOD;
+
+ foreach ($a_raid_conf['diskr'] as $diskrk => $diskrv) {
+ /* Get the disksize */
+ $disksize=get_disks_size($diskrv);
+ /* Remove the ending 'B' in 'MB' */
+ $disksize=rtrim($disksize, 'B');
+ /*
+ $raidconf .= <<<EOD
+sd length {$disksize} drive disk_{$diskrv}
+
+EOD;
+*/
+
+ $raidconf .= <<<EOD
+sd length 0 drive disk_{$diskrv}
+
+EOD;
+
+ } // end foreach
+ break;
+ } // end switch
+
+ fwrite($fd, $raidconf);
+ fclose($fd);
+
+ /* Create each volume */
+ mwexec("/sbin/gvinum create {$g['varetc_path']}/raid-{$a_raid_conf['name']}.conf");
+ } // end foreach
+
+
+ /* start each volume */
+
+ foreach ($freenas_config['gvinum']['vdisk'] as $a_raid_conf) {
+ exec("/sbin/gvinum lv $raidname",$rawdata);
+
+ if (strpos($rawdata[0],"State: up")>=0) { continue; }
+
+ mwexec("/sbin/gvinum start {$a_raid_conf['name']}");
+ }
+ } // end if
+
+ return 0;
+}
+
+function disks_raid_configure()
+{
+ global $freenas_config, $g;
+
+ /* Generate the raid.conf file */
+ if ($freenas_config['raid']['vdisk']) {
+ foreach ($freenas_config['raid']['vdisk'] as $a_raid_conf) {
+ if (file_exists($g['varrun_path'] . "/raid.conf.dirty") &&
+ ! in_array("{$a_raid_conf['name']}\n",file($g['varrun_path'] . "/raid.conf.dirty"))) { continue; }
+
+ /* generate raid.conf */
+ $fd = fopen("{$g['varetc_path']}/raid-{$a_raid_conf['name']}.conf", "w");
+
+ if (!$fd) {
+ printf("Error: cannot open raid.conf in services_raid_configure().\n");
+ return 1;
+ }
+
+ $raidconf="";
+ foreach ($a_raid_conf['diskr'] as $diskrk => $diskrv) {
+ $raidconf .= <<<EOD
+drive disk_{$diskrv} device /dev/{$diskrv}s1a
+
+EOD;
+
+ } // end foreach
+
+ $raidconf .= <<<EOD
+volume {$a_raid_conf['name']}
+
+EOD;
+
+ switch ($a_raid_conf['type']) {
+ case "0":
+ $raidconf .= <<<EOD
+plex org striped 256k
+
+EOD;
+
+ foreach ($a_raid_conf['diskr'] as $diskrk => $diskrv) {
+ /* Get the disksize */
+ $disksize=get_disks_size($diskrv);
+ /* Remove the ending 'B' in 'MB' */
+ $disksize=rtrim($disksize, 'B');
+ /*
+ $raidconf .= <<<EOD
+sd length {$disksize} drive disk_{$diskrv}
+
+EOD;
+*/
+
+$raidconf .= <<<EOD
+sd length 0 drive disk_{$diskrv}
+
+EOD;
+
+ } // end foreach
+ break;
+ case "1":
+ foreach ($a_raid_conf['diskr'] as $diskrk => $diskrv) {
+ $raidconf .= <<<EOD
+plex org concat
+
+EOD;
+
+ /* Get the disksize */
+ $disksize=get_disks_size($diskrv);
+ /* Remove the ending 'B' in 'MB' */
+ $disksize=rtrim($disksize, 'B');
+ /*
+ $raidconf .= <<<EOD
+sd length {$disksize} drive disk_{$diskrv}
+
+EOD;
+*/
+
+ $raidconf .= <<<EOD
+sd length 0 drive disk_{$diskrv}
+
+EOD;
+
+ } // end foreach
+ break;
+ case "5":
+ $raidconf .= <<<EOD
+plex org raid5 256k
+
+EOD;
+
+ foreach ($a_raid_conf['diskr'] as $diskrk => $diskrv) {
+ /* Get the disksize */
+ $disksize=get_disks_size($diskrv);
+ /* Remove the ending 'B' in 'MB' */
+ $disksize=rtrim($disksize, 'B');
+ /*
+ $raidconf .= <<<EOD
+sd length {$disksize} drive disk_{$diskrv}
+
+EOD;
+*/
+
+ $raidconf .= <<<EOD
+sd length 0 drive disk_{$diskrv}
+
+EOD;
+
+ } // end foreach
+ break;
+ } // end switch
+
+ fwrite($fd, $raidconf);
+ fclose($fd);
+
+ /* Create each volume */
+ mwexec("/sbin/gvinum create {$g['varetc_path']}/raid-{$a_raid_conf['name']}.conf");
+ } // end foreach
+
+ /* start each volume */
+ foreach ($freenas_config['raid']['vdisk'] as $a_raid_conf) {
+ exec("/sbin/gvinum lv $raidname",$rawdata);
+ if (strpos($rawdata[0],"State: up")>=0) { continue; }
+ mwexec("/sbin/gvinum start {$a_raid_conf['name']}");
+ }
+ } // end if
+
+ return 0;
+}
+
+/* Configure, create and start gmirror volume */
+function disks_raid_gmirror_configure() {
+ global $freenas_config, $g;
+
+ /* Create the gmirror device */
+ if ($freenas_config['gmirror']['vdisk']) {
+ // Load gmirror
+ mwexec("/sbin/gmirror load");
+
+ foreach ($freenas_config['gmirror']['vdisk'] as $a_raid_conf) {
+ /* Create each volume */
+ $cmd = "/sbin/gmirror label -b {$a_raid_conf['balance']} {$a_raid_conf['name']} ";
+
+ foreach ($a_raid_conf['diskr'] as $diskrk => $diskrv) {
+ $cmd .= "{$diskrv} ";
+ }
+
+ mwexec($cmd);
+ }
+ }
+
+ return 0;
+}
+
+/* Configure, create and start gconcat volume */
+function disks_raid_gconcat_configure() {
+ global $freenas_config, $g;
+
+ if ($freenas_config['gconcat']['vdisk']) {
+ // Load gconcat
+ mwexec("/sbin/gconcat load");
+
+ foreach ($freenas_config['gconcat']['vdisk'] as $a_raid_conf) {
+ /* Create each volume */
+ $cmd = "/sbin/gconcat label {$a_raid_conf['name']} ";
+
+ foreach ($a_raid_conf['diskr'] as $diskrk => $diskrv) {
+ $cmd .= "{$diskrv} ";
+ }
+
+ mwexec($cmd);
+
+ }
+ }
+
+ return 0;
+}
+
+/* Configure, create and start gstripe volume */
+function disks_raid_gstripe_configure() {
+ global $freenas_config, $g;
+
+ if ($freenas_config['gstripe']['vdisk']) {
+ // Load gstripe
+ mwexec("/sbin/gstripe load");
+
+ foreach ($freenas_config['gstripe']['vdisk'] as $a_raid_conf) {
+ /* Create each volume */
+ $cmd = "/sbin/gstripe label {$a_raid_conf['name']} ";
+
+ foreach ($a_raid_conf['diskr'] as $diskrk => $diskrv) {
+ $cmd .= "{$diskrv} ";
+ }
+
+ mwexec($cmd);
+ }
+ }
+
+ return 0;
+}
+
+/* Configure, create and start graid5 volume */
+
+function disks_raid_graid5_configure()
+{
+ global $freenas_config, $g;
+
+ if ($freenas_config['graid5']['vdisk']) {
+ /* Load graid5 */
+ mwexec("/sbin/graid5 load");
+
+ foreach ($freenas_config['graid5']['vdisk'] as $a_raid_conf) {
+ /* Create each volume */
+ $cmd = "/sbin/graid5 label -s 131072 {$a_raid_conf['name']} ";
+
+ foreach ($a_raid_conf['diskr'] as $diskrk => $diskrv) {
+ $cmd .= "{$diskrv} ";
+ }
+
+ mwexec($cmd);
+ }
+ }
+
+ return 0;
+}
+
+function disks_raid_start() {
+ global $freenas_config, $g;
+
+ /* WARNING: Must change this code for advanced RAID configuration ex: RAID1+0
+ * Geom RAID volume must be started in 'intelligent' sort, for RAID1+0, gmirror must
+ * be started before gstripe, etc...
+ */
+ disks_raid_gvinum_start();
+ disks_raid_gmirror_start();
+ disks_raid_gstripe_start();
+ disks_raid_gconcat_start();
+ disks_raid_graid5_start();
+
+ return 0;
+}
+
+
+function disks_raid_gvinum_start() {
+ global $freenas_config, $g;
+
+ /* Generate the raid.conf file */
+ if ($freenas_config['raid']['vdisk']) {
+ if ($g['booting'])
+ echo "Start gvinum raid... ";
+
+ /* start each volume */
+ foreach ($freenas_config['raid']['vdisk'] as $a_raid_conf) {
+ mwexec("/sbin/gvinum start {$a_raid_conf['name']}");
+ }
+
+ if ($g['booting'])
+ echo "done\n";
+ }
+
+ return 0;
+}
+
+function disks_raid_gmirror_start() {
+ global $freenas_config, $g;
+
+ /* Start Geom mirror */
+ if ($freenas_config['gmirror']['vdisk']) {
+ if ($g['booting'])
+ echo "Start gmirror raid... ";
+
+ // Load geom mirror module
+ mwexec("/sbin/gmirror load");
+
+ if ($g['booting'])
+ echo "done\n";
+ }
+
+ return 0;
+}
+
+/* Start geom concat volumes */
+function disks_raid_gconcat_start() {
+ global $freenas_config, $g;
+
+/* Start Geom concat */
+ if ($freenas_config['gconcat']['vdisk']) {
+ if ($g['booting'])
+ echo "Start gconcat raid... ";
+
+ // Load geom concat module
+ mwexec("/sbin/gconcat load");
+
+ if ($g['booting'])
+ echo "done\n";
+ }
+
+ return 0;
+}
+
+/* Start geom stripe volumes */
+function disks_raid_gstripe_start() {
+ global $freenas_config, $g;
+
+ /* Start Geom stripe */
+ if ($freenas_config['gstripe']['vdisk']) {
+ if ($g['booting'])
+ echo "Start gstripe raid... ";
+
+ // Load geom stripe module
+ mwexec("/sbin/gstripe load");
+
+ if ($g['booting'])
+ echo "done\n";
+ }
+
+ return 0;
+}
+
+/* Start geom raid5 volumes */
+function disks_raid_graid5_start() {
+ global $freenas_config, $g;
+
+ /* Start Geom RAID5 */
+ if ($freenas_config['graid5']['vdisk']) {
+ if ($g['booting'])
+ echo "Start graid5 raid... ";
+
+ // Load geom raid5 module
+ mwexec("/sbin/graid5 load");
+
+ if ($g['booting'])
+ echo "done\n";
+ }
+
+ return 0;
+}
+
+function disks_raid_stop() {
+ /* WARNING: Must change this code for advanced RAID configuration ex: RAID1+0
+ * Geom RAID volume must be started in 'intelligent' sort, for RAID1+0, gmirror must
+ * be started before gstripe, etc...
+ */
+ disks_raid_gvinum_stop();
+ disks_raid_graid5_stop();
+ disks_raid_gstripe_stop();
+ disks_raid_gconcat_stop();
+ disks_raid_gmirror_stop();
+
+ return 0;
+}
+
+function disks_raid_gvinum_stop() {
+ global $freenas_config, $g;
+
+ /* Generate the raid.conf file */
+ if ($freenas_config['raid']['vdisk']) {
+ /* stop each volume */
+ foreach ($freenas_config['raid']['vdisk'] as $a_raid_conf) {
+ mwexec("/sbin/gvinum stop {$a_raid_conf['name']}");
+ }
+ }
+
+ return 0;
+}
+
+function disks_raid_gmirror_stop() {
+ global $freenas_config, $g;
+
+ /* Generate the raid.conf file */
+ if ($freenas_config['gmirror']['vdisk']) {
+ /* start each volume */
+ foreach ($freenas_config['gmirror']['vdisk'] as $a_raid_conf) {
+ mwexec("/sbin/gmirror stop {$a_raid_conf['name']}");
+ }
+ }
+
+ return 0;
+}
+
+/* Stop all geom concat volumes */
+function disks_raid_gconcat_stop() {
+ global $freenas_config, $g;
+
+ /* Stop geom concat */
+ if ($freenas_config['gconcat']['vdisk']) {
+ /* start each volume */
+ foreach ($freenas_config['gconcat']['vdisk'] as $a_raid_conf) {
+ mwexec("/sbin/gconcat stop {$a_raid_conf['name']}");
+ }
+ }
+
+ return 0;
+}
+
+/* Stop all geom stripe volumes */
+function disks_raid_gstripe_stop() {
+ global $freenas_config, $g;
+
+ /* Stop geom stripe */
+ if ($freenas_config['gstripe']['vdisk']) {
+ /* start each volume */
+ foreach ($freenas_config['gstripe']['vdisk'] as $a_raid_conf) {
+ mwexec("/sbin/gstripe stop {$a_raid_conf['name']}");
+ }
+ }
+
+ return 0;
+}
+
+/* Stop all geom raid5 volumes */
+function disks_raid_graid5_stop() {
+ global $freenas_config, $g;
+
+ /* Generate the raid.conf file */
+ if ($freenas_config['graid5']['vdisk']) {
+ /* start each volume */
+ foreach ($freenas_config['graid5']['vdisk'] as $a_raid_conf) {
+ mwexec("/sbin/graid5 stop {$a_raid_conf['name']}");
+ }
+ }
+
+ return 0;
+}
+
+
+/* Delete geom gvinum volume given in parameter */
+function disks_raid_gvinum_delete($raidname) {
+ global $freenas_config, $g;
+
+ exec("/sbin/gvinum lv $raidname",$rawdata);
+
+ if (strpos($rawdata[0],"State: up") === false) {
+ return 0;
+ }
+
+ mwexec("/sbin/gvinum rm -r $raidname");
+
+ foreach ($freenas_config['gvinum']['vdisk'] as $a_raid) {
+ if ($a_raid['name'] == $raidname) {
+ foreach ($a_raid['diskr'] as $disk) {
+ mwexec("/sbin/gvinum rm -r disk_{$disk}");
+ }
+ }
+ }
+
+ return 0;
+}
+
+/* Delete geom mirror volume given in parameter */
+function disks_raid_gmirror_delete($raidname) {
+ global $freenas_config, $g;
+
+ // Stop the volume
+ mwexec("/sbin/gmirror stop $raidname");
+
+ // Clear the gmirror information on the hard drive
+ foreach ($freenas_config['gmirror']['vdisk'] as $a_raid) {
+ if ($a_raid['name'] == $raidname) {
+ foreach ($a_raid['diskr'] as $disk) {
+ mwexec("/sbin/gmirror clear {$disk}");
+ }
+ }
+ }
+
+ return 0;
+}
+
+/* Delete geom concat volume given in parameter */
+function disks_raid_gconcat_delete($raidname) {
+ global $freenas_config, $g;
+
+ // Stop the volume
+ mwexec("/sbin/gconcat stop $raidname");
+
+ // Clear the gconcat information on the hard drive
+ foreach ($freenas_config['gconcat']['vdisk'] as $a_raid) {
+ if ($a_raid['name'] == $raidname) {
+ foreach ($a_raid['diskr'] as $disk) {
+ mwexec("/sbin/gconcat clear {$disk}");
+ }
+
+ mwexec("/sbin/gconcat destroy $raidname");
+ }
+ }
+
+ return 0;
+}
+
+/* Delete geom stripe volume given in parameter */
+function disks_raid_gstripe_delete($raidname) {
+ global $freenas_config, $g;
+
+ // Stop the volume
+ mwexec("/sbin/gstripe stop $raidname");
+
+ // Clear the gconcat information on the hard drive
+ foreach ($freenas_config['gstripe']['vdisk'] as $a_raid) {
+ if ($a_raid['name'] == $raidname) {
+ foreach ($a_raid['diskr'] as $disk) {
+ mwexec("/sbin/gstripe clear {$disk}");
+ }
+
+ mwexec("/sbin/gstripe destroy $raidname");
+ }
+ }
+
+ return 0;
+}
+
+/* Delete geom raid5 volume given in parameter */
+function disks_raid_graid5_delete($raidname) {
+ global $freenas_config, $g;
+
+ // Stop the volume
+ mwexec("/sbin/graid5 stop $raidname");
+
+ // The volume can disapear a few second after stop
+ sleep(2);
+
+ // Clear the graid5 information on the hard drive
+ foreach ($freenas_config['graid5']['vdisk'] as $a_raid) {
+ if ($a_raid['name'] == $raidname) {
+ foreach ($a_raid['diskr'] as $disk) {
+ mwexec("/sbin/graid5 remove $raidname {$disk}");
+ }
+
+ mwexec("/sbin/graid5 destroy $raidname");
+ }
+ }
+
+ return 0;
+}
+
+/* Initialise HARD DRIVE for installing FreeNAS (creating 2 partition) */
+function fdisk_hd_install($harddrive) {
+ global $freenas_config, $g;
+
+ /* Initialise HARD DRIVE for installing FreeNAS (creating 2 partition) */
+
+ /* getting disk information */
+ $fdisk_info=fdisk_get_info($harddrive);
+
+ /* setting FreeNAS partition size to 32Mb */
+
+ $part_freenas_size=32;
+
+ /* convert Mb to b */
+ $part_freenas_size=$part_freenas_size * 1024 * 1024;
+
+ $part1_size=$part_freenas_size / $fdisk_info['sec_size'];
+ $part2_size=$fdisk_info['total'] - $part1_size;
+
+ /* Create fdisk config file */
+
+ /* generate fdisk.conf */
+ $fd = fopen("{$g['varetc_path']}/fdisk.conf", "w");
+ if (!$fd) {
+ printf("Error: cannot open fdisk.conf in fdisk_hd_install().\n");
+ return 1;
+ }
+
+$fdiskconf .= <<<EOD
+g c{$fdisk_info['cyl']} h{$fdisk_info['head']} s{$fdisk_info['sect']}
+p 1 165 1 $part1_size
+p 2 165 $part1_size $part2_size
+p 3 0 0 0
+p 4 0 0 0
+a 1
+
+EOD;
+
+ fwrite($fd, $fdiskconf);
+ fclose($fd);
+
+ /* Fdisk the disk */
+
+ /* Warning: Ask two questions to the user */
+ mwexec("/sbin/fdisk -f {$g['varetc_path']}/fdisk.conf /dev/$harddrive");
+
+ return 0;
+}
+
+function fdisk_get_info($harddrive) {
+ /* Return information about an harddrive
+
+ $result['total'] : size
+ $result['cyl'] : cylinders
+ $result['head'] : heads
+ $result['sect'] : sectors/track
+ $result['sec_size'] : Media sector size
+
+ */
+
+ global $freenas_config, $g;
+
+ exec("/sbin/fdisk /dev/$harddrive",$rawdata);
+
+ $result=array();
+
+ foreach ($rawdata as $line) {
+ /* separe the line by space or egal*/
+ $aline= preg_split("/[\s,]+|=/", $line);
+ $first_word = chop($aline[0]);
+
+ if ($aline[0] == "Media") {
+ $result['sec_size']=chop($aline[4]);
+ continue ;
+ }
+
+ if ($aline[0] == "cylinders") {
+ $result['cyl']=chop($aline[1]);
+ $result['head']=chop($aline[3]);
+ $result['sect']=chop($aline[5]);
+ continue ;
+ }
+ }
+
+ $result['total'] = $result['cyl'] * $result['head'] * $result['sect'] ;
+
+ return $result;
+}
+
+/* Is this function still used ??? */
+function disks_bsdlabel($harddrive,$partition,$type) {
+ global $freenas_config, $g;
+
+ // Generating BSD Label table
+ passthru("/sbin/bsdlabel " . escapeshellarg($harddrive) ."$partition > {$g['tmp_path']}/label.tmp");
+
+ // put this file on a array
+ $tableau = file("{$g['tmp_path']}/label.tmp");
+
+ // Open this file in add mode
+ $handle = fopen("{$g['tmp_path']}/label.tmp", 'a');
+
+ while(list(,$val) = each($tableau)) {
+ // If the line contain the word "unused"
+ if (ereg ("unused",$val)) {
+ // Replacing c: by a:
+ // Why ??? Must found the web page where I see this method
+ $val = ereg_replace ("c:","a:", $val);
+ // Peplacing unused by $type
+ $val = ereg_replace ("unused",$type, $val);
+ // Adding this line add the end of the file
+ fwrite($handle, $val);
+ }
+ }
+
+ // Closing file
+ fclose($handle);
+
+ // Injecting this new partition table
+ passthru("/sbin/bsdlabel -R -B " . escapeshellarg($harddrive) ."$partition {$g['tmp_path']}/label.tmp");
+}
+
+
+function disks_set_ataidle() {
+ global $g, $freenas_config;
+
+ if (is_array($freenas_config['disks']['disk'])) {
+ foreach ($freenas_config['disks']['disk'] as $disk) {
+ if ($disk['type']=="IDE") {
+ /* If UDMA mode forced, launch atacontrol */
+ if (isset($disk['udma']) && ($disk['udma'] != "auto")) {
+ mwexec("/sbin/atacontrol mode {$disk['name']} {$disk['udma']}");
+ }
+
+ /* Don't use ataidle if all is disabled */
+ if (($disk['harddiskstandby'] == 0) && ($disk['apm'] == 0) && ($disk['acoustic'] == 0)) { continue; }
+
+ /* Found the channel and device number from the /dev name */
+ /* Divise the number by 2, the interger is the channel number, the rest is the device */
+
+ $value=trim($disk['name'],'ad');
+
+ $value=intval($value);
+ $channel = $value/2;
+ $device=$value % 2;
+ $channel=intval($channel);
+ $time=$disk['harddiskstandby'];
+ $apm=$disk['apm'];
+ $ac=$disk['acoustic'];
+
+ $cmd = "/usr/local/sbin/ataidle ";
+
+ if ($disk['acoustic'] != 0) { $cmd .= "-A $ac "; }
+ if ($disk['apm'] != 0) { $cmd .= "-P $apm "; }
+ if ($disk['harddiskstandby'] !=0) { $cmd .= "-S $time "; }
+
+ $cmd .= "$channel $device";
+ mwexec($cmd);
+ } // end if
+ } // end foreach
+
+ return 1;
+ } // end if
+
+ return 0;
+}
+
+/* Is this function still used ???
+Get list of partition information from disk.
+Result is in the form:
+[1] => Array
+(
+ [start] => 31
+ [size] => 409169
+ [type] => 0xa5
+ [flags] => 0x80
+)
+
+Called in disks_manage_tools.php
+*/
+function disks_get_partition_info($disk) {
+ exec("/sbin/fdisk -s {$disk}", $rawdata);
+ array_shift($rawdata);
+ array_shift($rawdata);
+
+ $result = array();
+
+ foreach($rawdata as $partinfo) {
+ $apartinfo = preg_split("/\s+/", $partinfo);
+ $partid = chop($apartinfo[1],":");
+
+ $result[$partid] = array();
+ $result[$partid]['start'] = chop($apartinfo[2]);
+ $result[$partid]['size'] = chop($apartinfo[3]);
+ $result[$partid]['type'] = chop($apartinfo[4]);
+ $result[$partid]['flags'] = chop($apartinfo[5]);
+ }
+
+ return $result;
+}
+
+?>
diff --git a/config/freenas/pkg/freenas_functions.inc b/config/freenas/pkg/freenas_functions.inc
new file mode 100644
index 00000000..fcea4478
--- /dev/null
+++ b/config/freenas/pkg/freenas_functions.inc
@@ -0,0 +1,49 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ freenas_functions.inc
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+/* include all configuration functions */
+require_once ("freenas_disks.inc");
+require_once ("freenas_utils.inc");
+require_once ("freenas_services.inc");
+require_once ("freenas_system.inc");
+
+?> \ No newline at end of file
diff --git a/config/freenas/pkg/freenas_guiconfig.inc b/config/freenas/pkg/freenas_guiconfig.inc
new file mode 100644
index 00000000..2dec5a42
--- /dev/null
+++ b/config/freenas/pkg/freenas_guiconfig.inc
@@ -0,0 +1,288 @@
+<?php
+/*
+ guiconfig.inc
+ part of m0n0wall (http://m0n0.ch/wall)
+
+ Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+
+ Modified for FreeNAS (http://freenas.org) by Olivier Cochard <cochard@gmail.com>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+$d_mountdirty_path = $g['varrun_path'] . "/mount.dirty";
+$d_diskdirty_path = $g['varrun_path'] . "/disk.dirty";
+$d_raidconfdirty_path = $g['varrun_path'] . "/raid.conf.dirty";
+$d_userconfdirty_path = $g['varrun_path'] . "/user.conf.dirty";
+$d_groupconfdirty_path = $g['varrun_path'] . "/group.conf.dirty";
+$d_smbshareconfdirty_path = $g['varrun_path'] . "/smbshare.conf.dirty";
+$d_nfsexportconfdirty_path = $g['varrun_path'] . "/nfsexport.conf.dirty";
+$d_upnpconfdirty_path = $g['varrun_path'] . "/upnp.conf.dirty";
+
+/* ============================================================================= */
+/* == Constants used together with executing a UNIX command line tool == */
+/* ============================================================================= */
+
+define("DONE_PARAGRAPH", "
+ <p>
+ <span class='red' style='font-family: Courier, monospace; font-size: small;'><strong>Done!</strong></span>
+ </p>
+ ");
+
+define("CMDOUT_PARA", "
+ <p style='font-size: small;'>
+ <strong>Command output</strong> (use the toggle icon to unveil detailed infos):
+ </p>
+ ");
+
+define("CMDOUT_PARA_WOHINT", "
+ <p style='font-size: small;'>
+ <strong>Command output:</strong>
+ </p>
+ ");
+
+define("CMDOUT_TOGGLE_FUNC", "
+function toggle_cmdout(image, totoggle) {
+ var plusSrc = \"/themes/{$g['theme']}/images/misc/bullet_toggle_plus.png\";
+ var minusSrc = \"/themes/{$g['theme']}/images/misc/bullet_toggle_minus.png\";
+ var currentSrc = image.src;
+ var newSrc = (currentSrc.indexOf(\"plus\") >= 0) ? minusSrc : plusSrc;
+
+ image.src = newSrc;
+ Effect.toggle(totoggle, 'appear', { duration: 0.75 });
+}
+");
+
+define("CMDOUT_AJAX_SCRIPT", "
+ <script type='text/javascript'>
+ function execCMD() {
+ var to_insert = \"<div style='visibility:hidden' id='loading' name='loading'><img src='/themes/nervecenter/images/misc/loader_tab.gif' \/><\/div>\";
+ new Insertion.Before('doCMDSubmit', to_insert);
+
+ $('doCMDSubmit').style.visibility = 'hidden';
+ $('loading').style.visibility = 'visible';
+ $('cmdOutputTD').innerHTML = '';
+
+ new Ajax.Request(
+ \"{$_SERVER['SCRIPT_NAME']}\", {
+ method : 'post',
+ parameters : Form.serialize($('iform')),
+ onSuccess : execCMDComplete,
+ onFailure : execCMDFailure
+ }
+ );
+ }
+
+ function execCMDFailure(req) {
+ if($('doCMDSubmit')) $('doCMDSubmit').style.visibility = 'visible';
+ if($('loading')) $('loading').style.visibility = 'hidden';
+ if($('inputerrors')) window.scrollTo(0, 0);
+ if($('inputerrors')) new Effect.Shake($('inputerrors'));
+ if($('inputerrors')) $('inputerrors').innerHTML = req.responseText;
+ }
+
+ function execCMDComplete(req) {
+ $('cmdOutputTD').innerHTML = req.responseText;
+ $('loading').style.visibility = 'hidden';
+ $('doCMDSubmit').style.visibility = 'visible';
+ $('cmdOutputTD').style.visibility = 'visible';
+ }
+ </script>
+");
+
+$freenas_config =& $config['installedpackages']['freenas']['config'][0];
+
+/* ============================================================================= */
+/* == Functions used together with executing a UNIX command line tool == */
+/* ============================================================================= */
+
+function assemble_cmdout($button, $out, $done = false) {
+ $dopara = DONE_PARAGRAPH;
+
+ $retvalue =<<<EOD
+{$button}
+{$out}
+
+EOD;
+
+ if ($done) { $retvalue .= "{$dopara}\n"; }
+ return $retvalue;
+}
+
+function create_cmdout_container($id = "", $cmd = "") {
+ $diskinit_str = "";
+
+ if (is_array($cmd)) {
+ foreach ($cmd as $cmdline) {
+ $a_out = exec_command_and_return_text_array($cmdline);
+ $diskinit_str .= implode("\n", $a_out);
+ }
+ } else {
+ $a_out = exec_command_and_return_text_array($cmd);
+ $diskinit_str = implode("\n", $a_out);
+ }
+
+ $returnval =<<<EOD
+ <div id="{$id}" style="display: none; font-family: Courier, monospace; font-size: small;">
+ <pre style="font-family: Courier, monospace; font-size: small; font-style: italic;">{$diskinit_str}</pre>
+ </div>
+
+EOD;
+
+ return $returnval;
+}
+
+function create_toggle_button($title, $totoggle) {
+ global $g;
+
+ $returnval =<<<EOD
+ <table cellpadding="0" cellspacing="0" border="0" style="padding-bottom: 8px;">
+ <tr>
+ <td align="left" valign="middle" style="padding-right: 5px;">
+ <img src='/themes/{$g['theme']}/images/misc/bullet_toggle_plus.png' alt='' border='0' style='border: solid 1px silver; cursor: pointer;' onclick='toggle_cmdout(this, "{$totoggle}");' />
+ </td>
+ <td align="left" valign="middle" style='font-family: Courier, monospace; font-size: small;'>
+ {$title}:
+ </td>
+ </tr>
+ </table>
+EOD;
+
+ return $returnval;
+}
+
+function print_error_box_np($msg) {
+ global $g;
+
+ echo "<table border=\"0\" cellspacing=\"0\" cellpadding=\"4\" width=\"100%\">\n";
+ echo "<tr><td bgcolor=\"#A12A2A\" width=\"36\" align=\"center\" valign=\"top\"><img src=\"/themes/{$g['theme']}/images/icons/icon_error.gif\" width=\"28\" height=\"32\"></td>\n";
+ echo "<td bgcolor=\"#FFD9D1\" style=\"padding-left: 8px; padding-top: 6px\">";
+ echo "<span class=\"errmsg\">";
+ echo $msg;
+ echo "</span>";
+ echo "</td></tr></table>";
+}
+
+function print_error_box($msg) {
+ echo "<p>";
+ print_error_box_np($msg);
+ echo "</p>";
+}
+
+function mount_sort() {
+ global $g, $freenas_config;
+
+ function mountcmp($a, $b) {
+ return strcmp($a['mdisk'], $b['mdisk']);
+ }
+
+ usort($freenas_config['mounts']['mount'], "mountcmp");
+}
+
+function disks_sort() {
+ global $g, $freenas_config;
+
+ function diskcmp($a, $b) {
+ return strcmp($a['name'], $b['name']);
+ }
+
+ usort($freenas_config['disks']['disk'], "diskcmp");
+}
+
+function gvinum_sort() {
+ global $g, $freenas_config;
+
+ function gvinumcmp($a, $b) {
+ return strcmp($a['name'], $b['name']);
+ }
+
+ usort($freenas_config['gvinum']['vdisk'], "gvinumcmp");
+
+}
+
+function gmirror_sort() {
+ global $g, $freenas_config;
+
+ function gmirrorcmp($a, $b) {
+ return strcmp($a['name'], $b['name']);
+ }
+
+ usort($freenas_config['gmirror']['vdisk'], "gmirrorcmp");
+
+}
+
+function gconcat_sort() {
+ global $g, $freenas_config;
+
+ function gconcatcmp($a, $b) {
+ return strcmp($a['name'], $b['name']);
+ }
+
+ usort($freenas_config['gconcat']['vdisk'], "gconcatcmp");
+
+}
+
+function gstripe_sort() {
+ global $g, $freenas_config;
+
+ function gstripecmp($a, $b) {
+ return strcmp($a['name'], $b['name']);
+ }
+
+ usort($freenas_config['gstripe']['vdisk'], "gstripecmp");
+
+}
+
+function graid5_sort() {
+ global $g, $freenas_config;
+
+ function graid5cmp($a, $b) {
+ return strcmp($a['name'], $b['name']);
+ }
+
+ usort($freenas_config['graid5']['vdisk'], "graid5cmp");
+
+}
+
+/* TODO: This needs to be changed */
+function users_sort() {
+ global $g, $config;
+
+ function userscmp($a, $b) {
+ return strcmp($a['login'], $b['login']);
+ }
+
+ usort($config['system']['user'], "userscmp");
+}
+
+/* TODO: This needs to be changed */
+function groups_sort() {
+ global $g, $config;
+
+ function groupscmp($a, $b) {
+ return strcmp($a['name'], $b['name']);
+ }
+
+ usort($config['system']['group'], "groupscmp");
+}
+?> \ No newline at end of file
diff --git a/config/freenas/pkg/freenas_services.inc b/config/freenas/pkg/freenas_services.inc
new file mode 100644
index 00000000..71401211
--- /dev/null
+++ b/config/freenas/pkg/freenas_services.inc
@@ -0,0 +1,2025 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ freenas_services.inc
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+define ("FTP_BACKEND_PAM", "pam");
+define ("FTP_BACKEND_PLAINTEXT", "plaintext");
+define ("NFS_SERVICE_PORTS", "111 2049 4711");
+
+$freenas_config =& $config['installedpackages']['freenas']['config'][0];
+
+/* Stop samba, Generate the samba configuration
+ * file and start samba Return 0 if OK, 1 or
+ * error code if error
+ */
+function services_samba_configure() {
+ global $freenas_config, $g;
+
+ /* kill any running samba */
+ killbyname("smbd");
+ killbyname("winbindd");
+ killbyname("nmbd");
+
+ if (isset($freenas_config['samba']['enable'])) {
+ if ($g['booting']) { echo "Starting Samba... "; }
+
+ /* make sure any of the required dirs exist */
+ if (! file_exists("{$g['varetc_path']}/private")) {
+ mkdir("{$g['varetc_path']}/private");
+ }
+ if (! file_exists("{$g['varlog_path']}/samba")) {
+ mkdir("{$g['varlog_path']}/samba");
+ }
+
+ /* generate smb.conf */
+ $fd = fopen("{$g['varetc_path']}/smb.conf", "w");
+
+ if (!$fd) {
+ printf("Error: cannot open smb.conf in services_samba_configure().\n");
+ return 1;
+ }
+
+ /* If no share configured, exit */
+ if (!is_array($freenas_config['mounts']['mount'])) { return 0; }
+
+ $gen_date = date("F j, Y, g:i a");
+ $sambaconf = <<<EOD
+#
+# smb.conf generated by pfSense
+# Generated at: {$gen_date}
+#
+[global]
+encrypt passwords = yes
+netbios name = {$freenas_config['samba']['netbiosname']}
+workgroup = {$freenas_config['samba']['workgroup']}
+server string = {$freenas_config['samba']['serverdesc']}
+load printers = no
+security = {$freenas_config['samba']['security']}
+dns proxy = no
+socket options = IPTOS_LOWDELAY TCP_NODELAY
+EOD;
+
+ if ($freenas_config['samba']['sndbuf']) {
+ /* below is a continuation of socket options! */
+ $sambaconf .= <<<EOD
+ SO_SNDBUF={$freenas_config['samba']['sndbuf']}
+EOD;
+ } else {
+ /* below is a continuation of socket options! */
+ $sambaconf .= <<<EOD
+ SO_SNDBUF=16384
+EOD;
+ } // end if
+
+ if ($freenas_config['samba']['rcvbuf']) {
+ /* below is a continuation of socket options! */
+ $sambaconf .= <<<EOD
+ SO_RCVBUF={$freenas_config['samba']['rcvbuf']}
+EOD;
+ } else {
+ /* below is a continuation of socket options! */
+ $sambaconf .= <<<EOD
+ SO_RCVBUF=16384
+EOD;
+ } // end if
+
+ if ($freenas_config['samba']['winssrv']) {
+ $sambaconf .= <<<EOD
+
+wins server = {$freenas_config['samba']['winssrv']}
+
+EOD;
+ }
+
+ if (isset ($freenas_config['samba']['unixcharset'])) {
+ $sambaconf .= <<<EOD
+
+unix charset = {$freenas_config['samba']['unixcharset']}
+
+EOD;
+ } else {
+ $sambaconf .= <<<EOD
+
+unix charset = UTF-8
+
+EOD;
+
+ } // end if
+
+ $sambaconf .= <<<EOD
+
+local master = {$freenas_config['samba']['localmaster']}
+time server = {$freenas_config['samba']['timesrv']}
+guest account = ftp
+display charset = UTF-8
+max log size = 10
+syslog only = yes
+syslog = {$config['samba']['loglevel']}
+load printers = no
+printing = bsd
+printcap name = /dev/null
+disable spoolss = yes
+#Test: Try to improve samba performance under FreeBSD:
+use sendfile = yes
+strict locking = no
+#End of performance section
+log level = {$freenas_config['samba']['loglevel']}
+dos charset = {$freenas_config['samba']['doscharset']}
+smb passwd file = {$g['varetc_path']}/private/smbpasswd
+private dir = {$g['varetc_path']}/private
+
+EOD;
+
+ switch ($freenas_config['samba']['security']) {
+ case "share":
+ $sambaconf .= <<<EOD
+create mask = 0666
+directory mask = 0777
+passdb backend = smbpasswd
+
+EOD;
+
+ $guestmode = <<<EOD
+guest ok = yes
+
+EOD;
+
+ break; // end case "share"
+ case "domain":
+ $sambaconf .= <<<EOD
+passdb backend = smbpasswd
+allow trusted domains = No
+dns proxy = No
+ldap ssl = no
+idmap backend = rid:{$freenas_config['samba']['workgroup']}=10000-20000
+idmap uid = 10000-20000
+idmap gid = 10000-20000
+winbind enum groups = yes
+winbind enum users = yes
+winbind use default domain = Yes
+template homedir = /mnt
+template shell = /bin/sh
+
+EOD;
+
+ $guestmode = <<<EOD
+guest ok = no
+
+EOD;
+ break; // end case "domain":
+ case "user":
+ $sambaconf .= <<<EOD
+passdb backend = smbpasswd
+
+EOD;
+
+ $guestmode = <<<EOD
+guest ok = no
+
+EOD;
+
+ break; // end case "user":
+ } // end switch
+
+ foreach ($freenas_config['mounts']['mount'] as $mountent) {
+ /* Unmount filesystem if not booting mode*/
+ $sambaconf .= <<<EOD
+
+[{$mountent['sharename']}]
+comment = {$mountent['desc']}
+path = /mnt/{$mountent['sharename']}
+public = yes
+writeable = yes
+printable = no
+veto files = /Network Trash Folder/Icon?/:2e*/.AppleDesktop/.AppleDB/.AppleDouble/TheFindByContentFolder/TheVolumeSettingsFolder/Temporary Items/.snap/
+hide dot files = yes
+{$guestmode}
+
+EOD;
+
+ if ( (is_array($freenas_config['samba']['hidemount']) && in_array($mountent['sharename'],$freenas_config['samba']['hidemount']))) {
+ $sambaconf .= <<<EOD
+browseable = no
+
+EOD;
+
+ } // end if
+
+ if (isset($freenas_config['samba']['recyclebin'])) {
+ $sambaconf .= <<<EOD
+vfs object = recycle
+recycle:repository = Recycle Bin
+recycle:keeptree = Yes
+recycle:versions = Yes
+
+EOD;
+ } // end if
+ } // end foreach
+
+ fwrite($fd, $sambaconf);
+ fclose($fd);
+
+ /* run nmbd and nmbd */
+ if (isset($freenas_config['ad']['enable'])) {
+ mwexec("/usr/local/bin/net rpc join -S {$freenas_config['ad']['ad_srv_name']} -U {$freenas_config['ad']['admin_name']}%{$freenas_config['ad']['admin_pass']}");
+ }
+
+ $result |= mwexec("/usr/local/sbin/nmbd -D -s {$g['varetc_path']}/smb.conf");
+
+ if (isset($freenas_config['ad']['enable'])) {
+ mwexec("/usr/local/sbin/winbindd -s {$g['varetc_path']}/smb.conf");
+ //mwexec("/usr/local/sbin/wbinfo --set-auth-user {$freenas_config['ad']['admin_name']}%{$freenas_config['ad']['admin_pass']}");
+ }
+
+ $result |= mwexec("/usr/local/sbin/smbd -D -s {$g['varetc_path']}/smb.conf");
+
+ /* TEST: Wait for samba starting */
+ sleep(2);
+
+ /* Generate the samba password file */
+ $result |= system_user_samba();
+
+ if ($g['booting']) { echo "done\n"; }
+ }// end if
+
+ return $result;
+}
+
+/* Stop rsync, Generate the rsync configuration file and start
+ * rsync Return 0 if OK, 1 or error code if error
+ */
+function services_rsyncd_configure() {
+ global $freenas_config, $g;
+
+ /* kill any running rsync daemon */
+ sigkillbypid("{$g['varrun_path']}/rsyncd.pid", "TERM");
+
+ if (isset($freenas_config['rsyncd']['enable'])) {
+ if ($g['booting']) { echo "Starting RSYNC daemon... "; }
+
+ /* If no share configured, exit */
+ if (!is_array($freenas_config['mounts']['mount'])) { return 1; }
+
+ /* generate rsyncd.conf */
+ $fd = fopen("{$g['varetc_path']}/rsyncd.conf", "w");
+
+ if (!$fd) {
+ printf("Error: cannot open rsyncd.conf in services_rsyncd_configure().\n");
+ return 1;
+ }
+
+ $rsyncdconf = <<<EOD
+read only = {$freenas_config['rsyncd']['readonly']}
+syslog facility = local4
+list = yes
+port = {$freenas_config['rsyncd']['port']}
+pid file = {$g['varrun_path']}/rsyncd.pid
+
+EOD;
+
+ if (!empty($freenas_config['rsyncd']['maxcon'])) {
+ $rsyncdconf .= <<<EOD
+max connections = {$freenas_config['rsyncd']['maxcon']}
+
+EOD;
+ }
+
+ if (!empty($freenas_config['rsyncd']['motd'])) {
+ $rsyncdconf .= <<<EOD
+motd file = {$g['varetc_path']}/rsyncd.motd
+
+EOD;
+ }
+
+ if (isset($freenas_config['rsyncd']['rsyncd_user'])) {
+ $rsyncdconf .= <<<EOD
+uid = {$freenas_config['rsyncd']['rsyncd_user']}
+
+EOD;
+
+ } else {
+ $rsyncdconf .= <<<EOD
+uid = ftp
+gid = ftp
+
+EOD;
+ } // end if
+
+ foreach ($freenas_config['mounts']['mount'] as $mountent) {
+ /* Unmount filesystem if not booting mode*/
+ $rsyncdconf .= <<<EOD
+
+[{$mountent['sharename']}]
+comment = {$mountent['desc']}
+path = /mnt/{$mountent['sharename']}
+
+EOD;
+ } // end foreach
+
+ fwrite($fd, $rsyncdconf);
+ fclose($fd);
+
+ // Generate MOTD file if configured
+ if (!empty($freenas_config['rsyncd']['motd'])) {
+ $fd = fopen("{$g['varetc_path']}/rsyncd.motd", "w");
+
+ if (!$fd) {
+ printf("Error: cannot open rsyncd.motd in services_rsyncd_configure().\n");
+ return 1;
+ }
+
+ $motd = <<<EOD
+{$freenas_config['rsyncd']['motd']}
+
+EOD;
+
+ fwrite($fd, $motd);
+ fclose($fd);
+ } // end if
+
+ /* run rsync Daemon */
+ $result = mwexec("/usr/local/bin/rsync --daemon --config={$g['varetc_path']}/rsyncd.conf");
+
+ if ($g['booting']) { echo "done\n"; }
+ } // end if
+
+ return $result;
+}
+
+/* Stop nfs processes, Generate the nfs configuration file and
+ * start nfsd processes Return 0 if OK, 1 or error code if error
+ */
+function services_nfs_configure() {
+ global $freenas_config, $g;
+
+ /* kill any running nfsd */
+ killbyname("rpc.statd");
+ killbyname("rpc.lockd");
+ killbypid("{$g['varrun_path']}/mountd.pid");
+ forcekillbyname("nfsd");
+ killbyname("rpcbind");
+
+ if (isset($freenas_config['nfs']['enable'])) {
+ if ($g['booting']) { echo "Starting NFS... "; }
+
+ $nfsconf = "";
+ $a_nfsconf = array();
+
+ /* If no share configured, exit */
+ if (!is_array($freenas_config['mounts']['mount'])) { return 1; }
+
+ /* generate exports */
+ $fd = fopen("{$g['varetc_path']}/exports", "w");
+
+ if (!$fd) {
+ printf("Error: cannot open exports in services_nfs_configure().\n");
+ return 1;
+ }
+
+ $a_mount = &$freenas_config['mounts']['mount'];
+ $pfnetworks = array();
+
+ foreach ($a_mount as $mount) {
+ /* -mapall and -maproot mutually exclusive */
+ $mapping = $mount['nfs']['mapall'] == "yes" ? "-mapall=root" : "-maproot=root";
+ $networks = isset($mount['nfs']['networks']) ? $mount['nfs']['networks'] : "";
+
+ $nfsconf = "/mnt/{$mount['sharename']} -alldirs {$mapping}";
+
+ if ($networks <> "") {
+ foreach (explode(",", $networks) as $netel) {
+ list($network,$subnet) =
+ explode('/', $netel);
+
+ $subnet = gen_subnet_mask($subnet);
+ $pfnetworks[] = $network;
+
+ $tmp_nfsconf .= "{$nfsconf} -network {$network} -mask {$subnet}\n";
+ }
+
+ services_setup_transparency_for("nfs", implode(" ", $pfnetworks));
+ $nfsconf = $tmp_nfsconf;
+ } else {
+ $nfsconf .= "\n";
+ }
+ }
+
+ fwrite($fd, $nfsconf);
+ fclose($fd);
+
+ $nfsdbindto = $freenas_config['nfs']['bindto'] = "(ANY)" ? " -a" : " -h {$freenas_config['nfs']['bindto']}";
+ $rpcbbindto = $freenas_config['nfs']['bindto'] = "(ANY)" ? "" : " -h {$freenas_config['nfs']['bindto']}";
+ $servetcp = isset($freenas_config['nfs']['servetcp']) ? " -t" : "";
+ $serveudp = isset($freenas_config['nfs']['serveudp']) ? " -u" : "";
+
+ /* run rpcbind, nfsd and mountd */
+ mwexec("/usr/sbin/rpcbind{$rpcbbindto}");
+ mwexec("/usr/sbin/nfsd{$nfsdbindto}{$serveudp}{$servetcp} -n 4");
+ mwexec("/usr/sbin/mountd -p 4711 -r {$g['varetc_path']}/exports");
+ mwexec("/usr/sbin/rpc.lockd");
+ mwexec("/usr/sbin/rpc.statd");
+
+ if ($g['booting']) { echo "done\n"; }
+ } else {
+ services_remove_transparency_for("nfs");
+ }// end if
+
+ return 0;
+}
+
+function services_remove_transparency_for($whom) {
+ global $g;
+
+ $service_result = mwexec ("pfctl -a \"passin-package-freenas-{$whom}\" -F rules");
+ if($service_result <> 0) {
+ file_notice("FREENAS", "There were error(s) flushing the exclude table", "FREENAS", "");
+ }
+
+ unlink_if_exists("{$g['pkg_path']}/pf/freenas-{$whom}.sh");
+}
+
+function services_setup_transparency_for($whom, $networks) {
+ global $g, $config, $freenas_config;
+
+ if ($whom == "" || $networks == "") { return; }
+
+ $generatedLANSubnet = gen_subnet($config['interfaces']['lan']['ipaddr'],
+ $config['interfaces']['lan']['subnet']);
+ $aliases = "";
+
+ /* stolen from filter.inc */
+ $real_wanif = get_real_wan_interface();
+ $wanip = find_interface_ip($real_wanif);
+
+ $wan_aliases = " " . link_ip_to_carp_interface($wanip);
+
+ if (link_int_to_bridge_interface("wan"))
+ $wan_aliases .= " " . link_int_to_bridge_interface("wan");
+
+ if ($config['interfaces']['wan']['ipaddr'] == "pppoe" or $config['interfaces']['wan']['ipaddr'] == "pptp") {
+ $aliases .= "ng0 = \"{ {$config['interfaces']['wan']['if']} {$real_wanif} }\" \n";
+ $aliases .= "wan = \"{ {$config['interfaces']['wan']['if']} {$wan_aliases} ng0 }\"\n";
+ } else {
+ $aliases .= "wan = \"{ {$real_wanif} {$wan_aliases} }\"\n";
+ }
+
+ $trans_file = fopen("/tmp/freenas-{$whom}.rules","w");
+ fwrite($trans_file, "{$aliases}\n");
+
+ switch ($whom) {
+ case "nfs":
+ $nfs_ports = explode(" ", NFS_SERVICE_PORTS);
+
+ foreach ($nfs_ports as $port) {
+ fwrite($trans_file, "pass in quick on \$wan proto { tcp udp } from { {$networks} } to {$freenas_config['nfs']['bindto']} port = {$port} keep state label \"FreeNAS related rule for {$whom}-{$port}\"\n");
+ }
+ break;
+ }
+ fclose($trans_file);
+ $service_result = mwexec ("pfctl -a \"passin-package-freenas-{$whom}\" -f /tmp/freenas-{$whom}.rules");
+ if($service_result <> 0) {
+ file_notice("FREENAS", "There were error(s) loading the transparency rules", "FREENAS", "");
+ }
+
+ /* create a shell script to make sure our filter rules
+ * are getting loaded upon each filter realod cycle.
+ */
+ $scriptstr = "#!/bin/sh\n\n";
+ $scriptstr .= "case $1 in\n";
+ $scriptstr .= " start)\n";
+ $scriptstr .= " if [ -f /tmp/freenas-nfs.rules ]; then\n";
+ $scriptstr .= " /sbin/pfctl -a \"passin-package-freenas-{$whom}\" -f /tmp/freenas-{$whom}.rules\n";
+ $scriptstr .= " fi\n";
+ $scriptstr .= " ;;\n";
+ $scriptstr .= " *)\n";
+ $scriptstr .= " echo \"Usage: $0 (start|stop|restart|status|log)\"\n";
+ $scriptstr .= " exit 1\n";
+ $scriptstr .= "esac\n";
+
+ file_put_contents("{$g['pkg_path']}/pf/freenas-{$whom}.sh", $scriptstr);
+ chmod("{$g['pkg_path']}/pf/freenas-{$whom}.sh", 0700);
+}
+
+function services_ftpd_configure() {
+ global $freenas_config, $g;
+ // services_vsftpd_configure();
+ // services_pureftpd_configure();
+ services_wzdftpd_configure();
+}
+
+function services_wzdftpd_configure() {
+ global $freenas_config, $config, $g;
+
+ /* kill any WZDFTPD */
+ killbyname("wzdftpd");
+
+ if (isset($freenas_config['ftp']['enable'])) {
+ if ($g['booting']) { echo "Starting FTP server... "; }
+
+ /* create missing dirs if necessary */
+ if (! file_exists("/var/log/wzdftpd")) { mkdir("/var/log/wzdftpd"); }
+ if (! file_exists("/usr/local/etc/wzdftpd")) { mkdir("/usr/local/etc/wzdftpd"); }
+
+ /* generate wzd.cfg */
+ chmod("/usr/local/etc/wzdftpd/wzd.cfg", 0600);
+ $fd = fopen("/usr/local/etc/wzdftpd/wzd.cfg", "w");
+
+ if (!$fd) {
+ printf("Error: cannot open vsftpd.conf in services_vsftpd_configure().\n");
+ return 1;
+ }
+
+ $ftpconf = <<<EOD
+[GLOBAL]
+config version = 0.7.2
+backup config = true
+port = {$freenas_config['ftp']['port']}
+
+EOD;
+
+ if ($freenas_config['ftp']['pasv_min_port'] && $freenas_config['ftp']['pasv_max_port']) {
+ $ftpconf .= <<<EOD
+pasv_low_range = {$freenas_config['ftp']['pasv_min_port']}
+pasv_high_range = {$freenas_config['ftp']['pasv_max_port']}
+
+EOD;
+ }
+
+ $ftpconf .= <<<EOD
+
+pasv_ip = {$freenas_config['ftp']['pasv_address']}
+dir_message = .message
+logfile = /var/log/wzdftpd/wzd.log
+xferlog = /var/log/wzdftpd/xferlog
+logdir = /var/log/wzdftpd
+max_threads = {$freenas_config['ftp']['numberclients']}
+
+backend = /usr/local/share/wzdftpd/backends/libwzd{$freenas_config['ftp']['authentication_backend']}.so
+
+max_ul_speed = 0
+max_dl_speed = 0
+deny_access_files_uploaded = 1
+
+tls_certificate = /usr/local/etc/wzdftpd/wzd.pem
+sitefile_ginfo = /usr/local/etc/wzdftpd/file_ginfo.txt
+sitefile_group = /usr/local/etc/wzdftpd/file_group.txt
+sitefile_user = /usr/local/etc/wzdftpd/file_user.txt
+
+[pre_ip_check]
+localhost = allow
+
+[perms]
+site_addip = +O +G
+site_adduser = +O +G
+site_backend = +O
+site_chacl = +O
+site_change = +O +G
+site_changegrp = +O +G
+site_checkperm = +O
+site_chgrp = +O
+site_chmod = +O
+site_chown = +O
+site_chpass = *
+site_chratio = +O +G
+site_close = +O
+site_color = !=guest *
+site_delip = +O +G
+site_deluser = +O +G
+site_flags = -admin
+site_free = *
+site_ginfo = +O +G
+site_give = *
+site_group = +O
+site_groups = +O
+site_grpadd = +O
+site_grpaddip = +O
+site_grpchange = +O
+site_grpdel = +O
+site_grpdelip = +O
+site_grpkill = +O
+site_grpratio = +O
+site_grpren = +O
+site_gsinfo = +O +G
+site_help = *
+
+EOD;
+
+ if (! empty($freenas_config['ftp']['timeout'])) {
+ $ftpconf .= "site_idle ={$freenas_config['ftp']['timeout']}\n";
+ } else {
+ $ftpconf .= "site_idle = *\n";
+ }
+
+ $ftpconf .= <<<EOD
+site_invite = !=guest *
+site_kick = +O
+site_kill = +O
+site_link = +O
+site_msg = +O
+site_perm = +O
+site_purge = +O +G
+site_readd = +O +G
+site_reload = +O
+site_reopen = +O
+site_rules = *
+site_rusage = +O
+site_savecfg = +O
+site_sections = +O
+site_shutdown = +O
+site_su = +O
+site_swho = +O
+site_tagline = !=guest *
+site_take = +O
+site_unlock = +O
+site_uptime = *
+site_user = +O +G
+site_users = -admin
+site_utime = *
+site_vars = +O
+site_vars_group = +O
+site_vars_user = +O
+site_version = +O
+site_who = !=guest *
+site_wipe = +O
+site_vfsls = +O
+site_vfsadd = +O
+site_vfsdel = +O
+
+[modules]
+/usr/local/share/wzdftpd/modules/libwzd_debug.so = deny
+/usr/local/share/wzdftpd/modules/libwzd_test.so = deny
+/usr/local/share/wzdftpd/modules/libwzd_sfv.so = allow
+/usr/local/share/wzdftpd/modules/libwzd_tcl.so = deny
+/usr/local/share/wzdftpd/modules/libwzd_perl.so = deny
+
+EOD;
+
+ if (empty($config['system']['zeroconf_disable'])) {
+ $ftpconf .= <<<EOD
+/usr/local/share/wzdftpd/modules/libwzd_zeroconf.so = allow
+
+[ZEROCONF]
+zeroconf_port = {$freenas_config['ftp']['port']}
+zeroconf_username = wzdftpd
+zeroconf_password = wzdftpd
+zeroconf_path = /
+
+EOD;
+
+ }
+
+ $ftpconf .= <<<EOD
+
+[sfv]
+progressmeter = [WzD] - %3d%% Complete - [WzD]
+del_progressmeter = \[.*] - ...% Complete - \[WzD]
+incomplete_indicator = ../(incomplete)-%0
+other_completebar = [WzD] - ( %.0mM %fF - COMPLETE ) - [WzD]
+
+[plaintext]
+param = /usr/local/etc/wzdftpd/users
+
+[sections]
+ALL = /* ^([]\[A-Za-z0-9_.'() \\t+-])*\$
+
+[cron]
+
+[events]
+
+[custom_commands]
+site_rules = !/usr/local/etc/wzdftpd/file_rules.txt
+
+site_groups = !/usr/local/etc/wzdftpd/file_groups.txt
+site_help = !/usr/local/etc/wzdftpd/file_help.txt
+site_swho = !/usr/local/etc/wzdftpd/file_swho.txt
+site_users = !/usr/local/etc/wzdftpd/file_users.txt
+site_vfsls = !/usr/local/etc/wzdftpd/file_vfs.txt
+site_who = !/usr/local/etc/wzdftpd/file_who.txt
+
+[vfs]
+
+[messages]
+
+EOD;
+
+ if (isset($freenas_config['ftp']['banner'])) {
+ $ftpconf .= "200 = {$freenas_config['ftp']['banner']}";
+ } else {
+ $ftpconf .= "200 = Welcome to pfSense FTP service";
+ }
+
+ fwrite($fd, $ftpconf);
+ fclose($fd);
+ chmod("/usr/local/etc/wzdftpd/wzd.cfg", 0400);
+
+ /* now generate the plaintext users file (if applicable) */
+ if ($freenas_config['ftp']['authentication_backend'] == FTP_BACKEND_PLAINTEXT) {
+ $ftpusers = "[GROUPS]\n";
+ $a_group =& $config['system']['group'];
+ $a_user =& $config['system']['user'];
+
+ for ($i = 0; $i < count($a_group); $i++) {
+ $group = $a_group[$i];
+ $gid = $i + 1;
+
+ $ftpusers .= <<<EOD
+
+privgroup {$group['name']}
+gid={$gid}
+default_home=/
+
+EOD;
+ } // end foreach
+
+ /* anonymous group */
+ if (! empty($freenas_config['ftp']['anonymous'])) {
+ $ftpusers .= <<<EOD
+
+privgroup anonymous
+max_idle_time=10
+gid=3
+default_home=/home
+
+EOD;
+ }
+
+ /* same for users */
+ $ftpusers .= "[USERS]\n";
+ for ($i = 0; $i < count($a_user); $i++) {
+ $user = $a_user[$i];
+ $ftpusers .= <<<EOD
+
+name={$user['name']}
+pass={$user['password']}
+home=/
+uid={$i}
+groups={$user['groupname']}
+rights=0xffffffff
+
+EOD;
+ } // end foreach
+
+ /* anonymous user */
+ if (! empty($freenas_config['ftp']['anonymous'])) {
+ $ftpusers .= <<<EOD
+
+name=guest
+pass=%
+home=/tmp
+uid=200
+groups=anonymous
+rights=0x10003
+ip_allowed=*
+max_dl_speed=20480
+credits=0
+bytes_ul_total=0
+bytes_dl_total=1918812
+num_logins=2
+
+EOD;
+ } // end if
+
+ $ftpusers .= "[HOSTS]\nall = *\n";
+ chmod("/usr/local/etc/wzdftpd/users", 0600);
+ file_put_contents("/usr/local/etc/wzdftpd/users", $ftpusers);
+ chmod("/usr/local/etc/wzdftpd/users", 0400);
+ } // end if
+
+ /* run vsftpd */
+ mwexec("/usr/local/sbin/wzdftpd -f /usr/local/etc/wzdftpd/wzd.cfg");
+
+ if ($g['booting']) { echo "done\n"; }
+ } // end if
+
+ return 0;
+}
+
+/* this function is currently not used */
+function services_vsftpd_configure() {
+ global $freenas_config, $g;
+
+ /* kill any VSFTPD */
+ killbyname("vsftpd");
+
+ if (isset($freenas_config['ftp']['enable'])) {
+ if ($g['booting']) { echo "Starting FTP server... "; }
+
+ /* generate vfstpd.conf */
+ $fd = fopen("{$g['varetc_path']}/vsftpd.conf", "w");
+
+ if (!$fd) {
+ printf("Error: cannot open vsftpd.conf in services_vsftpd_configure().\n");
+ return 1;
+ }
+
+ $ftpconf = <<<EOD
+# Standalone mode
+listen=YES
+background=YES
+listen_port={$freenas_config['ftp']['port']}
+max_clients={$freenas_config['ftp']['numberclients']}
+max_per_ip={$freenas_config['ftp']['maxconperip']}
+xferlog_enable=YES
+#vsftpd_log_file=/var/log/ftp.log
+syslog_enable=YES
+# Access rights
+anonymous_enable={$freenas_config['ftp']['anonymous']}
+local_enable={$freenas_config['ftp']['localuser']}
+write_enable=YES
+hide_file=.snap
+anon_other_write_enable=YES
+anon_upload_enable=YES
+anon_mkdir_write_enable=YES
+chroot_local_user=YES
+local_umask=066
+anon_umask=066
+chmod_enable=YES
+pasv_address={$freenas_config['ftp']['pasv_address']}
+# Features
+ls_recurse_enable=YES
+# Performance
+idle_session_timeout={$freenas_config['ftp']['timeout']}
+
+EOD;
+ if (isset($freenas_config['ftp']['banner'])) {
+ $ftpconf .= <<<EOD
+ftpd_banner={$freenas_config['ftp']['banner']}
+
+EOD;
+ } else {
+ $ftpconf .= <<<EOD
+ftpd_banner=Welcome to pfSense FTP service
+
+EOD;
+ }
+
+ if ($freenas_config['ftp']['pasv_min_port'] && $freenas_config['ftp']['pasv_max_port']) {
+ $ftpconf .= <<<EOD
+pasv_max_port={$freenas_config['ftp']['pasv_max_port']}
+pasv_min_port={$freenas_config['ftp']['pasv_min_port']}
+
+EOD;
+ }
+
+ if ($freenas_config['ftp']['pasv_address']) {
+ $ftpconf .= <<<EOD
+pasv_address={$freenas_config['ftp']['pasv_address']}
+
+EOD;
+ }
+
+ fwrite($fd, $ftpconf);
+ fclose($fd);
+
+ /* run vsftpd */
+ mwexec("/usr/local/sbin/vsftpd {$g['varetc_path']}/vsftpd.conf");
+
+ if ($g['booting']) { echo "done\n"; }
+ }
+
+ return 0;
+}
+
+function services_pureftpd_configure() {
+ global $freenas_config, $g;
+
+ /* kill any Pure-FTPD */
+ killbyname("pure-ftpd");
+
+ if (isset($freenas_config['ftp']['enable'])) {
+ if ($g['booting']) { echo "Starting FTP server... "; }
+
+ /* Generate the banner file */
+ $fd = fopen("/mnt/.banner", "w");
+
+ if (!$fd) {
+ printf("Error: cannot open .banner in services_pureftpd_configure().\n");
+ return 1;
+ }
+
+ if (empty($freenas_config['ftp']['banner'])) {
+ $banner = <<<EOD
+Welcome to pfSense FTP service
+
+EOD;
+ } else {
+ $banner = <<<EOD
+{$freenas_config['ftp']['banner']}
+
+EOD;
+ } // end if
+
+ fwrite($fd, $banner);
+ fclose($fd);
+
+ /* run pure-ftpd */
+ $cmd = "/usr/local/sbin/pure-ftpd -S {$freenas_config['ftp']['port']} -c {$freenas_config['ftp']['numberclients']} -C {$freenas_config['ftp']['maxconperip']} -I {$freenas_config['ftp']['timeout']} -M U 077:077 -B -b ";
+
+ if ( (isset($freenas_config['ftp']['anonymous'])) && (!isset($freenas_config['ftp']['localuser']))) {
+ $cmd .= "-e ";
+ }
+
+ if ( (!isset($freenas_config['ftp']['anonymous'])) && (isset($freenas_config['ftp']['localuser']))) {
+ $cmd .= "-E ";
+ }
+
+ if ($freenas_config['ftp']['pasv_min_port'] && $freenas_config['ftp']['pasv_max_port']) {
+ $cmd .= "-p {$freenas_config['ftp']['pasv_min_port']}:{$freenas_config['ftp']['pasv_max_port']} ";
+ }
+
+ if ($freenas_config['ftp']['pasv_address']) {
+ $cmd .= "-P {$freenas_config['ftp']['pasv_address']} ";
+ }
+
+ if ($freenas_config['ftp']['natmode']) {
+ $cmd .= "-N ";
+ }
+
+ if ($freenas_config['ftp']['passiveip']) {
+ $cmd .= "-P {$freenas_config['ftp']['passiveip']} ";
+ }
+
+ if ($freenas_config['ftp']['fxp']) {
+ $cmd .= "-W ";
+ }
+
+ mwexec($cmd);
+
+ if ($g['booting']) { echo "done\n"; }
+ } // end if
+
+ return 0;
+}
+
+/* Stop smartd, Generate the configuration file and start
+ * smartd Return 0 if OK, 1 or error code if error
+ */
+function services_smart_configure() {
+ global $config, $g;
+
+ /* kill any running smartd */
+ killbyname("smartd");
+
+ if (isset($config['system']['smart'])) {
+ if ($g['booting']) { echo "Starting smartd... "; }
+
+ /* run smartd */
+ mwexec("/usr/local/sbin/smartd --logfacility=local5");
+
+ if ($g['booting']) { echo "done\n"; }
+ }
+
+ return 0;
+}
+
+/* Generate the unison configuration
+ * Return 0 if OK, 1 or error code if error
+ */
+function services_unison_configure() {
+ global $freenas_config, $g;
+ $result = 0 ;
+
+ if ($g['booting']) { echo "Configuring unison... \n"; }
+
+ if (isset($freenas_config['unison']['enable'])) {
+ /* ensure unison workdir exists */
+ $workdir = "/mnt/{$freenas_config['unison']['share']}/{$config['unison']['workdir']}";
+
+ if (isset($freenas_config['unison']['makedir']) && !file_exists($workdir)) {
+ if (!mkdir($workdir)) {
+ printf("Error: cannot mkdir $workdir in services_unison_configure().\n");
+ }
+
+ exec("/bin/chmod 775 $workdir");
+ }
+
+ if (!file_exists($workdir)) {
+ printf("Error: cannot open $workdir in services_unison_configure().\n");
+ $result = 1 ;
+ }
+
+ /* add workdir to login.conf UNISON environment variable */
+ $logfile = "{$g['etc_path']}/login.conf";
+
+ if (!file_exists("$logfile")) {
+ printf("Error: $logfile doesn't exist, in services_unison_configure().\n");
+ $result = 1 ;
+ }
+
+ $tmp = file_get_contents("$logfile");
+ $search = "/UNISON=.*?(?=[,:])/";
+
+ if (!preg_match($search, $tmp)) {
+ printf("Error: cannot find UNISON in $logfile, in services_unison_configure().\n");
+ $result = 1 ;
+ }
+
+ $tmp = preg_replace($search, "UNISON=$workdir", $tmp);
+
+ if (!file_put_contents($logfile, $tmp)) {
+ printf("Error: couldn't write $logfile, in services_unison_configure().\n");
+ $result = 1 ;
+ }
+ } // end if
+
+ $tmp = "";
+
+ return $result;
+}
+
+/* Stop and start ushare
+ * Return 0 if OK, 1 or error code if error
+ */
+function services_ushare_configure() {
+ global $freenas_config, $g;
+
+ $result = 0 ;
+
+ /* Kill any running uShare */
+ killbyname("ushare");
+
+ /* Delete multicast route. */
+ mwexec("/sbin/route delete -net 239.0.0.0");
+
+ if(isset($freenas_config['upnp']['enable'])) {
+ if($g['booting']) { echo "Starting UPnP server... "; }
+
+ /* Setup a multicast route for UPnP messages. */
+ // TODO: where to get the upnp iface?
+ $result = mwexec("/sbin/route add -net 239.0.0.0 -netmask 255.0.0.0 -interface " . escapeshellarg($freenas_config['upnp']['if']));
+
+ $content = "";
+ foreach($freenas_config['upnp']['content'] as $contentv) {
+ $content .= " --content=$contentv";
+ }
+
+ /* Run uShare as daemon. */
+ // TODO: where to get the upnp iface?
+ $result |= mwexec("/usr/local/bin/ushare --daemon --no-web --name={$freenas_config['upnp']['name']} --interface={$freenas_config['upnp']['if']} {$content}");
+ } // end if
+
+ return $result;
+}
+
+function services_cron_configure() {
+ global $freenas_config, $g;
+
+ /* kill any running cron */
+ killbyname("cron");
+
+ /* ======================================================================= */
+ /* = configure crontab item for rsyncclient = */
+ /* ======================================================================= */
+ if (isset($freenas_config['rsyncclient']['enable'])) {
+ if ($g['booting']) { echo "Configuring cron for rsync client... "; }
+
+ if ($freenas_config['rsyncclient']['all_mins'] == "0") {
+ foreach ($freenas_config['rsyncclient']['minute'] as $minutev) {
+ if (strlen($cron_min) > 0) {
+ $cron_min = $cron_min . "," . $minutev;
+ } else {
+ $cron_min = $minutev;
+ }
+ } // end foreach
+ } else {
+ $cron_min = "*";
+ } // end if
+
+ if ($freenas_config['rsyncclient']['all_hours'] == "0") {
+ foreach ($freenas_config['rsyncclient']['hour'] as $hourv) {
+ if (strlen($cron_hour) > 0) {
+ $cron_hour = $cron_hour . "," . $hourv;
+ } else {
+ $cron_hour = $hourv;
+ }
+ } // end foreach
+ } else {
+ $cron_hour = "*";
+ } // end if
+
+ if ($freenas_config['rsyncclient']['all_days'] == "0") {
+ foreach ($freenas_config['rsyncclient']['day'] as $dayv) {
+ if (strlen($cron_day) > 0) {
+ $cron_day = $cron_day . "," . $dayv;
+ } else {
+ $cron_day = $dayv;
+ }
+ } // end foreach
+ } else {
+ $cron_day = "*";
+ } // end if
+
+ if ($freenas_config['rsyncclient']['all_months'] == "0") {
+ foreach ($freenas_config['rsyncclient']['month'] as $monthv) {
+ if (strlen($cron_month) > 0) {
+ $cron_month = $cron_month . "," . $monthv;
+ } else {
+ $cron_month = $monthv;
+ }
+ } // end foreach
+ } else {
+ $cron_month = "*";
+ } // end if
+
+ if ($freenas_config['rsyncclient']['all_weekday'] == "0") {
+ foreach ($freenas_config['rsyncclient']['weekday'] as $weekdayv) {
+ if (strlen($cron_weekday) > 0) {
+ $cron_weekday = $cron_weekday . "," . $weekdayv;
+ } else {
+ $cron_weekday = $weekdayv;
+ }
+ } // end foreach
+ } else {
+ $cron_weekday = "*";
+ } // end if
+
+ $cron_item = array();
+ $cron_item['minute'] = "{$cron_min}";
+ $cron_item['hour'] = "{$cron_hour}";
+ $cron_item['mday'] = "{$cron_day}";
+ $cron_item['month'] = "{$cron_month}";
+ $cron_item['wday'] = "{$cron_weekday}";
+ $cron_item['who'] = "root";
+ $cron_item['command'] = "{$g['varrun_path']}/sync.sh";
+
+ $config['cron']['item'][] = $cron_item;
+
+ if ($g['booting']) { echo "done\n"; }
+ } // end if
+
+ /* Erase all variable used previously */
+ unset ($cron_min, $cron_hour, $cron_day, $cron_month, $cron_weekday);
+
+ /* ======================================================================= */
+ /* = configure crontab item for rsync local part = */
+ /* ======================================================================= */
+ if (isset($freenas_config['rsync_local']['enable'])) {
+ if ($g['booting']) { echo "Configuring cron for local rsync... "; }
+
+ if ($freenas_config['rsync_local']['all_mins'] == "0") {
+ foreach ($freenas_config['rsync_local']['minute'] as $minutev) {
+ if (strlen($cron_min) > 0) {
+ $cron_min = $cron_min . "," . $minutev;
+ } else {
+ $cron_min = $minutev;
+ }
+ } // end foreach
+ } else {
+ $cron_min = "*";
+ } // end if
+
+ if ($freenas_config['rsync_local']['all_hours'] == "0") {
+ foreach ($freenas_config['rsync_local']['hour'] as $hourv) {
+ if (strlen($cron_hour) > 0) {
+ $cron_hour = $cron_hour . "," . $hourv;
+ } else {
+ $cron_hour = $hourv;
+ }
+ } // end foreach
+ } else {
+ $cron_hour = "*";
+ } // end if
+
+ if ($freenas_config['rsync_local']['all_days'] == "0") {
+ foreach ($freenas_config['rsync_local']['day'] as $dayv) {
+ if (strlen($cron_day) > 0) {
+ $cron_day = $cron_day . "," . $dayv;
+ } else {
+ $cron_day = $dayv;
+ }
+ } // end foreach
+ } else {
+ $cron_day = "*";
+ } // end if
+
+ if ($freenas_config['rsync_local']['all_months'] == "0") {
+ foreach ($freenas_config['rsync_local']['month'] as $monthv) {
+ if (strlen($cron_month) > 0) {
+ $cron_month = $cron_month . "," . $monthv;
+ } else {
+ $cron_month = $monthv;
+ }
+ } // end foreach
+ } else {
+ $cron_month = "*";
+ } // end if
+
+ if ($freenas_config['rsync_local']['all_weekday'] == "0") {
+ foreach ($freenas_config['rsync_local']['weekday'] as $weekdayv) {
+ if (strlen($cron_weekday) > 0) {
+ $cron_weekday = $cron_weekday . "," . $weekdayv;
+ } else {
+ $cron_weekday = $weekdayv;
+ }
+ } // end foreach
+ } else {
+ $cron_weekday = "*";
+ }
+
+ $cron_item = array();
+ $cron_item['minute'] = "{$cron_min}";
+ $cron_item['hour'] = "{$cron_hour}";
+ $cron_item['mday'] = "{$cron_day}";
+ $cron_item['month'] = "{$cron_month}";
+ $cron_item['wday'] = "{$cron_weekday}";
+ $cron_item['who'] = "root";
+ $cron_item['command'] = "{$g['varrun_path']}/sync.sh";
+
+ $config['cron']['item'][] = $cron_item;
+
+ if ($g['booting']) { echo "done\n"; }
+ }
+
+ /* Erase all variable used previously */
+ unset ($cron_min, $cron_hour, $cron_day, $cron_month, $cron_weekday);
+
+ /* ======================================================================= */
+ /* = configure crontab item shutdown part = */
+ /* ======================================================================= */
+ if (isset($freenas_config['shutdown']['enable'])) {
+ if ($g['booting']) { echo "Configuring cron for shutdown... "; }
+
+ if ($freenas_config['shutdown']['all_mins'] == "0") {
+ foreach ($freenas_config['shutdown']['minute'] as $minutev) {
+ if (strlen($cron_min) > 0) {
+ $cron_min = $cron_min . "," . $minutev;
+ } else {
+ $cron_min = $minutev;
+ }
+ } // end foreach
+ } else {
+ $cron_min = "*";
+ } // end if
+
+ if ($freenas_config['shutdown']['all_hours'] == "0") {
+ foreach ($freenas_config['shutdown']['hour'] as $hourv) {
+ if (strlen($cron_hour) > 0) {
+ $cron_hour = $cron_hour . "," . $hourv;
+ } else {
+ $cron_hour = $hourv;
+ }
+ } // end foreach
+ } else {
+ $cron_hour = "*";
+ } // end if
+
+ if ($freenas_config['shutdown']['all_days'] == "0") {
+ foreach ($freenas_config['shutdown']['day'] as $dayv) {
+ if (strlen($cron_day) > 0) {
+ $cron_day = $cron_day . "," . $dayv;
+ } else {
+ $cron_day = $dayv;
+ }
+ } // end foreach
+ } else {
+ $cron_day = "*";
+ } // end if
+
+ if ($freenas_config['shutdown']['all_months'] == "0") {
+ foreach ($freenas_config['shutdown']['month'] as $monthv) {
+ if (strlen($cron_month) > 0) {
+ $cron_month = $cron_month . "," . $monthv;
+ } else {
+ $cron_month = $monthv;
+ }
+ } // end foreach
+ } else {
+ $cron_month = "*";
+ } // end if
+
+ if ($freenas_config['shutdown']['all_weekday'] == "0") {
+ foreach ($freenas_config['shutdown']['weekday'] as $weekdayv) {
+ if (strlen($cron_weekday) > 0) {
+ $cron_weekday = $cron_weekday . "," . $weekdayv;
+ } else {
+ $cron_weekday = $weekdayv;
+ }
+ } // end foreach
+ } else {
+ $cron_weekday = "*";
+ } // end if
+
+ $cron_item = array();
+ $cron_item['minute'] = "{$cron_min}";
+ $cron_item['hour'] = "{$cron_hour}";
+ $cron_item['mday'] = "{$cron_day}";
+ $cron_item['month'] = "{$cron_month}";
+ $cron_item['wday'] = "{$cron_weekday}";
+ $cron_item['who'] = "root";
+ $cron_item['command'] = "{$g['varrun_path']}/sync.sh";
+
+ $config['cron']['item'][] = $cron_item;
+
+ if ($g['booting']) { echo "done\n"; }
+ } // end if
+
+ /* call the pfSense configure_cron function */
+ configure_cron();
+
+ /* run cron */
+ mwexec("/usr/sbin/cron -s");
+
+ return 0;
+}
+
+function services_rsyncclient_configure() {
+ global $freenas_config, $g;
+
+ // Generate a shell script that is used by cron
+ // Generate crontab works
+ if (isset($freenas_config['rsyncclient']['enable'])) {
+ if ($g['booting']) { echo "Generating synchronizing cron script... "; }
+
+ /* generate /var/run/sync.sh script */
+ $fd = fopen("{$g['varrun_path']}/sync.sh", "w");
+
+ if (!$fd) {
+ printf("Error: cannot open /var/run/sync.sh in services_rsyncclient_configure().\n");
+ return 1;
+ }
+
+ $syncscript = <<<EOD
+#!/bin/sh
+
+if [ -r /var/run/rsync-running ]; then
+exit
+fi
+/usr/bin/touch /var/run/rsync-running
+
+EOD;
+
+ $opt_delete="";
+ if (isset($freenas_config['rsyncclient']['opt_delete'])) {
+ $opt_delete = "--delete --delete-after ";
+ }
+
+ foreach ($freenas_config['rsyncclient']['sharetosync'] as $sharek => $sharev) {
+ $syncscript .= <<<EOD
+/usr/local/bin/rsync -rtz {$opt_delete}rsync://{$freenas_config['rsyncclient']['rsyncserverip']}/{$sharev} /mnt/{$sharev}
+
+EOD;
+ } // end foreach
+
+ $syncscript .= <<<EOD
+/bin/rm -f /var/run/rsync-running
+
+EOD;
+
+ fwrite($fd,$syncscript);
+ fclose($fd);
+
+ /* Add exectutive right to the script */
+ exec("/bin/chmod 770 {$g['varrun_path']}/sync.sh");
+
+ if ($g['booting']) { echo "done\n"; }
+ } // end if
+
+ return 0;
+}
+
+function services_rsync_local_configure() {
+ global $freenas_config, $g;
+
+ // Generate a shell script that is used by cron
+ // Generate crontab works
+ if (isset($freenas_config['rsync_local']['enable'])) {
+ if ($g['booting']) { echo "Generating local rsync cron script... "; }
+
+ /* generate /var/run/sync_local.sh script */
+ $fd = fopen("{$g['varrun_path']}/sync_local.sh", "w");
+
+ if (!$fd) {
+ printf("Error: cannot open /var/run/sync_local.sh in services_rsync_local_configure().\n");
+ return 1;
+ }
+
+ $syncscript = <<<EOD
+#!/bin/sh
+
+if [ -r /var/run/rsync_local-running ]; then
+exit
+fi
+/usr/bin/touch /var/run/rsync_local-running
+
+EOD;
+
+ $opt_delete="";
+ if (isset($freenas_config['rsync_local']['opt_delete'])) {
+ $opt_delete = "--delete --delete-after ";
+ }
+
+ $syncscript .= <<<EOD
+/usr/local/bin/rsync -a {$opt_delete} /mnt/{$freenas_config['rsync_local']['source']} /mnt/{$freenas_config['rsync_local']['destination']}
+
+EOD;
+
+ $syncscript .= <<<EOD
+/bin/rm -f /var/run/rsync_local-running
+
+EOD;
+
+ fwrite($fd,$syncscript);
+ fclose($fd);
+
+ /* Add exectutive right to the script */
+ exec("/bin/chmod 770 {$g['varrun_path']}/sync_local.sh");
+
+ if ($g['booting']) { echo "done\n"; }
+ } // end if
+
+ return 0;
+}
+
+function services_radius_configure() {
+ global $freenas_config, $g;
+
+ if (isset($config['radius']['enable'])) {
+ /* generate radius.conf */
+ $fd = fopen("{$g['varetc_path']}/radius.conf", "w");
+
+ if (!$fd) {
+ printf("Error: cannot open radius.conf in services_radius_configure().\n");
+ return 1;
+ }
+
+ $radiusconf = <<<EOD
+auth {$config['radius']['radiusip']}:{$config['radius']['port']} {$config['radius']['secret']} {$config['radius']['timeout']} {$config['radius']['maxretry']}
+
+EOD;
+
+ fwrite($fd, $radiusconf);
+ fclose($fd);
+ } // end if
+
+ return 0;
+}
+
+/* Stop, Generate the config file and start
+ * AFP Return 0 if OK, 1 or error code if error
+ */
+function services_afpd_configure() {
+ global $freenas_config, $config, $g;
+
+ /* kill any afpd */
+ killbyname("afpd");
+
+ if (isset($freenas_config['afp']['enable'])) {
+ /* If no share configured, exit */
+ if (!is_array($freenas_config['mounts']['mount'])) { return 1; }
+ if ($g['booting']) { echo "Starting AFP server... "; }
+
+ if (empty($freenas_config['afp']['afpname'])) {
+ $afpname="-";
+ } else {
+ $afpname=$freenas_config['afp']['afpname'];
+ }
+
+ /* generate afpd.conf */
+ $fd = fopen("{$g['varetc_path']}/afpd.conf", "w");
+
+ if (!$fd) {
+ printf("Error: cannot open afpd.conf in services_afpd_configure().\n");
+ return 1;
+ }
+
+ $afpconf = <<<EOD
+{$afpname} -transall -uamlist
+EOD;
+
+ if (empty($config['system']['zeroconf_disable'])) {
+ $afpconf .= <<<EOD
+ -noslp -fqdn {$config['system']['hostname']}.{$config['system']['domain']} -uamlist
+EOD;
+ } else {
+ $afpconf .= <<<EOD
+ -noslp -nozeroconf -uamlist
+EOD;
+ } // end if
+
+ if (isset($freenas_config['afp']['guest']) && isset($freenas_config['afp']['local']) ) {
+ $afpconf .= <<<EOD
+ uams_guest.so,uams_clrtxt.so,uams_dhx.so
+EOD;
+ } else if (isset($freenas_config['afp']['guest'])) {
+ $afpconf .= <<<EOD
+ uams_guest.so
+EOD;
+ } else if (isset($freenas_config['afp']['local'])) {
+ $afpconf .= <<<EOD
+ uams_clrtxt.so,uams_dhx.so
+EOD;
+ }
+
+ $afpconf .= <<<EOD
+ -nosavepassword -defaultvol {$g['varetc_path']}/AppleVolumes.default -systemvol {$g['varetc_path']}/AppleVolumes.system -uampath /etc/uams -guestname ftp
+
+EOD;
+
+ fwrite($fd, $afpconf);
+ fclose($fd);
+
+ /* generate AppleVolumes.default */
+ $fd = fopen("{$g['varetc_path']}/AppleVolumes.default", "w");
+
+ if (!$fd) {
+ printf("Error: cannot open AppleVolumes.default in services_afpd_configure().\n");
+ return 1;
+ }
+
+ $a_mount = &$freenas_config['mounts']['mount'];
+
+ foreach ($a_mount as $mount) {
+ $AppleVolumes .= <<<EOD
+/mnt/{$mount['sharename']} "{$mount['sharename']}"
+
+EOD;
+
+ } // end foreach
+
+ fwrite($fd, $AppleVolumes);
+ fclose($fd);
+
+ /* run afpdpd */
+ mwexec("/usr/local/sbin/afpd -F {$g['varetc_path']}/afpd.conf");
+
+ if ($g['booting']) { echo "done\n"; }
+ } // end if
+
+ return 0;
+}
+
+function services_nis_configure() {
+ global $freenas_config, $g;
+
+ return 0;
+}
+
+/* Start iscsi initiator
+ * Return 0 if Ok, 1 or error code if problem
+ */
+/* TODO: NEED TO STOP IT TOO ??? */
+function services_iscsi_configure() {
+ global $freenas_config, $g;
+
+ if (isset($freenas_config['iscsi']['enable'])) {
+ if ($g['booting']) { echo "Starting iSCSI driver... "; }
+
+ $result = mwexec("/sbin/kldload kdload /boot/kernel/iscsi_initiator.ko");
+ $result |= mwexec("/sbin/sysctl debug.iscsi=0");
+ $result |= mwexec("/usr/local/sbin/iscontrol targetaddress={$freenas_config['iscsi']['targetaddress']} TargetName={$freenas_config['iscsi']['targetname']}");
+
+ if ($g['booting']) { echo "done\n"; }
+ }
+
+ if (isset($result)) { return $result; }
+ return 0;
+}
+
+function services_zeroconf_configure() {
+ //services_mdnsresponder_configure();
+ //services_howl_configure();
+ return services_avahi_configure();
+}
+
+function services_avahi_configure() {
+ global $freenas_config, $config, $g;
+
+ $service_template = <<<EOD
+<?xml version="1.0" standalone='no'?>
+<!DOCTYPE service-group SYSTEM "avahi-service.dtd">
+<service-group>
+
+ <name replace-wildcards="yes">@SERVICE_DESC@ on %h</name>
+
+ <service>
+ <type>@TYPE@</type>
+ <port>@PORT@</port>
+ @TXT_RECORDS@
+ </service>
+
+</service-group>
+
+EOD;
+
+ /* kill any running dbus daemon */
+ sigkillbypid("{$g['varrun_path']}/dbus/dbus.pid", "TERM");
+
+ unlink_if_exists("{$g['varrun_path']}/dbus/dbus.pid");
+
+ /* kill any running avahi daemons */
+ mwexec("/usr/local/sbin/avahi-daemon -k");
+
+ /* simply return if zeroconf isn't enabled */
+ if (isset($config['system']['zeroconf_disable'])) { return 0; }
+
+ /* configure Avahi and it's dependencies */
+ if (! file_exists("/usr/local/etc/avahi/services")) {
+ mwexec("mkdir -p /usr/local/etc/avahi/services");
+ }
+
+ /* add HTTP service type */
+ $webproto = $config['system']['webgui']['protocol'];
+
+ if (isset($config['system']['webgui']['port'])) {
+ $webservice = str_replace("@PORT@",
+ $config['system']['webgui']['port'],
+ $service_template);
+ $webservice = str_replace("@TYPE@",
+ "_{$webproto}._tcp",
+ $webservice);
+ $webservice = str_replace("@SERVICE_DESC@",
+ "pfSense webGUI",
+ $webservice);
+ $webservice = str_replace("@TXT_RECORDS@",
+ "",
+ $webservice);
+
+ file_put_contents("/usr/local/etc/avahi/services/http.service", $webservice);
+ } else {
+ $webservice = str_replace("@PORT@",
+ "80",
+ $service_template);
+ $webservice = str_replace("@TYPE@",
+ "_{$webproto}._tcp",
+ $webservice);
+ $webservice = str_replace("@SERVICE_DESC@",
+ "pfSense webGUI",
+ $webservice);
+ $webservice = str_replace("@TXT_RECORDS@",
+ "",
+ $webservice);
+
+ file_put_contents("/usr/local/etc/avahi/services/http.service", $webservice);
+ } // end if
+
+ /* afp is announcing itself */
+ if (isset($freenas_config['afp']['enable'])) {
+ /* NOP */
+ }
+
+ /* add rsync service type */
+ if (isset($freenas_config['rsyncd']['enable'])) {
+ $rsyncservice = str_replace("@PORT@",
+ $freenas_config['rsyncd']['port'],
+ $service_template);
+ $rsyncservice = str_replace("@TYPE@",
+ "_rsync._tcp",
+ $rsyncservice);
+ $rsyncservice = str_replace("@SERVICE_DESC@",
+ "Remote Sync Daemon",
+ $rsyncservice);
+ $rsyncservice = str_replace("@TXT_RECORDS@",
+ "",
+ $rsyncservice);
+
+ file_put_contents("/usr/local/etc/avahi/services/rsync.service", $rsyncservice);
+ } // end if
+
+ /* add ntp service type */
+ if ($config['ntpd']['mode'] == "server") {
+ $ntpdservice = str_replace("@PORT@",
+ "123",
+ $service_template);
+ $ntpdservice = str_replace("@TYPE@",
+ "_ntp._udp",
+ $ntpdservice);
+ $ntpdservice = str_replace("@SERVICE_DESC@",
+ "Network Time Daemon",
+ $ntpdservice);
+ $ntpdservice = str_replace("@TXT_RECORDS@",
+ "",
+ $ntpdservice);
+
+ file_put_contents("/usr/local/etc/avahi/services/ntpd.service", $ntpdservice);
+ } // end if
+
+ if (isset($config['system']['ssh']['enable'])) {
+ $sshservice = str_replace("@PORT@",
+ "22",
+ $service_template);
+ $sshservice = str_replace("@TYPE@",
+ "_ssh._tcp",
+ $sshservice);
+ $sshservice = str_replace("@SERVICE_DESC@",
+ "Remote Terminal",
+ $sshservice);
+ $sshservice = str_replace("@TXT_RECORDS@",
+ "",
+ $sshservice);
+
+ file_put_contents("/usr/local/etc/avahi/services/ssh.service", $sshservice);
+
+ /* do the same for sftp, cause we do enable it by dfeault */
+ $sftpservice = str_replace("@PORT@",
+ "22",
+ $service_template);
+ $sftpservice = str_replace("@TYPE@",
+ "_ssh._tcp",
+ $sftpservice);
+ $sftpservice = str_replace("@SERVICE_DESC@",
+ "Remote Terminal",
+ $sftpservice);
+ $sftpservice = str_replace("@TXT_RECORDS@",
+ "",
+ $sftpservice);
+
+ file_put_contents("/usr/local/etc/avahi/services/ssh-sftp.service", $sftpservice);
+ } // end if
+
+ /* we are using wzdftpd, which has the ability to announce itself */
+ if (isset($freenas_config['ftp']['enable'])) {
+ /* NOP */
+ }
+
+ if (isset($freenas_config['samba']['enable'])) {
+ $cifsservice = str_replace("@PORT@",
+ "139",
+ $service_template);
+ $cifsservice = str_replace("@TYPE@",
+ "_smb._tcp",
+ $cifsservice);
+ $cifsservice = str_replace("@SERVICE_DESC@",
+ "Samba Server",
+ $cifsservice);
+ $cifsservice = str_replace("@TXT_RECORDS@",
+ "",
+ $cifsservice);
+
+ file_put_contents("/usr/local/etc/avahi/services/cifs.service", $cifsservice);
+ }
+
+ if (isset($freenas_config['nfs']['enable'])) {
+ /* If no share configured, exit */
+ if (!is_array($freenas_config['mounts']['mount'])) { break; }
+
+ $a_mount = &$freenas_config['mounts']['mount'];
+
+ foreach ($a_mount as $mount) {
+ $sharename = str_replace(" ", "", $mount['sharename']);
+ $sharename = strtolower($sharename);
+
+ $nfsservice = str_replace("@PORT@",
+ "2049",
+ $service_template);
+ $nfsservice = str_replace("@TYPE@",
+ "_nfs._tcp",
+ $nfsservice);
+ $nfsservice = str_replace("@SERVICE_DESC@",
+ "NFS Mount: {$mount['sharename']}",
+ $nfsservice);
+ $nfsservice = str_replace("@TXT_RECORDS@",
+ "path=/mnt/{$mount['sharename']}",
+ $nfsservice);
+
+ file_put_contents("/usr/local/etc/avahi/services/{$sharename}_nfs.service", $nfsservice);
+ } // end foreach
+ } // end if
+
+ /* run dbus */
+ mwexec("/usr/local/bin/dbus-daemon --system");
+ /* run avahi */
+ mwexec("/usr/local/sbin/avahi-daemon -D");
+
+ if ($g['booting']) { echo "done\n"; }
+
+ return 0;
+}
+
+/* this function is currently not used */
+function services_howl_configure() {
+ global $freenas_config, $config, $g;
+
+ /* kill any mDNSResponder */
+ killbyname("mDNSResponder");
+
+ if (isset($config['system']['zeroconf_disable'])) { return 0; }
+
+ $fd = fopen("{$g['varetc_path']}/mDNSResponder.conf", "w");
+
+ if (!$fd) {
+ printf("Error: cannot open mDNSResponder.conf in services_howl_configure().\n");
+ return 1;
+ }
+
+ if ($config['system']['webgui']['port']) {
+ $mDNSResponder = <<<EOD
+"{$config['system']['hostname']} Web Admin" _http._tcp local. {$config['system']['webgui']['port']}
+
+EOD;
+ } else {
+ $mDNSResponder = <<<EOD
+"{$config['system']['hostname']} Web Admin" _http._tcp local. 80
+
+EOD;
+ } // end if
+
+ if (isset($freenas_config['afp']['enable'])) {
+ $mDNSResponder .= <<<EOD
+"{$config['system']['hostname']} AFP Server" _afpovertcp._tcp local. 548
+
+EOD;
+ }
+
+ if (isset($freenas_config['rsyncd']['enable'])) {
+ $mDNSResponder .= <<<EOD
+"{$config['system']['hostname']} RSYNC Server" _rsync._tcp. local. {$freenas_config['rsyncd']['port']}
+
+EOD;
+ }
+
+ if (isset($config['sshd']['enable'])) {
+ $mDNSResponder .= <<<EOD
+"{$config['system']['hostname']} SSH Server" _ssh._tcp local. {$config['sshd']['port']}
+
+EOD;
+ }
+
+ if (isset($freenas_config['ftp']['enable'])) {
+ $mDNSResponder .= <<<EOD
+"{$config['system']['hostname']} FTP Server" _ftp._tcp local. {$freenas_config['ftp']['port']}
+
+EOD;
+ }
+
+ if (isset($freenas_config['samba']['enable'])) {
+ $mDNSResponder .= <<<EOD
+"{$config['system']['hostname']} Samba Server" _smb._tcp local. 139
+
+EOD;
+ }
+
+ if (isset($freenas_config['nfs']['enable'])) {
+ /* If no share configured, exit */
+ if (!is_array($freenas_config['mounts']['mount'])) { break; }
+
+ $a_mount = &$freenas_config['mounts']['mount'];
+
+ foreach ($a_mount as $mount) {
+ $mDNSResponder .= <<<EOD
+"{$config['system']['hostname']} NFS: {$mount['sharename']}" _nfs._tcp local. 2049 path=/mnt/{$mount['sharename']}
+
+EOD;
+ } // end foreach
+ } // end if
+
+ fwrite($fd, $mDNSResponder);
+ fclose($fd);
+
+
+ /* run mDNSResponder */
+ mwexec("/usr/local/sbin/mDNSResponder -f {$g['varetc_path']}/mDNSResponder.conf");
+
+ if ($g['booting']) { echo "done\n"; }
+
+ return 0;
+}
+
+/* this function is currently not used */
+function services_mdnsresponder_configure() {
+ global $freenas_config, $config, $g;
+
+ /* kill any running snmpd */
+ sigkillbypid("{$g['varrun_path']}/mDNSResponder.pid", "TERM");
+
+ if (isset($config['system']['zeroconf_disable'])) { return 0; }
+
+ $fd = fopen("{$g['varetc_path']}/mDNSResponder.conf", "w");
+
+ if (!$fd) {
+ printf("Error: cannot open mDNSResponder.conf in services_bonjour_configure().\n");
+ return 1;
+ }
+
+ if ($config['system']['webgui']['port']) {
+ $mDNSResponder = <<<EOD
+"{$config['system']['hostname']} Web Admin"
+_http._tcp local.
+{$config['system']['webgui']['port']}
+
+EOD;
+ } else {
+ $mDNSResponder = <<<EOD
+"{$config['system']['hostname']} Web Admin"
+_http._tcp local.
+80
+
+EOD;
+ } // end if
+
+ if (isset($freenas_config['afp']['enable'])) {
+ $mDNSResponder .= <<<EOD
+
+"{$config['system']['hostname']} AFP Server"
+_afpovertcp._tcp local.
+548
+
+EOD;
+ }
+
+ if (isset($freenas_config['rsyncd']['enable'])) {
+ $mDNSResponder .= <<<EOD
+
+"{$config['system']['hostname']} RSYNC Server"
+_rsync._tcp. local.
+{$freenas_config['rsyncd']['port']}
+
+EOD;
+ }
+
+ if (isset($config['sshd']['enable'])) {
+ $mDNSResponder .= <<<EOD
+
+"{$freenas_config['system']['hostname']} SSH Server"
+_ssh._tcp local.
+{$config['sshd']['port']}
+
+EOD;
+ }
+
+ if (isset($freenas_config['ftp']['enable'])) {
+ $mDNSResponder .= <<<EOD
+
+"{$config['system']['hostname']} FTP Server"
+_ftp._tcp local.
+{$freenas_config['ftp']['port']}
+
+EOD;
+ }
+
+ if (isset($freenas_config['samba']['enable'])) {
+ $mDNSResponder .= <<<EOD
+
+"{$config['system']['hostname']} Samba Server"
+_smb._tcp local.
+139
+
+EOD;
+ }
+
+ if (isset($freenas_config['nfs']['enable'])) {
+ /* If no share configured, exit */
+ if (!is_array($freenas_config['mounts']['mount'])) { break; }
+
+ $a_mount = &$freenas_config['mounts']['mount'];
+
+ foreach ($a_mount as $mount) {
+ $mDNSResponder .= <<<EOD
+
+"{$config['system']['hostname']} NFS: {$mount['sharename']}"
+_nfs._tcp local.
+2049 path=/mnt/{$mount['sharename']}
+
+EOD;
+ } // end foreach
+ }
+
+ fwrite($fd, $mDNSResponder);
+ fclose($fd);
+
+
+ /* run mDNSResponder */
+ mwexec("/usr/local/sbin/mDNSResponderPosix -b -f {$g['varetc_path']}/mDNSResponder.conf");
+
+ if ($g['booting']) { echo "done\n"; }
+
+ return 0;
+}
+?> \ No newline at end of file
diff --git a/config/freenas/pkg/freenas_system.inc b/config/freenas/pkg/freenas_system.inc
new file mode 100644
index 00000000..2bd0a30a
--- /dev/null
+++ b/config/freenas/pkg/freenas_system.inc
@@ -0,0 +1,838 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ freenas_system.inc
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+require_once("globals.inc");
+
+$freenas_config =& $config['installedpackages']['freenas']['config'][0];
+
+function system_do_extensions($early = false) {
+ global $config, $g;
+
+ if (!is_dir("{$g['etc_path']}/inc/ext")) { return; }
+
+ $dh = @opendir("{$g['etc_path']}/inc/ext");
+
+ if ($dh) {
+ while (($extd = readdir($dh)) !== false) {
+ if (($extd === ".") || ($extd === "..")) { continue; }
+
+ $rcfile = "{$g['etc_path']}/inc/ext/" . $extd . "/" . ($early ? "rc.early" : "rc");
+
+ if (file_exists($rcfile)) { passthru($rcfile); }
+ } // end while
+
+ closedir($dh);
+ } // end if
+}
+
+function system_set_termcap() {
+ global $config;
+
+ if (isset($config['diag']['ipfstatentries'])) {
+ $lines = $config['diag']['ipfstatentries'] + 6;
+ } else {
+ $lines = 306;
+ }
+
+ /* do not remove the tabs below or replace them using whitespaces */
+ $termcap = <<<EOD
+cons25w|ansiw|ansi80x25-raw:\
+ :am:bs:NP:ms:pt:AX:eo:bw:ut:km:\
+ :co#80:li#25:pa#64:Co#8:it#8:\
+ :al=\E[L:cd=\E[J:ce=\E[K:cl=\E[H\E[J:cm=\E[%i%d;%dH:\
+ :dc=\E[P:dl=\E[M:do=\E[B:bt=\E[Z:ho=\E[H:ic=\E[@:cb=\E[1K:\
+ :nd=\E[C:rs=\Ec:so=\E[7m:se=\E[27m:up=\E[A:cr=^M:ta=^I:\
+ :AF=\E[3%dm:AB=\E[4%dm:op=\E[39;49m:sc=\E7:rc=\E8:\
+ :k1=\E[M:k2=\E[N:k3=\E[O:k4=\E[P:k5=\E[Q:k6=\E[R:k7=\E[S:k8=\E[T:\
+ :k9=\E[U:k;=\E[V:F1=\E[W:F2=\E[X:K2=\E[E:nw=\E[E:ec=\E[%dX:\
+ :kb=^H:kh=\E[H:ku=\E[A:kd=\E[B:kl=\E[D:kr=\E[C:le=^H:sf=\E[S:sr=\E[T:\
+ :kN=\E[G:kP=\E[I:@7=\E[F:kI=\E[L:kD=\\177:kB=\E[Z:\
+ :IC=\E[%d@:DC=\E[%dP:SF=\E[%dS:SR=\E[%dT:AL=\E[%dL:DL=\E[%dM:\
+ :DO=\E[%dB:LE=\E[%dD:RI=\E[%dC:UP=\E[%dA:cv=\E[%i%dd:ch=\E[%i%d`:\
+ :mb=\E[5m:md=\E[1m:mr=\E[7m:me=\E[m:bl=^G:\
+ :ve=\E[=S:vi=\E[=1S:vs=\E[=2S:
+cons25|ansis|ansi80x25:\
+ :ac=l\\332m\\300k\\277j\\331u\\264t\\303v\\301w\\302q\\304x\\263n\\305`^Da\\260f\\370g\\361~\\371.^Y-^Xh\\261i^U0\\333y\\363z\\362:\
+ :tc=cons25w:
+dumb|su|unknown:\
+ :am:co#132:li#$lines:do=^J:
+xterm-noapp|xterm with cursor keys in normal mode:\
+ :kl=\E[D:kd=\E[B:kr=\E[C:ku=\E[A:ks=\E=:ke=\E>:ti@:te@:tc=xterm:
+xterm|xterm-color|X11 terminal emulator:\
+ :ti@:te@:tc=xterm-xfree86:
+xterm-xfree86|XFree86 xterm:\
+ :k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:\
+ :k5=\E[15~:k6=\E[17~:k7=\E[18~:k8=\E[19~:\
+ :k9=\E[20~:k;=\E[21~:F1=\E[23~:F2=\E[24~:\
+ :kH=\EOF:@7=\EOF:kI=\E[2~:\
+ :kh=\EOH:*6=\EOF:kP=\E[5~:kN=\E[6~:\
+ :ku=\EOA:kd=\EOB:kr=\EOC:kl=\EOD:Km=\E[M:tc=xterm-basic:
+xterm-basic|xterm common (XFree86):\
+ :li#24:co#80:am:kn#12:km:mi:ms:xn:bl=^G:\
+ :is=\E[!p\E[?3;4l\E[4l\E>:rs=\E[!p\E[?3;4l\E[4l\E>:le=^H:\
+ :AL=\E[%dL:DL=\E[%dM:DC=\E[%dP:al=\E[L:dc=\E[P:dl=\E[M:\
+ :UP=\E[%dA:DO=\E[%dB:LE=\E[%dD:RI=\E[%dC:\
+ :ho=\E[H:cd=\E[J:ce=\E[K:cl=\E[H\E[2J:cm=\E[%i%d;%dH:cs=\E[%i%d;%dr:\
+ :im=\E[4h:ei=\E[4l:ks=\E[?1h\E=:ke=\E[?1l\E>:kD=\E[3~:kb=^H:\
+ :sf=\n:sr=\EM:st=\EH:ct=\E[3g:sc=\E7:rc=\E8:\
+ :eA=\E(B\E)0:as=^N:ae=^O:ml=\El:mu=\Em:up=\E[A:nd=\E[C:\
+ :md=\E[1m:me=\E[m^O:mr=\E[7m:so=\E[7m:se=\E[27m:us=\E[4m:ue=\E[24m:\
+ :ti=\E[?1049h:te=\E[?1049l:vi=\E[?25l:ve=\E[?25h:\
+ :ut:Co#8:pa#64:op=\E[39;49m:AB=\E[4%dm:AF=\E[3%dm:\
+
+EOD;
+
+ if (!file_exists("/usr/share/misc")) { mkdir("/usr/share/misc"); }
+
+ $fd = @fopen("/usr/share/misc/termcap", "w");
+
+ if (!$fd) {
+ printf("Error: cannot open termcap in system_set_termcap().\n");
+ return 1;
+ }
+
+ chmod("/usr/share/misc/termcap", 0644);
+ fwrite($fd, $termcap);
+ fclose($fd);
+
+ return 0;
+}
+
+/* TODO: Figure out whether this function can be removed cause
+ * implements its own user management framework.
+ */
+function system_users_create() {
+ /* Create All the passwd file */
+ global $config, $g;
+
+ if ($g['booting']) { echo "Generating user database... "; }
+
+ system_user_masterpasswd();
+ system_user_group();
+ system_user_pwdmkdb();
+
+ if ($g['booting']) { echo "done\n"; }
+
+ return 0;
+}
+
+/* TODO: Figure out whether this function can be removed cause
+ * implements its own user management framework.
+ */
+function system_user_masterpasswd() {
+ /* Create the master.passwd file*/
+ global $config, $g, $userindex, $groupindex;
+ $root = getUNIXRoot();
+
+ $masterpasswd = <<<EOD
+root:{$root['password']}:0:0::0:0:Charlie &:/root:/bin/sh
+toor:*:0:0::0:0:Bourne-again Superuser:/root:
+daemon:*:1:1::0:0:Owner of many system processes:/root:/usr/sbin/nologin
+operator:*:2:5::0:0:System &:/:/usr/sbin/nologin
+bin:*:3:7::0:0:Binaries Commands and Source:/:/usr/sbin/nologin
+tty:*:4:65533::0:0:Tty Sandbox:/:/usr/sbin/nologin
+kmem:*:5:65533::0:0:KMem Sandbox:/:/usr/sbin/nologin
+smmsp:*:25:25::0:0:Sendmail Submission User:/var/spool/clientmqueue:/usr/sbin/nologin
+mailnull:*:26:26::0:0:Sendmail Default User:/var/spool/mqueue:/usr/sbin/nologin
+proxy:*:62:62::0:0:Packet Filter pseudo-user:/nonexistent:/usr/sbin/nologin
+_pflogd:*:64:64::0:0:pflogd privsep user:/var/empty:/usr/sbin/nologin
+www:*:80:80::0:0:World Wide Web Owner:/nonexistent:/usr/sbin/nologin
+nobody:*:65534:65534::0:0:Unprivileged user:/nonexistent:/usr/sbin/nologin
+dhcpd:*:1002:1002::0:0:DHCP Daemon:/nonexistent:/sbin/nologin
+_dhcp:*:65:65::0:0:dhcp programs:/var/empty:/usr/sbin/nologin
+_isakmpd:*:68:68::0:0:isakmpd privsep:/var/empty:/sbin/nologin
+ftp:*:21:50::0:0:FTP user:/mnt:/sbin/nologin
+sshd:*:22:22::0:0:Secure Shell Daemon:/var/empty:/usr/sbin/nologin
+
+EOD;
+
+ if (is_array($config['system']['user'])) {
+ foreach ($config['system']['user'] as $user) {
+ $password= $user['password'];
+ $groupname = $user['groupname'];
+ $group =& $config['system']['group'][$groupindex[$groupname]];
+
+ if (empty($user['uid'])) {
+ $newuser = assignUID($user['name']);
+ $newgroup = assignGID($groupname);
+ if (! empty($newuser)) { $user = $newuser; }
+ if (! empty($newgroup)) { $group = $newgroup; }
+ }
+
+ if (hasShellAccess($user['name'])) {
+ $masterpasswd .= <<<EOD
+{$user['name']}:{$password}:{$user['uid']}:{$group['gid']}::0:0:{$user['fullname']}:/mnt:/etc/rc.initial
+
+EOD;
+ } else {
+ $masterpasswd .= <<<EOD
+{$user['name']}:{$password}:{$user['uid']}:{$group['gid']}::0:0:{$user['fullname']}:/mnt:/usr/local/bin/scponly
+
+EOD;
+ } // end if
+ } // end foreach
+ } // end if
+
+ $fd = fopen("/etc/master.passwd", "w");
+
+ if (!$fd) {
+ printf("Error: cannot open master.passwd in system_user_masterpasswd().\n");
+ return 1;
+ }
+
+ fwrite($fd, $masterpasswd);
+ fclose($fd);
+
+return 0;
+}
+
+/* TODO: Figure out whether this function can be removed cause
+ * implements its own user management framework.
+ */
+function system_user_group() {
+ /* Create the group file*/
+ global $config, $g;
+
+ $groupfile = <<<EOD
+wheel:*:0:root
+EOD;
+
+ /* If user exist with full shell, put them on the wheel group */
+ if (is_array($config['system']['user'])) {
+ foreach ($config['system']['user'] as $user) {
+ if (hasShellAccess($user['name']) && isSystemAdmin($user['name'])) {
+ $groupfile .= <<<EOD
+,{$user['name']}
+EOD;
+ } // end if
+ } // end foreach
+ } // end if
+
+ $groupfile .= <<<EOD
+
+daemon:*:1:
+kmem:*:2:
+sys:*:3:
+tty:*:4:
+operator:*:5:root
+mail:*:6:
+bin:*:7:
+staff:*:20:
+EOD;
+
+ /* If user exist without full shell, put them on the staff group */
+ if (is_array($config['system']['user'])) {
+ foreach ($config['system']['user'] as $user) {
+ if (hasShellAccess($user['name'])) {
+ $groupfile .= <<<EOD
+{$user['name']},
+EOD;
+ } // end if
+ } // end foreach
+ } // end if
+
+ $groupfile .= <<<EOD
+
+sshd:*:22:
+smmsp:*:25:
+mailnull:*:26:
+guest:*:31:
+proxy:*:62:
+_pflogd:*:64:
+_dhcp:*:65:
+ftp:*:50:
+authpf:*:63:
+network:*:69:
+www:*:80:
+nogroup:*:65533:
+nobody:*:65534:
+admin:*:0:
+
+EOD;
+
+ if (is_array($config['system']['group'])) {
+ foreach ($config['system']['group'] as $group) {
+ if (empty($group['gid'])) {
+ $newgroup = assignGID($group['name']);
+ if (! empty($newgroup)) { $group = $newgroup; }
+ }
+
+ $groupfile .= <<<EOD
+{$group['name']}:*:{$group['gid']}:
+
+EOD;
+ } // end foreach
+ } // end if
+
+ $fd = fopen("/etc/group", "w");
+
+ if (!$fd) {
+ printf("Error: cannot open group in system_user_group().\n");
+ return 1;
+ }
+
+ fwrite($fd, $groupfile);
+ fclose($fd);
+
+ return 0;
+}
+
+function system_user_pwdmkdb() {
+ /* Generate the db of password */
+ global $config, $g;
+
+ mwexec("/usr/sbin/pwd_mkdb -p -d /etc /etc/master.passwd");
+
+ return 0;
+}
+
+function system_user_samba() {
+ /* Generate the db of password */
+
+ // TODO: MUST FIND A WAY OF USING UNIX CRYPTED PASSWORD IN THE PLACE OF CLEAR TEXT PASSWORD FOR GENERATING SAMBA DB!!!
+
+ global $config, $g;
+
+ if (is_array($config['system']['user'])) {
+ foreach ($config['system']['user'] as $user) {
+ /* TODO: the password in config.xml is already encrypted */
+ $password = escapeshellcmd($user['password']);
+ $login = escapeshellcmd($user['name']);
+ mwexec("(/bin/echo {$password}; /bin/echo {$password}) | /usr/local/bin/smbpasswd -s -a {$login}");
+ //mwexec("(/bin/echo {$password}; /bin/echo {$password}) | /usr/local/bin/pdbedit -tau {$login}");
+ } // end foreach
+ } // end if
+
+ return 0;
+
+}
+
+function system_pam_configure() {
+ /* Create the pam configuration files*/
+ global $config, $g;
+
+ if (!file_exists("{$g['varetc_path']}/pam.d")) {
+ mkdir("{$g['varetc_path']}/pam.d", 0744);
+ }
+
+ $system = <<<EOD
+# System-wide defaults
+# auth
+auth sufficient pam_opie.so no_warn no_fake_prompts
+auth requisite pam_opieaccess.so no_warn allow_local
+
+EOD;
+
+ if (isset($config['ad']['enable'])) {
+ $system .= <<<EOD
+#auth sufficient /usr/local/lib/pam_winbind.so debug try_first_pass
+
+EOD;
+ }
+
+ $system .= <<<EOD
+auth required pam_unix.so no_warn try_first_pass nullok
+
+# account
+
+EOD;
+
+ if (isset($config['ad']['enable'])) {
+ $system .= <<<EOD
+#account sufficient /usr/local/lib/pam_winbind.so
+
+EOD;
+ }
+
+ $system .= <<<EOD
+account required pam_login_access.so
+account required pam_unix.so
+
+# session
+session required pam_lastlog.so no_fail
+
+# password
+
+EOD;
+
+ if (isset($config['ad']['enable'])) {
+ $system .= <<<EOD
+#password sufficient /usr/local/lib/pam_winbind.so debug try_first_pass
+
+EOD;
+ }
+
+ $system .= <<<EOD
+password required pam_unix.so no_warn try_first_pass
+
+EOD;
+
+ $fd = fopen("{$g['varetc_path']}/pam.d/system", "w");
+
+ if (!$fd) {
+ printf("Error: cannot open /pam.d/system in system_pam_configure().\n");
+ return 1;
+ }
+
+ fwrite($fd, $system);
+ fclose($fd);
+
+ $sshd .= <<<EOD
+# PAM configuration for the "sshd" service
+
+# auth
+auth required pam_nologin.so no_warn
+auth sufficient pam_opie.so no_warn no_fake_prompts
+auth requisite pam_opieaccess.so no_warn allow_local
+
+EOD;
+
+ if (isset($config['ad']['enable'])) {
+ $sshd .= <<<EOD
+auth sufficient /usr/local/lib/pam_winbind.so debug try_first_pass
+
+EOD;
+ }
+
+ $sshd .= <<<EOD
+auth required pam_unix.so no_warn try_first_pass
+
+# account
+
+EOD;
+
+ if (isset($config['ad']['enable'])) {
+ $sshd .= <<<EOD
+account sufficient /usr/local/lib/pam_winbind.so
+
+EOD;
+ }
+
+ $sshd .= <<<EOD
+account required pam_unix.so
+
+# session
+session required pam_permit.so
+
+# password
+
+EOD;
+
+ if (isset($config['ad']['enable'])) {
+ $sshd .= <<<EOD
+password sufficient /usr/local/lib/pam_winbind.so debug try_first_pass
+
+EOD;
+ }
+
+ $sshd .= <<<EOD
+password required pam_unix.so no_warn try_first_pass
+
+EOD;
+
+ unset($fd);
+ $fd = fopen("{$g['varetc_path']}/pam.d/sshd", "w");
+
+ if (!$fd) {
+ printf("Error: cannot open /pam.d/sshd in system_pam_configure().\n");
+ return 1;
+ }
+
+ fwrite($fd, $sshd);
+ fclose($fd);
+
+ $ftp = <<<EOD
+# PAM configuration for the "ftpd" service
+
+# auth
+auth required pam_nologin.so no_warn
+auth sufficient pam_opie.so no_warn no_fake_prompts
+auth requisite pam_opieaccess.so no_warn allow_local
+
+EOD;
+
+ if (isset($config['ad']['enable'])) {
+ $ftp .= <<<EOD
+auth sufficient /usr/local/lib/pam_winbind.so debug try_first_pass
+
+EOD;
+ }
+
+ $ftp .= <<<EOD
+auth required pam_unix.so no_warn try_first_pass
+
+# account
+
+EOD;
+
+ if (isset($config['ad']['enable'])) {
+ $ftp .= <<<EOD
+account sufficient /usr/local/lib/pam_winbind.so
+
+EOD;
+ }
+
+ $ftp .= <<<EOD
+account required pam_login_access.so
+account required pam_unix.so
+
+# session
+session required pam_permit.so
+
+EOD;
+
+ unset($fd);
+ $fd = fopen("{$g['varetc_path']}/pam.d/ftp", "w");
+
+ if (!$fd) {
+ printf("Error: cannot open /pam.d/ftp in system_pam_configure().\n");
+ return 1;
+ }
+
+ fwrite($fd, $ftp);
+ fclose($fd);
+
+ $login = <<<EOD
+# PAM configuration for the "login" service
+#
+
+# auth
+auth required pam_nologin.so no_warn
+
+EOD;
+
+ if (isset($config['ad']['enable'])) {
+ $login .= <<<EOD
+auth sufficient /usr/local/lib/pam_winbind.so debug try_first_pass
+
+EOD;
+ }
+
+ $login .= <<<EOD
+auth sufficient pam_self.so no_warn
+auth include system
+
+# account
+
+EOD;
+
+ if (isset($config['ad']['enable'])) {
+ $login .= <<<EOD
+account sufficient /usr/local/lib/pam_winbind.so
+
+EOD;
+ }
+
+ $login .= <<<EOD
+account requisite pam_securetty.so
+account include system
+
+# session
+session include system
+
+# password
+password include system
+
+EOD;
+
+ unset($fd);
+ $fd = fopen("{$g['varetc_path']}/pam.d/login", "w");
+
+ if (!$fd) {
+ printf("Error: cannot open /pam.d/login in system_pam_configure().\n");
+ return 1;
+ }
+
+ fwrite($fd, $login);
+ fclose($fd);
+
+ unset($fd);
+
+ /* Create the nsswitch.conf file*/
+ if (isset($config['ad']['enable'])) {
+ $nsswitch = <<<EOD
+group: files winbind
+group_compat: nis
+hosts: files dns wins
+networks: files
+passwd: files winbind
+passwd_compat: nis
+shells: files
+
+EOD;
+ } else {
+ $nsswitch = <<<EOD
+group: compat
+group_compat: nis
+hosts: files dns
+networks: files
+passwd: compat
+passwd_compat: nis
+shells: files
+
+EOD;
+ } // end if
+
+ $fd = fopen("{$g['varetc_path']}/nsswitch.conf", "w");
+
+ if (!$fd) {
+ printf("Error: cannot open /var/etc/nsswitch.conf in system_pam_configure().\n");
+ return 1;
+ }
+
+ fwrite($fd, $nsswitch);
+ fclose($fd);
+
+ unset($fd);
+
+ return 0;
+}
+
+function system_tuning() {
+ /* fine tune kernel value */
+ global $config, $g;
+
+ if (isset($config['system']['tune'])) {
+ if ($g['booting']) { echo 'Tuning the system... '; }
+
+ mwexec('/sbin/sysctl net.inet.tcp.delayed_ack=0');
+ mwexec('/sbin/sysctl net.inet.tcp.sendspace=65536');
+ mwexec('/sbin/sysctl net.inet.tcp.recvspace=65536');
+ mwexec('/sbin/sysctl net.inet.udp.recvspace=65536');
+ mwexec('/sbin/sysctl net.inet.udp.maxdgram=57344');
+ mwexec('/sbin/sysctl net.local.stream.recvspace=65535');
+ mwexec('/sbin/sysctl net.local.stream.sendspace=65535');
+ mwexec('/sbin/sysctl kern.ipc.maxsockbuf=2097152');
+ mwexec('/sbin/sysctl kern.ipc.somaxconn=8192');
+ /* This variable can be set on the boot conf file only: */
+ /* mwexec('/sbin/sysctl kern.ipc.maxsockets=16424'); */
+ mwexec('/sbin/sysctl kern.ipc.nmbclusters=60000');
+ mwexec('/sbin/sysctl kern.maxfiles=65536');
+ mwexec('/sbin/sysctl kern.maxfilesperproc=32768');
+ mwexec('/sbin/sysctl net.inet.tcp.inflight.enable=0');
+
+ if ($g['booting']) { echo "done\n"; }
+ return 0;
+ } else {
+ /* Set the default value (if previously changed) if not booting mode */
+ if (!$g['booting']) {
+ mwexec('/sbin/sysctl net.inet.tcp.delayed_ack=1');
+ mwexec('/sbin/sysctl net.inet.tcp.sendspace=32768');
+ mwexec('/sbin/sysctl net.inet.tcp.recvspace=65536');
+ mwexec('/sbin/sysctl net.inet.udp.recvspace=42080');
+ mwexec('/sbin/sysctl net.inet.udp.maxdgram=9216');
+ mwexec('/sbin/sysctl net.local.stream.recvspace=8192');
+ mwexec('/sbin/sysctl net.local.stream.sendspace=8192');
+ mwexec('/sbin/sysctl kern.ipc.maxsockbuf=262144');
+ mwexec('/sbin/sysctl kern.ipc.somaxconn=128');
+ /* mwexec('/sbin/sysctl kern.ipc.maxsockets=16424'); */
+ mwexec('/sbin/sysctl kern.ipc.nmbclusters=3072');
+ mwexec('/sbin/sysctl kern.maxfiles=1064');
+ mwexec('/sbin/sysctl kern.maxfilesperproc=957');
+ } // end if
+
+ return 0;
+ } // end if
+}
+
+/* TODO: Probably a function that is not needed */
+function system_install_mount_cd($cdrom) {
+ /* Part of install process: Mount the CDROM */
+ global $config, $g;
+
+ /* Creating tempo directory for cdrom*/
+ echo "Creating Mount point for the CDROM:\n";
+ if (mwexec("/bin/mkdir /mnt/cdrom_fr_0507")) { return 1; }
+
+ /* Mounting the CDROM */
+ echo "Mount CDROM:\n";
+ if (mwexec("/sbin/mount_cd9660 /dev/$cdrom /mnt/cdrom_fr_0507")) { return 1; }
+
+ return 0;
+}
+
+/* TODO: Probably a function that is not needed */
+function system_install_init_fulldisk($harddrive) {
+ /* Part of install process: Initialize the destination disk with one partition */
+ global $config, $g;
+
+ echo "Erasing partitions:\n";
+ if (mwexec("/bin/dd if=/dev/zero of=/dev/$harddrive bs=1k count=20")) { return 1; }
+
+ echo "Creating the primary partition and install simple MBR:\n";
+ if (mwexec("/sbin/fdisk -BI -b /boot/mbr $harddrive")) { return 1; }
+
+ /* Must wait that the /dev is upatded with the new information */
+ /* There should be a more intelligent code here than this stupid timer... */
+ echo "Waiting for system update..";
+ $devtotest="/dev/$harddrive". "s1";
+ $i=0;
+
+ while (!file_exists($devtotest)) {
+ sleep(1);
+ echo ".";
+ $i++;
+
+ if ($i==20) { return 1; }
+ }
+ echo "\n";
+
+ echo "Erasing primary partition:\n";
+ if (mwexec("/bin/dd if=/dev/zero of=/dev/" . escapeshellarg($harddrive) . "s1 bs=32k count=16")) {
+ return 1;
+ }
+
+ echo "Creating FreeBSD partition:\n";
+ if (mwexec("/sbin/bsdlabel -B -w -b /boot/boot " . escapeshellarg($harddrive) ."s1 auto")) {
+ return 1;
+ }
+
+ echo "Setting BSDlabel:\n";
+
+ disks_bsdlabel($harddrive,"s1","4.2BSD");
+
+ echo "Creating UFS filesystem:\n";
+ if (mwexec("/sbin/newfs -U /dev/" . escapeshellarg($harddrive) . "s1")) { return 1; }
+
+ return 0;
+}
+
+/* TODO: Probably a function that is not needed */
+function system_install_init_halfdisk($harddrive) {
+ /* Part of install process: Initialize the destination disk with 2 partitions */
+ global $config, $g;
+
+ /* Create the partitions */
+ fdisk_hd_install($harddrive);
+
+ if (mwexec("(/bin/echo y; /bin/echo y) | /sbin/fdisk -B -b /boot/mbr $harddrive")) { return 0; }
+
+ /* Must wait that the /dev is upatded with the new information */
+ echo "Waiting for system update..";
+
+ $devtotest="/dev/$harddrive". "s2";
+ $i=0;
+ while (!file_exists($devtotest)) {
+ sleep(1);
+ echo ".";
+ $i++;
+
+ if ($i==20) { return 1; }
+ }
+ echo "\n";
+
+ echo "Creating BSD Label:\n";
+ if (mwexec("/sbin/bsdlabel -B -w -b /boot/boot " . escapeshellarg($harddrive) ."s1 auto")) {
+ return 1;
+ }
+ if (mwexec("/sbin/bsdlabel -w " . escapeshellarg($harddrive) ."s2 auto")) {
+ return 1;
+ }
+
+ echo "Modify BSD Label information:\n";
+
+ disks_bsdlabel($harddrive,"s1","4.2BSD");
+ disks_bsdlabel($harddrive,"s2","4.2BSD");
+
+ echo "Creating filesystem:\n";
+ if (mwexec("/sbin/newfs -U /dev/" . escapeshellarg($harddrive) . "s1")) {
+ return 1;
+ }
+ if (mwexec("/sbin/newfs -U /dev/" . escapeshellarg($harddrive) . "s2")) {
+ return 1;
+ }
+
+ return 0;
+}
+
+/* TODO: Probably a function that is not needed */
+function system_install_mount_destdisk($harddrive) {
+ /* Part of install process: Mount the destination disk */
+ global $config, $g;
+
+ echo "Creation tempory mouting point:\n";
+ if (mwexec("/bin/mkdir /mnt/install_fr_0507")) { return 1; }
+
+ echo "Mount destination disk:\n";
+ if (mwexec("/sbin/mount /dev/" . escapeshellarg($harddrive) . "s1 /mnt/install_fr_0507")) {
+ return 1;
+ }
+
+ return 0;
+}
+
+/* TODO: Probably a function that is not needed */
+function system_install_unmount() {
+ /* Part of install process: Unmounting the disk */
+ global $config, $g;
+
+ /* Unmounting disk */
+ if (mwexec("/sbin/umount /mnt/install_fr_0507")) { return 1; }
+ if (mwexec("/sbin/umount /mnt/cdrom_fr_0507")) { return 1; }
+
+ /* using 'rm -rf' for deleting the temp directory is too dangerous here... */
+ /*
+ if (mwexec("/bin/rm -rf /mnt/cdrom_fr_0507")) { return 1; }
+ if (mwexec("/bin/rm -rf /mnt/install_fr_0507")) { return 1; }
+ */
+
+ /* Test: replace with PHP function rmdir */
+ @rmdir ("/mnt/cdrom_fr_0507");
+ @rmdir ("/mnt/install_fr_0507");
+
+ return 0;
+}
+
+/* TODO: Probably a function that is not needed */
+function system_install_installation($harddrive) {
+ /* Part of install process: dd image file on the destination disk */
+ global $config, $g;
+
+ echo "Installation:\n";
+ if (mwexec("/usr/bin/gunzip -S \"\" -c /mnt/cdrom_fr_0507/FreeNAS-generic-pc.gz | dd of=/dev/" . escapeshellarg($harddrive) . " bs=16k > /dev/null 2>&1")) {
+ return 1;
+ }
+
+ return 0;
+}
+
+?> \ No newline at end of file
diff --git a/config/freenas/pkg/freenas_utils.inc b/config/freenas/pkg/freenas_utils.inc
new file mode 100644
index 00000000..6e5d8872
--- /dev/null
+++ b/config/freenas/pkg/freenas_utils.inc
@@ -0,0 +1,1049 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ freenas_utils.inc
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+/* returns true if $desc is a valid description (alphanum and space, _ , - , .)*/
+function is_validdesc($desc) {
+ if (!is_string($desc)) { return false; }
+
+ if (preg_match("/^[A-Za-z0-9]([A-Za-z0-9_\-\.\s]*[A-Za-z0-9])*$/", $desc)) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+/* returns true if $login is a valid login name (alphanum,dot, _ , -)*/
+function is_validlogin($login) {
+ if (!is_string($login)) { return false; }
+
+ if (preg_match("/^[A-Za-z0-9]([A-Za-z0-9_\-\.\s]*[A-Za-z0-9])*$/", $login)) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+/* returns true if $password is a valid password (not used of special : character)*/
+function is_validpassword($password) {
+ if (!is_string($password)) { return false; }
+
+ if (strstr($password, ':')) {
+ return false;
+ } else {
+ return true;
+ }
+}
+
+/* returns true if $login is a valid share name (alphanum,dot, _ , -)*/
+function is_validsharename($sharename) {
+ if (!is_string($sharename)) { return false; }
+
+ if (preg_match("/^[A-Za-z0-9]([A-Za-z0-9_\-\.\s]*[A-Za-z0-9])*$/", $sharename)){
+ return true;
+ } else {
+ return false;
+ }
+}
+
+/* Returns true if $workgroup is a valid workgroup name */
+/* A workgroup name can contain up to 15 characters, including letters, numbers, */
+/* and the following characters: ! @ # $ % ^ & ( ) _ - ; : ' " , . */
+/* It cannot contain any spaces, and must begin with a letter or number. */
+function is_workgroup($workgroup) {
+ if (!is_string($workgroup)) { return false; }
+
+ if (preg_match("/^[\w\d]+[\w\d\!\@\#\$\%\^\&\(\)\_\-\;\:\'\"\,\.]*$/", $workgroup)) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+function get_mounts_list()
+{
+ // Return list of mounted disk
+ //example: Array
+ // [0] => Array
+ // (
+ // [mp] => /mnt/ad0s1
+ // [mdisk] => ad0s1
+ // )
+ global $g;
+
+ exec("/sbin/mount",$rawdata);
+
+ $mountlist = array();
+ $i=0;
+
+ foreach ($rawdata as $line) {
+ $aline = explode(" ", $line);
+
+ if ((chop($aline[0]) == "/dev/md0") || (chop($aline[0]) == "devfs") || (chop($aline[0]) == "/dev/fd0")) {
+ continue;
+ }
+
+ $mountlist[$i]['fullname'] = chop($aline[0]);
+ $mountlist[$i]['mp'] = chop($aline[2]);
+
+ // Get the complete name /dev/devicename
+ $complete = explode("/",chop($aline[0]));
+ $devname = $complete[2];
+
+ // Test if it's a gvinum or gmirror device
+ if ((strcmp($devname,"gvinum") == 0) || (strcmp($devname,"mirror") == 0)) {
+ $devname = $complete[3];
+ }
+
+ $mountlist[$i]['mdisk']=$devname;
+ $i++;
+ } // end foreach
+
+ return $mountlist;
+}
+
+function get_mount_use() {
+ // Return list of mounted use
+ // example: Array
+ // [mount_point_name] => Array
+ // (
+ // [capacity] => 48%
+ // [used] => 2.4G
+ // [avail] => 2.6G
+ // [size] => 5.4G
+ // )
+ global $freenas_config, $g;
+
+ exec("/bin/df -h",$rawdata);
+
+ $result = array();
+
+ foreach ($rawdata as $line) {
+ /* separe the line by space*/
+ $aline = preg_split("/[\s,]+/", $line);
+ $tmp = explode("/",chop($aline[5]));
+ $mounted_on = $tmp[2];
+ $capacity = chop($aline[4]);
+ $avail = chop($aline[3]);
+ $used = chop($aline[2]);
+ $size = chop($aline[1]);
+
+ if (is_array($freenas_config['mounts']['mount'])) {
+ foreach ($freenas_config['mounts']['mount'] as $mountcfg) {
+ if (strcmp($mounted_on,$mountcfg['sharename']) == 0) {
+ $result[$mounted_on] = array();
+ $result[$mounted_on]['capacity'] = $capacity;
+ $result[$mounted_on]['avail'] = $avail;
+ $result[$mounted_on]['used'] = $used;
+ $result[$mounted_on]['size'] = $size;
+ }
+ } // end foreach
+ } else {
+ return 0;
+ } // end if
+ } // end foreach
+
+ //print_r($result);
+
+ return $result;
+}
+
+function get_sraid_disks_list() {
+ /* Return list of ALL software volume: gvinum, gmirror */
+ $disklist = array_merge((array)get_gvinum_disks_list(),(array)get_gmirror_disks_list(),(array)get_gconcat_disks_list(),(array)get_gstripe_disks_list(),(array)get_graid5_disks_list());
+ return $disklist;
+}
+
+function get_gvinum_disks_list() {
+ /* Get information about gvinum volume */
+ global $g;
+
+ /* Return list of Software RAID disk */
+ //[volumename] => Array
+ // (
+ // [type] => Software RAID - gvinum
+ // [desc] => UP
+ // [size] => 6149 MB
+ // )
+
+ /* on envoie la commande d'affichage de la liste des volumes*/
+ exec("/sbin/gvinum list",$rawdata);
+
+ foreach ($rawdata as $line) {
+ /* Split the line using the space as separator */
+ $aline = preg_split("/\s+/", $line);
+
+ /* Get the line that begin with the letter 'V' */
+ if ($aline[0] != "V") { continue ; }
+
+ $diskname = chop($aline[1]);
+ $disklist[$diskname] = array();
+
+ $disklist[$diskname]['name'] = $diskname;
+ $disklist[$diskname]['fullname'] = "/dev/gvinum/" . $diskname;
+ $disklist[$diskname]['type'] = "Software RAID - gvinum";
+ $disklist[$diskname]['size'] = "$aline[7] $aline[8]" ;
+ $disklist[$diskname]['desc'] = $aline[3];
+ } // end foreach
+
+ return $disklist;
+}
+
+function get_gmirror_disks_list() {
+ /* Get information about gmirror volume */
+ global $g;
+
+ //[volumename] => Array
+ // (
+ // [type] => Software RAID - gmirror
+ // [desc] => COMPLETE
+ // [size] => 6149M
+ // )
+
+ /* Display all configured gmirror volume */
+ exec("/sbin/gmirror list", $rawdata);
+
+ $foundname = 0 ;
+ $founddesc = 0 ;
+ $goodname = 0 ;
+
+ foreach ($rawdata as $line) {
+ /* Use space for break the line */
+ $aline = preg_split("/\s+/", $line);
+
+ // First Step: Getting the array name
+ // look for this output:
+ // Geom name: pouet
+ if ( (strcmp($aline[0],"Geom") == 0) && (strcmp($aline[1],"name:") == 0) ) {
+ $diskname = $aline[2];
+ $disklist[$diskname]=array();
+ $disklist[$diskname]['name']=$diskname;
+ $disklist[$diskname]['fullname']= "/dev/mirror/" . $diskname;
+ $foundname = 1 ;
+ continue ;
+ }
+
+ // Second Step: Getting the array status
+ // look for this output:
+ // State: COMPLETE
+ if ( (strcmp($aline[0],"State:") == 0) && $foundname) {
+ $desc = $aline[1];
+ $disklist[$diskname]['desc'] = $desc;
+ $founddesc=1;
+ continue ;
+ }
+
+ // Third Step: Getting the array Size
+ // look for this output:
+ // Name: mirror/pouet
+ // Mediasize: 107373568 (102M)
+ if (preg_match("/Name: mirror\/(.*)$/", $line, $matches)) {
+ if ($matches[1]=$diskname) {
+ $goodname=1;
+ continue ;
+ }
+ }
+
+ if (($aline[0] = "Mediasize:") && $goodname) {
+ // extract the size between the ( )
+ preg_match("/.*\\(([^\)]*)\).*/",$aline[3],$match);
+ $disklist[$diskname]['size'] = $match[1];
+ $disklist[$diskname]['type'] = "Software RAID - gmirror";
+
+ // init the check variable for the next RAID volume
+ $foundname = 0 ;
+ $founddesc = 0 ;
+ $goodname = 0 ;
+
+ continue ;
+
+ }
+ } // end foreach
+
+ return $disklist;
+}
+
+function get_gconcat_disks_list() {
+ /* Get information about gconcat volume */
+ global $g;
+
+ //[volumename] => Array
+ // (
+ // [type] => Software RAID - gconcat
+ // [desc] => COMPLETE
+ // [size] => 6149M
+ // [name] => concat1
+ // [fullname] => /dev/concat/concat1
+ // )
+
+ /* Display all configured gconcat volume*/
+ exec("/sbin/gconcat list",$rawdata);
+
+ $foundname = 0 ;
+ $founddesc = 0 ;
+ $goodname = 0 ;
+
+ foreach ($rawdata as $line) {
+ /* Use space for break the line */
+ $aline = preg_split("/\s+/", $line);
+
+ // First Step: Getting the array name
+ // look for this output:
+ // Geom name: pouet
+ if ( (strcmp($aline[0],"Geom") == 0) && (strcmp($aline[1],"name:") == 0) ) {
+ $diskname = $aline[2];
+ $disklist[$diskname]=array();
+ $disklist[$diskname]['name']=$diskname;
+ $disklist[$diskname]['fullname']= "/dev/concat/" . $diskname;
+ $foundname = 1 ;
+ continue ;
+ }
+
+ // Second Step: Getting the array status
+ // look for this output:
+ // State: UP
+ if ( (strcmp($aline[0],"State:") == 0) && $foundname) {
+
+ $desc = $aline[1];
+ $disklist[$diskname]['desc'] = $desc;
+ $founddesc=1;
+ continue ;
+ }
+
+ // Third Step: Getting the array Size
+ // look for this output:
+ // Name: concat/pouet
+ // Mediasize: 107373568 (102M)
+ if (preg_match("/Name: concat\/(.*)$/", $line, $matches)) {
+ if ($matches[1]=$diskname) {
+ $goodname=1;
+ continue ;
+ }
+
+ }
+
+ if (($aline[0] = "Mediasize:") && $goodname) {
+ // extract the size between the ( )
+ preg_match("/.*\\(([^\)]*)\).*/",$aline[3],$match);
+ $disklist[$diskname]['size'] = $match[1];
+ $disklist[$diskname]['type'] = "Software RAID - gconcat";
+
+ // init the check variable for the next RAID volume
+ $foundname = 0 ;
+ $founddesc = 0 ;
+ $goodname = 0 ;
+
+ continue ;
+ }
+ }
+
+ return $disklist;
+}
+
+function get_gstripe_disks_list() {
+ /* Get information about gstripe volume */
+ global $g;
+
+ //[volumename] => Array
+ // (
+ // [type] => Software RAID - gstripe
+ // [desc] => COMPLETE
+ // [size] => 6149M
+ // [name] => raid0
+ // [fullname] => /dev/stripe/raid0
+ // )
+
+ /* Display all configured gstripe volume*/
+ exec("/sbin/gstripe list",$rawdata);
+
+ $foundname = 0 ;
+ $founddesc = 0 ;
+ $goodname = 0 ;
+
+ foreach ($rawdata as $line) {
+ /* Use space for break the line */
+ $aline = preg_split("/\s+/", $line);
+
+ // First Step: Getting the array name
+ // look for this output:
+ // Geom name: pouet
+ if ( (strcmp($aline[0],"Geom") == 0) && (strcmp($aline[1],"name:") == 0) ) {
+ $diskname = $aline[2];
+ $disklist[$diskname]=array();
+ $disklist[$diskname]['name']=$diskname;
+ $disklist[$diskname]['fullname']= "/dev/stripe/" . $diskname;
+ $foundname = 1 ;
+ continue ;
+ }
+
+ // Second Step: Getting the array status
+ // look for this output:
+ // State: UP
+ if ( (strcmp($aline[0],"State:") == 0) && $foundname) {
+ $desc = $aline[1];
+ $disklist[$diskname]['desc'] = $desc;
+ $founddesc=1;
+ continue ;
+ }
+
+ // Third Step: Getting the array Size
+ // look for this output:
+ // Name: stripe/pouet
+ // Mediasize: 107373568 (102M)
+ if (preg_match("/Name: stripe\/(.*)$/", $line, $matches)) {
+ if ($matches[1]=$diskname) {
+ $goodname=1;
+ continue ;
+ }
+
+ }
+
+ if (($aline[0] = "Mediasize:") && $goodname) {
+ // extract the size between the ( )
+ preg_match("/.*\\(([^\)]*)\).*/",$aline[3],$match);
+ $disklist[$diskname]['size'] = $match[1];
+ $disklist[$diskname]['type'] = "Software RAID - gstripe";
+
+ // init the check variable for the next RAID volume
+ $foundname = 0 ;
+ $founddesc = 0 ;
+ $goodname = 0 ;
+
+ continue ;
+
+ }
+ }
+
+ return $disklist;
+}
+
+function get_graid5_disks_list() {
+ /* Get information about graid5 volume */
+ global $g;
+
+ //[volumename] => Array
+ // (
+ // [type] => Software RAID - graid5
+ // [desc] => COMPLETE
+ // [size] => 6149M
+ // [name] => BIG1
+ // [fullname] => /dev/raid5/BIG1
+ // )
+
+ /* Display all configured graid5 volume*/
+ exec("/sbin/graid5 list",$rawdata);
+
+ $foundname = 0 ;
+ $founddesc = 0 ;
+ $goodname = 0 ;
+
+ foreach ($rawdata as $line) {
+ /* Use space for break the line */
+ $aline = preg_split("/\s+/", $line);
+
+ // First Step: Getting the array name
+ // look for this output:
+ // Geom name: pouet
+ if ( (strcmp($aline[0],"Geom") == 0) && (strcmp($aline[1],"name:") == 0) ) {
+ $diskname = $aline[2];
+ $disklist[$diskname]=array();
+ $disklist[$diskname]['name']=$diskname;
+ $disklist[$diskname]['fullname']= "/dev/raid5/" . $diskname;
+ $foundname = 1 ;
+ continue ;
+ }
+
+ // Second Step: Getting the array status
+ // look for this output:
+ // State: COMPLETE
+ if ( (strcmp($aline[0],"State:") == 0) && $foundname) {
+ $desc = $aline[1];
+ $disklist[$diskname]['desc'] = $desc;
+ $founddesc=1;
+ continue ;
+ }
+
+ // Third Step: Getting the array Size
+ // look for this output:
+ // Name: raid5/pouet
+ // Mediasize: 107373568 (102M)
+ if (preg_match("/Name: raid5\/(.*)$/", $line, $matches)) {
+ if ($matches[1]=$diskname) {
+ $goodname=1;
+ continue ;
+ }
+ }
+
+ if (($aline[0] = "Mediasize:") && $goodname) {
+ // extract the size between the ( )
+ preg_match("/.*\\(([^\)]*)\).*/",$aline[3],$match);
+ $disklist[$diskname]['size'] = $match[1];
+ $disklist[$diskname]['type'] = "Software RAID - graid5";
+
+ // init the check variable for the next RAID volume
+ $foundname = 0 ;
+ $founddesc = 0 ;
+ $goodname = 0 ;
+
+ continue ;
+ }
+ }
+
+ return $disklist;
+}
+
+function get_ata_disks_list() {
+ /* Return list of ATA disk */
+
+ //[ad0] => Array
+ // (
+ // [type] => IDE
+ // [desc] => QUANTUM FIREBALL EX6.4A/A0A.0D00
+ // [size] => 6149MB
+ // )
+
+ global $g;
+
+ /* Recupere le dmesg */
+ exec("/sbin/dmesg",$rawdmesg);
+
+ $disklist = array();
+
+ /******* Getting IDE disk informations *******/
+ exec("/sbin/atacontrol list",$rawdata);
+
+ foreach ($rawdata as $line) {
+ /* Separe la ligne par les espace */
+ $aline = preg_split("/\s+/", $line);
+
+ /* Si ATA alors NEXT */
+ if ($aline[0] == "ATA") { continue ; }
+
+ $diskname = chop($aline[2]);
+
+ /* Exlude CDROM (acdX) and Empty (no) */
+ if (!preg_match("/^(acd)/", $diskname ) & $diskname != "no") {
+ $disklist[$diskname] = array();
+ $disklist[$diskname]['name']=$diskname;
+ $disklist[$diskname]['fullname']= "/dev/" . $diskname;
+
+ $disklist[$diskname]['type'] = "IDE";
+
+ /* Match the description witch is include between < and > */
+ preg_match("/.*\<([^>]*)>.*/",$line,$match);
+
+ $disklist[$diskname]['desc'] = $match[1];
+
+ /* Looking for the disk size */
+ foreach ($rawdmesg as $dmesgline) {
+ /* Take only the first dmesg line */
+ if (!$disklist[$diskname]['size']) {
+ /* Separe la ligne par les espace */
+ $dmesgtab = explode(" ", $dmesgline);
+ $dmesgtab[0] = rtrim($dmesgtab[0],":");
+ /* When there is a wrong DMA cable, the first line is:
+ * ad0: DMA limited to UDMA33, controller found non-ATA66 cable
+ */
+ if ($dmesgtab[0]!="" && (strcasecmp($dmesgtab[0],$diskname) == 0) &&
+ strcmp($dmesgtab[1],"DMA") !=0) {
+ $disklist[$diskname]['size'] = $dmesgtab[1];
+ }
+ } // end if
+ } // end foreach
+ } // end if
+ } // end foreach
+
+ return $disklist;
+}
+
+function get_scsi_disks_list() {
+ /* Recupere la liste des disques SCSI */
+
+ //[ad0] => Array
+ // (
+ // [type] => IDE
+ // [desc] => QUANTUM FIREBALL EX6.4A/A0A.0D00
+ // [size] => 6149MB
+ // )
+
+ global $g;
+
+ /* Recupere le dmesg */
+ exec("/sbin/dmesg",$rawdmesg);
+
+ /* on envoie la commande d'affichage de la liste des disques*/
+ exec("/sbin/camcontrol devlist",$rawdata);
+
+ foreach ($rawdata as $line) {
+ /* Get information include between parenthese: (pass0,da0) or (da0,pass0)*/
+ preg_match("/.*\(([^>]*)\).*/",$line,$match);
+
+ /* Sépare le resultat par la virgule */
+ $temp = preg_split("/,/", $match[1]);
+
+ // Check if diskname is the first (da0,pass0) or the second (pass0,da0) arguement
+ $diskname = $temp[1];
+
+ if ($diskname[0] == "p") { $diskname = $temp[0]; }
+
+ /* On exlus les lecteurs cd */
+ if (!preg_match("/^(cd)/", $diskname )) {
+ $disklist[$diskname] = array();
+ $disklist[$diskname]['name'] = $diskname;
+ $disklist[$diskname]['fullname'] = "/dev/" . $diskname;
+ $disklist[$diskname]['type'] = "SCSI";
+ /* Recupère la description: ce qu'il y a entre < et > */
+
+ preg_match("/.*\<([^>]*)>.*/",$line,$match);
+
+ $disklist[$diskname]['desc'] = $match[1];
+
+ /* Looking for the disk size */
+ foreach ($rawdmesg as $dmesgline) {
+ /* Separe la ligne par les espace */
+ $dmesgtab = explode(" ", $dmesgline);
+ $dmesgtab[0] = rtrim($dmesgtab[0],":");
+ if ($dmesgtab[0]!="" &&(strcasecmp($dmesgtab[0],$diskname) == 0)) {
+ $disklist[$diskname]['size'] = $dmesgtab[1];
+ }
+ } // end foreach
+ } // end if
+ } // end foreach
+
+ return $disklist;
+}
+
+function get_hraid_disks_list() {
+ /* Recupere la liste des disques RAID */
+ $kerneldisks = explode(" ", trim(preg_replace("/kern.disks: /", "", exec("/sbin/sysctl kern.disks"))));
+
+ /* Recupere la liste des disques ATA et SCSI */
+ $diskdetected = array_merge((array)get_ata_disks_list(),(array)get_scsi_disks_list());
+
+ /* Recupere le dmesg */
+ exec("/sbin/dmesg",$rawdmesg);
+
+ foreach ($kerneldisks as $diskname) {
+ $allready=1;
+
+ // Check of this entry is IDE or SCSI (allready detected)
+ foreach ($diskdetected as $diskfoundk => $diskfoundv) {
+ if (strcasecmp($diskfoundk,$diskname) == 0) {
+ $allready = 0;
+ }
+ }
+
+ if ($allready) {
+ /* If not an IDE and SCSI disk */
+ $disklist[$diskname]=array();
+ $disklist[$diskname]['name']=$diskname;
+ $disklist[$diskname]['fullname']= "/dev/" . $diskname;
+
+ $disklist[$diskname]['type'] = "RAID";
+
+ /* Looking for the disk size in the dmesg */
+ foreach ($rawdmesg as $dmesgline) {
+ /* Separe la ligne par les espace */
+ $dmesgtab = explode(" ", $dmesgline);
+ $dmesgtab[0] = rtrim($dmesgtab[0],":");
+ // si la ligne commence par le nom du disque: attention il y a 2 lignes
+ if ($dmesgtab[0]!="" &&(strcasecmp($dmesgtab[0],$diskname) == 0)) {
+ // the first line as this example "aacd0: <RAID 5> on aac0"
+ if (strcasecmp(substr($dmesgtab[1], 0, 1),"<") == 0) {
+ /* Match the description witch is include between < and > */
+ preg_match("/.*\<([^>]*)>.*/",$dmesgline,$match);
+ $disklist[$diskname]['desc'] = $match[1];
+ } else{
+ // si c'est la deuxieme ligne, elle ressemble a "aacd0: 138850MB (284365824 sectors)"
+ $disklist[$diskname]['size'] = $dmesgtab[1];
+ } // end if
+ } // end if
+ } // end foreach
+ } // end if
+ } // end foreach
+
+ return $disklist;
+}
+
+function get_physical_disks_list() {
+ /* Return list of ALL disk: physical, hardware RAID and Software RAID disk */
+ $disklist = array_merge((array)get_ata_disks_list(),(array)get_scsi_disks_list(),(array)get_hraid_disks_list());
+ return $disklist;
+}
+
+function get_all_disks_list() {
+ /* Return list of ALL disk: physical, hardware RAID and Software RAID disk */
+ $disklist = array_merge((array)get_ata_disks_list(),(array)get_scsi_disks_list(),(array)get_hraid_disks_list(), (array)get_sraid_disks_list());
+ return $disklist;
+}
+
+function get_disks_size($diskname) {
+ /* Return size of the disk */
+ $disklist=get_physical_disks_list();
+ $disksize=0;
+
+ foreach ($disklist as $diskk => $diskv) {
+ if (strcmp($diskk,$diskname)==0) {
+ $disksize=$diskv['size'];
+ }
+ }
+
+ return $disksize;
+}
+
+function get_cdrom_list() {
+ /* Return list of IDE AND SCSI CDROM */
+ // exemple: Array
+ // [acd0] => Array
+ // (
+ // [type] => IDE
+ // [desc] => TDK CDRW241040B/57S2
+ // )
+
+ global $g;
+
+ /* Recupere la liste des disques IDE */
+ exec("/sbin/atacontrol list",$rawdata);
+
+ /* Recupere le dmesg */
+ exec("/sbin/dmesg",$rawdmesg);
+
+ $disklist = array();
+
+ /* Variable $i utilisé pour l'index du tableau */
+ $i=0;
+ foreach ($rawdata as $line) {
+ /* Separe la ligne par les espace */
+ $aline = preg_split("/\s+/", $line);
+
+ /* Si ATA alors NEXT */
+ if ($aline[0] == "ATA") { continue ; }
+
+ $diskname = chop($aline[2]);
+
+ /* Exlude disk (adX) and Empty (no) */
+ if (!preg_match("/^(ad)/", $diskname ) & $diskname != "no") {
+ $disklist[$diskname]=array();
+ $disklist[$diskname]['name']=$diskname;
+ $disklist[$diskname]['fullname']= "/dev/" . $diskname;
+
+ $disklist[$diskname]['type'] = "IDE";
+
+ /* Match the description witch is include between < and > */
+ preg_match("/.*\<([^>]*)>.*/",$line,$match);
+
+ $disklist[$diskname]['desc'] = $match[1];
+
+ $i++;
+ } // end if
+ } // end foreach
+
+ /* Get the SCSI disk list */
+
+ /* Cleaning used variable and initialize array */
+ unset($rawdata);
+ unset($dmesgtab);
+ reset($rawdmesg);
+
+ /* Get the result of the command camcontrol*/
+ exec("/sbin/camcontrol devlist",$rawdata);
+
+ foreach ($rawdata as $line) {
+ /* Get information include between parenthese: (pass0,da0) or (da0,pass0)*/
+ preg_match("/.*\(([^>]*)\).*/",$line,$match);
+
+ /* Sépare le resultat par la virgule */
+ $temp = preg_split("/,/", $match[1]);
+
+ // Check if diskname is the first (da0,pass0) or the second (pass0,da0) arguement
+ $diskname = $temp[1];
+ if ($diskname[0] == "p") { $diskname = $temp[0]; }
+
+ /* On exlus les lecteurs disque dur da */
+ if (!preg_match("/^(da)/", $diskname )) {
+ $disklist[$diskname]=array();
+ $disklist[$diskname]['name']=$diskname;
+ $disklist[$diskname]['fullname']= "/dev/" . $diskname;
+ $disklist[$diskname]['type'] = "SCSI";
+
+ /* Recupère la description: ce qu'il y a entre < et > */
+ preg_match("/.*\<([^>]*)>.*/",$line,$match);
+
+ $disklist[$diskname]['desc'] = $match[1];
+
+ $i++;
+ } // end if
+ } // end foreach
+
+ return $disklist;
+}
+
+/* Get list of disks from given type of filesystem. */
+function get_fstype_disks_list($fstype) {
+ global $freenas_config;
+
+ $result = array();
+
+ /* Scan all physical disk */
+ if (is_array($freenas_config['disks']['disk'])) {
+ foreach ($freenas_config['disks']['disk'] as $disk) {
+ if (strcmp($disk['fstype'],$fstype) == 0) {
+ $result[] = $disk;
+ }
+ } // end foreach
+ } // end if
+
+ /* Scan all gmirror volume */
+ if (is_array($freenas_config['gmirror']['vdisk'])) {
+ foreach ($freenas_config['gmirror']['vdisk'] as $disk) {
+ if (strcmp($disk['fstype'],$fstype) == 0) {
+ $result[] = $disk;
+ }
+ } // end foreach
+ } // end if
+
+ /* Scan all gconcat volume */
+ if (is_array($freenas_config['gconcat']['vdisk'])) {
+ foreach ($freenas_config['gconcat']['vdisk'] as $disk) {
+ if (strcmp($disk['fstype'],$fstype) == 0) {
+ $result[] = $disk;
+ }
+ } // end foreach
+ } // end if
+
+ /* Scan all gstripe volume */
+ if (is_array($freenas_config['gstripe']['vdisk'])) {
+ foreach ($freenas_config['gstripe']['vdisk'] as $disk) {
+ if (strcmp($disk['fstype'],$fstype) == 0) {
+ $result[] = $disk;
+ }
+ } // end foreach
+ } // end if
+
+ /* Scan all gvinum volume */
+ if (is_array($freenas_config['gvinum']['vdisk'])) {
+ foreach ($freenas_config['gvinum']['vdisk'] as $disk) {
+ if (strcmp($disk['fstype'],$fstype) == 0) {
+ $result[] = $disk;
+ }
+ } // end foreach
+ } // end if
+
+ /* Scan all graid5 volume */
+ if (is_array($freenas_config['graid5']['vdisk'])) {
+ foreach ($freenas_config['graid5']['vdisk'] as $disk) {
+ if (strcmp($disk['fstype'],$fstype) == 0) {
+ $result[] = $disk;
+ }
+ } // end foreach
+ } // end if
+
+ return $result;
+}
+
+/* Get list of supported filesystem types */
+function get_fstype_list() {
+ $fstlist = array(
+ ""=>"Unformated",
+ "ufs"=>"UFS with Soft Updates (use 8% space disk)",
+ "ufs_no_su"=>"UFS",
+ "ufsgpt"=>"UFS (EFI/GPT) with Soft Updates (use 8% space disk)",
+ "ufsgpt_no_su"=>"UFS (EFI/GPT)",
+ "msdos"=>"FAT32",
+ "ntfs"=>"NTFS",
+ "softraid"=>"Software RAID");
+/*
+ "gmirror"=>"Software RAID: gmirror",
+ "gconcat"=>"Software RAID: gconcat",
+ "gstripe"=>"Software RAID: gstripe",
+ "graid5"=>"Software RAID: graid5",
+ "gvinum"=>"Software RAID: gvinum");
+*/
+ return $fstlist;
+}
+
+function get_fstype_shortdesc($fstype) {
+ $shortdesc = "";
+
+ switch($fstype) {
+ case "": $shortdesc = "Unformated";
+ break;
+ case "ufs":
+ case "ufs_no_su":
+ case "ufsgpt":
+ case "ufsgpt_no_su": $shortdesc = "UFS";
+ break;
+ case "msdos": $shortdesc = "FAT32";
+ break;
+ case "ntfs": $shortdesc = "NTFS";
+ break;
+ case "gmirror": $shortdesc = "gmirror";
+ break;
+ case "gconcat": $shortdesc = "gconcat";
+ break;
+ case "gstripe": $shortdesc = "gstripe";
+ break;
+ case "graid5": $shortdesc = "graid5";
+ break;
+ case "gvinum": $shortdesc = "gvinum";
+ break;
+ case "softraid": $shortdesc = "softraid";
+ break;
+ } // end switch
+
+ return $shortdesc;
+}
+
+/* Search in a multidimensional array */
+function array_search_ex($needle, $haystack, $key) {
+ foreach($haystack as $haystackval => $value) {
+ $found = false;
+
+ if (is_array($needle) && is_array($key)) {
+ foreach ($needle as $n => $needlev) {
+ $found = ($value[$key[$n]] == $needlev);
+
+ if (false == $found) { break; }
+ }
+ } else {
+ $found = ($value[$key] == $needle);
+ } // end if
+
+ if (true == $found) { return $haystackval; }
+ } // end foreach
+
+ return false;
+}
+
+/* TODO: This function is probably not needed. */
+function freenas_install($src,$dst) {
+ // Creating source directory
+ passthru("/bin/mkdir /mnt/src");
+
+ // Mount the source function is_cdrom must BE CREATED!!!!
+
+ if (is_cdrom($src)) {
+ echo "Mount CDROM:\n";
+ passthru("/sbin/mount_cd9660 /dev/$src /mnt/src");
+ } else {
+ echo "Mount disk:\n";
+ passthru("/sbin/mount -t ufs /dev/$src /mnt/src");
+ } // end if
+
+ echo "Erasing primary partitions:\n";
+ passthru("/bin/dd if=/dev/zero of=/dev/$dst bs=1k count=20");
+
+ echo "Creation 1 booting primary parition:\n";
+ passthru("/sbin/fdisk -BI -b /boot/boot0 $dst");
+
+ /* echo "Installing bootloader:\n";
+ passthru("/usr/sbin/boot0cfg -B -b /boot/boot0 $dst"); */
+
+ echo "Erasing FreeBSD partition on the primary:\n";
+ passthru("/bin/dd if=/dev/zero of=/dev/" . escapeshellarg($dst) . "s1 bs=32k count=16");
+
+ echo "Creating FreeBSD partition:\n";
+ passthru("/sbin/bsdlabel -B -w -b /boot/boot " . escapeshellarg($dst) ."s1 auto");
+
+ echo "Modify partition information:\n";
+
+ /* Generation de la table des partitions dans un fichier temp */
+
+ passthru("/sbin/bsdlabel " . escapeshellarg($dst) ."s1 > label.tmp");
+
+ /* copie de ce fichier dans un tableau*/
+ $tableau = file("label.tmp");
+
+ // Ouverture du fichier en mode ajout
+ $handle = fopen("label.tmp", 'a');
+
+ while(list(,$val) = each($tableau)) {
+ // Si la ligne contient le mot "unused"
+
+ if (ereg ("unused",$val)) {
+ // On remplace c: par a:
+ $val = ereg_replace ("c:","a:", $val);
+ // On remplace unused par 4.2BSD
+ $val = ereg_replace ("unused","4.2BSD", $val);
+ // On ajoute cette ligne à la fin du fichier
+ fwrite($handle, $val);
+ } // end if
+ } // end while
+
+ // Fermeture du fichier
+ fclose($handle);
+
+ // On injecte la nouvelle table des paritions
+ passthru("/sbin/bsdlabel -R -B " . escapeshellarg($dst) ."s1 label.tmp");
+
+ echo "Creating filesystem:\n";
+ passthru("/sbin/newfs /dev/" . escapeshellarg($dst) . "s1");
+
+ echo "Creation temp mouting point:\n";
+ passthru("/bin/mkdir /mnt/src");
+
+ echo "Mount disk:\n";
+ passthru("/sbin/mount /dev/" . escapeshellarg($dst) . "s1 /mnt/dst");
+
+ echo "Installation:\n";
+
+ passthru("/bin/cp -pr /mnt/src/boot /mnt/dst");
+ passthru("/bin/cp /mnt/src/cf.gz /mnt/dst/mfsroot.gz");
+
+ if ($src == CDROM) {
+ passthru("/bin/rm -f /mnt/dst/boot/cdloader");
+ }
+
+ passthru("mkdir /mnt/dst/conf");
+ passthru("/bin/cp /conf/config.xml /mnt/dst/conf/");
+
+ /* demontage des disques */
+ passthru("/sbin/umount /mnt/dst");
+ passthru("/sbin/umount /mnt/src");
+ passthru("/bin/rm -rf /mnt/src");
+ passthru("/bin/rm -rf /mnt/dst");
+}
+
+/* Force kill a process by name */
+function forcekillbyname($procname) {
+ return mwexec("/usr/bin/killall -9 " . escapeshellarg($procname));
+}
+?> \ No newline at end of file
diff --git a/config/freenas/pkg/rc.freenas b/config/freenas/pkg/rc.freenas
new file mode 100644
index 00000000..3b5c6c0c
--- /dev/null
+++ b/config/freenas/pkg/rc.freenas
@@ -0,0 +1,102 @@
+#!/usr/local/bin/php -f
+<?php
+/* $Id$ */
+/* ========================================================================== */
+ rc.freenas
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt
+ All rights reserved.
+/* ========================================================================== */
+/*
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+require_once("globals.inc");
+
+/* parse the configuration and include all functions used below */
+require_once("config.inc");
+require_once("functions.inc");
+require_once("freenas_functions.inc");
+
+/* Tune the system */
+system_tuning();
+
+/* Generate local user base */
+system_users_create();
+
+/* start iSCSI service */
+services_iscsi_configure();
+
+/* start the S.M.A.R.T daemon */
+services_smart_configure();
+
+/* ATA disk Idle configuration */
+disks_set_ataidle();
+
+/* RAID configuration */
+disks_raid_start();
+
+/* Mount the disks */
+disks_mount_all();
+
+/* Generate the pam configuration file */
+system_pam_configure();
+
+/* start NIS service */
+services_nis_configure();
+
+/* start SAMBA service */
+services_samba_configure();
+
+/* start Rsynd service */
+services_rsyncd_configure();
+
+/* start FTP service */
+services_ftpd_configure();
+
+/* start NFS service */
+services_nfs_configure();
+
+/* configure Unison service */
+services_unison_configure();
+
+/* start SSH service */
+/* services_sshd_configure(); */
+
+/* start AFP service */
+services_afpd_configure();
+
+/* start RSYNC client/slave mode service */
+services_rsyncclient_configure();
+
+/* start RSYNC local service */
+services_rsync_local_configure();
+
+/* Start cron */
+services_cron_configure();
+
+/* Start mdnsresponder (Zeroconf/Bonjour) */
+services_zeroconf_configure();
+
+?> \ No newline at end of file
diff --git a/config/freenas/www/diag_ad_infos.php b/config/freenas/www/diag_ad_infos.php
new file mode 100644
index 00000000..e9882a70
--- /dev/null
+++ b/config/freenas/www/diag_ad_infos.php
@@ -0,0 +1,159 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ diag_ad_infos.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+$pgtitle = array(gettext("Diagnostics"),
+ gettext("Active Directory Infos"));
+
+require_once("freenas_config.inc");
+require_once("guiconfig.inc");
+require_once("freenas_guiconfig.inc");
+require_once("freenas_functions.inc");
+
+if (! empty($_POST))
+{
+ /* hash */
+ unset($error_bucket);
+ /* simple error list */
+ unset($input_errors);
+
+ if (is_array($error_bucket))
+ foreach($error_bucket as $elem)
+ $input_errors[] =& $elem["error"];
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($error_bucket)) {
+ input_errors2Ajax(NULL, $error_bucket);
+ exit;
+ }
+}
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc"); ?>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+
+<form action="diag_ad_infos.php" method="post" name="iform" id="iform">
+
+<div id="inputerrors"></div>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Disks"), false, "diag_disks_infos.php");
+ $tab_array[1] = array(gettext("Partitions"), false, "diag_part_infos.php");
+ $tab_array[2] = array(gettext("SMART"), false, "diag_smart_infos.php");
+ $tab_array[3] = array(gettext("ataidle"), false, "diag_ataidle_infos.php");
+ $tab_array[4] = array(gettext("Space used"), false, "diag_space_infos.php");
+ $tab_array[5] = array(gettext("Mounts"), false, "diag_mounts_infos.php");
+ $tab_array[6] = array(gettext("Software RAID"), false, "diag_raid_infos.php");
+ $tab_array[7] = array(gettext("iSCSI"), false, "diag_iscsi_infos.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("MS Domain"), true, "diag_ad_infos.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <table class="tabcont" width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td align="left" valign="top">
+ <?php
+ if (! isset($freenas_config['ad']['enable'])) {
+ echo "<strong>AD Authentication disable</strong><br />";
+ } else {
+ echo "<pre style=\"font-size: medium;\">";
+ echo "<strong>Accessiblity test to MS domain:</strong><br />";
+ echo htmlspecialchars("Results for net rpc testjoin:") . "<br />";
+ exec("/usr/local/bin/net rpc testjoin",$rawdata);
+ foreach ($rawdata as $line)
+ {
+ echo htmlspecialchars($line) . "<br />";
+ }
+ unset ($rawdata);
+ echo "<br />";
+ echo htmlspecialchars("Ping winbindd to see if it is alive:") . "<br />";
+ exec("/usr/local/bin/wbinfo -p",$rawdata);
+ foreach ($rawdata as $line)
+ {
+ echo htmlspecialchars($line) . "<br />";
+ }
+ unset ($rawdata);
+ echo "<br />";
+ echo htmlspecialchars("Check shared secret:") . "<br />";
+ exec("/usr/local/bin/wbinfo -t",$rawdata);
+ foreach ($rawdata as $line)
+ {
+ echo htmlspecialchars($line) . "<br />";
+ }
+ unset ($rawdata);
+ echo "<br>";
+ echo "</pre>";
+ }
+ ?>
+ </td>
+ </tr>
+ </table>
+ </div>
+ </td>
+ </tr>
+</table>
+</form>
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/freenas/www/diag_ataidle_infos.php b/config/freenas/www/diag_ataidle_infos.php
new file mode 100644
index 00000000..7ba6c737
--- /dev/null
+++ b/config/freenas/www/diag_ataidle_infos.php
@@ -0,0 +1,149 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ diag_ataidle_infos.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+$pgtitle = array(gettext("Diagnostics"),
+ gettext("ATAidle Infos"));
+
+require_once("freenas_config.inc");
+require_once("guiconfig.inc");
+require_once("freenas_guiconfig.inc");
+require_once("freenas_functions.inc");
+
+if (! empty($_POST))
+{
+ /* hash */
+ unset($error_bucket);
+ /* simple error list */
+ unset($input_errors);
+
+ if (is_array($error_bucket))
+ foreach($error_bucket as $elem)
+ $input_errors[] =& $elem["error"];
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($error_bucket)) {
+ input_errors2Ajax(NULL, $error_bucket);
+ exit;
+ }
+}
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc"); ?>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+
+<form action="diag_ataidle_infos.php" method="post" name="iform" id="iform">
+
+<div id="inputerrors"></div>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Disks"), false, "diag_disks_infos.php");
+ $tab_array[1] = array(gettext("Partitions"), false, "diag_part_infos.php");
+ $tab_array[2] = array(gettext("SMART"), false, "diag_smart_infos.php");
+ $tab_array[3] = array(gettext("ataidle"), true, "diag_ataidle_infos.php");
+ $tab_array[4] = array(gettext("Space used"), false, "diag_space_infos.php");
+ $tab_array[5] = array(gettext("Mounts"), false, "diag_mounts_infos.php");
+ $tab_array[6] = array(gettext("Software RAID"), false, "diag_raid_infos.php");
+ $tab_array[7] = array(gettext("iSCSI"), false, "diag_iscsi_infos.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("MS Domain"), false, "diag_ad_infos.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <table class="tabcont" width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td align="left" valign="top">
+ <?php
+ echo "<pre style=\"font-size: medium;\">";
+ $disklist=get_ata_disks_list();
+ echo "<strong>List of Advanced ATA capabilities on all ATA disk:</strong><br />";
+ foreach ($disklist as $disknamek => $disknamev)
+ {
+ /* Found the channel and device number from the /dev name */
+ /* Divise the number by 2, the interger is the channel number, the rest is the device */
+ echo htmlspecialchars("Results for $disknamek:") . "<br />";
+ $value=trim($disknamek,'ad');
+ $value=intval($value);
+ $channel = $value/2;
+ $device=$value % 2;
+ $channel=intval($channel);
+ exec("/usr/local/sbin/ataidle $channel $device",$rawdata);
+ foreach ($rawdata as $line)
+ {
+ echo htmlspecialchars($line) . "<br />";
+ }
+ unset ($rawdata);
+ }
+ echo "</pre>";
+ ?>
+ </td>
+ </tr>
+ </table>
+ </div>
+ </td>
+ </tr>
+</table>
+</form>
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/freenas/www/diag_disk_infos.php b/config/freenas/www/diag_disk_infos.php
new file mode 100644
index 00000000..31419040
--- /dev/null
+++ b/config/freenas/www/diag_disk_infos.php
@@ -0,0 +1,143 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ diag_ataidle_infos.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+$pgtitle = array(gettext("Diagnostics"),
+ gettext("Disk Infos"));
+
+require_once("freenas_config.inc");
+require_once("guiconfig.inc");
+require_once("freenas_guiconfig.inc");
+require_once("freenas_functions.inc");
+
+if (! empty($_POST))
+{
+ /* hash */
+ unset($error_bucket);
+ /* simple error list */
+ unset($input_errors);
+
+ if (is_array($error_bucket))
+ foreach($error_bucket as $elem)
+ $input_errors[] =& $elem["error"];
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($error_bucket)) {
+ input_errors2Ajax(NULL, $error_bucket);
+ exit;
+ }
+}
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc"); ?>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+
+<form action="diag_disk_infos.php" method="post" name="iform" id="iform">
+
+<div id="inputerrors"></div>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Disks"), true, "diag_disks_infos.php");
+ $tab_array[1] = array(gettext("Partitions"), false, "diag_part_infos.php");
+ $tab_array[2] = array(gettext("SMART"), false, "diag_smart_infos.php");
+ $tab_array[3] = array(gettext("ataidle"), false, "diag_ataidle_infos.php");
+ $tab_array[4] = array(gettext("Space used"), false, "diag_space_infos.php");
+ $tab_array[5] = array(gettext("Mounts"), false, "diag_mounts_infos.php");
+ $tab_array[6] = array(gettext("Software RAID"), false, "diag_raid_infos.php");
+ $tab_array[7] = array(gettext("iSCSI"), false, "diag_iscsi_infos.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("MS Domain"), false, "diag_ad_infos.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <table class="tabcont" width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td align="left" valign="top">
+ <?php
+ exec("/sbin/atacontrol list",$iderawdata);
+ echo "<pre style=\"font-size: medium;\">";
+ echo "<strong>List of detected ATA disks:</strong><br />";
+ foreach ($iderawdata as $line)
+ {
+ echo htmlspecialchars($line) . "<br />";
+ }
+ unset ($line);
+ exec("/sbin/camcontrol devlist",$scsirawdata);
+ echo "<strong>List of detected SCSI disks:</strong><br />";
+ foreach ($scsirawdata as $line)
+ {
+ echo htmlspecialchars($line) . "<br />";
+ }
+ echo "</pre>";
+ ?>
+ </td>
+ </tr>
+ </table>
+ </div>
+ </td>
+ </tr>
+</table>
+</form>
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/freenas/www/diag_fn_logs_daemon.php b/config/freenas/www/diag_fn_logs_daemon.php
new file mode 100644
index 00000000..1eaa1f0f
--- /dev/null
+++ b/config/freenas/www/diag_fn_logs_daemon.php
@@ -0,0 +1,119 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ diag_fn_logs_daemon.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+$pgtitle = array(gettext("Diagnostics"),
+ gettext("System logs"),
+ gettext("Daemon"));
+
+require_once("freenas_config.inc");
+require_once("guiconfig.inc");
+require_once("freenas_guiconfig.inc");
+require_once("freenas_functions.inc");
+
+$nentries = $config['syslog']['nentries'];
+if (!$nentries)
+ $nentries = 50;
+
+if ($_POST['clear'])
+{
+ exec("/usr/sbin/clog -i -s 262144 /var/log/daemon.log");
+ /* redirect to avoid reposting form data on refresh */
+ pfSenseHeader("diag_fn_logs_daemon.php");
+ exit;
+}
+
+/* if ajax is calling, give them an update message */
+if(isAjax())
+ print_info_box_np($savemsg);
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+echo $pfSenseHead->getHTML();
+
+?>
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc"); ?>
+<form action="diag_fn_logs_daemon.php" method="post" name="iform" id="iform">
+<div id="inputerrors"></div>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr><td>
+<?php
+ $tab_array = array();
+ $tab_array[] = array(gettext("Samba"), false, "diag_fn_logs_samba.php");
+ $tab_array[] = array(gettext("FTP"), false, "diag_fn_logs_ftp.php");
+ $tab_array[] = array(gettext("RSYNCD"), false, "diag_fn_logs_rsyncd.php");
+ $tab_array[] = array(gettext("SSHD"), false, "diag_fn_logs_sshd.php");
+ $tab_array[] = array(gettext("SMARTD"), false, "diag_fn_logs_smartd.php");
+ $tab_array[] = array(gettext("Daemon"), true, "diag_fn_logs_daemon.php");
+ $tab_array[] = array(gettext("Settings"), false, "diag_fn_logs_settings.php");
+ display_top_tabs($tab_array);?>
+ </td></tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <table class="tabcont" width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td class="listtopic">
+ Last <?=$nentries;?> Daemon log entries
+ </td>
+ </tr>
+ <?php dump_clog("/var/log/daemon.log", $nentries); ?>
+ <tr>
+ <td align="left" valign="top" height="12">&nbsp;</td>
+ </tr>
+ <tr>
+ <td align="left" valign="top">
+ <input name="clear" type="submit" class="formbtn" value="Clear log" />
+ </td>
+ </tr>
+ </table>
+ </div>
+ </td>
+ </tr>
+</table>
+</form>
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/freenas/www/diag_fn_logs_ftp.php b/config/freenas/www/diag_fn_logs_ftp.php
new file mode 100644
index 00000000..21d8cfb2
--- /dev/null
+++ b/config/freenas/www/diag_fn_logs_ftp.php
@@ -0,0 +1,118 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ diag_fn_logs_ftp.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+$pgtitle = array(gettext("Diagnostics"),
+ gettext("System logs"),
+ gettext("FTP"));
+
+require_once("freenas_config.inc");
+require_once("guiconfig.inc");
+require_once("freenas_guiconfig.inc");
+require_once("freenas_functions.inc");
+
+$nentries = $config['syslog']['nentries'];
+if (!$nentries) { $nentries = 50; }
+
+if ($_POST['clear'])
+{
+ exec("/usr/sbin/clog -i -s 262144 /var/log/ftp.log");
+ /* redirect to avoid reposting form data on refresh */
+ pfSenseHeader("diag_fn_logs_ftp.php");
+ exit;
+}
+
+/* if ajax is calling, give them an update message */
+if(isAjax())
+ print_info_box_np($savemsg);
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+echo $pfSenseHead->getHTML();
+
+?>
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc"); ?>
+<form action="diag_fn_logs_ftp.php" method="post" name="iform" id="iform">
+<div id="inputerrors"></div>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr><td>
+<?php
+ $tab_array = array();
+ $tab_array[] = array(gettext("Samba"), false, "diag_fn_logs_samba.php");
+ $tab_array[] = array(gettext("FTP"), true, "diag_fn_logs_ftp.php");
+ $tab_array[] = array(gettext("RSYNCD"), false, "diag_fn_logs_rsyncd.php");
+ $tab_array[] = array(gettext("SSHD"), false, "diag_fn_logs_sshd.php");
+ $tab_array[] = array(gettext("SMARTD"), false, "diag_fn_logs_smartd.php");
+ $tab_array[] = array(gettext("Daemon"), false, "diag_fn_logs_daemon.php");
+ $tab_array[] = array(gettext("Settings"), false, "diag_fn_logs_settings.php");
+ display_top_tabs($tab_array);?>
+ </td></tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <table class="tabcont" width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td class="listtopic">
+ Last <?=$nentries;?> FTP log entries
+ </td>
+ </tr>
+ <?php dump_clog("/var/log/ftp.log", $nentries); ?>
+ <tr>
+ <td align="left" valign="top" height="12">&nbsp;</td>
+ </tr>
+ <tr>
+ <td align="left" valign="top">
+ <input name="clear" type="submit" class="formbtn" value="Clear log" />
+ </td>
+ </tr>
+ </table>
+ </div>
+ </td>
+ </tr>
+</table>
+</form>
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/freenas/www/diag_fn_logs_rsyncd.php b/config/freenas/www/diag_fn_logs_rsyncd.php
new file mode 100644
index 00000000..44ab3d85
--- /dev/null
+++ b/config/freenas/www/diag_fn_logs_rsyncd.php
@@ -0,0 +1,117 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ diag_fn_logs_rsyncd.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+$pgtitle = array(gettext("Diagnostics"),
+ gettext("System logs"),
+ gettext("RSYNCD"));
+
+require_once("freenas_config.inc");
+require_once("guiconfig.inc");
+require_once("freenas_guiconfig.inc");
+require_once("freenas_functions.inc");
+
+$nentries = $config['syslog']['nentries'];
+if (!$nentries) { $nentries = 50; }
+
+if ($_POST['clear']) {
+ exec("/usr/sbin/clog -i -s 262144 /var/log/rsyncd.log");
+ /* redirect to avoid reposting form data on refresh */
+ pfSenseHeader("diag_fn_logs_rsyncd.php");
+ exit;
+}
+
+/* if ajax is calling, give them an update message */
+if(isAjax())
+ print_info_box_np($savemsg);
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+echo $pfSenseHead->getHTML();
+
+?>
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc"); ?>
+<form action="diag_fn_logs_rsyncd.php" method="post" name="iform" id="iform">
+<div id="inputerrors"></div>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr><td>
+<?php
+ $tab_array = array();
+ $tab_array[] = array(gettext("Samba"), false, "diag_fn_logs_samba.php");
+ $tab_array[] = array(gettext("FTP"), false, "diag_fn_logs_ftp.php");
+ $tab_array[] = array(gettext("RSYNCD"), true, "diag_fn_logs_rsyncd.php");
+ $tab_array[] = array(gettext("SSHD"), false, "diag_fn_logs_sshd.php");
+ $tab_array[] = array(gettext("SMARTD"), false, "diag_fn_logs_smartd.php");
+ $tab_array[] = array(gettext("Daemon"), false, "diag_fn_logs_daemon.php");
+ $tab_array[] = array(gettext("Settings"), false, "diag_fn_logs_settings.php");
+ display_top_tabs($tab_array);?>
+ </td></tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <table class="tabcont" width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td class="listtopic">
+ Last <?=$nentries;?> RSYNCD log entries
+ </td>
+ </tr>
+ <?php dump_clog("/var/log/rsyncd.log", $nentries); ?>
+ <tr>
+ <td align="left" valign="top" height="12">&nbsp;</td>
+ </tr>
+ <tr>
+ <td align="left" valign="top">
+ <input name="clear" type="submit" class="formbtn" value="Clear log" />
+ </td>
+ </tr>
+ </table>
+ </div>
+ </td>
+ </tr>
+</table>
+</form>
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/freenas/www/diag_fn_logs_samba.php b/config/freenas/www/diag_fn_logs_samba.php
new file mode 100644
index 00000000..436de12d
--- /dev/null
+++ b/config/freenas/www/diag_fn_logs_samba.php
@@ -0,0 +1,174 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ diag_fn_logs_samba.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+$pgtitle = array(gettext("Diagnostics"),
+ gettext("System logs"),
+ gettext("Samba"));
+
+require_once("freenas_config.inc");
+require_once("guiconfig.inc");
+require_once("freenas_guiconfig.inc");
+require_once("freenas_functions.inc");
+
+$nentries = $config['syslog']['nentries'];
+if (!$nentries) { $nentries = 50; }
+
+if ($_POST['clear']) {
+ exec("/bin/cp /dev/null /var/log/samba/log.nmbd");
+ exec("/bin/cp /dev/null /var/log/samba/log.smbd");
+ exec("/bin/cp /dev/null /var/log/samba/log.winbindd");
+ /* redirect to avoid reposting form data on refresh */
+ pfSenseHeader("diag_fn_logs_samba.php");
+ exit;
+}
+
+/* if ajax is calling, give them an update message */
+if(isAjax())
+ print_info_box_np($savemsg);
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+echo $pfSenseHead->getHTML();
+
+?>
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc"); ?>
+<form action="diag_fn_logs_samba.php" method="post" name="iform" id="iform">
+<div id="inputerrors"></div>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr><td>
+<?php
+ $tab_array = array();
+ $tab_array[] = array(gettext("Samba"), true, "diag_fn_logs_samba.php");
+ $tab_array[] = array(gettext("FTP"), false, "diag_fn_logs_ftp.php");
+ $tab_array[] = array(gettext("RSYNCD"), false, "diag_fn_logs_rsyncd.php");
+ $tab_array[] = array(gettext("SSHD"), false, "diag_fn_logs_sshd.php");
+ $tab_array[] = array(gettext("SMARTD"), false, "diag_fn_logs_smartd.php");
+ $tab_array[] = array(gettext("Daemon"), false, "diag_fn_logs_daemon.php");
+ $tab_array[] = array(gettext("Settings"), false, "diag_fn_logs_settings.php");
+ display_top_tabs($tab_array);?>
+ </td></tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <table class="tabcont" width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td class="listtopic">
+ Last <?=$nentries;?> nmbd service log entries
+ </td>
+ </tr>
+ <?php
+ if (file_exists("/var/log/samba/log.nmbd")) {
+ exec("cat /var/log/samba/log.nmbd", $rawlog);
+ } else {
+ $rawlog=array("No logs");
+ }
+ ?>
+ <?php foreach ($rawlog as $log) { ?>
+ <tr>
+ <td class="listr" nowrap>
+ <pre><?php echo htmlspecialchars($log); } ?></pre>
+ </td>
+ </tr>
+ <tr>
+ <td align="left" valign="top" height="12">&nbsp;</td>
+ </tr>
+ <?php unset ($rawlog); ?>
+ <tr>
+ <td class="listtopic">
+ Last <?=$nentries;?> smbd service log entries
+ </td>
+ </tr>
+ <?php
+ if (file_exists("/var/log/samba/log.smbd")) {
+ exec("cat /var/log/samba/log.smbd", $rawlog);
+ } else {
+ $rawlog=array("No logs");
+ }
+ ?>
+ <?php foreach ($rawlog as $log) { ?>
+ <tr>
+ <td class="listr" nowrap>
+ <pre><?php echo htmlspecialchars($log); } ?></pre>
+ </td>
+ </tr>
+ <tr>
+ <td align="left" valign="top" height="12">&nbsp;</td>
+ </tr>
+ <tr>
+ <td class="listtopic">
+ Last <?=$nentries;?> winbindd service log entries
+ </td>
+ </tr>
+ <?php
+ if (file_exists("/var/log/samba/log.winbindd")) {
+ exec("cat /var/log/samba/log.winbindd", $rawlog);
+ } else {
+ $rawlog=array("No logs");
+ }
+ ?>
+ <?php foreach ($rawlog as $log) { ?>
+ <tr>
+ <td class="listr" nowrap>
+ <pre><?php echo htmlspecialchars($log); } ?></pre>
+ </td>
+ </tr>
+ <tr>
+ <td align="left" valign="top" height="12">&nbsp;</td>
+ </tr>
+ <tr>
+ <td align="left" valign="top">
+ <input name="clear" type="submit" class="formbtn" value="Clear log" />
+ </td>
+ </tr>
+ </table>
+ </div>
+ </td>
+ </tr>
+</table>
+</form>
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/freenas/www/diag_fn_logs_settings.php b/config/freenas/www/diag_fn_logs_settings.php
new file mode 100644
index 00000000..a51e8479
--- /dev/null
+++ b/config/freenas/www/diag_fn_logs_settings.php
@@ -0,0 +1,310 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ diag_fn_logs_settings.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+$pgtitle = array(gettext("Diagnostics"),
+ gettext("System logs"),
+ gettext("Settings"));
+
+require_once("freenas_config.inc");
+require_once("guiconfig.inc");
+require_once("freenas_guiconfig.inc");
+require_once("freenas_functions.inc");
+
+$pconfig['reverse'] = isset($config['syslog']['reverse']);
+$pconfig['nentries'] = $config['syslog']['nentries'];
+$pconfig['remoteserver'] = $config['syslog']['remoteserver'];
+$pconfig['filter'] = isset($config['syslog']['filter']);
+$pconfig['dhcp'] = isset($config['syslog']['dhcp']);
+$pconfig['portalauth'] = isset($config['syslog']['portalauth']);
+$pconfig['vpn'] = isset($config['syslog']['vpn']);
+$pconfig['system'] = isset($config['syslog']['system']);
+$pconfig['enable'] = isset($config['syslog']['enable']);
+$pconfig['logdefaultblock'] = !isset($config['syslog']['nologdefaultblock']);
+$pconfig['rawfilter'] = isset($config['syslog']['rawfilter']);
+$pconfig['disablelocallogging'] = isset($config['syslog']['disablelocallogging']);
+$pconfig['webservlogs'] = isset($config['syslog']['webservlogs']);
+
+$pconfig['sshd'] = isset($config['syslog']['sshd']);
+$pconfig['ftp'] = isset($config['syslog']['ftp']);
+$pconfig['rsyncd'] = isset($config['syslog']['rsyncd']);
+$pconfig['smartd'] = isset($config['syslog']['smartd']);
+$pconfig['daemon'] = isset($config['syslog']['daemon']);
+
+if (!$pconfig['nentries']) { $pconfig['nentries'] = 50; }
+
+if ($_POST) {
+ unset($input_errors);
+ $pconfig = $_POST;
+
+ /* input validation */
+ if ($_POST['enable'] && !is_ipaddr($_POST['remoteserver'])) {
+ $input_errors[] = gettext("A valid IP address must be specified.");
+ }
+ if (($_POST['nentries'] < 5) || ($_POST['nentries'] > 2000)) {
+ $input_errors[] = gettext("Number of log entries to show must be between 5 and 2000.");
+ }
+
+ if (!$input_errors) {
+ $config['syslog']['reverse'] = $_POST['reverse'] ? true : false;
+ $config['syslog']['nentries'] = (int)$_POST['nentries'];
+ $config['syslog']['remoteserver'] = $_POST['remoteserver'];
+ $config['syslog']['filter'] = $_POST['filter'] ? true : false;
+ $config['syslog']['dhcp'] = $_POST['dhcp'] ? true : false;
+ $config['syslog']['portalauth'] = $_POST['portalauth'] ? true : false;
+ $config['syslog']['vpn'] = $_POST['vpn'] ? true : false;
+ $config['syslog']['system'] = $_POST['system'] ? true : false;
+ $config['syslog']['disablelocallogging'] = $_POST['disablelocallogging'] ? true : false;
+ $config['syslog']['enable'] = $_POST['enable'] ? true : false;
+ $oldnologdefaultblock = isset($config['syslog']['nologdefaultblock']);
+ $config['syslog']['nologdefaultblock'] = $_POST['logdefaultblock'] ? false : true;
+ $config['syslog']['rawfilter'] = $_POST['rawfilter'] ? true : false;
+ $config['syslog']['webservlogs'] = $_POST['webservlogs'] ? true : false;
+ $config['syslog']['sshd'] = $_POST['sshd'] ? true : false;
+ $config['syslog']['ftp'] = $_POST['ftp'] ? true : false;
+ $config['syslog']['rsyncd'] = $_POST['rsyncd'] ? true : false;
+ $config['syslog']['smartd'] = $_POST['smartd'] ? true : false;
+ $config['syslog']['daemon'] = $_POST['daemon'] ? true : false;
+ if($config['syslog']['enable'] == false)
+ unset($config['syslog']['remoteserver']);
+
+ write_config();
+
+ $retval = 0;
+ config_lock();
+ $retval = system_syslogd_start();
+ if ($oldnologdefaultblock !== isset($config['syslog']['nologdefaultblock']))
+ $retval |= filter_configure();
+ config_unlock();
+ $savemsg = get_std_save_message($retval);
+ }
+}
+
+/* if ajax is calling, give them an update message */
+if(isAjax())
+ print_info_box_np($savemsg);
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+
+$jscriptstr = <<<EOD
+<script language="JavaScript" type="text/javascript">
+<!--
+function enable_change(enable_over) {
+ endis = !(document.iform.enable.checked || enable_over);
+ endis ? color = '#D4D0C8' : color = '#FFFFFF';
+
+ if (document.iform.enable.checked || enable_over) {
+ document.iform.remoteserver.disabled = 0;
+ document.iform.filter.disabled = 0;
+ document.iform.dhcp.disabled = 0;
+ document.iform.portalauth.disabled = 0;
+ document.iform.vpn.disabled = 0;
+ document.iform.system.disabled = 0;
+ document.iform.webservlogs.disabled = 0;
+ document.iform.sshd.disabled = 0;
+ document.iform.ftp.disabled = 0;
+ document.iform.rsyncd.disabled = 0;
+ document.iform.smartd.disabled = 0;
+ document.iform.daemon.disabled = 0;
+
+ } else {
+ document.iform.remoteserver.disabled = 1;
+ document.iform.filter.disabled = 1;
+ document.iform.dhcp.disabled = 1;
+ document.iform.portalauth.disabled = 1;
+ document.iform.vpn.disabled = 1;
+ document.iform.system.disabled = 1;
+ document.iform.webservlogs.disabled = 1;
+ document.iform.sshd.disabled = 1;
+ document.iform.ftp.disabled = 1;
+ document.iform.rsyncd.disabled = 1;
+ document.iform.smartd.disabled = 1;
+ document.iform.daemon.disabled = 1;
+ }
+
+ /* color adjustments */
+ document.iform.remoteserver.style.backgrounColor = color;
+ document.iform.filter.style.backgrounColor = color;
+ document.iform.dhcp.style.backgrounColor = color;
+ document.iform.portalauth.style.backgrounColor = color;
+ document.iform.vpn.style.backgrounColor = color;
+ document.iform.system.style.backgrounColor = color;
+ document.iform.webservlogs.style.backgrounColor = color;
+ document.iform.sshd.style.backgrounColor = color;
+ document.iform.ftp.style.backgrounColor = color;
+ document.iform.rsyncd.style.backgrounColor = color;
+ document.iform.smartd.style.backgrounColor = color;
+ document.iform.daemon.style.backgrounColor = color;
+}
+// -->
+</script>
+
+EOD;
+
+$pfSenseHead->addScript($jscriptstr);
+echo $pfSenseHead->getHTML();
+
+?>
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc"); ?>
+<form action="diag_fn_logs_settings.php" method="post" name="iform" id="iform">
+<div id="inputerrors"></div>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr><td>
+<?php
+ $tab_array = array();
+ $tab_array[] = array(gettext("Samba"), false, "diag_fn_logs_samba.php");
+ $tab_array[] = array(gettext("FTP"), false, "diag_fn_logs_ftp.php");
+ $tab_array[] = array(gettext("RSYNCD"), false, "diag_fn_logs_rsyncd.php");
+ $tab_array[] = array(gettext("SSHD"), false, "diag_fn_logs_sshd.php");
+ $tab_array[] = array(gettext("SMARTD"), false, "diag_fn_logs_smartd.php");
+ $tab_array[] = array(gettext("Daemon"), false, "diag_fn_logs_daemon.php");
+ $tab_array[] = array(gettext("Settings"), true, "diag_fn_logs_settings.php");
+ display_top_tabs($tab_array);?>
+ </td></tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <table class="tabcont" width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="22%" valign="top" class="vtable">&nbsp;</td>
+ <td width="78%" class="vtable"> <input name="reverse" class="formfld" type="checkbox" id="reverse" value="yes" <?php if ($pconfig['reverse']) echo "checked"; ?> />
+ <strong><?=gettext("Show log entries in reverse order (newest entries on top)");?></strong>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vtable">&nbsp;</td>
+ <td width="78%" class="vtable"><?=gettext("Number of log entries to show");?>:
+ <input name="nentries" id="nentries" type="text" class="formfld unknown" size="4" value="<?=htmlspecialchars($pconfig['nentries']);?>" />
+ </td>
+ </tr>
+ <tr>
+ <td valign="top" class="vtable">&nbsp;</td>
+ <td class="vtable"> <input name="logdefaultblock" class="formfld" type="checkbox" id="logdefaultblock" value="yes" <?php if ($pconfig['logdefaultblock']) echo "checked"; ?> />
+ <strong><?=gettext("Log packets blocked by the default rule");?></strong><br />
+ <?=gettext("Hint: packets that are blocked by the
+ implicit default block rule will not be logged anymore
+ if you uncheck this option. Per-rule logging options are not affected.");?>
+ </td>
+ </tr>
+ <tr>
+ <td valign="top" class="vtable">&nbsp;</td>
+ <td class="vtable"> <input name="rawfilter" class="formfld" type="checkbox" id="rawfilter" value="yes" <?php if ($pconfig['rawfilter']) echo "checked"; ?> />
+ <strong><?=gettext("Show raw filter logs");?></strong><br />
+ <?=gettext("Hint: If this is checked, filter logs are shown as generated by the packet filter, without any formatting. This will reveal more detailed information.");?>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vtable">&nbsp;</td>
+ <td width="78%" class="vtable"> <input name="disablelocallogging" class="formfld" type="checkbox" id="disablelocallogging" value="yes" <?php if ($pconfig['disablelocallogging']) echo "checked"; ?> onclick="enable_change(false)" />
+ <strong><?=gettext("Disable writing log files to the local disk");?></strong>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vtable">&nbsp;</td>
+ <td width="78%" class="vtable"> <input name="enable" class="formfld" type="checkbox" id="enable" value="yes" <?php if ($pconfig['enable']) echo "checked"; ?> onclick="enable_change(false)" />
+ <strong><?=gettext("Enable syslog'ing to remote syslog server");?></strong>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Remote syslog server</td>
+ <td width="78%" class="vtable">
+ <input name="remoteserver" id="remoteserver" type="text" class="formfld unknown" size="20" value="<?=htmlspecialchars($pconfig['remoteserver']);?>" />
+ <br /><?=gettext("IP address of remote syslog server");?>
+ <br /><br />
+ <input name="system" id="system" class="formfld" type="checkbox" value="yes" onclick="enable_change(false)" <?php if ($pconfig['system']) echo "checked=\"checked\""; ?> />
+ <?=gettext("system events");?><br />
+ <input name="filter" id="filter" class="formfld" type="checkbox" value="yes" <?php if ($pconfig['filter']) echo "checked=\"checked\""; ?> />
+ <?=gettext("firewall events");?><br />
+ <input name="dhcp" id="dhcp" class="formfld" type="checkbox" value="yes" <?php if ($pconfig['dhcp']) echo "checked=\"checked\""; ?> />
+ <?=gettext("DHCP service events");?><br />
+ <input name="portalauth" id="portalauth" class="formfld" type="checkbox" value="yes" <?php if ($pconfig['portalauth']) echo "checked=\"checked\""; ?> />
+ <?=gettext("Portal Auth");?><br />
+ <input name="vpn" id="vpn" class="formfld" type="checkbox" value="yes" <?php if ($pconfig['vpn']) echo "checked=\"checked\""; ?> />
+ <?=gettext("PPTP VPN events");?><br />
+ <input name="webservlogs" id="webservlogs" class="formfld" type="checkbox" value="yes" <?php if ($pconfig['webservlogs']) echo "checked=\"checked\""; ?> />
+ <?=gettext("webConfigurator Logs");?><br />
+ <input name="sshd" id="sshd" class="formfld" type="checkbox" value="yes" <?php if ($pconfig['sshd']) echo "checked=\"checked\""; ?> />
+ <?=gettext("SSHD events");?><br />
+ <input name="ftp" id="ftp" class="formfld" type="checkbox" value="yes" <?php if ($pconfig['ftp']) echo "checked=\"checked\""; ?> />
+ <?=gettext("FTP events");?><br />
+ <input name="rsyncd" id="rsyncd" class="formfld" type="checkbox" value="yes" <?php if ($pconfig['rsyncd']) echo "checked=\"checked\""; ?> />
+ <?=gettext("RSYNCD events");?><br />
+ <input name="smartd" id="smartd" class="formfld" type="checkbox" value="yes" <?php if ($pconfig['smartd']) echo "checked=\"checked\""; ?> />
+ <?=gettext("SMARTD events");?><br />
+ <input name="daemon" id="daemon" class="formfld" type="checkbox" value="yes" <?php if ($pconfig['daemon']) echo "checked=\"checked\""; ?> />
+ <?=gettext("Daemon events");?><br />
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <input id="submit" name="Submit" type="submit" class="formbtn" value="Save" onclick="enable_change(true)" />
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" height="53" valign="top">&nbsp;</td>
+ <td width="78%"><strong><span class="red"><?=gettext("Note");?>:</span></strong><br />
+ <?=gettext("
+ syslog sends UDP datagrams to port 514 on the specified
+ remote syslog server. Be sure to set syslogd on the
+ remote server to accept syslog messages from {$g['product_name']}.
+ ");?>
+ </td>
+ </tr>
+ </table>
+ </div>
+ </td>
+ </tr>
+</table>
+</form>
+<script language="JavaScript" type="text/javascript">
+<!--
+enable_change(false);
+//-->
+</script>
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/freenas/www/diag_fn_logs_smartd.php b/config/freenas/www/diag_fn_logs_smartd.php
new file mode 100644
index 00000000..7e57d543
--- /dev/null
+++ b/config/freenas/www/diag_fn_logs_smartd.php
@@ -0,0 +1,118 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ diag_fn_logs_smartd.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+$pgtitle = array(gettext("Diagnostics"),
+ gettext("System logs"),
+ gettext("SMARTD"));
+
+require_once("freenas_config.inc");
+require_once("guiconfig.inc");
+require_once("freenas_guiconfig.inc");
+require_once("freenas_functions.inc");
+
+$nentries = $config['syslog']['nentries'];
+if (!$nentries) { $nentries = 50; }
+
+if ($_POST['clear'])
+{
+ exec("/usr/sbin/clog -i -s 262144 /var/log/smartd.log");
+ /* redirect to avoid reposting form data on refresh */
+ pfSenseHeader("diag_fn_logs_smartd.php");
+ exit;
+}
+
+/* if ajax is calling, give them an update message */
+if(isAjax())
+ print_info_box_np($savemsg);
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+echo $pfSenseHead->getHTML();
+
+?>
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc"); ?>
+<form action="diag_fn_logs_smartd.php" method="post" name="iform" id="iform">
+<div id="inputerrors"></div>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr><td>
+<?php
+ $tab_array = array();
+ $tab_array[] = array(gettext("Samba"), false, "diag_fn_logs_samba.php");
+ $tab_array[] = array(gettext("FTP"), false, "diag_fn_logs_ftp.php");
+ $tab_array[] = array(gettext("RSYNCD"), false, "diag_fn_logs_rsyncd.php");
+ $tab_array[] = array(gettext("SSHD"), false, "diag_fn_logs_sshd.php");
+ $tab_array[] = array(gettext("SMARTD"), true, "diag_fn_logs_smartd.php");
+ $tab_array[] = array(gettext("Daemon"), false, "diag_fn_logs_daemon.php");
+ $tab_array[] = array(gettext("Settings"), false, "diag_fn_logs_settings.php");
+ display_top_tabs($tab_array);?>
+ </td></tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <table class="tabcont" width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td class="listtopic">
+ Last <?=$nentries;?> SmartD log entries
+ </td>
+ </tr>
+ <?php dump_clog("/var/log/smartd.log", $nentries); ?>
+ <tr>
+ <td align="left" valign="top" height="12">&nbsp;</td>
+ </tr>
+ <tr>
+ <td align="left" valign="top">
+ <input name="clear" type="submit" class="formbtn" value="Clear log" />
+ </td>
+ </tr>
+ </table>
+ </div>
+ </td>
+ </tr>
+</table>
+</form>
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/freenas/www/diag_fn_logs_sshd.php b/config/freenas/www/diag_fn_logs_sshd.php
new file mode 100644
index 00000000..bc61d57f
--- /dev/null
+++ b/config/freenas/www/diag_fn_logs_sshd.php
@@ -0,0 +1,117 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ diag_fn_logs_sshd.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+$pgtitle = array(gettext("Diagnostics"),
+ gettext("System logs"),
+ gettext("SSHD"));
+
+require_once("freenas_config.inc");
+require_once("guiconfig.inc");
+require_once("freenas_guiconfig.inc");
+require_once("freenas_functions.inc");
+
+$nentries = $config['syslog']['nentries'];
+if (!$nentries) { $nentries = 50; }
+
+if ($_POST['clear']) {
+ exec("/usr/sbin/clog -i -s 262144 /var/log/sshd.log");
+ /* redirect to avoid reposting form data on refresh */
+ pfSenseHeader("diag_fn_logs_sshd.php");
+ exit;
+}
+
+/* if ajax is calling, give them an update message */
+if(isAjax())
+ print_info_box_np($savemsg);
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+echo $pfSenseHead->getHTML();
+
+?>
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc"); ?>
+<form action="diag_fn_logs_sshd.php" method="post" name="iform" id="iform">
+<div id="inputerrors"></div>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr><td>
+<?php
+ $tab_array = array();
+ $tab_array[] = array(gettext("Samba"), false, "diag_fn_logs_samba.php");
+ $tab_array[] = array(gettext("FTP"), false, "diag_fn_logs_ftp.php");
+ $tab_array[] = array(gettext("RSYNCD"), false, "diag_fn_logs_rsyncd.php");
+ $tab_array[] = array(gettext("SSHD"), true, "diag_fn_logs_sshd.php");
+ $tab_array[] = array(gettext("SMARTD"), false, "diag_fn_logs_smartd.php");
+ $tab_array[] = array(gettext("Daemon"), false, "diag_fn_logs_daemon.php");
+ $tab_array[] = array(gettext("Settings"), false, "diag_fn_logs_settings.php");
+ display_top_tabs($tab_array);?>
+ </td></tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <table class="tabcont" width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td class="listtopic">
+ Last <?=$nentries;?> SSHD log entries
+ </td>
+ </tr>
+ <?php dump_clog("/var/log/sshd.log", $nentries); ?>
+ <tr>
+ <td align="left" valign="top" height="12">&nbsp;</td>
+ </tr>
+ <tr>
+ <td align="left" valign="top">
+ <input name="clear" type="submit" class="formbtn" value="Clear log" />
+ </td>
+ </tr>
+ </table>
+ </div>
+ </td>
+ </tr>
+</table>
+</form>
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/freenas/www/diag_iscsi_infos.php b/config/freenas/www/diag_iscsi_infos.php
new file mode 100644
index 00000000..05c136e8
--- /dev/null
+++ b/config/freenas/www/diag_iscsi_infos.php
@@ -0,0 +1,142 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ diag_iscsi_infos.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+$pgtitle = array(gettext("Diagnostics"),
+ gettext("iSCSI Infos"));
+
+require_once("freenas_config.inc");
+require_once("guiconfig.inc");
+require_once("freenas_guiconfig.inc");
+require_once("freenas_functions.inc");
+
+if (! empty($_POST))
+{
+ /* hash */
+ unset($error_bucket);
+ /* simple error list */
+ unset($input_errors);
+
+ if (is_array($error_bucket))
+ foreach($error_bucket as $elem)
+ $input_errors[] =& $elem["error"];
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($error_bucket)) {
+ input_errors2Ajax(NULL, $error_bucket);
+ exit;
+ }
+}
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc"); ?>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+
+<form action="diag_iscsi_infos.php" method="post" name="iform" id="iform">
+
+<div id="inputerrors"></div>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Disks"), false, "diag_disks_infos.php");
+ $tab_array[1] = array(gettext("Partitions"), false, "diag_part_infos.php");
+ $tab_array[2] = array(gettext("SMART"), false, "diag_smart_infos.php");
+ $tab_array[3] = array(gettext("ataidle"), false, "diag_ataidle_infos.php");
+ $tab_array[4] = array(gettext("Space used"), false, "diag_space_infos.php");
+ $tab_array[5] = array(gettext("Mounts"), false, "diag_mounts_infos.php");
+ $tab_array[6] = array(gettext("Software RAID"), false, "diag_raid_infos.php");
+ $tab_array[7] = array(gettext("iSCSI"), true, "diag_iscsi_infos.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("MS Domain"), false, "diag_ad_infos.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <table class="tabcont" width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td align="left" valign="top">
+ <?php
+ if (! isset($freenas_config['iscsi']['enable'])) {
+ echo "<strong>iSCSI initiator disabled</strong><br />";
+ } else {
+ echo "<pre style=\"font-size: medium;\">";
+ echo "<strong>Show the list of available target Name on the iSCSI target</strong><br>";
+
+ exec("/usr/local/sbin/iscontrol -d targetaddress={$freenas_config['iscsi']['targetaddress']}",$rawdata);
+ foreach ($rawdata as $line)
+ {
+ echo htmlspecialchars($line) . "<br>";
+ }
+ unset ($rawdata);
+ echo "</pre>";
+ }
+ ?>
+ </td>
+ </tr>
+ </table>
+ </div>
+ </td>
+ </tr>
+</table>
+</form>
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/freenas/www/diag_mounts_infos.php b/config/freenas/www/diag_mounts_infos.php
new file mode 100644
index 00000000..29eb49f5
--- /dev/null
+++ b/config/freenas/www/diag_mounts_infos.php
@@ -0,0 +1,137 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ diag_mounts_infos.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+$pgtitle = array(gettext("Diagnostics"),
+ gettext("Mount Infos"));
+
+require_once("freenas_config.inc");
+require_once("guiconfig.inc");
+require_once("freenas_guiconfig.inc");
+require_once("freenas_functions.inc");
+
+if (! empty($_POST))
+{
+ /* hash */
+ unset($error_bucket);
+ /* simple error list */
+ unset($input_errors);
+
+ if (is_array($error_bucket))
+ foreach($error_bucket as $elem)
+ $input_errors[] =& $elem["error"];
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($error_bucket)) {
+ input_errors2Ajax(NULL, $error_bucket);
+ exit;
+ }
+}
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc"); ?>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+
+<form action="diag_mounts_infos.php" method="post" name="iform" id="iform">
+
+<div id="inputerrors"></div>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Disks"), false, "diag_disks_infos.php");
+ $tab_array[1] = array(gettext("Partitions"), false, "diag_part_infos.php");
+ $tab_array[2] = array(gettext("SMART"), false, "diag_smart_infos.php");
+ $tab_array[3] = array(gettext("ataidle"), false, "diag_ataidle_infos.php");
+ $tab_array[4] = array(gettext("Space used"), false, "diag_space_infos.php");
+ $tab_array[5] = array(gettext("Mounts"), true, "diag_mounts_infos.php");
+ $tab_array[6] = array(gettext("Software RAID"), false, "diag_raid_infos.php");
+ $tab_array[7] = array(gettext("iSCSI"), false, "diag_iscsi_infos.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Manage RAID"), false, "diag_ad_infos.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <table class="tabcont" width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td align="left" valign="top">
+ <?php
+ echo "<pre style=\"font-size: medium;\">";
+ echo "<strong>List of mounted point:</strong><br />";
+ exec("/sbin/mount",$mountrawdata);
+ foreach ($mountrawdata as $line)
+ {
+ echo htmlspecialchars($line) . "<br />";
+ }
+ unset ($line);
+ echo "</pre>";
+ ?>
+ </td>
+ </tr>
+ </table>
+ </div>
+ </td>
+ </tr>
+</table>
+</form>
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/freenas/www/diag_part_infos.php b/config/freenas/www/diag_part_infos.php
new file mode 100644
index 00000000..011a771c
--- /dev/null
+++ b/config/freenas/www/diag_part_infos.php
@@ -0,0 +1,141 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ diag_part_infos.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+$pgtitle = array(gettext("Diagnostics"),
+ gettext("Partition Infos"));
+
+require_once("freenas_config.inc");
+require_once("guiconfig.inc");
+require_once("freenas_guiconfig.inc");
+require_once("freenas_functions.inc");
+
+if (! empty($_POST))
+{
+ /* hash */
+ unset($error_bucket);
+ /* simple error list */
+ unset($input_errors);
+
+ if (is_array($error_bucket))
+ foreach($error_bucket as $elem)
+ $input_errors[] =& $elem["error"];
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($error_bucket)) {
+ input_errors2Ajax(NULL, $error_bucket);
+ exit;
+ }
+}
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc"); ?>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+
+<form action="diag_part_infos.php" method="post" name="iform" id="iform">
+
+<div id="inputerrors"></div>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Disks"), false, "diag_disks_infos.php");
+ $tab_array[1] = array(gettext("Partitions"), true, "diag_part_infos.php");
+ $tab_array[2] = array(gettext("SMART"), false, "diag_smart_infos.php");
+ $tab_array[3] = array(gettext("ataidle"), false, "diag_ataidle_infos.php");
+ $tab_array[4] = array(gettext("Space used"), false, "diag_space_infos.php");
+ $tab_array[5] = array(gettext("Mounts"), false, "diag_mounts_infos.php");
+ $tab_array[6] = array(gettext("Software RAID"), false, "diag_raid_infos.php");
+ $tab_array[7] = array(gettext("iSCSI"), false, "diag_iscsi_infos.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Manage RAID"), false, "diag_ad_infos.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <table class="tabcont" width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td align="left" valign="top">
+ <?php
+ echo "<pre style=\"font-size: medium;\">";
+ $disklist = get_physical_disks_list();
+ echo "<strong>List of partition on all detected disk:</strong><br />";
+ foreach ($disklist as $disknamek => $disknamev)
+ {
+ exec("/sbin/fdisk $disknamek",$fdiskrawdata);
+ foreach ($fdiskrawdata as $line)
+ {
+ echo htmlspecialchars($line) . "<br />";
+ }
+ unset ($fdiskrawdata);
+ }
+ echo "</pre>";
+ ?>
+ </td>
+ </tr>
+ </table>
+ </div>
+ </td>
+ </tr>
+</table>
+</form>
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/freenas/www/diag_raid_infos.php b/config/freenas/www/diag_raid_infos.php
new file mode 100644
index 00000000..ad1621c1
--- /dev/null
+++ b/config/freenas/www/diag_raid_infos.php
@@ -0,0 +1,163 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ diag_raid_infos.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+$pgtitle = array(gettext("Diagnostics"),
+ gettext("RAID Infos"));
+
+require_once("freenas_config.inc");
+require_once("guiconfig.inc");
+require_once("freenas_guiconfig.inc");
+require_once("freenas_functions.inc");
+
+if (! empty($_POST))
+{
+ /* hash */
+ unset($error_bucket);
+ /* simple error list */
+ unset($input_errors);
+
+ if (is_array($error_bucket))
+ foreach($error_bucket as $elem)
+ $input_errors[] =& $elem["error"];
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($error_bucket)) {
+ input_errors2Ajax(NULL, $error_bucket);
+ exit;
+ }
+}
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc"); ?>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+
+<form action="diag_raid_infos.php" method="post" name="iform" id="iform">
+
+<div id="inputerrors"></div>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Disks"), false, "diag_disks_infos.php");
+ $tab_array[1] = array(gettext("Partitions"), false, "diag_part_infos.php");
+ $tab_array[2] = array(gettext("SMART"), false, "diag_smart_infos.php");
+ $tab_array[3] = array(gettext("ataidle"), false, "diag_ataidle_infos.php");
+ $tab_array[4] = array(gettext("Space used"), false, "diag_space_infos.php");
+ $tab_array[5] = array(gettext("Mounts"), false, "diag_mounts_infos.php");
+ $tab_array[6] = array(gettext("Software RAID"), true, "diag_raid_infos.php");
+ $tab_array[7] = array(gettext("iSCSI"), false, "diag_iscsi_infos.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("MS Domain"), false, "diag_ad_infos.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <table class="tabcont" width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td align="left" valign="top">
+ <?php
+ echo "<pre style=\"font-size: medium;\">";
+ echo "<strong>" . gettext("Software RAID") . " - " . gettext("Geom Mirror") . ":</strong><br /><br />";
+ exec("/sbin/gmirror list",$rawdata);
+ foreach ($rawdata as $line) {
+ echo htmlspecialchars($line) . "<br />";
+ }
+ unset ($line);
+ unset ($rawdata);
+ echo "<strong>" . gettext("Software RAID") . " - " . gettext("Geom Vinum") . ":</strong><br /><br />";
+ exec("/sbin/gvinum list",$rawdata);
+ foreach ($rawdata as $line) {
+ echo htmlspecialchars($line) . "<br />";
+ }
+ unset ($line);
+ unset ($rawdata);
+ echo "<strong>" . gettext("Software RAID") . " - " . gettext("Geom Concat") . ":</strong><br /><br />";
+ exec("/sbin/gconcat list",$rawdata);
+ foreach ($rawdata as $line) {
+ echo htmlspecialchars($line) . "<br />";
+ }
+ unset ($line);
+ unset ($rawdata);
+ echo "<strong>" . gettext("Software RAID") . " - " . gettext("Geom Stripe") . ":</strong><br /><br />";
+ exec("/sbin/gstripe list",$rawdata);
+ foreach ($rawdata as $line) {
+ echo htmlspecialchars($line) . "<br />";
+ }
+ unset ($line);
+ unset ($rawdata);
+ echo "<strong>" . gettext("Software RAID") . " - " . gettext("Geom Raid5") . ":</strong><br /><br />";
+ exec("/sbin/graid5 list",$rawdata);
+ foreach ($rawdata as $line) {
+ echo htmlspecialchars($line) . "<br />";
+ }
+ echo "</pre>";
+ ?>
+ </td>
+ </tr>
+ </table>
+ </div>
+ </td>
+ </tr>
+</table>
+</form>
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/freenas/www/diag_smart_infos.php b/config/freenas/www/diag_smart_infos.php
new file mode 100644
index 00000000..d265d1b7
--- /dev/null
+++ b/config/freenas/www/diag_smart_infos.php
@@ -0,0 +1,141 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ diag_smart_infos.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+$pgtitle = array(gettext("Diagnostics"),
+ gettext("SMART Infos"));
+
+require_once("freenas_config.inc");
+require_once("guiconfig.inc");
+require_once("freenas_guiconfig.inc");
+require_once("freenas_functions.inc");
+
+if (! empty($_POST))
+{
+ /* hash */
+ unset($error_bucket);
+ /* simple error list */
+ unset($input_errors);
+
+ if (is_array($error_bucket))
+ foreach($error_bucket as $elem)
+ $input_errors[] =& $elem["error"];
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($error_bucket)) {
+ input_errors2Ajax(NULL, $error_bucket);
+ exit;
+ }
+}
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc"); ?>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+
+<form action="diag_smart_infos.php" method="post" name="iform" id="iform">
+
+<div id="inputerrors"></div>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Disks"), false, "diag_disks_infos.php");
+ $tab_array[1] = array(gettext("Partitions"), false, "diag_part_infos.php");
+ $tab_array[2] = array(gettext("SMART"), true, "diag_smart_infos.php");
+ $tab_array[3] = array(gettext("ataidle"), false, "diag_ataidle_infos.php");
+ $tab_array[4] = array(gettext("Space used"), false, "diag_space_infos.php");
+ $tab_array[5] = array(gettext("Mounts"), false, "diag_mounts_infos.php");
+ $tab_array[6] = array(gettext("Software RAID"), false, "diag_raid_infos.php");
+ $tab_array[7] = array(gettext("iSCSI"), false, "diag_iscsi_infos.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("MS Domain"), false, "diag_ad_infos.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <table class="tabcont" width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td align="left" valign="top">
+ <?php
+ echo "<pre style=\"font-size: medium;\">";
+ $disklist = get_physical_disks_list();
+ echo "<strong>List of SMART capabilities on all detected disk:</strong><br />";
+ foreach ($disklist as $disknamek => $disknamev)
+ {
+ exec("/usr/local/sbin/smartctl -a /dev/$disknamek",$fdiskrawdata);
+ foreach ($fdiskrawdata as $line)
+ {
+ echo htmlspecialchars($line) . "<br />";
+ }
+ unset ($fdiskrawdata);
+ }
+ echo "</pre>";
+ ?>
+ </td>
+ </tr>
+ </table>
+ </div>
+ </td>
+ </tr>
+</table>
+</form>
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/freenas/www/diag_space_infos.php b/config/freenas/www/diag_space_infos.php
new file mode 100644
index 00000000..e0726b07
--- /dev/null
+++ b/config/freenas/www/diag_space_infos.php
@@ -0,0 +1,136 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ diag_space_infos.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+$pgtitle = array(gettext("Diagnostics"),
+ gettext("Space Infos"));
+
+require_once("freenas_config.inc");
+require_once("guiconfig.inc");
+require_once("freenas_guiconfig.inc");
+require_once("freenas_functions.inc");
+
+if (! empty($_POST))
+{
+ /* hash */
+ unset($error_bucket);
+ /* simple error list */
+ unset($input_errors);
+
+ if (is_array($error_bucket))
+ foreach($error_bucket as $elem)
+ $input_errors[] =& $elem["error"];
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($error_bucket)) {
+ input_errors2Ajax(NULL, $error_bucket);
+ exit;
+ }
+}
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc"); ?>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+
+<form action="diag_space_infos.php" method="post" name="iform" id="iform">
+
+<div id="inputerrors"></div>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Disks"), false, "diag_disks_infos.php");
+ $tab_array[1] = array(gettext("Partitions"), false, "diag_part_infos.php");
+ $tab_array[2] = array(gettext("SMART"), false, "diag_smart_infos.php");
+ $tab_array[3] = array(gettext("ataidle"), false, "diag_ataidle_infos.php");
+ $tab_array[4] = array(gettext("Space used"), true, "diag_space_infos.php");
+ $tab_array[5] = array(gettext("Mounts"), false, "diag_mounts_infos.php");
+ $tab_array[6] = array(gettext("Software RAID"), false, "diag_raid_infos.php");
+ $tab_array[7] = array(gettext("iSCSI"), false, "diag_iscsi_infos.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("MS Domain"), false, "diag_ad_infos.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <table class="tabcont" width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td align="left" valign="top">
+ <?php
+ echo "<pre style=\"font-size: medium;\">";
+ exec("/bin/df -h",$rawdata);
+ echo "<strong>Free Space:</strong><br />";
+ foreach ($rawdata as $line)
+ {
+ echo htmlspecialchars($line) . "<br />";
+ }
+ echo "</pre>";
+ ?>
+ </td>
+ </tr>
+ </table>
+ </div>
+ </td>
+ </tr>
+</table>
+</form>
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/freenas/www/disks_manage.php b/config/freenas/www/disks_manage.php
new file mode 100644
index 00000000..b6dece05
--- /dev/null
+++ b/config/freenas/www/disks_manage.php
@@ -0,0 +1,208 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ disks_manage.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+$pgtitle = array(gettext("System"),
+ gettext("Disks"),
+ gettext("Management"));
+
+require_once("freenas_config.inc");
+require_once("guiconfig.inc");
+require_once("freenas_guiconfig.inc");
+require_once("freenas_functions.inc");
+
+if (!is_array($freenas_config['disks']['disk']))
+ $freenas_config['disks']['disk'] = array();
+
+disks_sort();
+
+$a_disk_conf = &$freenas_config['disks']['disk'];
+
+if ($_POST) {
+ unset($input_errors);
+
+ /* input validation */
+
+ if ($_POST['apply']) {
+ $retval = 0;
+ if (! file_exists($d_sysrebootreqd_path)) {
+ config_lock();
+ /* reload all components that mount disk */
+ // disks_mount_all();
+ /* Is formated?: If not create FS */
+ /* $retval = disk_disks_create_ufs(); */
+
+ config_unlock();
+ }
+ $savemsg = get_std_save_message($retval);
+ if ($retval == 0) {
+ if (file_exists($d_diskdirty_path)) {
+ unlink($d_diskdirty_path);
+ }
+ }
+ }
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($input_errors)) {
+ input_errors2Ajax($input_errors);
+ exit;
+ }
+
+ if (!$input_errors) {
+ /* No errors detected, so update the config */
+ }
+}
+
+if ($_GET['act'] == "del") {
+ if ($a_disk_conf[$_GET['id']]) {
+ unset($a_disk_conf[$_GET['id']]);
+ write_config();
+ touch($d_diskdirty_path);
+ pfSenseHeader("disks_manage.php");
+ exit;
+ }
+}
+
+/* if ajax is calling, give them an update message */
+if(isAjax())
+ print_info_box_np($savemsg);
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc"); ?>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+
+<form action="disks_manage.php" method="post" name="iform" id="iform">
+<?php if (file_exists($d_diskdirty_path)): ?>
+<?php print_info_box_np(gettext("The disk list has been changed.") . "<br />" .
+ gettext("You must apply the changes in order for them to take effect."));?>
+<?php endif; ?>
+
+<div id="inputerrors"></div>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr><td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Manage"), true, "disks_manage.php");
+ $tab_array[1] = array(gettext("Format"), false, "disks_manage_init.php");
+ $tab_array[2] = array(gettext("Tools"), false, "disks_manage_tools.php");
+ $tab_array[3] = array(gettext("iSCSI Initiator"), false, "disks_manage_iscsi.php");
+ display_top_tabs($tab_array);
+?>
+ </td></tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <table class="tabcont" width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="listhdrr"><?=gettext("Disk");?></td>
+ <td class="listhdrr"><?=gettext("Size");?></td>
+ <td class="listhdrr"><?=gettext("Description");?></td>
+ <td class="listhdrr"><?=gettext("Standby time");?></td>
+ <td class="listhdrr"><?=gettext("File system");?></td>
+ <td class="listhdrr"><?=gettext("Status");?></td>
+ <td class="list">&nbsp;</td>
+ </tr>
+ <?php $i = 0; foreach ($a_disk_conf as $disk): ?>
+ <tr>
+ <td valign="middle" class="listr">
+ <?=htmlspecialchars($disk['name']);?>
+ </td>
+ <td valign="middle" class="listr">
+ <?=htmlspecialchars($disk['size']);?>
+ </td>
+ <td valign="middle" class="listr">
+ <?=htmlspecialchars($disk['desc']);?>&nbsp;
+ </td>
+ <td valign="middle" class="listr">
+ <?php
+ if ($disk['harddiskstandby']) {
+ $value = $disk['harddiskstandby'];
+ //htmlspecialchars($value);
+ echo $value;
+ } else {
+ echo "Always on";
+ }
+ ?>
+ </td>
+ <td valign="middle" class="listr">
+ <?= ($disk['fstype']) ? $disk['fstype']: gettext("unknown or unformatted"); ?>
+ </td>
+ <td valign="middle" class="listr">
+ <?php
+ $stat = disks_status($disk);
+ echo $stat;
+ ?>
+ </td>
+ <td valign="middle" class="list">
+ <a href="disks_manage_edit.php?id=<?=$i;?>">
+ <img src="./themes/<?= $g['theme']; ?>/images/icons/icon_e.gif" title="<?=gettext("edit disk");?>" width="17" height="17" border="0" alt="" />
+ </a>
+ <a href="disks_manage.php?act=del&id=<?=$i;?>">
+ <img src="./themes/<?= $g['theme']; ?>/images/icons/icon_x.gif" title="<?=gettext("delete disk");?>" width="17" height="17" border="0" alt="" />
+ </a>
+ </td>
+ </tr>
+ <?php $i++; endforeach; ?>
+ <tr>
+ <td class="list" colspan="6"></td>
+ <td class="list" nowrap>
+ <a href="disks_manage_edit.php">
+ <img src="./themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" title="<?=gettext("add disk");?>" width="17" height="17" border="0" alt="" />
+ </a>
+ </td>
+ </tr>
+ </table>
+ </div>
+ </td>
+ </tr>
+</table>
+</form>
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/freenas/www/disks_manage_edit.php b/config/freenas/www/disks_manage_edit.php
new file mode 100644
index 00000000..80e11ef3
--- /dev/null
+++ b/config/freenas/www/disks_manage_edit.php
@@ -0,0 +1,275 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ disks_manage_edit.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+$pgtitle = array(gettext("System"),
+ gettext("Disks"),
+ gettext("Management"),
+ gettext("Edit"));
+
+require_once("freenas_config.inc");
+require_once("guiconfig.inc");
+require_once("freenas_guiconfig.inc");
+require_once("freenas_functions.inc");
+
+$id = $_GET['id'];
+if (isset($_POST['id']))
+ $id = $_POST['id'];
+
+/* get disk list (without CDROM) */
+$disklist = get_physical_disks_list();
+
+if (!is_array($freenas_config['disks']['disk']))
+ $freenas_config['disks']['disk'] = array();
+
+disks_sort();
+
+$a_disk = &$freenas_config['disks']['disk'];
+
+if (isset($id) && $a_disk[$id])
+{
+ $pconfig['name'] = $a_disk[$id]['name'];
+ $pconfig['harddiskstandby'] = $a_disk[$id]['harddiskstandby'];
+ $pconfig['acoustic'] = $a_disk[$id]['acoustic'];
+ $pconfig['fstype'] = $a_disk[$id]['fstype'];
+ $pconfig['apm'] = $a_disk[$id]['apm'];
+ $pconfig['udma'] = $a_disk[$id]['udma'];
+ $pconfig['fullname'] = $a_disk[$id]['fullname'];
+}
+
+if (! empty($_POST))
+{
+ /* hash */
+ unset($error_bucket);
+ /* simple error list */
+ unset($input_errors);
+ $pconfig = $_POST;
+
+ /* input validation */
+ $reqdfields = split(" ", "name");
+ $reqdfieldsn = split(",", "Name");
+
+ do_input_validation_new($_POST, $reqdfields, $reqdfieldsn, &$error_bucket);
+ $pconfig = $_POST;
+
+ /* check for name conflicts */
+ foreach ($a_disk as $disk)
+ {
+ if (isset($id) && ($a_disk[$id]) && ($a_disk[$id] === $disk)) { continue; }
+
+ if ($disk['name'] == $_POST['name'])
+ {
+ $error_bucket[] = array("error" => gettext("This disk already exists in the disk list."),
+ "field" => "name");
+ break;
+ }
+ }
+
+ if (is_array($error_bucket))
+ foreach($error_bucket as $elem)
+ $input_errors[] =& $elem["error"];
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($error_bucket)) {
+ input_errors2Ajax(NULL, $error_bucket);
+ exit;
+ }
+
+ if (!$input_errors)
+ {
+ $disks = array();
+
+ $devname = $_POST['name'];
+ $devharddiskstandby = $_POST['harddiskstandby'];
+ $harddiskacoustic = $_POST['acoustic'];
+ $harddiskapm = $_POST['apm'];
+ $harddiskudma = $_POST['udma'];
+ $harddiskfstype = $_POST['fstype'];
+
+ $disks['name'] = $devname;
+ $disks['fullname'] = "/dev/$devname";
+ $disks['harddiskstandby'] = $devharddiskstandby ;
+ $disks['acoustic'] = $harddiskacoustic ;
+ if ($harddiskfstype) { $disks['fstype'] = $harddiskfstype; }
+ $disks['apm'] = $harddiskapm ;
+ $disks['udma'] = $harddiskudma ;
+ $disks['type'] = $disklist[$devname]['type'];
+ $disks['desc'] = $disklist[$devname]['desc'];
+ $disks['size'] = $disklist[$devname]['size'];
+
+ if (isset($id) && $a_disk[$id]) {
+ $a_disk[$id] = $disks;
+ } else {
+ $a_disk[] = $disks;
+ }
+
+ touch($d_diskdirty_path);
+
+ disks_set_ataidle();
+ write_config();
+
+ pfSenseHeader("disks_manage.php");
+ exit;
+ }
+}
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc"); ?>
+
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+ <div id="inputerrors"></div>
+ <form id="iform" name="iform" action="disks_manage_edit.php" method="post">
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?=gettext("Disk");?></td>
+ <td width="78%" class="vtable">
+ <select name="name" class="formselect" id="name">
+ <?php foreach ($disklist as $diski => $diskv): ?>
+ <option value="<?=$diski;?>" <?php if ($diski == $pconfig['name']) echo "selected=\"selected\"";?>>
+ <?php echo htmlspecialchars($diski . ": " .$diskv['size'] . " (" . $diskv['desc'] . ")");?>
+ </option>
+ <?php endforeach; ?>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("UDMA mode");?></td>
+ <td width="78%" class="vtable">
+ <select name="udma" class="formselect" id="udma">
+ <?php
+ $types = explode(",", "Auto,UDMA-33,UDMA-66,UDMA-100,UDMA-133");
+ $vals = explode(" ", "auto UDMA2 UDMA4 UDMA5 UDMA6");
+ $j = 0;
+
+ for ($j = 0; $j < count($vals); $j++):
+ ?>
+ <option value="<?=$vals[$j];?>" <?php if ($vals[$j] == $pconfig['udma']) echo "selected=\"selected\"";?>>
+ <?=htmlspecialchars($types[$j]);?>
+ </option>
+ <?php endfor; ?>
+ </select>
+ <br />
+ <?= gettext("You can force UDMA mode if you have \"UDMA_ERROR.... LBA\" message with your hard drive."); ?>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("Hard disk standby time");?></td>
+ <td width="78%" class="vtable">
+ <select name="harddiskstandby" class="formselect">
+ <?php
+ $sbvals = array(0=>"Always on",5=>"5 minutes",10=>"10 minutes",20=>"20 minutes",30=>"30 minutes",60=>"60 minutes");
+ ?>
+ <?php foreach ($sbvals as $sbval => $sbname): ?>
+ <option value="<?=$sbval;?>" <?php if($pconfig['harddiskstandby'] == $sbval) echo 'selected="selected"';?>><?=htmlspecialchars($sbname);?></option>
+ <?php endforeach; ?>
+ </select>
+ <br />
+ <?= gettext("Puts the hard disk into standby mode when the selected amount of time after the last
+ access has elapsed. <em>Do not set this for CF cards.</em>"); ?>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("Advanced Power Management");?></td>
+ <td width="78%" class="vtable">
+ <select name="apm" class="formselect">
+ <?php
+ $apmvals = array(0=>"Disabled",1=>"Minimum power usage with Standby",64=>"Medium power usage with Standby",128=>"Minimum power usage without Standby",192=>"Medium power usage without Standby",254=>"Maximum performance, maximum power usage");
+ ?>
+ <?php foreach ($apmvals as $apmval => $apmname): ?>
+ <option value="<?=$apmval;?>" <?php if($pconfig['apm'] == $apmval) echo 'selected="selected"';?>><?=htmlspecialchars($apmname);?></option>
+ <?php endforeach; ?>
+ </select>
+ <br />
+ <?= gettext("This allows you to lower the power consumption of the drive, at the expense of performance.<em>Do not set this for CF cards.</em>"); ?>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("acoustic level");?></td>
+ <td width="78%" class="vtable">
+ <select name="acoustic" class="formselect">
+ <?php
+ $acvals = array(0=>"Disabled",1=>"Minimum performance, Minimum acoustic output",64=>"Medium acoustic output",127=>"Maximum performance, maximum acoustic output");
+ ?>
+ <?php foreach ($acvals as $acval => $acname): ?>
+ <option value="<?=$acval;?>" <?php if($pconfig['acoustic'] == $acval) echo 'selected';?>><?=htmlspecialchars($acname);?></option>
+ <?php endforeach; ?>
+ </select>
+ <br />
+ <?= gettext("This allows you to set how loud the drive is while it\'s operating.<em>Do not set this for CF cards.</em>"); ?>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("preformated FS");?></td>
+ <td width="78%" class="vtable">
+ <select name="fstype" class="formselect">
+ <?php $fstlist = get_fstype_list(); ?>
+ <?php foreach ($fstlist as $fstval => $fstname): ?>
+ <option value="<?=$fstval;?>" <?php if($pconfig['fstype'] == $fstval) echo 'selected';?>><?=htmlspecialchars($fstname);?></option>
+ <?php endforeach; ?>
+ </select>
+ <br />
+ <?= gettext("This allows you to set FS type for preformated disk with data.<br />
+ <em>Leave \"unformated\" for unformated disk and then use Format menu.</em>"); ?>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <input id="submit" name="Submit" type="submit" class="formbtn" value="<?=gettext("Save");?>" />
+ <?php if (isset($id) && $a_disk[$id]): ?>
+ <input name="id" type="hidden" value="<?=$id;?>">
+ <?php endif; ?>
+ </td>
+ </tr>
+ </table>
+ </form>
+<?php include("fend.inc"); ?>
+<?= checkForInputErrors(); ?>
+</body>
+</html>
diff --git a/config/freenas/www/disks_manage_init.php b/config/freenas/www/disks_manage_init.php
new file mode 100644
index 00000000..e8d939d3
--- /dev/null
+++ b/config/freenas/www/disks_manage_init.php
@@ -0,0 +1,511 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ disks_manage_init.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+$pgtitle = array(gettext("System"),
+ gettext("Disks"),
+ gettext("Initialize"));
+
+require_once("freenas_config.inc");
+require_once("guiconfig.inc");
+require_once("freenas_guiconfig.inc");
+require_once("freenas_functions.inc");
+
+define("DISK_DETAILS_PARA", "
+ <p style='font-size: small;'>
+ <strong>Disk initialization details</strong> (use the toggle icon to unveil detailed infos):
+ </p>
+ ");
+
+function create_format_output($disk, $type, $notinitmbr) {
+ $ddetails = DISK_DETAILS_PARA;
+
+ ob_end_flush();
+
+ $retvalue =<<<EOD
+{$ddetails}
+
+EOD;
+
+ // Erase MBR if not checked
+ if (!$notinitmbr) {
+ $button = create_toggle_button("Erasing MBR and all paritions", "mbr_out");
+ $cmd = "dd if=/dev/zero of=" . escapeshellarg($disk) . " bs=32k count=640";
+ $out = create_cmdout_container("mbr_out", $cmd);
+ $retvalue .= assemble_cmdout($button, $out);
+ } else {
+ $diskinit_str = "Keeping the MBR and all partitions";
+ $retvalue .=<<<EOD
+ <div id="mbr_out" style="font-family: Courier, monospace; font-size: small;">
+ <pre style="font-family: Courier, monospace; font-size: small; font-style: italic;">{$diskinit_str}</pre>
+ </div>
+
+EOD;
+ } // end if
+
+ switch ($type) {
+ case "ufs":
+ $button = create_toggle_button("Creating one partition", "ufs_fdisk_out");
+ /* Initialize disk */
+ $cmd = "/sbin/fdisk -I -b /boot/mbr " . escapeshellarg($disk);
+ $out = create_cmdout_container("ufs_fdisk_out", $cmd);
+ $retvalue .= assemble_cmdout($button, $out);
+
+ $button = create_toggle_button("Initializing partition", "ufs_dd_out");
+ /* Initialise the partition (optional) */
+ $cmd = "/bin/dd if=/dev/zero of=" . escapeshellarg($disk) . "s1 bs=32k count=16";
+ $out = create_cmdout_container("ufs_dd_out", $cmd);
+ $retvalue .= assemble_cmdout($button, $out);
+
+ $button = create_toggle_button("Creating BSD label", "ufs_label_out");
+ /* Create s1 label */
+ $cmd = "/sbin/bsdlabel -w " . escapeshellarg($disk) . "s1 auto";
+ $out = create_cmdout_container("ufs_label_out", $cmd);
+ $retvalue .= assemble_cmdout($button, $out);
+
+ $button = create_toggle_button("Creating Filesystem", "ufs_newfs_out");
+ /* Create filesystem */
+ $cmd = "/sbin/newfs -U " . escapeshellarg($disk) . "s1";
+ $out = create_cmdout_container("ufs_newfs_out", $cmd);
+ $retvalue .= assemble_cmdout($button, $out);
+
+ break; // end case "ufs":
+ case "ufs_no_su":
+ $button = create_toggle_button("Creating one partition", "ufsn_fdisk_out");
+ /* Initialize disk */
+ $cmd = "/sbin/fdisk -I -b /boot/mbr " . escapeshellarg($disk);
+ $out = create_cmdout_container("ufsn_fdisk_out", $cmd);
+ $retvalue .= assemble_cmdout($button, $out);
+
+ $button = create_toggle_button("Initializing partition", "ufsn_dd_out");
+ /* Initialise the partition (optional) */
+ $cmd = "/bin/dd if=/dev/zero of=" . escapeshellarg($disk) . "s1 bs=32k count=16";
+ $out = create_cmdout_container("ufsn_dd_out", $cmd);
+ $retvalue .= assemble_cmdout($button, $out);
+
+ $button = create_toggle_button("Creating BSD label", "ufsn_label_out");
+ /* Create s1 label */
+ $cmd = "/sbin/bsdlabel -w " . escapeshellarg($disk) . "s1 auto";
+ $out = create_cmdout_container("ufsn_label_out", $cmd);
+ $retvalue .= assemble_cmdout($button, $out);
+
+ $button = create_toggle_button("Creating Filesystem", "ufsn_newfs_out");
+ /* Create filesystem */
+ $cmd = "/sbin/newfs -m 0 " . escapeshellarg($disk) . "s1";
+ $out = create_cmdout_container("ufsn_newfs_out", $cmd);
+ $retvalue .= assemble_cmdout($button, $out);
+
+ break; // end ufs_no_su
+ case "ufsgpt":
+ $button = create_toggle_button("Destroying old GTP information", "ufsg_gptd_out");
+ /* Destroy GPT partition table */
+ $cmd = "/sbin/gpt destroy " . escapeshellarg($disk);
+ $out = create_cmdout_container("ufsg_gptd_out", $cmd);
+ $retvalue .= assemble_cmdout($button, $out);
+
+ $button = create_toggle_button("Creating GPT partition", "ufsg_gptc_out");
+ /* Create GPT partition table */
+ $cmd = array("/sbin/gpt create -f " . escapeshellarg($disk),
+ "/sbin/gpt add -t ufs " . escapeshellarg($disk));
+ $out = create_cmdout_container("ufsg_gptc_out", $cmd);
+ $retvalue .= assemble_cmdout($button, $out);
+
+ $button = create_toggle_button("Creating Filesystem with Soft Updates", "ufsg_newfs_out");
+ /* Create filesystem */
+ $cmd = "/sbin/newfs -U " . escapeshellarg($disk) . "p1";
+ $out = create_cmdout_container("ufsg_newfs_out", $cmd);
+ $retvalue .= assemble_cmdout($button, $out);
+
+ break; // end case "ufsgpt":
+ case "ufsgpt_no_su":
+ $button = create_toggle_button("Destroying old GTP information", "ufsgn_gpt_out");
+ /* Destroy GPT partition table */
+ $cmd = "/sbin/gpt destroy " . escapeshellarg($disk);
+ $out = create_cmdout_container("ufsgn_gpt_out", $cmd);
+ $retvalue .= assemble_cmdout($button, $out);
+
+ $button = create_toggle_button("Creating GPT partition", "ufsgn_gptc_out");
+ /* Create GPT partition table */
+ $cmd = array("/sbin/gpt create -f " . escapeshellarg($disk),
+ "/sbin/gpt add -t ufs " . escapeshellarg($disk));
+ $out = create_cmdout_container("ufsgn_gptc_out", $cmd);
+ $retvalue .= assemble_cmdout($button, $out);
+
+ $button = create_toggle_button("Creating Filesystem without Soft Updates", "ufsgn_newfs_out");
+ /* Create filesystem */
+ $cmd = "/sbin/newfs -m 0 " . escapeshellarg($disk) . "p1";
+ $out = create_cmdout_container("ufsgn_newfs_out", $cmd);
+ $retvalue .= assemble_cmdout($button, $out);
+
+ break; // end case "ufsgpt_no_su":
+ case "softraid":
+ $button = create_toggle_button("Initializing disk", "softr_fdisk_out");
+ /* Initialize disk */
+ $cmd = "/sbin/fdisk -I -b /boot/mbr " . escapeshellarg($disk);
+ $out = create_cmdout_container("softr_fdisk_out", $cmd);
+ $retvalue .= assemble_cmdout($button, $out);
+
+ $button = create_toggle_button("Initializing partition", "softr_dd_out");
+ /* Initialise the partition (optional) */
+ $cmd = "/bin/dd if=/dev/zero of=" . escapeshellarg($disk) . "s1 bs=32k count=16";
+ $out = create_cmdout_container("softr_dd_out", $cmd);
+ $retvalue .= assemble_cmdout($button, $out);
+
+ $button = create_toggle_button("Delete old gmirror information", "softr_dd_out");
+ /* Delete old gmirror information */
+ $cmd = "/sbin/gmirror clear " . escapeshellarg($disk);
+ $out = create_cmdout_container("softr_dd_out", $cmd);
+ $retvalue .= assemble_cmdout($button, $out);
+
+ break; // end case "softraid":
+ case "msdos":
+ $button = create_toggle_button("Initialize disk", "dos_fdisk_out");
+ /* Initialize disk */
+ $cmd = "/sbin/fdisk -I -b /boot/mbr " . escapeshellarg($disk);
+ $out = create_cmdout_container("dos_fdisk_out", $cmd);
+ $retvalue .= assemble_cmdout($button, $out);
+
+ $button = create_toggle_button("Initialize partion", "dos_dd_out");
+ /* Initialise the partition (optional) */
+ $cmd = "/bin/dd if=/dev/zero of=" . escapeshellarg($disk) . "s1 bs=32k count=16";
+ $out = create_cmdout_container("dos_dd_out", $cmd);
+ $retvalue .= assemble_cmdout($button, $out);
+
+ $button = create_toggle_button("Creating BSD label", "dos_label_out");
+ /* Initialise the partition (optional) */
+ $cmd = "/sbin/bsdlabel -w " . escapeshellarg($disk) . "s1 auto";
+ $out = create_cmdout_container("dos_label_out", $cmd);
+ $retvalue .= assemble_cmdout($button, $out);
+
+ $button = create_toggle_button("Creating Filesystem", "dos_newfs_out");
+ /* Initialise the partition (optional) */
+ $a_out = "/sbin/newfs_msdos -F 32 " . escapeshellarg($disk) . "s1";
+ $out = create_cmdout_container("dos_newfs_out", $cmd);
+ $retvalue .= assemble_cmdout($button, $out, true);
+
+ break; // end case "msdos":
+ } // end switch
+
+ return $retvalue;
+}
+
+if (!is_array($freenas_config['disks']['disk']))
+ $freenas_config['disks']['disk'] = array();
+
+disks_sort();
+
+if (!is_array($freenas_config['gconcat']['vdisk']))
+ $freenas_config['gconcat']['vdisk'] = array();
+
+gconcat_sort();
+
+if (!is_array($freenas_config['gmirror']['vdisk']))
+ $freenas_config['gmirror']['vdisk'] = array();
+
+gmirror_sort();
+
+if (!is_array($freenas_config['graid5']['vdisk']))
+ $freenas_config['graid5']['vdisk'] = array();
+
+graid5_sort();
+
+if (!is_array($freenas_config['gstripe']['vdisk']))
+ $freenas_config['gstripe']['vdisk'] = array();
+
+gstripe_sort();
+
+if (!is_array($freenas_config['gvinum']['vdisk']))
+ $freenas_config['gvinum']['vdisk'] = array();
+
+gvinum_sort();
+
+// Get all fstype supported by FreeNAS
+$a_fst = get_fstype_list();
+// Remove NTFS: can't format on NTFS under FreeNAS
+unset($a_fst['ntfs']);
+// Remove the first blank line 'unknown'
+$a_fst = array_slice($a_fst, 1);
+
+$a_disk = &$freenas_config['disks']['disk'];
+$a_gconcat = &$freenas_config['gconcat']['vdisk'];
+$a_gmirror = &$freenas_config['gmirror']['vdisk'];
+$a_gstripe = &$freenas_config['gstripe']['vdisk'];
+$a_graid5 = &$freenas_config['graid5']['vdisk'];
+$a_gvinum = &$freenas_config['gvinum']['vdisk'];
+ $a_alldisk = array_merge($a_disk,
+ $a_gconcat,
+ $a_gmirror,
+ $a_gstripe,
+ $a_graid5,
+ $a_gvinum);
+
+if (! empty($_POST))
+{
+ /* hash */
+ unset($error_bucket);
+ /* simple error list */
+ unset($input_errors);
+ unset($do_format);
+ $pconfig = $_POST;
+
+ /* input validation */
+ $reqdfields = explode(" ", "disk type");
+ $reqdfieldsn = explode(",", "Disk,Type");
+
+ do_input_validation_new($_POST, $reqdfields, $reqdfieldsn, &$error_bucket);
+
+ if (is_array($error_bucket))
+ foreach($error_bucket as $elem)
+ $input_errors[] =& $elem["error"];
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($error_bucket)) {
+ input_errors2Ajax(NULL, $error_bucket);
+ exit;
+ }
+
+ if (!$input_errors)
+ {
+ $do_format = true;
+ $disk = $_POST['disk'];
+ $type = $_POST['type'];
+ $notinitmbr= $_POST['notinitmbr'];
+
+ /* Check if disk is mounted. */
+ if(isAjax() && disks_check_mount_fullname($disk)) {
+ $statustxt = sprintf(gettext("The disk is currently mounted! <a href=%s>Unmount</a> this disk first before proceeding."), "disks_mount_tools.php?disk={$disk}&amp;action=umount");
+
+ $divcontents = "<div style='background:#990000'><table>";
+ $divcontents .= "<tr><td>";
+ $divcontents .= "<img src='/themes/{$g['theme']}/images/icons/icon_error.gif' width='28' height='32'>";
+ $divcontents .= "</td><td><font color='white'><br>&nbsp;&nbsp;The following errors have occured:<p><ul>";
+ $divcontents .= "<font color='white'><li> " . $statustxt . "</li>";
+ $divcontents .= "</ul></td></table></div><br />";
+
+ header("HTTP/1.0 500 Internal Server Error");
+ header("Status: 500 Internal Server Error. {$statustxt}");
+ echo $divcontents;
+ exit;
+ } else if (disks_check_mount_fullname($disk)) {
+ $errormsg = sprintf(gettext("The disk is currently mounted! <a href=%s>Unmount</a> this disk first before proceeding."), "disks_mount_tools.php?disk={$disk}&action=umount");
+ $do_format = false;
+ }
+
+ if($do_format) {
+ /* Get the id of the disk array entry. */
+ $NotFound = 1;
+ $id = array_search_ex($disk, $a_disk, "fullname");
+
+ if ($id) {
+ /* Set new filesystem type. */
+ $a_disk[$id]['fstype'] = $type;
+ $NotFound = 0;
+ }
+ else {
+ $id = array_search_ex($disk, $a_gmirror, "fullname");
+ }
+ if (($id !== false) && $NotFound) {
+ /* Set new filesystem type. */
+ $a_gmirror[$id]['fstype'] = $type;
+ $NotFound = 0;
+ }
+ else {
+ $id = array_search_ex($disk, $a_gstripe, "fullname");
+ }
+ if (($id !== false) && $NotFound) {
+ /* Set new filesystem type. */
+ $a_gstripe[$id]['fstype'] = $type;
+ $NotFound = 0;
+ }
+ else {
+ $id = array_search_ex($disk, $a_gconcat, "fullname");
+ }
+ if (($id !== false) && $NotFound) {
+ /* Set new filesystem type. */
+ $a_gconcat[$id]['fstype'] = $type;
+ $NotFound = 0;
+ }
+ else {
+ $id = array_search_ex($disk, $a_graid5, "fullname");
+ }
+ if (($id !== false) && $NotFound) {
+ /* Set new filesystem type. */
+ $a_graid5[$id]['fstype'] = $type;
+ $NotFound = 0;
+ }
+ else {
+ $id = array_search_ex($disk, $a_gvinum, "fullname");
+ }
+ if (($id !== false) && $NotFound) {
+ /* Set new filesystem type. */
+ $a_gvinum[$id]['fstype'] = $type;
+ $NotFound = 0;
+ }
+
+ write_config();
+
+ echo create_format_output($disk, $type, $notinitmbr);
+ exit; // cause of Ajax
+ }
+ }
+}
+
+if (!isset($do_format))
+{
+ $do_format = false;
+ $disk = '';
+ $type = '';
+}
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+$pfSenseHead->setCloseHead(false);
+echo $pfSenseHead->getHTML();
+
+?>
+<script type="text/javascript">
+<!--
+function disk_change() {
+ switch(document.iform.disk.value)
+ {
+ <?php foreach ($a_alldisk as $diskv): ?>
+ case "<?=$diskv['fullname'];?>":
+ <?php $i = 0;?>
+ <?php foreach ($a_fst as $fstval => $fstname): ?>
+ document.iform.type.options[<?=$i++;?>].selected = <?php if($diskv['fstype'] == $fstval){echo "true";}else{echo "false";};?>;
+ <?php endforeach; ?>
+ break;
+ <?php endforeach; ?>
+ }
+}
+
+<?= CMDOUT_TOGGLE_FUNC ?>
+// -->
+</script>
+</head>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc"); ?>
+
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+<?php if($errormsg) print_error_box($errormsg);?>
+<div id="inputerrors"></div>
+<table width="100%" border="0" cellspacing="0" cellpadding="0">
+ <tr>
+ <td>
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Manage"), false, "disks_manage.php");
+ $tab_array[1] = array(gettext("Format"), true, "disks_manage_init.php");
+ $tab_array[2] = array(gettext("Tools"), false, "disks_manage_tools.php");
+ $tab_array[3] = array(gettext("iSCSI Initiator"), false, "disks_manage_iscsi.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <form id="iform" name="iform" action="disks_manage_init.php" method="post">
+ <?= CMDOUT_AJAX_SCRIPT ?>
+ <table class="tabcont" align="center" width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?=gettext("Disk");?></td>
+ <td width="78%" class="vtable">
+ <select name="disk" class="formselect" id="disk" onchange="disk_change();">
+ <?php foreach ($a_alldisk as $diskv): ?>
+ <option value="<?=$diskv['fullname'];?>" <?php if ($diskv['name'] == $disk) echo "selected=\selected\"";?>>
+ <?php echo htmlspecialchars($diskv['name'] . ": " .$diskv['size'] . " (" . $diskv['desc'] . ")");?>
+ <?php endforeach; ?>
+ </option>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?=gettext("File system");?></td>
+ <td width="78%" class="vtable">
+ <select name="type" class="formselect" id="type">
+ <?php foreach ($a_fst as $fstval => $fstname): ?>
+ <option value="<?=$fstval;?>" <?php if($type == $fstval) echo 'selected="selected"';?>><?=htmlspecialchars($fstname);?></option>
+ <?php endforeach; ?>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?=gettext("Don't Erase MBR");?></td>
+ <td width="78%" class="vtable">
+ <input name="notinitmbr" id="notinitmbr" type="checkbox" value="yes" /><br />
+ <?= gettext("don't erase the MBR (useful for some RAID controller cards)"); ?>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <input id="doCMDSubmit" name="doCMDSubmit" type="button" class="formbtn" value="<?=gettext("Format disk!");?>" onclick="execCMD();" />
+ </td>
+ </tr>
+ <tr>
+ <!-- Format Output Container - Do Not Delete -->
+ <td id="cmdOutputTD" valign="top" colspan="2" style="visibility: hidden; border: solid 1px silver; vertical-align: middle; width: 100%"></td>
+ </tr>
+ <tr>
+ <td align="left" valign="top" colspan="2">
+ <span class="red">
+ <strong>WARNING:</strong>
+ </span>
+ <br />
+ <span class="vexpl">
+ <?= gettext("This step will erase all your partition, create partition number 1 and format the hard drive with the file system specified."); ?>
+ </span>
+ </td>
+ </tr>
+ </table>
+ </form>
+ </div>
+ </td>
+ </tr>
+</table>
+<?php include("fend.inc"); ?>
+<?= checkForInputErrors(); ?>
+</body>
+</html>
diff --git a/config/freenas/www/disks_manage_iscsi.php b/config/freenas/www/disks_manage_iscsi.php
new file mode 100644
index 00000000..5180fc1a
--- /dev/null
+++ b/config/freenas/www/disks_manage_iscsi.php
@@ -0,0 +1,209 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ disks_manage_iscsi.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+$pgtitle = array(gettext("System"),
+ gettext("Disks"),
+ gettext("iSCSI Initiator"));
+
+require_once("freenas_config.inc");
+require_once("guiconfig.inc");
+require_once("freenas_guiconfig.inc");
+require_once("freenas_functions.inc");
+
+if (! is_array($freenas_config['iscsi']))
+{
+ $freenas_config['iscsi'] = array();
+}
+
+$pconfig['enable'] = isset($freenas_config['iscsi']['enable']);
+$pconfig['targetaddress'] = $freenas_config['iscsi']['targetaddress'];
+$pconfig['targetname'] = $freenas_config['iscsi']['targetname'];
+
+if (! empty($_POST))
+{
+ /* hash */
+ unset($error_bucket);
+ /* simple error list */
+ unset($input_errors);
+
+ $pconfig = $_POST;
+
+ /* input validation */
+ if ($_POST['enable'])
+ {
+ $reqdfields = array_merge($reqdfields, explode(" ", "targetaddress targetname"));
+ $reqdfieldsn = array_merge($reqdfieldsn, explode(",", "targetaddress,targetname"));
+ }
+
+ do_input_validation($_POST, $reqdfields, $reqdfieldsn, &$input_errors);
+
+ if ($_POST['enable'] && !is_ipaddr($_POST['targetaddress'])){
+ $error_bucket[] = array("error" => gettext("A valid IP address must be specified."),
+ "field" => "targetaddress");
+ }
+
+ if (is_array($error_bucket))
+ foreach($error_bucket as $elem)
+ $input_errors[] =& $elem["error"];
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($error_bucket)) {
+ input_errors2Ajax(NULL, $error_bucket);
+ exit;
+ }
+
+ if (!$input_errors)
+ {
+ $freenas_config['iscsi']['enable'] = $_POST['enable'] ? true : false;
+ $freenas_config['iscsi']['targetaddress'] = $_POST['targetaddress'];
+ $freenas_config['iscsi']['targetname'] = $_POST['targetname'];
+
+ write_config();
+
+ $retval = 0;
+ if (! file_exists($d_sysrebootreqd_path))
+ {
+ /* nuke the cache file */
+ config_lock();
+ services_iscsi_configure();
+ config_unlock();
+ }
+ $savemsg = get_std_save_message($retval);
+ }
+}
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+
+$jscriptstr = <<<EOD
+<script type="text/javascript">
+<!--
+function enable_change(enable_change) {
+ var endis;
+
+ endis = !(document.iform.enable.checked || enable_change);
+ endis ? color = '#D4D0C8' : color = '#FFFFFF';
+
+ document.iform.targetname.disabled = endis;
+ document.iform.targetaddress.disabled = endis;
+ /* adjust colors */
+ document.iform.targetname.style.backgroundColor = color;
+ document.iform.targetaddress.style.backgroundColor = color;
+}
+//-->
+</script>
+
+EOD;
+
+$pfSenseHead->addScript($jscriptstr);
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc"); ?>
+
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+<div id="inputerrors"></div>
+<table width="100%" border="0" cellspacing="0" cellpadding="0">
+ <tr>
+ <td>
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Manage"), false, "disks_manage.php");
+ $tab_array[1] = array(gettext("Format"), false, "disks_manage_init.php");
+ $tab_array[2] = array(gettext("Tools"), false, "disks_manage_tools.php");
+ $tab_array[3] = array(gettext("iSCSI Initiator"), true, "disks_manage_iscsi.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <form id="iform" name="iform" action="disks_manage_iscsi.php" method="post">
+ <table class="tabcont" align="center" width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="100%" valign="middle" class="listtopic" colspan="2">
+ <span style="vertical-align: middle; position: relative; left: 0px;"><?=gettext("iSCSI Initiator");?></span>
+ <span style="vertical-align: middle; position: relative; left: 81%;">
+ <input name="enable" type="checkbox" value="yes" <?php if ($pconfig['enable']) echo "checked=\"checked\""; ?> onClick="enable_change(false)" />&nbsp;<?= gettext("Enable"); ?>
+ </span>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?= gettext("Target IP address"); ?></td>
+ <td width="78%" class="vtable">
+ <input name="targetaddress" type="text" class="formfld unknown" id="targetaddress" size="20" value="<?=htmlspecialchars($pconfig['targetaddress']);?>" />
+ <br /><?= gettext("Target IP address"); ?>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?= gettext("targetname"); ?></td>
+ <td width="78%" class="vtable">
+ <input name="targetname" type="text" class="formfld unknown" id="targetname" size="20" value="<?=htmlspecialchars($pconfig['targetname']);?>" />
+ <br /><?= gettext("targetname"); ?>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <input id="submit" name="Submit" type="submit" class="formbtn" value="<?=gettext("Save");?>" />
+ </td>
+ </tr>
+ </table>
+ </form>
+ </div>
+ </td>
+ </tr>
+</table>
+<?php include("fend.inc"); ?>
+<?= checkForInputErrors(); ?>
+<script type="text/javascript">
+<!--
+enable_change(false);
+//-->
+</script>
+</body>
+</html>
diff --git a/config/freenas/www/disks_manage_tools.php b/config/freenas/www/disks_manage_tools.php
new file mode 100644
index 00000000..d851f65c
--- /dev/null
+++ b/config/freenas/www/disks_manage_tools.php
@@ -0,0 +1,331 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ disks_manage_tools.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+$pgtitle = array(gettext("System"),
+ gettext("Disks"),
+ gettext("Tools"));
+
+require_once("freenas_config.inc");
+require_once("guiconfig.inc");
+require_once("freenas_guiconfig.inc");
+require_once("freenas_functions.inc");
+
+function create_cmd_output(&$action, &$a_disk, &$disk, &$partition, &$umount) {
+ $cmdout = CMDOUT_PARA;
+
+ ob_end_flush();
+
+ $retvalue =<<<EOD
+{$cmdout}
+
+EOD;
+
+ switch($action)
+ {
+ case "fsck":
+ /* Get the id of the disk. */
+ $id = array_search_ex($disk, $a_disk, "name");
+ /* Get the filesystem type of the disk. */
+ $type = $a_disk[$id]['fstype'];
+ /* Check if disk is mounted. */
+ $ismounted = disks_check_mount_fullname($disk.$partition);
+
+ /* Umount disk if necessary. */
+ if($umount && $ismounted) {
+ $diskinit_str = "<strong class='red'>" . gettext("Note") . ":</strong> " . gettext("The disk is currently mounted! The mount point will be removed temporary to perform selected command.") . "<br /><br />";
+ $retvalue .=<<<EOD
+ <div id="ismounted_out" style="font-family: Courier, monospace; font-size: small;">
+ <pre style="font-family: Courier, monospace; font-size: small; font-style: italic;">{$diskinit_str}</pre>
+ </div>
+
+EOD;
+
+ disks_umount_fullname($disk.$partition);
+ }
+
+ switch($type)
+ {
+ case "":
+ case "ufs":
+ case "ufs_no_su":
+ case "ufsgpt":
+ case "ufsgpt_no_su":
+ $button = create_toggle_button("Checking disk", "ufsgn_fsck_out");
+ $cmd = "/sbin/fsck_ufs -y -f " . escapeshellarg($disk . $partition);
+ $out = create_cmdout_container("ufsgn_fsck_out", $cmd);
+ $retvalue .= assemble_cmdout($button, $out);
+ break;
+ case "gmirror":
+ case "gvinum":
+ case "graid5":
+ $diskinit_str = sprintf(gettext("Use <a href='%s'>RAID tools</a> for this disk!"), "disks_raid_{$type}_tools.php");
+ $retvalue .=<<<EOD
+ <div id="graid5_out" style="display: none; font-family: Courier, monospace; font-size: small;">
+ <pre style="font-family: Courier, monospace; font-size: small; font-style: italic;">{$diskinit_str}</pre>
+ </div>
+
+EOD;
+ break;
+ case "msdos":
+ $button = create_toggle_button("Checking disk", "dos_fsck_out");
+ $cmd = "/sbin/fsck_msdosfs -y -f " . escapeshellarg($disk . $partition);
+ $out = create_cmdout_container("dos_fsck_out", $cmd);
+ $retvalue .= assemble_cmdout($button, $out);
+ break;
+ }
+
+ /* Mount disk if necessary. */
+ if($umount && $ismounted) {
+ disks_mount_fullname($disk.$partition);
+ }
+
+ break;
+ }
+
+ return $retvalue;
+}
+
+if (!is_array($freenas_config['disks']['disk']))
+ $freenas_config['disks']['disk'] = array();
+
+disks_sort();
+
+if (!is_array($freenas_config['gvinum']['vdisk']))
+ $freenas_config['gvinum']['vdisk'] = array();
+
+gvinum_sort();
+
+if (!is_array($freenas_config['gmirror']['vdisk']))
+ $freenas_config['gmirror']['vdisk'] = array();
+
+gmirror_sort();
+
+if (!is_array($freenas_config['gconcat']['vdisk']))
+ $freenas_config['gconcat']['vdisk'] = array();
+
+gconcat_sort();
+
+if (!is_array($freenas_config['gstripe']['vdisk']))
+ $freenas_config['gstripe']['vdisk'] = array();
+
+gstripe_sort();
+
+if (!is_array($freenas_config['graid5']['vdisk']))
+ $freenas_config['graid5']['vdisk'] = array();
+
+graid5_sort();
+
+$a_disk = array_merge($freenas_config['disks']['disk'],
+ $freenas_config['gvinum']['vdisk'],
+ $freenas_config['gmirror']['vdisk'],
+ $freenas_config['gconcat']['vdisk'],
+ $freenas_config['gstripe']['vdisk'],
+ $freenas_config['graid5']['vdisk']);
+
+if ($_POST) {
+ unset($input_errors);
+ unset($do_action);
+
+ /* input validation */
+ $reqdfields = explode(" ", "disk action");
+ $reqdfieldsn = explode(",", "Disk,Action");
+ do_input_validation($_POST, $reqdfields, $reqdfieldsn, &$input_errors);
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($error_bucket)) {
+ input_errors2Ajax(NULL, $error_bucket);
+ exit;
+ }
+
+ if (!$input_errors)
+ {
+ $do_action = true;
+ $disk = $_POST['disk'];
+ $action = $_POST['action'];
+ $partition = $_POST['partitionno'];
+ $umount = $_POST['umount'];
+
+ echo create_cmd_output($action, $a_disk, $disk, $partition, $umount);
+ exit; // cause of Ajax
+ }
+}
+
+if (!isset($do_action))
+{
+ $do_action = false;
+ $disk = '';
+ $action = '';
+ $partition = '';
+ $umount = false;
+}
+
+/* if ajax is calling, give them an update message */
+if(isAjax())
+ print_info_box_np($savemsg);
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+$pfSenseHead->setCloseHead(false);
+echo $pfSenseHead->getHTML();
+
+?>
+<script type="text/javascript">
+<!--
+function disk_change() {
+ var next = null;
+ // Remove all entries from partition combobox.
+ document.iform.partitionno.length = 0;
+ // Insert entries for partition combobox.
+ alert(document.iform.disk.value);
+ switch(document.iform.disk.value)
+ {
+ <?php foreach ($a_disk as $diskv): ?>
+ <?php if (strcmp($diskv['fstype'],"softraid")==0): ?>
+ <?php continue; ?>
+ <?php endif; ?>
+ case "/dev/<?=$diskv['name'];?>":
+ <?php $partinfo = disks_get_partition_info($diskv['name']);?>
+ <?php foreach($partinfo as $partinfon => $partinfov): ?>
+ if(document.all) // MS IE workaround.
+ next = document.iform.partitionno.length;
+ alert(document.iform.partitionno);
+ document.iform.partitionno.add(new Option("<?=$partinfon;?>","s<?=$partinfon;?>",false,<?php if("s{$partinfon}"==$partition){echo "true";}else{echo "false";};?>), next);
+ <?php endforeach; ?>
+ break;
+ <?php endforeach; ?>
+ }
+}
+
+<?= CMDOUT_TOGGLE_FUNC ?>
+// -->
+</script>
+</head>
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc"); ?>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+
+<form action="disks_manage_tools.php" method="post" name="iform" id="iform">
+<div id="inputerrors"></div>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr><td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Manage"), false, "disks_manage.php");
+ $tab_array[1] = array(gettext("Format"), false, "disks_manage_init.php");
+ $tab_array[2] = array(gettext("Tools"), true, "disks_manage_tools.php");
+ $tab_array[3] = array(gettext("iSCSI Initiator"), false, "disks_manage_iscsi.php");
+ display_top_tabs($tab_array);
+?>
+ </td></tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <?= CMDOUT_AJAX_SCRIPT ?>
+ <table class="tabcont" width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?=gettext("Disk");?></td>
+ <td width="78%" class="vtable">
+ <select name="disk" class="formselect" id="disk" onchange="disk_change();">
+ <?php foreach ($a_disk as $diskn): ?>
+ <?php if (strcmp($diskn['fstype'],"softraid")==0): ?>
+ <?php continue; ?>
+ <?php endif; ?>
+ <option value="<?=$diskn['fullname'];?>"<?php if ($diskn['fullname'] == $disk) echo "selected=\"selected\"";?>>
+ <?php echo htmlspecialchars($diskn['name'] . ": " .$diskn['size'] . " (" . $diskn['desc'] . ")");?>
+ <?php endforeach; ?>
+ </option>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?=gettext("Partition");?></td>
+ <td width="78%" class="vtable">
+ <select name="partitionno" class="formselect" id="partitionno"></select>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?=gettext("Command");?></td>
+ <td width="78%" class="vtable">
+ <select name="action" class="formselect" id="action">
+ <option value="fsck" <?php if ($action == "fsck") echo "selected"; ?>>fsck</option>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"></td>
+ <td width="78%" class="vtable">
+ <input name="umount" type="checkbox" id="umount" value="yes" <?php if ($umount) echo "checked"; ?> />
+ <strong>
+ <?= gettext("Unmount disk/partition"); ?>
+ </strong>
+ <span class="vexpl">
+ <br />
+ <?= gettext("If the selected disk/partition is mounted it will be unmounted temporary to perform selected command, otherwise the commands work in read-only mode."); ?>
+ </span>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <input id="doCMDSubmit" name="doCMDSubmit" type="button" class="formbtn" value="<?=gettext("Send Command!");?>" onclick="execCMD();" />
+ </td>
+ </tr>
+ <tr>
+ <!-- Format Output Container - Do Not Delete -->
+ <td id="cmdOutputTD" valign="top" colspan="2" style="visibility: hidden; border: solid 1px silver; vertical-align: middle; width: 100%"></td>
+ </tr>
+ </table>
+ </div>
+ </td>
+ </tr>
+</table>
+</form>
+<script type="text/javascript">
+<!--
+ disk_change();
+//-->
+</script>
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/freenas/www/disks_mount.php b/config/freenas/www/disks_mount.php
new file mode 100644
index 00000000..c72b0d82
--- /dev/null
+++ b/config/freenas/www/disks_mount.php
@@ -0,0 +1,235 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ disks_mount.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+$pgtitle = array(gettext("System"),
+ gettext("Disks"),
+ gettext("Mount Point"));
+
+require_once("freenas_config.inc");
+require_once("guiconfig.inc");
+require_once("freenas_guiconfig.inc");
+require_once("freenas_functions.inc");
+
+if (!is_array($freenas_config['mounts']['mount']))
+ $freenas_config['mounts']['mount'] = array();
+
+mount_sort();
+
+$a_mount = &$freenas_config['mounts']['mount'];
+
+if (! empty($_POST))
+{
+ /* hash */
+ unset($error_bucket);
+ /* simple error list */
+ unset($input_errors);
+
+ if (is_array($error_bucket))
+ foreach($error_bucket as $elem)
+ $input_errors[] =& $elem["error"];
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($error_bucket)) {
+ input_errors2Ajax(NULL, $error_bucket);
+ exit;
+ }
+
+ if ($_POST['apply']) {
+ $retval = 0;
+
+ if (!file_exists($d_sysrebootreqd_path)) {
+ config_lock();
+ /* reload all components that mount disk */
+ disks_mount_all();
+ /* reload all components that use mount */
+ services_samba_configure();
+ services_nfs_configure();
+ services_rsyncd_configure();
+ services_afpd_configure();
+ config_unlock();
+ }
+ $savemsg = get_std_save_message($retval);
+ if ($retval == 0) {
+ if (file_exists($d_mountdirty_path))
+ unlink($d_mountdirty_path);
+ }
+ }
+}
+
+if ($_GET['act'] == "del")
+{
+ if ($a_mount[$_GET['id']]) {
+ disks_umount_adv($a_mount[$_GET['id']]);
+ unset($a_mount[$_GET['id']]);
+ write_config();
+ touch($d_mountdirty_path);
+ pfSenseHeader("disks_mount.php");
+ exit;
+ }
+}
+
+if ($_GET['act'] == "ret")
+{
+ if ($a_mount[$_GET['id']]) {
+ disks_mount($a_mount[$_GET['id']]);
+ pfSenseHeader("disks_mount.php");
+ exit;
+ }
+}
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc"); ?>
+
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+
+<form id="iform" name="iform" action="disks_mount.php" method="post">
+<?php if (file_exists($d_mountdirty_path)): ?>
+<?php print_info_box_np(gettext("The mount point list has been changed.") . "<br />" .
+ gettext("You must apply the changes in order for them to take effect."));?>
+<?php endif; ?>
+
+<div id="inputerrors"></div>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr><td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Manage"), true, "disks_mount.php");
+ $tab_array[1] = array(gettext("Tools"), false, "disks_mount_tools.php");
+ display_top_tabs($tab_array);
+?>
+ </td></tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <table class="tabcont" width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="listhdrr"><?=gettext("Disk");?></td>
+ <td class="listhdrr"><?=gettext("Partition");?></td>
+ <td class="listhdrr"><?=gettext("File system");?></td>
+ <td class="listhdrr"><?=gettext("Share name");?></td>
+ <td class="listhdrr"><?=gettext("Description");?></td>
+ <td class="listhdrr"><?=gettext("Status");?></td>
+ <td class="list">&nbsp;</td>
+ </tr>
+ <?php $i = 0; foreach ($a_mount as $mount): ?>
+ <tr>
+ <td valign="middle" class="listlr">
+ <?=htmlspecialchars($mount['mdisk']);?> &nbsp;
+ </td>
+ <td valign="middle" class="listr">
+ <?=htmlspecialchars($mount['partition']);?>&nbsp;
+ </td>
+ <td valign="middle" class="listr">
+ <?=htmlspecialchars($mount['fstype']);?>&nbsp;
+ </td>
+ <td valign="middle" class="listr">
+ <?=htmlspecialchars($mount['sharename']);?>&nbsp;
+ </td>
+ <td valign="middle" class="listr">
+ <?=htmlspecialchars($mount['desc']);?>&nbsp;
+ </td>
+ <td valign="middle" class="listbg" style="color: #FFFFFF;">
+ <?php
+ if (file_exists($d_mountdirty_path)) {
+ $stat = gettext("configuring");
+ } else {
+ $stat = disks_check_mount($mount);
+ if ($stat == false) {
+ $stat = "ERROR - <a href=\"disks_mount.php?act=ret&amp;id=$i\">retry</a>";
+ } else {
+ $stat = gettext("OK");
+ }
+ }
+ echo $stat;
+ ?>
+ </td>
+ <td valign="middle" class="list">
+ <a href="disks_mount_edit.php?id=<?=$i;?>">
+ <img src="./themes/<?= $g['theme']; ?>/images/icons/icon_e.gif" title="<?=gettext("edit mount");?>" width="17" height="17" border="0" alt="" />
+ </a>
+ <a href="disks_mount.php?act=del&id=<?=$i;?>">
+ <img src="./themes/<?= $g['theme']; ?>/images/icons/icon_x.gif" onclick="return confirm('<?= gettext("Do you really want to delete this mount point? All elements that still use it will become invalid (e.g. share)!"); ?>');" title="<?=gettext("delete mount");?>" width="17" height="17" border="0" alt="" />
+ </a>
+ </td>
+ </tr>
+ <?php $i++; endforeach; ?>
+ <tr>
+ <td class="list" colspan="6"></td>
+ <td class="list" nowrap>
+ <a href="disks_mount_edit.php">
+ <img src="./themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" title="<?=gettext("add mount");?>" width="17" height="17" border="0" alt="" />
+ </a>
+ </td>
+ </tr>
+ <tr>
+ <td align="left" valign="top" colspan="7">
+ <span class="red">
+ <strong>Note:</strong>
+ </span>
+ <br />
+ <span class="vexpl">
+ <?= gettext("Second configuration step: Declaring the filesystem used by your"); ?>
+ </span>
+ <br />
+ <span class="vexpl">
+ <a href="disks_manage.php">previously configured disk</a>
+ </span>
+ </td>
+ </tr>
+ </table>
+ </div>
+ </td>
+ </tr>
+ </table>
+</form>
+<?php include("fend.inc"); ?>
+<?= checkForInputErrors(); ?>
+</body>
+</html>
diff --git a/config/freenas/www/disks_mount_edit.php b/config/freenas/www/disks_mount_edit.php
new file mode 100644
index 00000000..6b7a2248
--- /dev/null
+++ b/config/freenas/www/disks_mount_edit.php
@@ -0,0 +1,307 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ disks_mount_edit.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+$pgtitle = array(gettext("System"),
+ gettext("Disks"),
+ gettext("Mount Point"),
+ gettext("Edit"));
+
+require_once("freenas_config.inc");
+require_once("guiconfig.inc");
+require_once("freenas_guiconfig.inc");
+require_once("freenas_functions.inc");
+
+$id = $_GET['id'];
+if (isset($_POST['id']))
+ $id = $_POST['id'];
+
+if (!is_array($freenas_config['mounts']['mount']))
+ $freenas_config['mounts']['mount'] = array();
+
+mount_sort();
+
+if (!is_array($freenas_config['disks']['disk']))
+ $freenas_config['disks']['disk'] = array();
+
+disks_sort();
+
+if (!is_array($freenas_config['gvinum']['vdisk']))
+ $freenas_config['gvinum']['vdisk'] = array();
+
+gvinum_sort();
+
+if (!is_array($freenas_config['gmirror']['vdisk']))
+ $freenas_config['gmirror']['vdisk'] = array();
+
+gmirror_sort();
+
+if (!is_array($freenas_config['gconcat']['vdisk']))
+ $freenas_config['gconcat']['vdisk'] = array();
+
+gconcat_sort();
+
+if (!is_array($freenas_config['gstripe']['vdisk']))
+ $freenas_config['gstripe']['vdisk'] = array();
+
+gstripe_sort();
+
+if (!is_array($freenas_config['graid5']['vdisk']))
+ $freenas_config['graid5']['vdisk'] = array();
+
+graid5_sort();
+
+$a_mount = &$freenas_config['mounts']['mount'];
+
+$a_disk = array_merge($freenas_config['disks']['disk'],$freenas_config['gvinum']['vdisk'],$freenas_config['gmirror']['vdisk'],$freenas_config['gconcat']['vdisk'],$freenas_config['gstripe']['vdisk'],$freenas_config['graid5']['vdisk']);
+
+/* Load the cfdevice file*/
+$filename=$g['varetc_path']."/cfdevice";
+if (file_exists($filename))
+ $cfdevice = trim(file_get_contents("$filename"));
+
+if (isset($id) && $a_mount[$id]) {
+ $pconfig['mdisk'] = $a_mount[$id]['mdisk'];
+ $pconfig['partition'] = $a_mount[$id]['partition'];
+ $pconfig['fullname'] = $a_mount[$id]['fullname'];
+ $pconfig['fstype'] = $a_mount[$id]['fstype'];
+ $pconfig['sharename'] = $a_mount[$id]['sharename'];
+ $pconfig['desc'] = $a_mount[$id]['desc'];
+}
+
+if (! empty($_POST))
+{
+ /* hash */
+ unset($error_bucket);
+ /* simple error list */
+ unset($input_errors);
+ $pconfig = $_POST;
+
+ /* input validation */
+ $reqdfields = split(" ", "partitionno mdisk fstype");
+ $reqdfieldsn = split(",", "Partition,Mdisk,Fstype");
+
+ do_input_validation_new($_POST, $reqdfields, $reqdfieldsn, &$error_bucket);
+
+ if (($_POST['sharename'] && !is_validsharename($_POST['sharename'])))
+ {
+ $error_bucket[] = array("error" => gettext("The share name may only consist of the characters a-z, A-Z, 0-9, _ , -."),
+ "field" => "sharename");
+ }
+
+
+ if (($_POST['desc'] && !is_validdesc($_POST['desc'])))
+ {
+ $error_bucket[] = array("error" => gettext("The description name contain invalid characters."),
+ "field" => "desc");
+
+ }
+ $device=$_POST['mdisk'].$_POST['partitionno'];
+
+ if ($device == $cfdevice )
+ {
+ $error_bucket[] = array("error" => gettext("Can't mount the system partition 1, the DATA partition is the 2."),
+ "field" => "mdisk");
+
+ }
+
+ /* check for name conflicts */
+ foreach ($a_mount as $mount)
+ {
+ if (isset($id) && ($a_mount[$id]) && ($a_mount[$id] === $mount))
+ continue;
+
+ /* Check for duplicate mount point */
+ if ($mount['mdisk'] == $_POST['mdisk'])
+ {
+ $error_bucket[] = array("error" => gettext("This disk/partition is allready configured."),
+ "field" => "mdisk");
+ break;
+ }
+
+ if (($_POST['sharename']) && ($mount['sharename'] == $_POST['sharename']))
+ {
+ $error_bucket[] = array("error" => gettext("Duplicate Share Name."),
+ "field" => "sharename");
+ break;
+ }
+ }
+
+ if (is_array($error_bucket))
+ foreach($error_bucket as $elem)
+ $input_errors[] =& $elem["error"];
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($error_bucket)) {
+ input_errors2Ajax(NULL, $error_bucket);
+ exit;
+ }
+
+ if (!$input_errors)
+ {
+ $mount = array();
+ $mount['mdisk'] = $_POST['mdisk'];
+ $mount['partition'] = $_POST['partitionno'];
+ $mount['fstype'] = $_POST['fstype'];
+ $mount['desc'] = $_POST['desc'];
+ /* if not sharename given, create one */
+ if (!$_POST['sharename'])
+ $mount['sharename'] = "disk_{$_POST['mdisk']}_part_{$_POST['partitionno']}";
+ else
+ $mount['sharename'] = $_POST['sharename'];
+
+ // Generate fullname
+ $mount['fullname'] = "{$mount['mdisk']}{$mount['partition']}";
+
+ if (isset($id) && $a_mount[$id])
+ $a_mount[$id] = $mount;
+ else
+ $a_mount[] = $mount;
+
+ touch($d_mountdirty_path);
+
+ write_config();
+
+ pfSenseHeader("disks_mount.php");
+ exit;
+ }
+}
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc"); ?>
+
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+ <div id="inputerrors"></div>
+ <form id="iform" name="iform" action="disks_mount_edit.php" method="post">
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?=gettext("Disk");?></td>
+ <td width="78%" class="vtable">
+ <select name="mdisk" class="formselect" id="mdisk">
+ <?php foreach ($a_disk as $disk): ?>
+ <?php if (strcmp($disk['fstype'],"softraid")==0): ?>
+ <?php continue; ?>
+ <?php endif; ?>
+ <option value="<?=$disk['fullname'];?>" <?php if ($pconfig['mdisk'] == $disk['name']) echo "selected";?>>
+ <?php echo htmlspecialchars($disk['name'] . ": " .$disk['size'] . " (" . $disk['desc'] . ")"); ?>
+ </option>
+ <?php endforeach; ?>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?=gettext("Partition");?></td>
+ <td width="78%" class="vtable">
+ <select name="partitionno" class="formselect" id="partition_number">
+ <option value="s1" <?php if ($pconfig['partition'] == "s1") echo "selected"; ?>>1 (or new software RAID method)</option>
+ <option value="s2" <?php if ($pconfig['partition'] == "s2") echo "selected"; ?>>2</option>
+ <option value="s3" <?php if ($pconfig['partition'] == "s3") echo "selected"; ?>>3</option>
+ <option value="s4" <?php if ($pconfig['partition'] == "s4") echo "selected"; ?>>4</option>
+ <option value="gmirror" <?php if ($pconfig['partition'] == "gmirror") echo "selected"; ?>>previous <?=_SOFTRAID ;?> - gmirror</option>
+ <option value="graid5" <?php if ($pconfig['partition'] == "graid5") echo "selected"; ?>>previous <?=_SOFTRAID ;?> - graid5</option>
+ <option value="gvinum" <?php if ($pconfig['partition'] == "gvinum") echo "selected"; ?>>previous <?=_SOFTRAID ;?> - gvinum</option>
+ <option value="p1" <?php if ($pconfig['partition'] == "gpt") echo "selected"; ?>>GPT (or new software RAID method with GPT)</option>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?=gettext("File system");?></td>
+ <td width="78%" class="vtable">
+ <select name="fstype" class="formselect" id="fstype">
+ <option value="ufs" <?php if ($pconfig['fstype'] == "ufs") echo "selected=\"selected\""; ?>>UFS</option>
+ <option value="msdosfs" <?php if ($pconfig['fstype'] == "msdosfs") echo "selected\"selected\""; ?>>FAT</option>
+ <option value="ntfs" <?php if ($pconfig['fstype'] == "ntfs") echo "selected\"selected\""; ?>>NTFS (read-only)</option>
+ <option value="ext2fs" <?php if ($pconfig['fstype'] == "ext2fs") echo "selected\"selected\""; ?>>EXT2 FS</option>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("Share name");?></td>
+ <td width="78%" class="vtable">
+ <input name="sharename" type="text" class="formfld unknown" id="sharename" size="20" value="<?=htmlspecialchars($pconfig['sharename']);?>" />
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("Description");?></td>
+ <td width="78%" class="vtable">
+ <input name="desc" type="text" class="formfld unknown" id="desc" size="20" value="<?=htmlspecialchars($pconfig['desc']);?>" />
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <input id="submit" name="Submit" type="submit" class="formbtn" value="<?=gettext("Save");?>" />
+ <?php if (isset($id) && $a_mount[$id]): ?>
+ <input name="id" type="hidden" value="<?=$id;?>" />
+ <?php endif; ?>
+ </td>
+ </tr>
+ <tr>
+ <td width="100%" align="left" valign="top" colspan="2">
+ <span class="red">
+ <strong><?= gettext("WARNING"); ?>:</strong>
+ </span>
+ <ol>
+ <li>
+ <span class="vexpl">
+ <?= gettext("You can't mount the partition '"); ?>
+ <?php echo htmlspecialchars($cfdevice);?>
+ <?= gettext("' where the config file is stored"); ?>
+ </span>
+ </li>
+ <li><span class="vexpl"><?= gettext("FreeBSD NTFS has lots of bugs."); ?></span></li>
+ </ol>
+ </td>
+ </tr>
+ </table>
+ </form>
+<?php include("fend.inc"); ?>
+<?= checkForInputErrors(); ?>
+</body>
+</html>
diff --git a/config/freenas/www/disks_mount_tools.php b/config/freenas/www/disks_mount_tools.php
new file mode 100644
index 00000000..4f415b77
--- /dev/null
+++ b/config/freenas/www/disks_mount_tools.php
@@ -0,0 +1,233 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ disks_mount_tools.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+$pgtitle = array(gettext("System"),
+ gettext("Disks"),
+ gettext("Mount Point"),
+ gettext("Tools"));
+
+require_once("freenas_config.inc");
+require_once("guiconfig.inc");
+require_once("freenas_guiconfig.inc");
+require_once("freenas_functions.inc");
+
+function create_cmd_output(&$action, &$a_mount, &$fullname) {
+ $cmdout = CMDOUT_PARA_WOHINT;
+
+ ob_end_flush();
+
+ $retvalue =<<<EOD
+{$cmdout}
+
+EOD;
+
+ /* Get the id of the mount array entry. */
+ $id = array_search_ex($fullname, $a_mount, "fullname");
+ /* Get the mount data. */
+ $mount = $a_mount[$id];
+
+ switch($action)
+ {
+ case "mount":
+ $diskinit_str = gettext("Mounting '{$fullname}'...") . "<br />";
+ $result = disks_mount_fullname($fullname);
+ break;
+ case "umount":
+ $diskinit_str = gettext("Umounting '{$fullname}'...") . "<br />";
+ $result = disks_umount_fullname($fullname);
+ break;
+ }
+
+ /* Display result */
+ (0 == $result) ? $diskinit_str .= gettext("Successful") : $diskinit_str .= gettext("Failed");
+
+ $retvalue .=<<<EOD
+ <div id="ismounted_out" style="font-family: Courier, monospace; font-size: small;">
+ <pre style="font-family: Courier, monospace; font-size: small; font-style: italic;">{$diskinit_str}</pre>
+ </div>
+
+EOD;
+
+ return $retvalue;
+}
+
+if (!is_array($freenas_config['mounts']['mount']))
+ $freenas_config['mounts']['mount'] = array();
+
+mount_sort();
+
+$a_mount = &$freenas_config['mounts']['mount'];
+
+if (! empty($_POST))
+{
+ /* hash */
+ unset($error_bucket);
+ /* simple error list */
+ unset($input_errors);
+ unset($do_action);
+
+ /* input validation */
+ $reqdfields = explode(" ", "fullname action");
+ $reqdfieldsn = explode(",", "Fullname,Action");
+ do_input_validation($_POST, $reqdfields, $reqdfieldsn, &$input_errors);
+
+ if (is_array($error_bucket))
+ foreach($error_bucket as $elem)
+ $input_errors[] =& $elem["error"];
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($error_bucket)) {
+ input_errors2Ajax(NULL, $error_bucket);
+ exit;
+ }
+
+ if(!$input_errors)
+ {
+ $do_action = true;
+ $fullname = $_POST['fullname'];
+ $action = $_POST['action'];
+
+ echo create_cmd_output($action, $a_mount, $fullname);
+ exit; // cause of Ajax
+ }
+}
+
+if(!isset($do_action))
+{
+ $do_action = false;
+ $fullname = '';
+ $action = '';
+}
+
+// URL GET from the disks_manage_init.php page:
+// we get the $disk value, must found the $fullname now
+if(isset($_GET['disk'])) {
+ $disk = $_GET['disk'];
+ $id = array_search_ex($disk, $a_mount, "mdisk");
+
+ $fullname = $a_mount[$id]['fullname'];
+}
+if(isset($_GET['action'])) {
+ $action = $_GET['action'];
+}
+
+/* if ajax is calling, give them an update message */
+if(isAjax())
+ print_info_box_np($savemsg);
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+$pfSenseHead->setCloseHead(false);
+echo $pfSenseHead->getHTML();
+
+?>
+<script type="text/javascript">
+<!--
+<?= CMDOUT_TOGGLE_FUNC ?>
+// -->
+</script>
+</head>
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc"); ?>
+
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+
+<form action="disks_mount_tools.php" method="post" name="iform" id="iform">
+<div id="inputerrors"></div>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr><td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Manage"), false, "disks_mount.php");
+ $tab_array[1] = array(gettext("Tools"), true, "disks_mount_tools.php");
+ display_top_tabs($tab_array);
+?>
+ </td></tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <?= CMDOUT_AJAX_SCRIPT ?>
+ <?php if ($input_errors) print_input_errors($input_errors); ?>
+ <table class="tabcont" width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td valign="top" class="vncellreq"><?= gettext("Share Name"); ?></td>
+ <td class="vtable">
+ <select name="fullname" class="formselect" id="fullname">
+ <?php foreach ($a_mount as $mountv): ?>
+ <option value="<?=$mountv['fullname'];?>"<?php if ($mountv['fullname'] == $fullname) echo "selected";?>>
+ <?php echo htmlspecialchars($mountv['sharename'] . " (" . gettext("Disk") . ": " . $mountv['mdisk'] . " " . gettext("Partition") . ": " . $mountv['partition'] . ")");?>
+ <?php endforeach; ?>
+ </option>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td valign="top" class="vncellreq"><?= gettext("Command"); ?></td>
+ <td class="vtable">
+ <select name="action" class="formselect" id="action">
+ <option value="mount" <?php if ($action == "mount") echo "selected"; ?>>mount</option>
+ <option value="umount" <?php if ($action == "umount") echo "selected"; ?>>umount</option>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <input id="doCMDSubmit" name="doCMDSubmit" type="button" class="formbtn" value="<?=gettext("Send Command!");?>" onclick="execCMD();" />
+ </td>
+ </tr>
+ <tr>
+ <!-- Format Output Container - Do Not Delete -->
+ <td id="cmdOutputTD" valign="top" colspan="2" style="visibility: hidden; border: solid 1px silver; vertical-align: middle; width: 100%"></td>
+ </tr>
+ </table>
+ </div>
+ </td>
+ </tr>
+ </table>
+ </form>
+<?php include("fend.inc"); ?>
+<?= checkForInputErrors(); ?>
+</body>
+</html>
diff --git a/config/freenas/www/disks_raid_gconcat.php b/config/freenas/www/disks_raid_gconcat.php
new file mode 100644
index 00000000..e7fc9f81
--- /dev/null
+++ b/config/freenas/www/disks_raid_gconcat.php
@@ -0,0 +1,236 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ disks_raid_gconcat.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+$pgtitle = array(gettext("System"),
+ gettext("Disks"),
+ gettext("GEOM Concat"),
+ gettext("RAID"));
+
+require_once("freenas_config.inc");
+require_once("guiconfig.inc");
+require_once("freenas_guiconfig.inc");
+require_once("freenas_functions.inc");
+
+if (!is_array($freenas_config['gconcat']['vdisk']))
+ $freenas_config['gconcat']['vdisk'] = array();
+
+gconcat_sort();
+
+$raidstatus=get_sraid_disks_list();
+
+$a_raid = &$freenas_config['gconcat']['vdisk'];
+
+if (! empty($_POST))
+{
+ /* hash */
+ unset($error_bucket);
+ /* simple error list */
+ unset($input_errors);
+
+ $pconfig = $_POST;
+
+ if (is_array($error_bucket))
+ foreach($error_bucket as $elem)
+ $input_errors[] =& $elem["error"];
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($error_bucket)) {
+ input_errors2Ajax(NULL, $error_bucket);
+ exit;
+ }
+
+ if ($_POST['apply']) {
+ $retval = 0;
+ if (!file_exists($d_sysrebootreqd_path))
+ {
+ config_lock();
+ /* reload all components that create raid device */
+ disks_raid_gconcat_configure();
+ config_unlock();
+ write_config();
+ }
+ $savemsg = get_std_save_message($retval);
+ if ($retval == 0) {
+ if (file_exists($d_raidconfdirty_path))
+ unlink($d_raidconfdirty_path);
+ }
+ }
+}
+
+if ($_GET['act'] == "del") {
+ if ($a_raid[$_GET['id']]) {
+ $raidname=$a_raid[$_GET['id']]['name'];
+ disks_raid_gconcat_delete($raidname);
+ unset($a_raid[$_GET['id']]);
+ write_config();
+ touch($d_raidconfdirty_path);
+ pfSenseHeader("disks_raid_gconcat.php");
+ exit;
+ }
+}
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc"); ?>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+
+<form action="disks_raid_gconcat.php" method="post" name="iform" id="iform">
+<?php if (file_exists($d_diskdirty_path)): ?>
+<?php print_info_box_np(gettext("The Raid configuration has been changed.") . "<br />" .
+ gettext("You must apply the changes in order for them to take effect."));?>
+<?php endif; ?>
+
+<div id="inputerrors"></div>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Geom Mirror"), false, "disks_raid_gmirror.php");
+ $tab_array[1] = array(gettext("Geom Concat"), true, "disks_raid_gconcat.php");
+ $tab_array[2] = array(gettext("Geom Stripe"), false, "disks_raid_gstripe.php");
+ $tab_array[3] = array(gettext("Geom RAID5"), false, "disks_raid_graid5.php");
+ $tab_array[4] = array(gettext("Geom Vinum"), false, "disks_raid_gvinum.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Manage RAID"), true, "disks_raid_gconcat.php");
+ /* $tab_array[1] = array(gettext("Format RAID"), false, "disks_raid_gmirror_init.php"); */
+ $tab_array[1] = array(gettext("Tools"), false, "disks_raid_gconcat_tools.php");
+ $tab_array[2] = array(gettext("Information"), false, "disks_raid_gconcat_infos.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <table class="tabcont" width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="listhdrr"><?=gettext("Volume name");?></td>
+ <td class="listhdrr"><?=gettext("Type");?></td>
+ <td class="listhdrr"><?=gettext("Size");?></td>
+ <td class="listhdrr"><?=gettext("Status");?></td>
+ <td class="list">&nbsp;</td>
+ </tr>
+ <?php $i = 0; foreach ($a_raid as $raid): ?>
+ <tr>
+ <td valign="middle" class="listr">
+ <?=htmlspecialchars($raid['name']);?>
+ </td>
+ <td valign="middle" class="listr">
+ <?=htmlspecialchars($raid['type']);?>
+ </td>
+ <td valign="middle" class="listr">
+ <?php
+ $raidconfiguring = file_exists($d_raidconfdirty_path) &&
+ in_array($raid['name']."\n",file($d_raidconfdirty_path));
+ if ($raidconfiguring)
+ echo gettext("configuring");
+ else {
+ $tempo=$raid['name'];
+ echo "{$raidstatus[$tempo]['size']}";
+ }
+ ?>&nbsp;
+ </td>
+ <td valign="middle" class="listr">
+ <?php
+ if ($raidconfiguring)
+ echo gettext("configuring");
+ else {
+ echo "{$raidstatus[$tempo]['desc']}";
+ }
+ ?>&nbsp;
+ </td>
+ <td valign="middle" class="list">
+ <a href="disks_raid_gconcat_edit.php?id=<?=$i;?>">
+ <img src="./themes/<?= $g['theme']; ?>/images/icons/icon_e.gif" title="<?=gettext("edit raid");?>" width="17" height="17" border="0" alt="" />
+ </a>
+ <a href="disks_raid_gconcat.php?act=del&id=<?=$i;?>">
+ <img src="./themes/<?= $g['theme']; ?>/images/icons/icon_x.gif" title="<?=gettext("delete raid");?>" width="17" height="17" border="0" alt="" />
+ </a>
+ </td>
+ </tr>
+ <?php $i++; endforeach; ?>
+ <tr>
+ <td class="list" colspan="4"></td>
+ <td class="list" nowrap>
+ <a href="disks_raid_gconcat_edit.php">
+ <img src="./themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" title="<?=gettext("add disk");?>" width="17" height="17" border="0" alt="" />
+ </a>
+ </td>
+ </tr>
+ <tr>
+ <td align="left" valign="top" colspan="5">
+ <span class="red">
+ <strong><?= gettext("Note:"); ?></strong>
+ </span>
+ <br />
+ <span class="vexpl"><?= gettext("Optional configuration step: Configuring a virtual RAID disk using your"); ?></span>
+ <br />
+ <span class="vexpl"><a href="disks_manage.php"><?= gettext("previsously configured disk."); ?></a></span>
+ <br />
+ <span class="vexpl"><?= gettext("Wait for the \"up\" status before format it and mount it!."); ?></span>
+ </span>
+ </td>
+ </tr>
+ </table>
+ </div>
+ </td>
+ </tr>
+</table>
+</form>
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/freenas/www/disks_raid_gconcat_edit.php b/config/freenas/www/disks_raid_gconcat_edit.php
new file mode 100644
index 00000000..f4bd33cc
--- /dev/null
+++ b/config/freenas/www/disks_raid_gconcat_edit.php
@@ -0,0 +1,256 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ disks_raid_gconcat_edit.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+$pgtitle = array(gettext("System"),
+ gettext("Disks"),
+ gettext("GEOM Concat"),
+ gettext("RAID"),
+ isset($id) ? gettext("Edit") : gettext("Add"));
+
+require_once("freenas_config.inc");
+require_once("guiconfig.inc");
+require_once("freenas_guiconfig.inc");
+require_once("freenas_functions.inc");
+
+$id = $_GET['id'];
+if (isset($_POST['id']))
+ $id = $_POST['id'];
+
+if (!is_array($freenas_config['gconcat']['vdisk']))
+ $freenas_config['gconcat']['vdisk'] = array();
+
+gconcat_sort();
+disks_sort();
+
+$a_raid = &$freenas_config['gconcat']['vdisk'];
+$all_raid = array_merge((array)$freenas_config['graid5']['vdisk'],(array)$freenas_config['gconcat']['vdisk'],(array)$freenas_config['gvinum']['vdisk'],(array)$freenas_config['gstripe']['vdisk'],(array)$freenas_config['gconcat']['vdisk']);
+$a_disk = get_fstype_disks_list("softraid");
+
+if (!sizeof($a_disk)) {
+ $nodisk_errors[] = gettext("You must add disks first.");
+}
+
+if (isset($id) && $a_raid[$id]) {
+ $pconfig['name'] = $a_raid[$id]['name'];
+ $pconfig['type'] = $a_raid[$id]['type'];
+ $pconfig['diskr'] = $a_raid[$id]['diskr'];
+ $pconfig['fullname'] = $a_raid[$id]['fullname'];
+}
+
+if (! empty($_POST))
+{
+ /* hash */
+ unset($error_bucket);
+ /* simple error list */
+ unset($input_errors);
+
+ $reqdfields = explode(" ", "name");
+ $reqdfieldsn = explode(",", "Name");
+
+ do_input_validation($_POST, $reqdfields, $reqdfieldsn, &$input_errors);
+
+ if (($_POST['name'] && !is_validaliasname($_POST['name'])))
+ {
+ $error_bucket[] = array("error" => gettext("The device name may only consist of the characters a-z, A-Z, 0-9."),
+ "field" => "name");
+ }
+
+ /* check for name conflicts */
+ foreach ($a_raid as $raid)
+ {
+ if (isset($id) && ($a_raid[$id]) && ($a_raid[$id] === $raid))
+ continue;
+
+ if ($raid['name'] == $_POST['name'])
+ {
+ $error_bucket[] = array("error" => gettext("This device already exists in the raid volume list."),
+ "field" => "name");
+ break;
+ }
+ }
+
+ /* check the number of RAID disk for volume */
+
+ if (count($_POST['diskr']) < 2)
+ $error_bucket[] = array("error" => gettext("There must be a minimum of 2 disks in a JBOD."),
+ "field" => "diskr");
+
+ if (is_array($error_bucket))
+ foreach($error_bucket as $elem)
+ $input_errors[] =& $elem["error"];
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($error_bucket)) {
+ input_errors2Ajax(NULL, $error_bucket);
+ exit;
+ }
+
+ if (!$input_errors) {
+ $raid = array();
+ $raid['name'] = $_POST['name'];
+ $raid['type'] = "JBOD";
+ $raid['diskr'] = $_POST['diskr'];
+ $raid['desc'] = "Software gconcat JBOD";
+ $raid['fullname'] = "/dev/concat/{$raid['name']}";
+
+ if (isset($id) && $a_raid[$id])
+ $a_raid[$id] = $raid;
+ else
+ $a_raid[] = $raid;
+
+ $fd = @fopen("$d_raidconfdirty_path", "a");
+ if (!$fd) {
+ echo "ERR Could not save RAID configuration.\n";
+ exit(0);
+ }
+ fwrite($fd, "$raid[name]\n");
+ fclose($fd);
+
+ write_config();
+
+ pfSenseHeader("disks_raid_gconcat.php");
+ exit;
+ }
+}
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc"); ?>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+
+<div id="inputerrors"></div>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Geom Mirror"), false, "disks_raid_gmirror.php");
+ $tab_array[1] = array(gettext("Geom Concat"), true, "disks_raid_gconcat.php");
+ $tab_array[2] = array(gettext("Geom Stripe"), false, "disks_raid_gstripe.php");
+ $tab_array[3] = array(gettext("Geom RAID5"), false, "disks_raid_graid5.php");
+ $tab_array[4] = array(gettext("Geom Vinum"), false, "disks_raid_gvinum.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Manage RAID"), true, "disks_raid_gmirror.php");
+ /* $tab_array[1] = array(gettext("Format RAID"), false, "disks_raid_gmirror_init.php"); */
+ $tab_array[1] = array(gettext("Tools"), false, "disks_raid_gmirror_tools.php");
+ $tab_array[2] = array(gettext("Information"), false, "disks_raid_gmirror_infos.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <form action="disks_raid_gconcat_edit.php" method="post" name="iform" id="iform">
+ <table class="tabcont" align="center" width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?=gettext("Raid name");?></td>
+ <td width="78%" class="vtable">
+ <input name="name" type="text" class="formfld unknown" id="name" size="20" value="<?=htmlspecialchars($pconfig['name']);?>" />
+ </td>
+ </tr>
+ <tr>
+ <td valign="top" class="vncellreq"><?= gettext("Type"); ?></td>
+ <td class="vtable">JBOD</td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?= gettext("Members of this volume"); ?></td>
+ <td width="78%" class="vtable">
+ <?
+ $i=0;
+ $disable_script="";
+
+ foreach ($a_disk as $diskv) {
+ $r_name="";
+
+ foreach($all_raid as $raid) {
+ if (in_array($diskv['fullname'],(array)$raid['diskr'])) {
+ $r_name=$raid['name'];
+ if ($r_name!=$pconfig['name']) $disable_script.="document.getElementById($i).disabled=1;\n";
+ break;
+ }
+ }
+ echo "<input name='diskr[]' id='$i' type='checkbox' value='$diskv[fullname]'".
+ ((is_array($pconfig['diskr']) && in_array($diskv['fullname'],$pconfig['diskr'])) ? " checked=\"checked\"" : "") .
+ " />$diskv[name] ($diskv[size], $diskv[desc])".(($r_name) ? " - assigned to $r_name" : "")."<br />\n";
+ $i++;
+
+ $i++;
+ }
+
+ if ($disable_script)
+ echo "<script type='text/javascript'><!--\n$disable_script--></script>\n";
+ ?>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <input name="Submit" type="submit" class="formbtn" value="Save" />
+ <?php if (isset($id) && $a_raid[$id]): ?>
+ <input name="id" type="hidden" value="<?=$id;?>" />
+ <?php endif; ?>
+ </td>
+ </tr>
+ </table>
+ </form>
+ </div>
+ </td>
+ </tr>
+</table>
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/freenas/www/disks_raid_gconcat_infos.php b/config/freenas/www/disks_raid_gconcat_infos.php
new file mode 100644
index 00000000..09dfd76a
--- /dev/null
+++ b/config/freenas/www/disks_raid_gconcat_infos.php
@@ -0,0 +1,143 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ disks_raid_gconcat_infos.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+$pgtitle = array(gettext("System"),
+ gettext("Disks"),
+ gettext("GEOM Concat"),
+ gettext("Information"));
+
+require_once("guiconfig.inc");
+require_once("freenas_guiconfig.inc");
+require_once("freenas_functions.inc");
+
+if (! empty($_POST))
+{
+ /* hash */
+ unset($error_bucket);
+ /* simple error list */
+ unset($input_errors);
+
+ if (is_array($error_bucket))
+ foreach($error_bucket as $elem)
+ $input_errors[] =& $elem["error"];
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($error_bucket)) {
+ input_errors2Ajax(NULL, $error_bucket);
+ exit;
+ }
+
+ if (!$input_errors) {
+ }
+}
+if (!isset($do_action)) {
+}
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc"); ?>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+
+<div id="inputerrors"></div>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Geom Mirror"), false, "disks_raid_gmirror.php");
+ $tab_array[1] = array(gettext("Geom Concat"), true, "disks_raid_gconcat.php");
+ $tab_array[2] = array(gettext("Geom Stripe"), false, "disks_raid_gstripe.php");
+ $tab_array[3] = array(gettext("Geom RAID5"), false, "disks_raid_graid5.php");
+ $tab_array[4] = array(gettext("Geom Vinum"), false, "disks_raid_gvinum.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Manage RAID"), false, "disks_raid_gconcat.php");
+ /* $tab_array[1] = array(gettext("Format RAID"), false, "disks_raid_gconcat_init.php"); */
+ $tab_array[1] = array(gettext("Tools"), false, "disks_raid_gconcat_tools.php");
+ $tab_array[2] = array(gettext("Information"), true, "disks_raid_gconcat_infos.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <form action="disks_raid_gconcat_infos.php" method="post" name="iform" id="iform">
+ <table class="tabcont" align="center" width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="100%" class="vtable">
+ <?php
+ echo "<pre>";
+ echo "<strong>" . gettext("Software RAID information and status") . "</strong><br />";
+
+ exec("/sbin/gconcat list",$rawdata);
+ foreach ($rawdata as $line){
+ echo htmlspecialchars($line) . "<br>";
+ }
+
+ unset ($line);
+ echo "</pre>";
+ ?>
+ </td>
+ </tr>
+ </table>
+ </form>
+ </div>
+ </td>
+ </tr>
+</table>
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/freenas/www/disks_raid_gconcat_tools.php b/config/freenas/www/disks_raid_gconcat_tools.php
new file mode 100644
index 00000000..7783450d
--- /dev/null
+++ b/config/freenas/www/disks_raid_gconcat_tools.php
@@ -0,0 +1,187 @@
+<?php
+/*
+ disks_raid_gmirror_tools.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+$pgtitle = array(gettext("System"),
+ gettext("Disks"),
+ gettext("GEOM Concat"),
+ gettext("Tools"));
+
+require_once("freenas_config.inc");
+require_once("guiconfig.inc");
+require_once("freenas_guiconfig.inc");
+require_once("freenas_functions.inc");
+
+if (! empty($_POST))
+{
+ /* hash */
+ unset($error_bucket);
+ /* simple error list */
+ unset($input_errors);
+ unset($do_action);
+
+ $reqdfields = explode(" ", "action object");
+ $reqdfieldsn = explode(",", "Action,Object");
+
+ do_input_validation($_POST, $reqdfields, $reqdfieldsn, &$input_errors);
+
+ if (is_array($error_bucket))
+ foreach($error_bucket as $elem)
+ $input_errors[] =& $elem["error"];
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($error_bucket)) {
+ input_errors2Ajax(NULL, $error_bucket);
+ exit;
+ }
+
+ if (!$input_errors) {
+ $do_action = true;
+ $action = $_POST['action'];
+ $object = $_POST['object'];
+ }
+ }
+ if (!isset($do_action)) {
+ $do_action = false;
+ $action = '';
+ $object = '';
+}
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc"); ?>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+
+<div id="inputerrors"></div>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Geom Mirror"), false, "disks_raid_gmirror.php");
+ $tab_array[1] = array(gettext("Geom Concat"), true, "disks_raid_gconcat.php");
+ $tab_array[2] = array(gettext("Geom Stripe"), false, "disks_raid_gstripe.php");
+ $tab_array[3] = array(gettext("Geom RAID5"), false, "disks_raid_graid5.php");
+ $tab_array[4] = array(gettext("Geom Vinum"), false, "disks_raid_gvinum.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Manage RAID"), false, "disks_raid_gmirror.php");
+ /* $tab_array[1] = array(gettext("Format RAID"), false, "disks_raid_gmirror_init.php"); */
+ $tab_array[1] = array(gettext("Tools"), true, "disks_raid_gmirror_tools.php");
+ $tab_array[2] = array(gettext("Information"), false, "disks_raid_gmirror_infos.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <form action="disks_raid_gmirror_tools.php" method="post" name="iform" id="iform">
+ <table class="tabcont" align="center" width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?=gettext("Object name");?></td>
+ <td width="78%" class="vtable">
+ <input name="object" type="text" class="formfld unknown" id="object" size="20" value="<?=htmlspecialchars($disk);?>" />
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?=gettext("Object name");?></td>
+ <td width="78%" class="vtable">
+ <select name="action" class="formselect" id="action">
+ <option value="list" <?php if ($action == "list") echo "selected"; ?>>list</option>
+ <option value="status" <?php if ($action == "status") echo "selected"; ?>>status</option>
+ <option value="clear" <?php if ($action == "clear") echo "selected"; ?>>clear</option>
+ <option value="stop" <?php if ($action == "stop") echo "selected"; ?>>stop</option>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <input name="Submit" type="submit" class="formbtn" value="Send Command!" />
+ </td>
+ </tr>
+ <tr>
+ <td valign="top" colspan="2">
+ <?
+ if ($do_action) {
+ echo("<strong>" . gettext("GCONCAT command output:") . "</strong><br />");
+ echo('<pre>');
+ ob_end_flush();
+
+ system("/sbin/gmirror $action " . escapeshellarg($object));
+
+ echo('</pre>');
+ }
+ ?>
+ </td>
+ </tr>
+ <tr>
+ <td align="left" valign="top" colspan="2">
+ <span class="red">
+ <strong>WARNING:</strong><br />
+ </span>
+ <ol>
+ <li><span class="vexpl"><?= gettext("Use these specials actions for debugging only!"); ?></span></li>
+ <li><span class="vexpl"><?= gettext("There is no need of using this menu for start a RAID volume (start automaticaly)."); ?></span></li>
+ </ol>
+ </td>
+ </tr>
+ </table>
+ </form>
+ </div>
+ </td>
+ </tr>
+</table>
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/freenas/www/disks_raid_gmirror.php b/config/freenas/www/disks_raid_gmirror.php
new file mode 100644
index 00000000..78390a64
--- /dev/null
+++ b/config/freenas/www/disks_raid_gmirror.php
@@ -0,0 +1,236 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ disks_raid_gmirror.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+$pgtitle = array(gettext("System"),
+ gettext("Disks"),
+ gettext("GEOM Mirror"),
+ gettext("RAID"));
+
+require_once("freenas_config.inc");
+require_once("guiconfig.inc");
+require_once("freenas_guiconfig.inc");
+require_once("freenas_functions.inc");
+
+if (!is_array($freenas_config['gmirror']['vdisk']))
+ $freenas_config['gmirror']['vdisk'] = array();
+
+gmirror_sort();
+
+$raidstatus=get_sraid_disks_list();
+
+$a_raid = &$freenas_config['gmirror']['vdisk'];
+
+if (! empty($_POST))
+{
+ /* hash */
+ unset($error_bucket);
+ /* simple error list */
+ unset($input_errors);
+
+ $pconfig = $_POST;
+
+ if (is_array($error_bucket))
+ foreach($error_bucket as $elem)
+ $input_errors[] =& $elem["error"];
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($error_bucket)) {
+ input_errors2Ajax(NULL, $error_bucket);
+ exit;
+ }
+
+ if ($_POST['apply']) {
+ $retval = 0;
+ if (!file_exists($d_sysrebootreqd_path))
+ {
+ config_lock();
+ /* reload all components that create raid device */
+ disks_raid_gmirror_configure();
+ config_unlock();
+ write_config();
+ }
+ $savemsg = get_std_save_message($retval);
+ if ($retval == 0) {
+ if (file_exists($d_raidconfdirty_path))
+ unlink($d_raidconfdirty_path);
+ }
+ }
+}
+
+if ($_GET['act'] == "del") {
+ if ($a_raid[$_GET['id']]) {
+ $raidname=$a_raid[$_GET['id']]['name'];
+ disks_raid_gmirror_delete($raidname);
+ unset($a_raid[$_GET['id']]);
+ write_config();
+ touch($d_raidconfdirty_path);
+ pfSenseHeader("disks_raid_gmirror.php");
+ exit;
+ }
+}
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc"); ?>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+
+<form action="disks_raid_gmirror.php" method="post" name="iform" id="iform">
+<?php if (file_exists($d_diskdirty_path)): ?>
+<?php print_info_box_np(gettext("The Raid configuration has been changed.") . "<br />" .
+ gettext("You must apply the changes in order for them to take effect."));?>
+<?php endif; ?>
+
+<div id="inputerrors"></div>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Geom Mirror"), true, "disks_raid_gmirror.php");
+ $tab_array[1] = array(gettext("Geom Concat"), false, "disks_raid_gconcat.php");
+ $tab_array[2] = array(gettext("Geom Stripe"), false, "disks_raid_gstripe.php");
+ $tab_array[3] = array(gettext("Geom RAID5"), false, "disks_raid_graid5.php");
+ $tab_array[4] = array(gettext("Geom Vinum"), false, "disks_raid_gvinum.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Manage RAID"), true, "disks_raid_gmirror.php");
+ /* $tab_array[1] = array(gettext("Format RAID"), false, "disks_raid_gmirror_init.php"); */
+ $tab_array[1] = array(gettext("Tools"), false, "disks_raid_gmirror_tools.php");
+ $tab_array[2] = array(gettext("Information"), false, "disks_raid_gmirror_infos.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <table class="tabcont" width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="listhdrr"><?=gettext("Volume name");?></td>
+ <td class="listhdrr"><?=gettext("Type");?></td>
+ <td class="listhdrr"><?=gettext("Size");?></td>
+ <td class="listhdrr"><?=gettext("Status");?></td>
+ <td class="list">&nbsp;</td>
+ </tr>
+ <?php $i = 0; foreach ($a_raid as $raid): ?>
+ <tr>
+ <td valign="middle" class="listr">
+ <?=htmlspecialchars($raid['name']);?>
+ </td>
+ <td valign="middle" class="listr">
+ <?=htmlspecialchars($raid['type']);?>
+ </td>
+ <td valign="middle" class="listr">
+ <?php
+ $raidconfiguring = file_exists($d_raidconfdirty_path) &&
+ in_array($raid['name']."\n",file($d_raidconfdirty_path));
+ if ($raidconfiguring)
+ echo gettext("configuring");
+ else {
+ $tempo=$raid['name'];
+ echo "{$raidstatus[$tempo]['size']}";
+ }
+ ?>&nbsp;
+ </td>
+ <td valign="middle" class="listr">
+ <?php
+ if ($raidconfiguring)
+ echo gettext("configuring");
+ else {
+ echo "{$raidstatus[$tempo]['desc']}";
+ }
+ ?>&nbsp;
+ </td>
+ <td valign="middle" class="list">
+ <a href="disks_raid_gmirror_edit.php?id=<?=$i;?>">
+ <img src="./themes/<?= $g['theme']; ?>/images/icons/icon_e.gif" title="<?=gettext("edit raid");?>" width="17" height="17" border="0" alt="" />
+ </a>
+ <a href="disks_raid_gmirror.php?act=del&id=<?=$i;?>">
+ <img src="./themes/<?= $g['theme']; ?>/images/icons/icon_x.gif" title="<?=gettext("delete raid");?>" width="17" height="17" border="0" alt="" />
+ </a>
+ </td>
+ </tr>
+ <?php $i++; endforeach; ?>
+ <tr>
+ <td class="list" colspan="4"></td>
+ <td class="list" nowrap>
+ <a href="disks_raid_gmirror_edit.php">
+ <img src="./themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" title="<?=gettext("add disk");?>" width="17" height="17" border="0" alt="" />
+ </a>
+ </td>
+ </tr>
+ <tr>
+ <td align="left" valign="top" colspan="5">
+ <span class="red">
+ <strong><?= gettext("Note:"); ?></strong>
+ </span>
+ <br />
+ <span class="vexpl"><?= gettext("Optional configuration step: Configuring a virtual RAID disk using your"); ?></span>
+ <br />
+ <span class="vexpl"><a href="disks_manage.php"><?= gettext("previsously configured disk."); ?></a></span>
+ <br />
+ <span class="vexpl"><?= gettext("Wait for the \"up\" status before format it and mount it!."); ?></span>
+ </span>
+ </td>
+ </tr>
+ </table>
+ </div>
+ </td>
+ </tr>
+</table>
+</form>
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/freenas/www/disks_raid_gmirror_edit.php b/config/freenas/www/disks_raid_gmirror_edit.php
new file mode 100644
index 00000000..ac08a442
--- /dev/null
+++ b/config/freenas/www/disks_raid_gmirror_edit.php
@@ -0,0 +1,277 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ disks_raid_gmirror_edit.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+$pgtitle = array(gettext("System"),
+ gettext("Disks"),
+ gettext("GEOM Mirror"),
+ gettext("RAID"),
+ isset($id) ? gettext("Edit") : gettext("Add"));
+
+require_once("freenas_config.inc");
+require_once("guiconfig.inc");
+require_once("freenas_guiconfig.inc");
+require_once("freenas_functions.inc");
+
+$id = $_GET['id'];
+if (isset($_POST['id']))
+ $id = $_POST['id'];
+
+if (!is_array($freenas_config['gmirror']['vdisk']))
+ $freenas_config['gmirror']['vdisk'] = array();
+
+gmirror_sort();
+disks_sort();
+
+$a_raid = &$freenas_config['gmirror']['vdisk'];
+$all_raid = array_merge((array)$freenas_config['graid5']['vdisk'],(array)$freenas_config['gmirror']['vdisk'],(array)$freenas_config['gvinum']['vdisk'],(array)$freenas_config['gstripe']['vdisk'],(array)$freenas_config['gconcat']['vdisk']);
+$a_disk = get_fstype_disks_list("softraid");
+
+if (!sizeof($a_disk)) {
+ $nodisk_errors[] = gettext("You must add disks first.");
+}
+
+if (isset($id) && $a_raid[$id]) {
+ $pconfig['name'] = $a_raid[$id]['name'];
+ $pconfig['fullname'] = $a_raid[$id]['fullname'];
+ $pconfig['type'] = $a_raid[$id]['type'];
+ $pconfig['balance'] = $a_raid[$id]['balance'];
+ $pconfig['diskr'] = $a_raid[$id]['diskr'];
+}
+
+if (! empty($_POST))
+{
+ /* hash */
+ unset($error_bucket);
+ /* simple error list */
+ unset($input_errors);
+
+ $reqdfields = explode(" ", "name");
+ $reqdfieldsn = explode(",", "Name");
+
+ do_input_validation($_POST, $reqdfields, $reqdfieldsn, &$input_errors);
+
+ if (($_POST['name'] && !is_validaliasname($_POST['name'])))
+ {
+ $error_bucket[] = array("error" => gettext("The device name may only consist of the characters a-z, A-Z, 0-9."),
+ "field" => "name");
+ }
+
+
+ /* check for name conflicts */
+ foreach ($a_raid as $raid)
+ {
+ if (isset($id) && ($a_raid[$id]) && ($a_raid[$id] === $raid))
+ continue;
+
+ if ($raid['name'] == $_POST['name'])
+ {
+ $error_bucket[] = array("error" => gettext("This device already exists in the raid volume list."),
+ "field" => "name");
+ break;
+ }
+ }
+
+ /* check the number of RAID disk for volume */
+
+ if (count($_POST['diskr']) != 2)
+ $error_bucket[] = array("error" => gettext("There must be 2 disks in a RAID 1 volume."),
+ "field" => "diskr");
+
+ if (is_array($error_bucket))
+ foreach($error_bucket as $elem)
+ $input_errors[] =& $elem["error"];
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($error_bucket)) {
+ input_errors2Ajax(NULL, $error_bucket);
+ exit;
+ }
+
+ if (!$input_errors) {
+ $raid = array();
+ $raid['name'] = $_POST['name'];
+ $raid['balance'] = $_POST['balance'];
+ $raid['type'] = 1;
+ $raid['diskr'] = $_POST['diskr'];
+ $raid['desc'] = "Software RAID {$_POST['type']}";
+ $raid['fullname'] = "/dev/mirror/{$raid['name']}";
+
+ if (isset($id) && $a_raid[$id])
+ $a_raid[$id] = $raid;
+ else
+ $a_raid[] = $raid;
+
+ $fd = @fopen("$d_raidconfdirty_path", "a");
+ if (!$fd) {
+ echo "ERR Could not save RAID configuration.\n";
+ exit(0);
+ }
+ fwrite($fd, "$raid[name]\n");
+ fclose($fd);
+
+ write_config();
+
+ pfSenseHeader("disks_raid_gmirror.php");
+ exit;
+ }
+}
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc"); ?>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+
+<div id="inputerrors"></div>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Geom Mirror"), true, "disks_raid_gmirror.php");
+ $tab_array[1] = array(gettext("Geom Concat"), false, "disks_raid_gconcat.php");
+ $tab_array[2] = array(gettext("Geom Stripe"), false, "disks_raid_gstripe.php");
+ $tab_array[3] = array(gettext("Geom RAID5"), false, "disks_raid_graid5.php");
+ $tab_array[4] = array(gettext("Geom Vinum"), false, "disks_raid_gvinum.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Manage RAID"), true, "disks_raid_gmirror.php");
+ /* $tab_array[1] = array(gettext("Format RAID"), false, "disks_raid_gmirror_init.php"); */
+ $tab_array[1] = array(gettext("Tools"), false, "disks_raid_gmirror_tools.php");
+ $tab_array[2] = array(gettext("Information"), false, "disks_raid_gmirror_infos.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <form action="disks_raid_gmirror_edit.php" method="post" name="iform" id="iform">
+ <table class="tabcont" align="center" width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?=gettext("Raid name");?></td>
+ <td width="78%" class="vtable">
+ <input name="name" type="text" class="formfld unknown" id="name" size="20" value="<?=htmlspecialchars($pconfig['name']);?>" />
+ </td>
+ </tr>
+ <tr>
+ <td valign="top" class="vncellreq"><?= gettext("Type"); ?></td>
+ <td class="vtable">
+ RAID 1 (<?= gettext("mirroring"); ?>)
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?= gettext("Balance algorithm"); ?></td>
+ <td width="78%" class="vtable">
+ <select name="balance" class="formselect">
+ <?php $balvals = array(
+ "split"=>"Split request",
+ "load"=>"Read from lowest load",
+ "round-robin"=>"Round-robin read");
+ ?>
+ <?php foreach ($balvals as $balval => $balname): ?>
+ <option value="<?=$balval;?>" <?php if($pconfig['balance'] == $balval) echo 'selected';?>><?=htmlspecialchars($balname);?></option>
+ <?php endforeach; ?>
+ </select>
+ <br />
+ <?= gettext("Select your read balance algorithm."); ?></td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?= gettext("Members of this volume"); ?></td>
+ <td width="78%" class="vtable">
+ <?
+ $i=0;
+ $disable_script="";
+
+ foreach ($a_disk as $diskv) {
+ $r_name="";
+
+ foreach($all_raid as $raid) {
+ if (in_array($diskv['fullname'],(array)$raid['diskr'])) {
+ $r_name=$raid['name'];
+ if ($r_name!=$pconfig['name']) $disable_script.="document.getElementById($i).disabled=1;\n";
+ break;
+ }
+ }
+ echo "<input name='diskr[]' id='$i' type='checkbox' value='$diskv[fullname]'".
+ ((is_array($pconfig['diskr']) && in_array($diskv['fullname'],$pconfig['diskr'])) ? " checked=\"checked\"" : "") .
+ " />$diskv[name] ($diskv[size], $diskv[desc])".(($r_name) ? " - assigned to $r_name" : "")."<br />\n";
+ $i++;
+
+ $i++;
+ }
+
+ if ($disable_script)
+ echo "<script type='text/javascript'><!--\n$disable_script--></script>\n";
+ ?>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <input name="Submit" type="submit" class="formbtn" value="Save" />
+ <?php if (isset($id) && $a_raid[$id]): ?>
+ <input name="id" type="hidden" value="<?=$id;?>" />
+ <?php endif; ?>
+ </td>
+ </tr>
+ </table>
+ </form>
+ </div>
+ </td>
+ </tr>
+</table>
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/freenas/www/disks_raid_gmirror_infos.php b/config/freenas/www/disks_raid_gmirror_infos.php
new file mode 100644
index 00000000..878f571e
--- /dev/null
+++ b/config/freenas/www/disks_raid_gmirror_infos.php
@@ -0,0 +1,143 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ disks_raid_gmirror_infos.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+$pgtitle = array(gettext("System"),
+ gettext("Disks"),
+ gettext("GEOM Mirror"),
+ gettext("Information"));
+
+require_once("guiconfig.inc");
+require_once("freenas_guiconfig.inc");
+require_once("freenas_functions.inc");
+
+if (! empty($_POST))
+{
+ /* hash */
+ unset($error_bucket);
+ /* simple error list */
+ unset($input_errors);
+
+ if (is_array($error_bucket))
+ foreach($error_bucket as $elem)
+ $input_errors[] =& $elem["error"];
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($error_bucket)) {
+ input_errors2Ajax(NULL, $error_bucket);
+ exit;
+ }
+
+ if (!$input_errors) {
+ }
+}
+if (!isset($do_action)) {
+}
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc"); ?>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+
+<div id="inputerrors"></div>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Geom Mirror"), true, "disks_raid_gmirror.php");
+ $tab_array[1] = array(gettext("Geom Concat"), false, "disks_raid_gconcat.php");
+ $tab_array[2] = array(gettext("Geom Stripe"), false, "disks_raid_gstripe.php");
+ $tab_array[3] = array(gettext("Geom RAID5"), false, "disks_raid_graid5.php");
+ $tab_array[4] = array(gettext("Geom Vinum"), false, "disks_raid_gvinum.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Manage RAID"), false, "disks_raid_gmirror.php");
+ /* $tab_array[1] = array(gettext("Format RAID"), false, "disks_raid_gmirror_init.php"); */
+ $tab_array[1] = array(gettext("Tools"), false, "disks_raid_gmirror_tools.php");
+ $tab_array[2] = array(gettext("Information"), true, "disks_raid_gmirror_infos.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <form action="disks_raid_gmirror_infos.php" method="post" name="iform" id="iform">
+ <table class="tabcont" align="center" width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="100%" class="vtable">
+ <?php
+ echo "<pre>";
+ echo "<strong>" . gettext("Software RAID information and status") . "</strong><br />";
+
+ exec("/sbin/gmirror list",$rawdata);
+ foreach ($rawdata as $line){
+ echo htmlspecialchars($line) . "<br>";
+ }
+
+ unset ($line);
+ echo "</pre>";
+ ?>
+ </td>
+ </tr>
+ </table>
+ </form>
+ </div>
+ </td>
+ </tr>
+</table>
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/freenas/www/disks_raid_gmirror_init.php b/config/freenas/www/disks_raid_gmirror_init.php
new file mode 100644
index 00000000..2b2d59af
--- /dev/null
+++ b/config/freenas/www/disks_raid_gmirror_init.php
@@ -0,0 +1,179 @@
+<?php
+/* $Id$ */
+/*
+ disks_raid_gmirror_init.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/* == T H I S F I L E I S C U R R E N T L Y N O T U S E D == */
+/* ========================================================================== */
+
+$pgtitle = array(gettext("System"),
+ gettext("Disks"),
+ gettext("GEOM Mirror"),
+ gettext("Initialize"));
+
+require_once("freenas_config.inc");
+require_once("guiconfig.inc");
+require_once("freenas_guiconfig.inc");
+require_once("freenas_functions.inc");
+
+if (! empty($_POST))
+{
+ /* hash */
+ unset($error_bucket);
+ /* simple error list */
+ unset($input_errors);
+
+ $reqdfields = explode(" ", "disk");
+ $reqdfieldsn = explode(",", "Disk");
+
+ do_input_validation($_POST, $reqdfields, $reqdfieldsn, &$input_errors);
+
+ if (is_array($error_bucket))
+ foreach($error_bucket as $elem)
+ $input_errors[] =& $elem["error"];
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($error_bucket)) {
+ input_errors2Ajax(NULL, $error_bucket);
+ exit;
+ }
+
+ if (! $input_errors) {
+ $do_format = true;
+ $disk = $_POST['disk'];
+ }
+}
+
+if (! isset($do_format)) {
+ $do_format = false;
+ $disk = '';
+}
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc"); ?>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+
+<div id="inputerrors"></div>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Geom Mirror"), true, "disks_raid_gmirror.php");
+ $tab_array[1] = array(gettext("Geom Vinum (unstable)"), false, "disks_raid_gvinum.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Manage RAID"), false, "disks_raid_gmirror.php");
+ $tab_array[1] = array(gettext("Format RAID"), true, "disks_raid_gmirror_init.php");
+ $tab_array[2] = array(gettext("Tools"), false, "disks_raid_gmirror_tools.php");
+ $tab_array[3] = array(gettext("Information"), false, "disks_raid_gmirror_infos.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <form action="disks_raid_gmirror_init.php" method="post" name="iform" id="iform">
+ <table class="tabcont" align="center" width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?=gettext("Volume name");?></td>
+ <td width="78%" class="vtable">
+ <input name="disk" type="text" class="formfld" id="disk" size="20" value="<?=htmlspecialchars($disk);?>" />
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <input name="Submit" type="submit" class="formbtn" value="Save" />
+ <?php if (isset($id) && $a_raid[$id]): ?>
+ <input name="id" type="hidden" value="<?=$id;?>" />
+ <?php endif; ?>
+ </td>
+ </tr>
+ <tr>
+ <td valign="top" colspan="2">
+ <?
+ if ($do_format) {
+ echo("<strong>" . gettext("Disk format UFS output:") . "</strong><br />");
+ echo('<pre>');
+ ob_end_flush();
+
+ /* Create filesystem */
+ system("/sbin/newfs -U /dev/mirror/" . escapeshellarg($disk));
+
+ echo('</pre>');
+ }
+ ?>
+ </td>
+ </tr>
+ <tr>
+ <td align="left" valign="top" colspan="2">
+ <span class="red">
+ <strong>WARNING:</strong><br />
+ </span>
+ <span class="vexpl">
+ <?= gettext("This step will format the RAID volume in Unix FileSystem (UFS)."); ?>
+ </span>
+ </td>
+ </tr>
+ </table>
+ </form>
+ </div>
+ </td>
+ </tr>
+</table>
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/freenas/www/disks_raid_gmirror_tools.php b/config/freenas/www/disks_raid_gmirror_tools.php
new file mode 100644
index 00000000..0fe99576
--- /dev/null
+++ b/config/freenas/www/disks_raid_gmirror_tools.php
@@ -0,0 +1,191 @@
+<?php
+/*
+ disks_raid_gmirror_tools.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+$pgtitle = array(gettext("System"),
+ gettext("Disks"),
+ gettext("GEOM Mirror"),
+ gettext("Tools"));
+
+require_once("freenas_config.inc");
+require_once("guiconfig.inc");
+require_once("freenas_guiconfig.inc");
+require_once("freenas_functions.inc");
+
+if (! empty($_POST))
+{
+ /* hash */
+ unset($error_bucket);
+ /* simple error list */
+ unset($input_errors);
+
+ $reqdfields = explode(" ", "action object");
+ $reqdfieldsn = explode(",", "Action,Object");
+
+ do_input_validation($_POST, $reqdfields, $reqdfieldsn, &$input_errors);
+
+ if (is_array($error_bucket))
+ foreach($error_bucket as $elem)
+ $input_errors[] =& $elem["error"];
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($error_bucket)) {
+ input_errors2Ajax(NULL, $error_bucket);
+ exit;
+ }
+
+ if (!$input_errors) {
+ $do_action = true;
+ $action = $_POST['action'];
+ $object = $_POST['object'];
+ }
+ }
+ if (!isset($do_action)) {
+ $do_action = false;
+ $action = '';
+ $object = '';
+}
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc"); ?>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+
+<div id="inputerrors"></div>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Geom Mirror"), true, "disks_raid_gmirror.php");
+ $tab_array[1] = array(gettext("Geom Concat"), false, "disks_raid_gconcat.php");
+ $tab_array[2] = array(gettext("Geom Stripe"), false, "disks_raid_gstripe.php");
+ $tab_array[3] = array(gettext("Geom RAID5"), false, "disks_raid_graid5.php");
+ $tab_array[4] = array(gettext("Geom Vinum"), false, "disks_raid_gvinum.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Manage RAID"), false, "disks_raid_gmirror.php");
+ /* $tab_array[1] = array(gettext("Format RAID"), false, "disks_raid_gmirror_init.php"); */
+ $tab_array[1] = array(gettext("Tools"), true, "disks_raid_gmirror_tools.php");
+ $tab_array[2] = array(gettext("Information"), false, "disks_raid_gmirror_infos.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <form action="disks_raid_gmirror_tools.php" method="post" name="iform" id="iform">
+ <table class="tabcont" align="center" width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?=gettext("Object name");?></td>
+ <td width="78%" class="vtable">
+ <input name="object" type="text" class="formfld unknown" id="object" size="20" value="<?=htmlspecialchars($disk);?>" />
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?=gettext("Object name");?></td>
+ <td width="78%" class="vtable">
+ <select name="action" class="formselect" id="action">
+ <option value="rebuild" <?php if ($action == "rebuild") echo "selected=\"selected\""; ?>>rebuild</option>
+ <option value="list" <?php if ($action == "list") echo "selected=\"selected\""; ?>>list</option>
+ <option value="status" <?php if ($action == "status") echo "selected=\"selected\""; ?>>status</option>
+ <option value="remove" <?php if ($action == "remove") echo "selected=\"selected\""; ?>>remove</option>
+ <option value="activate" <?php if ($action == "activate") echo "selected=\"selected\""; ?>>activate</option>
+ <option value="deactivate" <?php if ($action == "deactivate") echo "selected=\"selected\""; ?>>deactivate</option>
+ <option value="forget" <?php if ($action == "forget") echo "selected=\"selected\""; ?>>forget</option>
+ <option value="clear" <?php if ($action == "clear") echo "selected=\"selected\""; ?>>clear</option>
+ <option value="stop" <?php if ($action == "stop") echo "selected=\"selected\""; ?>>stop</option>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <input name="Submit" type="submit" class="formbtn" value="Send Command!" />
+ </td>
+ </tr>
+ <tr>
+ <td valign="top" colspan="2">
+ <?
+ if ($do_action) {
+ echo("<strong>" . gettext("GMIRROR command output:") . "</strong><br />");
+ echo('<pre>');
+ ob_end_flush();
+
+ system("/sbin/gmirror $action " . escapeshellarg($object));
+
+ echo('</pre>');
+ }
+ ?>
+ </td>
+ </tr>
+ <tr>
+ <td align="left" valign="top" colspan="2">
+ <span class="red">
+ <strong>WARNING:</strong><br />
+ </span>
+ <ol>
+ <li><span class="vexpl"><?= gettext("Use these specials actions for debugging only!"); ?></span></li>
+ <li><span class="vexpl"><?= gettext("There is no need of using this menu for start a RAID volume (start automaticaly)."); ?></span></li>
+ </ol>
+ </td>
+ </tr>
+ </table>
+ </form>
+ </div>
+ </td>
+ </tr>
+</table>
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/freenas/www/disks_raid_graid5.php b/config/freenas/www/disks_raid_graid5.php
new file mode 100644
index 00000000..6273b077
--- /dev/null
+++ b/config/freenas/www/disks_raid_graid5.php
@@ -0,0 +1,236 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ disks_raid_graid5.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+$pgtitle = array(gettext("System"),
+ gettext("Disks"),
+ gettext("GEOM RAID5"),
+ gettext("RAID"));
+
+require_once("freenas_config.inc");
+require_once("guiconfig.inc");
+require_once("freenas_guiconfig.inc");
+require_once("freenas_functions.inc");
+
+if (!is_array($freenas_config['graid5']['vdisk']))
+ $freenas_config['graid5']['vdisk'] = array();
+
+graid5_sort();
+
+$raidstatus=get_sraid_disks_list();
+
+$a_raid = &$freenas_config['graid5']['vdisk'];
+
+if (! empty($_POST))
+{
+ /* hash */
+ unset($error_bucket);
+ /* simple error list */
+ unset($input_errors);
+
+ $pconfig = $_POST;
+
+ if (is_array($error_bucket))
+ foreach($error_bucket as $elem)
+ $input_errors[] =& $elem["error"];
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($error_bucket)) {
+ input_errors2Ajax(NULL, $error_bucket);
+ exit;
+ }
+
+ if ($_POST['apply']) {
+ $retval = 0;
+ if (!file_exists($d_sysrebootreqd_path))
+ {
+ config_lock();
+ /* reload all components that create raid device */
+ disks_raid_graid5_configure();
+ config_unlock();
+ write_config();
+ }
+ $savemsg = get_std_save_message($retval);
+ if ($retval == 0) {
+ if (file_exists($d_raidconfdirty_path))
+ unlink($d_raidconfdirty_path);
+ }
+ }
+}
+
+if ($_GET['act'] == "del") {
+ if ($a_raid[$_GET['id']]) {
+ $raidname=$a_raid[$_GET['id']]['name'];
+ disks_raid_graid5_delete($raidname);
+ unset($a_raid[$_GET['id']]);
+ write_config();
+ touch($d_raidconfdirty_path);
+ pfSenseHeader("disks_raid_graid5.php");
+ exit;
+ }
+}
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc"); ?>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+
+<form action="disks_raid_graid5.php" method="post" name="iform" id="iform">
+<?php if (file_exists($d_diskdirty_path)): ?>
+<?php print_info_box_np(gettext("The Raid configuration has been changed.") . "<br />" .
+ gettext("You must apply the changes in order for them to take effect."));?>
+<?php endif; ?>
+
+<div id="inputerrors"></div>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Geom Mirror"), false, "disks_raid_gmirror.php");
+ $tab_array[1] = array(gettext("Geom Concat"), false, "disks_raid_gconcat.php");
+ $tab_array[2] = array(gettext("Geom Stripe"), false, "disks_raid_gstripe.php");
+ $tab_array[3] = array(gettext("Geom RAID5"), true, "disks_raid_graid5.php");
+ $tab_array[4] = array(gettext("Geom Vinum"), false, "disks_raid_gvinum.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Manage RAID"), true, "disks_raid_graid5.php");
+ /* $tab_array[1] = array(gettext("Format RAID"), false, "disks_raid_gmirror_init.php"); */
+ $tab_array[1] = array(gettext("Tools"), false, "disks_raid_graid5_tools.php");
+ $tab_array[2] = array(gettext("Information"), false, "disks_raid_graid5_infos.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <table class="tabcont" width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="listhdrr"><?=gettext("Volume name");?></td>
+ <td class="listhdrr"><?=gettext("Type");?></td>
+ <td class="listhdrr"><?=gettext("Size");?></td>
+ <td class="listhdrr"><?=gettext("Status");?></td>
+ <td class="list">&nbsp;</td>
+ </tr>
+ <?php $i = 0; foreach ($a_raid as $raid): ?>
+ <tr>
+ <td valign="middle" class="listr">
+ <?=htmlspecialchars($raid['name']);?>
+ </td>
+ <td valign="middle" class="listr">
+ <?=htmlspecialchars($raid['type']);?>
+ </td>
+ <td valign="middle" class="listr">
+ <?php
+ $raidconfiguring = file_exists($d_raidconfdirty_path) &&
+ in_array($raid['name']."\n",file($d_raidconfdirty_path));
+ if ($raidconfiguring)
+ echo gettext("configuring");
+ else {
+ $tempo=$raid['name'];
+ echo "{$raidstatus[$tempo]['size']}";
+ }
+ ?>&nbsp;
+ </td>
+ <td valign="middle" class="listr">
+ <?php
+ if ($raidconfiguring)
+ echo gettext("configuring");
+ else {
+ echo "{$raidstatus[$tempo]['desc']}";
+ }
+ ?>&nbsp;
+ </td>
+ <td valign="middle" class="list">
+ <a href="disks_raid_graid5_edit.php?id=<?=$i;?>">
+ <img src="./themes/<?= $g['theme']; ?>/images/icons/icon_e.gif" title="<?=gettext("edit raid");?>" width="17" height="17" border="0" alt="" />
+ </a>
+ <a href="disks_raid_graid5.php?act=del&id=<?=$i;?>">
+ <img src="./themes/<?= $g['theme']; ?>/images/icons/icon_x.gif" title="<?=gettext("delete raid");?>" width="17" height="17" border="0" alt="" />
+ </a>
+ </td>
+ </tr>
+ <?php $i++; endforeach; ?>
+ <tr>
+ <td class="list" colspan="4"></td>
+ <td class="list" nowrap>
+ <a href="disks_raid_graid5_edit.php">
+ <img src="./themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" title="<?=gettext("add disk");?>" width="17" height="17" border="0" alt="" />
+ </a>
+ </td>
+ </tr>
+ <tr>
+ <td align="left" valign="top" colspan="5">
+ <span class="red">
+ <strong><?= gettext("Note:"); ?></strong>
+ </span>
+ <br />
+ <span class="vexpl"><?= gettext("Optional configuration step: Configuring a virtual RAID disk using your"); ?></span>
+ <br />
+ <span class="vexpl"><a href="disks_manage.php"><?= gettext("previsously configured disk."); ?></a></span>
+ <br />
+ <span class="vexpl"><?= gettext("Wait for the \"up\" status before format it and mount it!."); ?></span>
+ </span>
+ </td>
+ </tr>
+ </table>
+ </div>
+ </td>
+ </tr>
+</table>
+</form>
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/freenas/www/disks_raid_graid5_edit.php b/config/freenas/www/disks_raid_graid5_edit.php
new file mode 100644
index 00000000..27069f6c
--- /dev/null
+++ b/config/freenas/www/disks_raid_graid5_edit.php
@@ -0,0 +1,258 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ disks_raid_graid5_edit.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+$pgtitle = array(gettext("System"),
+ gettext("Disks"),
+ gettext("GEOM RAID5"),
+ gettext("RAID"),
+ isset($id) ? gettext("Edit") : gettext("Add"));
+
+require_once("freenas_config.inc");
+require_once("guiconfig.inc");
+require_once("freenas_guiconfig.inc");
+require_once("freenas_functions.inc");
+
+$id = $_GET['id'];
+if (isset($_POST['id']))
+ $id = $_POST['id'];
+
+if (!is_array($freenas_config['graid5']['vdisk']))
+ $freenas_config['graid5']['vdisk'] = array();
+
+graid5_sort();
+disks_sort();
+
+$a_raid = &$freenas_config['graid5']['vdisk'];
+$all_raid = array_merge((array)$freenas_config['graid5']['vdisk'],(array)$freenas_config['graid5']['vdisk'],(array)$freenas_config['gvinum']['vdisk'],(array)$freenas_config['gstripe']['vdisk'],(array)$freenas_config['graid5']['vdisk']);
+$a_disk = get_fstype_disks_list("softraid");
+
+if (!sizeof($a_disk)) {
+ $nodisk_errors[] = gettext("You must add disks first.");
+}
+
+if (isset($id) && $a_raid[$id]) {
+ $pconfig['name'] = $a_raid[$id]['name'];
+ $pconfig['type'] = $a_raid[$id]['type'];
+ $pconfig['diskr'] = $a_raid[$id]['diskr'];
+ $pconfig['fullname'] = $a_raid[$id]['fullname'];
+}
+
+if (! empty($_POST))
+{
+ /* hash */
+ unset($error_bucket);
+ /* simple error list */
+ unset($input_errors);
+
+ $reqdfields = explode(" ", "name");
+ $reqdfieldsn = explode(",", "Name");
+
+ do_input_validation($_POST, $reqdfields, $reqdfieldsn, &$input_errors);
+
+ if (($_POST['name'] && !is_validaliasname($_POST['name'])))
+ {
+ $error_bucket[] = array("error" => gettext("The device name may only consist of the characters a-z, A-Z, 0-9."),
+ "field" => "name");
+ }
+
+ /* check for name conflicts */
+ foreach ($a_raid as $raid)
+ {
+ if (isset($id) && ($a_raid[$id]) && ($a_raid[$id] === $raid))
+ continue;
+
+ if ($raid['name'] == $_POST['name'])
+ {
+ $error_bucket[] = array("error" => gettext("This device already exists in the raid volume list."),
+ "field" => "name");
+ break;
+ }
+ }
+
+ /* check the number of RAID disk for volume */
+
+ if (count($_POST['diskr']) < 3)
+ $error_bucket[] = array("error" => gettext("There must be a minimum of 3 disks in a RAID 5 volume."),
+ "field" => "diskr");
+
+ if (is_array($error_bucket))
+ foreach($error_bucket as $elem)
+ $input_errors[] =& $elem["error"];
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($error_bucket)) {
+ input_errors2Ajax(NULL, $error_bucket);
+ exit;
+ }
+
+ if (!$input_errors) {
+ $raid = array();
+ $raid['name'] = $_POST['name'];
+ $raid['type'] = "JBOD";
+ $raid['diskr'] = $_POST['diskr'];
+ $raid['desc'] = "Software graid5 RAID 5";
+ $raid['fullname'] = "/dev/raid5/{$raid['name']}";
+
+ if (isset($id) && $a_raid[$id])
+ $a_raid[$id] = $raid;
+ else
+ $a_raid[] = $raid;
+
+ $fd = @fopen("$d_raidconfdirty_path", "a");
+ if (!$fd) {
+ echo "ERR Could not save RAID configuration.\n";
+ exit(0);
+ }
+ fwrite($fd, "$raid[name]\n");
+ fclose($fd);
+
+ write_config();
+
+ pfSenseHeader("disks_raid_graid5.php");
+ exit;
+ }
+}
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc"); ?>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+
+<div id="inputerrors"></div>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Geom Mirror"), false, "disks_raid_gmirror.php");
+ $tab_array[1] = array(gettext("Geom Concat"), false, "disks_raid_gconcat.php");
+ $tab_array[2] = array(gettext("Geom Stripe"), false, "disks_raid_gstripe.php");
+ $tab_array[3] = array(gettext("Geom RAID5"), true, "disks_raid_graid5.php");
+ $tab_array[4] = array(gettext("Geom Vinum"), false, "disks_raid_gvinum.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Manage RAID"), true, "disks_raid_graid5.php");
+ /* $tab_array[1] = array(gettext("Format RAID"), false, "disks_raid_gmirror_init.php"); */
+ $tab_array[1] = array(gettext("Tools"), false, "disks_raid_graid5_tools.php");
+ $tab_array[2] = array(gettext("Information"), false, "disks_raid_graid5_infos.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <form action="disks_raid_graid5_edit.php" method="post" name="iform" id="iform">
+ <table class="tabcont" align="center" width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?=gettext("Raid name");?></td>
+ <td width="78%" class="vtable">
+ <input name="name" type="text" class="formfld unknown" id="name" size="20" value="<?=htmlspecialchars($pconfig['name']);?>" />
+ </td>
+ </tr>
+ <tr>
+ <td valign="top" class="vncellreq"><?= gettext("Type"); ?></td>
+ <td class="vtable">
+ RAID 5 (<?= gettext("rotated block-interleaved parity"); ?>)
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?= gettext("Members of this volume"); ?></td>
+ <td width="78%" class="vtable">
+ <?
+ $i=0;
+ $disable_script="";
+
+ foreach ($a_disk as $diskv) {
+ $r_name="";
+
+ foreach($all_raid as $raid) {
+ if (in_array($diskv['fullname'],(array)$raid['diskr'])) {
+ $r_name=$raid['name'];
+ if ($r_name!=$pconfig['name']) $disable_script.="document.getElementById($i).disabled=1;\n";
+ break;
+ }
+ }
+ echo "<input name='diskr[]' id='$i' type='checkbox' value='$diskv[fullname]'".
+ ((is_array($pconfig['diskr']) && in_array($diskv['fullname'],$pconfig['diskr'])) ? " checked=\"checked\"" : "") .
+ " />$diskv[name] ($diskv[size], $diskv[desc])".(($r_name) ? " - assigned to $r_name" : "")."<br />\n";
+ $i++;
+
+ $i++;
+ }
+
+ if ($disable_script)
+ echo "<script type='text/javascript'><!--\n$disable_script--></script>\n";
+ ?>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <input name="Submit" type="submit" class="formbtn" value="Save" />
+ <?php if (isset($id) && $a_raid[$id]): ?>
+ <input name="id" type="hidden" value="<?=$id;?>" />
+ <?php endif; ?>
+ </td>
+ </tr>
+ </table>
+ </form>
+ </div>
+ </td>
+ </tr>
+</table>
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/freenas/www/disks_raid_graid5_infos.php b/config/freenas/www/disks_raid_graid5_infos.php
new file mode 100644
index 00000000..31506011
--- /dev/null
+++ b/config/freenas/www/disks_raid_graid5_infos.php
@@ -0,0 +1,143 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ disks_raid_graid5_infos.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+$pgtitle = array(gettext("System"),
+ gettext("Disks"),
+ gettext("GEOM RAID5"),
+ gettext("Information"));
+
+require_once("guiconfig.inc");
+require_once("freenas_guiconfig.inc");
+require_once("freenas_functions.inc");
+
+if (! empty($_POST))
+{
+ /* hash */
+ unset($error_bucket);
+ /* simple error list */
+ unset($input_errors);
+
+ if (is_array($error_bucket))
+ foreach($error_bucket as $elem)
+ $input_errors[] =& $elem["error"];
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($error_bucket)) {
+ input_errors2Ajax(NULL, $error_bucket);
+ exit;
+ }
+
+ if (!$input_errors) {
+ }
+}
+if (!isset($do_action)) {
+}
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc"); ?>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+
+<div id="inputerrors"></div>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Geom Mirror"), false, "disks_raid_gmirror.php");
+ $tab_array[1] = array(gettext("Geom Concat"), false, "disks_raid_gconcat.php");
+ $tab_array[2] = array(gettext("Geom Stripe"), false, "disks_raid_gstripe.php");
+ $tab_array[3] = array(gettext("Geom RAID5"), true, "disks_raid_graid5.php");
+ $tab_array[4] = array(gettext("Geom Vinum"), false, "disks_raid_gvinum.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Manage RAID"), false, "disks_raid_graid5.php");
+ /* $tab_array[1] = array(gettext("Format RAID"), false, "disks_raid_gconcat_init.php"); */
+ $tab_array[1] = array(gettext("Tools"), false, "disks_raid_graid5_tools.php");
+ $tab_array[2] = array(gettext("Information"), true, "disks_raid_graid5_infos.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <form action="disks_raid_graid5_infos.php" method="post" name="iform" id="iform">
+ <table class="tabcont" align="center" width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="100%" class="vtable">
+ <?php
+ echo "<pre>";
+ echo "<strong>" . gettext("Software RAID information and status") . "</strong><br />";
+
+ exec("/sbin/graid5 list",$rawdata);
+ foreach ($rawdata as $line){
+ echo htmlspecialchars($line) . "<br>";
+ }
+
+ unset ($line);
+ echo "</pre>";
+ ?>
+ </td>
+ </tr>
+ </table>
+ </form>
+ </div>
+ </td>
+ </tr>
+</table>
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/freenas/www/disks_raid_graid5_tools.php b/config/freenas/www/disks_raid_graid5_tools.php
new file mode 100644
index 00000000..c8b3cf5b
--- /dev/null
+++ b/config/freenas/www/disks_raid_graid5_tools.php
@@ -0,0 +1,190 @@
+<?php
+/*
+ disks_raid_graid5_tools.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+$pgtitle = array(gettext("System"),
+ gettext("Disks"),
+ gettext("GEOM RAID5"),
+ gettext("Tools"));
+
+require_once("freenas_config.inc");
+require_once("guiconfig.inc");
+require_once("freenas_guiconfig.inc");
+require_once("freenas_functions.inc");
+
+if (! empty($_POST))
+{
+ /* hash */
+ unset($error_bucket);
+ /* simple error list */
+ unset($input_errors);
+ unset($do_action);
+
+ $reqdfields = explode(" ", "action object");
+ $reqdfieldsn = explode(",", "Action,Object");
+
+ do_input_validation($_POST, $reqdfields, $reqdfieldsn, &$input_errors);
+
+ if (is_array($error_bucket))
+ foreach($error_bucket as $elem)
+ $input_errors[] =& $elem["error"];
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($error_bucket)) {
+ input_errors2Ajax(NULL, $error_bucket);
+ exit;
+ }
+
+ if (!$input_errors) {
+ $do_action = true;
+ $action = $_POST['action'];
+ $object = $_POST['object'];
+ }
+ }
+ if (!isset($do_action)) {
+ $do_action = false;
+ $action = '';
+ $object = '';
+}
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc"); ?>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+
+<div id="inputerrors"></div>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Geom Mirror"), false, "disks_raid_gmirror.php");
+ $tab_array[1] = array(gettext("Geom Concat"), false, "disks_raid_gconcat.php");
+ $tab_array[2] = array(gettext("Geom Stripe"), false, "disks_raid_gstripe.php");
+ $tab_array[3] = array(gettext("Geom RAID5"), true, "disks_raid_graid5.php");
+ $tab_array[4] = array(gettext("Geom Vinum"), false, "disks_raid_gvinum.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Manage RAID"), false, "disks_raid_graid5.php");
+ /* $tab_array[1] = array(gettext("Format RAID"), false, "disks_raid_graid5_init.php"); */
+ $tab_array[1] = array(gettext("Tools"), true, "disks_raid_graid5_tools.php");
+ $tab_array[2] = array(gettext("Information"), false, "disks_raid_graid5_infos.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <form action="disks_raid_graid5_tools.php" method="post" name="iform" id="iform">
+ <table class="tabcont" align="center" width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?=gettext("Object name");?></td>
+ <td width="78%" class="vtable">
+ <input name="object" type="text" class="formfld unknown" id="object" size="20" value="<?=htmlspecialchars($disk);?>" />
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?=gettext("Object name");?></td>
+ <td width="78%" class="vtable">
+ <select name="action" class="formselect" id="action">
+ <option value="list" <?php if ($action == "list") echo "selected"; ?>>list</option>
+ <option value="status" <?php if ($action == "status") echo "selected"; ?>>status</option>
+ <option value="insert" <?php if ($action == "insert") echo "selected"; ?>>insert</option>
+ <option value="remove" <?php if ($action == "remove") echo "selected"; ?>>remove</option>
+ <option value="clear" <?php if ($action == "clear") echo "selected"; ?>>clear</option>
+ <option value="stop" <?php if ($action == "stop") echo "selected"; ?>>stop</option>
+ <option value="destroy" <?php if ($action == "destroy") echo "selected"; ?>>destroy</option>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <input name="Submit" type="submit" class="formbtn" value="Send Command!" />
+ </td>
+ </tr>
+ <tr>
+ <td valign="top" colspan="2">
+ <?
+ if ($do_action) {
+ echo("<strong>" . gettext("GCONCAT command output:") . "</strong><br />");
+ echo('<pre>');
+ ob_end_flush();
+
+ system("/sbin/graid5 $action " . escapeshellarg($object));
+
+ echo('</pre>');
+ }
+ ?>
+ </td>
+ </tr>
+ <tr>
+ <td align="left" valign="top" colspan="2">
+ <span class="red">
+ <strong>WARNING:</strong><br />
+ </span>
+ <ol>
+ <li><span class="vexpl"><?= gettext("Use these specials actions for debugging only!"); ?></span></li>
+ <li><span class="vexpl"><?= gettext("There is no need of using this menu for start a RAID volume (start automaticaly)."); ?></span></li>
+ </ol>
+ </td>
+ </tr>
+ </table>
+ </form>
+ </div>
+ </td>
+ </tr>
+</table>
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/freenas/www/disks_raid_gstripe.php b/config/freenas/www/disks_raid_gstripe.php
new file mode 100644
index 00000000..4d5f622d
--- /dev/null
+++ b/config/freenas/www/disks_raid_gstripe.php
@@ -0,0 +1,236 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ disks_raid_gstripe.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+$pgtitle = array(gettext("System"),
+ gettext("Disks"),
+ gettext("GEOM Stripe"),
+ gettext("RAID"));
+
+require_once("freenas_config.inc");
+require_once("guiconfig.inc");
+require_once("freenas_guiconfig.inc");
+require_once("freenas_functions.inc");
+
+if (!is_array($freenas_config['gstripe']['vdisk']))
+ $freenas_config['gstripe']['vdisk'] = array();
+
+gstripe_sort();
+
+$raidstatus=get_sraid_disks_list();
+
+$a_raid = &$freenas_config['gstripe']['vdisk'];
+
+if (! empty($_POST))
+{
+ /* hash */
+ unset($error_bucket);
+ /* simple error list */
+ unset($input_errors);
+
+ $pconfig = $_POST;
+
+ if (is_array($error_bucket))
+ foreach($error_bucket as $elem)
+ $input_errors[] =& $elem["error"];
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($error_bucket)) {
+ input_errors2Ajax(NULL, $error_bucket);
+ exit;
+ }
+
+ if ($_POST['apply']) {
+ $retval = 0;
+ if (!file_exists($d_sysrebootreqd_path))
+ {
+ config_lock();
+ /* reload all components that create raid device */
+ disks_raid_gstripe_configure();
+ config_unlock();
+ write_config();
+ }
+ $savemsg = get_std_save_message($retval);
+ if ($retval == 0) {
+ if (file_exists($d_raidconfdirty_path))
+ unlink($d_raidconfdirty_path);
+ }
+ }
+}
+
+if ($_GET['act'] == "del") {
+ if ($a_raid[$_GET['id']]) {
+ $raidname=$a_raid[$_GET['id']]['name'];
+ disks_raid_gstripe_delete($raidname);
+ unset($a_raid[$_GET['id']]);
+ write_config();
+ touch($d_raidconfdirty_path);
+ pfSenseHeader("disks_raid_gstripe.php");
+ exit;
+ }
+}
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc"); ?>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+
+<form action="disks_raid_gstripe.php" method="post" name="iform" id="iform">
+<?php if (file_exists($d_diskdirty_path)): ?>
+<?php print_info_box_np(gettext("The Raid configuration has been changed.") . "<br />" .
+ gettext("You must apply the changes in order for them to take effect."));?>
+<?php endif; ?>
+
+<div id="inputerrors"></div>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Geom Mirror"), false, "disks_raid_gmirror.php");
+ $tab_array[1] = array(gettext("Geom Concat"), false, "disks_raid_gconcat.php");
+ $tab_array[2] = array(gettext("Geom Stripe"), true, "disks_raid_gstripe.php");
+ $tab_array[3] = array(gettext("Geom RAID5"), false, "disks_raid_graid5.php");
+ $tab_array[4] = array(gettext("Geom Vinum"), false, "disks_raid_gvinum.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Manage RAID"), true, "disks_raid_gstripe.php");
+ /* $tab_array[1] = array(gettext("Format RAID"), false, "disks_raid_gmirror_init.php"); */
+ $tab_array[1] = array(gettext("Tools"), false, "disks_raid_gstripe_tools.php");
+ $tab_array[2] = array(gettext("Information"), false, "disks_raid_gstripe_infos.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <table class="tabcont" width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="listhdrr"><?=gettext("Volume name");?></td>
+ <td class="listhdrr"><?=gettext("Type");?></td>
+ <td class="listhdrr"><?=gettext("Size");?></td>
+ <td class="listhdrr"><?=gettext("Status");?></td>
+ <td class="list">&nbsp;</td>
+ </tr>
+ <?php $i = 0; foreach ($a_raid as $raid): ?>
+ <tr>
+ <td valign="middle" class="listr">
+ <?=htmlspecialchars($raid['name']);?>
+ </td>
+ <td valign="middle" class="listr">
+ <?=htmlspecialchars($raid['type']);?>
+ </td>
+ <td valign="middle" class="listr">
+ <?php
+ $raidconfiguring = file_exists($d_raidconfdirty_path) &&
+ in_array($raid['name']."\n",file($d_raidconfdirty_path));
+ if ($raidconfiguring)
+ echo gettext("configuring");
+ else {
+ $tempo=$raid['name'];
+ echo "{$raidstatus[$tempo]['size']}";
+ }
+ ?>&nbsp;
+ </td>
+ <td valign="middle" class="listr">
+ <?php
+ if ($raidconfiguring)
+ echo gettext("configuring");
+ else {
+ echo "{$raidstatus[$tempo]['desc']}";
+ }
+ ?>&nbsp;
+ </td>
+ <td valign="middle" class="list">
+ <a href="disks_raid_gstripe_edit.php?id=<?=$i;?>">
+ <img src="./themes/<?= $g['theme']; ?>/images/icons/icon_e.gif" title="<?=gettext("edit raid");?>" width="17" height="17" border="0" alt="" />
+ </a>
+ <a href="disks_raid_gstripe.php?act=del&id=<?=$i;?>">
+ <img src="./themes/<?= $g['theme']; ?>/images/icons/icon_x.gif" title="<?=gettext("delete raid");?>" width="17" height="17" border="0" alt="" />
+ </a>
+ </td>
+ </tr>
+ <?php $i++; endforeach; ?>
+ <tr>
+ <td class="list" colspan="4"></td>
+ <td class="list" nowrap>
+ <a href="disks_raid_gstripe_edit.php">
+ <img src="./themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" title="<?=gettext("add disk");?>" width="17" height="17" border="0" alt="" />
+ </a>
+ </td>
+ </tr>
+ <tr>
+ <td align="left" valign="top" colspan="5">
+ <span class="red">
+ <strong><?= gettext("Note:"); ?></strong>
+ </span>
+ <br />
+ <span class="vexpl"><?= gettext("Optional configuration step: Configuring a virtual RAID disk using your"); ?></span>
+ <br />
+ <span class="vexpl"><a href="disks_manage.php"><?= gettext("previsously configured disk."); ?></a></span>
+ <br />
+ <span class="vexpl"><?= gettext("Wait for the \"up\" status before format it and mount it!."); ?></span>
+ </span>
+ </td>
+ </tr>
+ </table>
+ </div>
+ </td>
+ </tr>
+</table>
+</form>
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/freenas/www/disks_raid_gstripe_edit.php b/config/freenas/www/disks_raid_gstripe_edit.php
new file mode 100644
index 00000000..ab18d6e7
--- /dev/null
+++ b/config/freenas/www/disks_raid_gstripe_edit.php
@@ -0,0 +1,258 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ disks_raid_gstripe_edit.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+$pgtitle = array(gettext("System"),
+ gettext("Disks"),
+ gettext("GEOM Stripe"),
+ gettext("RAID"),
+ gettext("Edit"));
+
+require_once("freenas_config.inc");
+require_once("guiconfig.inc");
+require_once("freenas_guiconfig.inc");
+require_once("freenas_functions.inc");
+
+$id = $_GET['id'];
+if (isset($_POST['id']))
+ $id = $_POST['id'];
+
+if (!is_array($freenas_config['gstripe']['vdisk']))
+ $freenas_config['gstripe']['vdisk'] = array();
+
+gstripe_sort();
+disks_sort();
+
+$a_raid = &$freenas_config['gstripe']['vdisk'];
+$all_raid = array_merge((array)$freenas_config['gstripe']['vdisk'],(array)$freenas_config['gstripe']['vdisk'],(array)$freenas_config['gvinum']['vdisk'],(array)$freenas_config['gstripe']['vdisk'],(array)$freenas_config['gstripe']['vdisk']);
+$a_disk = get_fstype_disks_list("softraid");
+
+if (!sizeof($a_disk)) {
+ $nodisk_errors[] = gettext("You must add disks first.");
+}
+
+if (isset($id) && $a_raid[$id]) {
+ $pconfig['name'] = $a_raid[$id]['name'];
+ $pconfig['type'] = $a_raid[$id]['type'];
+ $pconfig['diskr'] = $a_raid[$id]['diskr'];
+ $pconfig['fullname'] = $a_raid[$id]['fullname'];
+}
+
+if (! empty($_POST))
+{
+ /* hash */
+ unset($error_bucket);
+ /* simple error list */
+ unset($input_errors);
+
+ $reqdfields = explode(" ", "name");
+ $reqdfieldsn = explode(",", "Name");
+
+ do_input_validation($_POST, $reqdfields, $reqdfieldsn, &$input_errors);
+
+ if (($_POST['name'] && !is_validaliasname($_POST['name'])))
+ {
+ $error_bucket[] = array("error" => gettext("The device name may only consist of the characters a-z, A-Z, 0-9."),
+ "field" => "name");
+ }
+
+ /* check for name conflicts */
+ foreach ($a_raid as $raid)
+ {
+ if (isset($id) && ($a_raid[$id]) && ($a_raid[$id] === $raid))
+ continue;
+
+ if ($raid['name'] == $_POST['name'])
+ {
+ $error_bucket[] = array("error" => gettext("This device already exists in the raid volume list."),
+ "field" => "name");
+ break;
+ }
+ }
+
+ /* check the number of RAID disk for volume */
+
+ if (count($_POST['diskr']) < 2)
+ $error_bucket[] = array("error" => gettext("There must be a minimum of 2 disks in a RAID 0 volume."),
+ "field" => "diskr");
+
+ if (is_array($error_bucket))
+ foreach($error_bucket as $elem)
+ $input_errors[] =& $elem["error"];
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($error_bucket)) {
+ input_errors2Ajax(NULL, $error_bucket);
+ exit;
+ }
+
+ if (!$input_errors) {
+ $raid = array();
+ $raid['name'] = $_POST['name'];
+ $raid['type'] = "JBOD";
+ $raid['diskr'] = $_POST['diskr'];
+ $raid['desc'] = "Software gstripe RAID 0";
+ $raid['fullname'] = "/dev/stripe/{$raid['name']}";
+
+ if (isset($id) && $a_raid[$id])
+ $a_raid[$id] = $raid;
+ else
+ $a_raid[] = $raid;
+
+ $fd = @fopen("$d_raidconfdirty_path", "a");
+ if (!$fd) {
+ echo "ERR Could not save RAID configuration.\n";
+ exit(0);
+ }
+ fwrite($fd, "$raid[name]\n");
+ fclose($fd);
+
+ write_config();
+
+ pfSenseHeader("disks_raid_gstripe.php");
+ exit;
+ }
+}
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc"); ?>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+
+<div id="inputerrors"></div>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Geom Mirror"), false, "disks_raid_gmirror.php");
+ $tab_array[1] = array(gettext("Geom Concat"), false, "disks_raid_gconcat.php");
+ $tab_array[2] = array(gettext("Geom Stripe"), true, "disks_raid_gstripe.php");
+ $tab_array[3] = array(gettext("Geom RAID5"), false, "disks_raid_graid5.php");
+ $tab_array[4] = array(gettext("Geom Vinum"), false, "disks_raid_gvinum.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Manage RAID"), true, "disks_raid_gstripe.php");
+ /* $tab_array[1] = array(gettext("Format RAID"), false, "disks_raid_gmirror_init.php"); */
+ $tab_array[1] = array(gettext("Tools"), false, "disks_raid_gstripe_tools.php");
+ $tab_array[2] = array(gettext("Information"), false, "disks_raid_gstripe_infos.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <form action="disks_raid_gstripe_edit.php" method="post" name="iform" id="iform">
+ <table class="tabcont" align="center" width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?=gettext("Raid name");?></td>
+ <td width="78%" class="vtable">
+ <input name="name" type="text" class="formfld unknown" id="name" size="20" value="<?=htmlspecialchars($pconfig['name']);?>" />
+ </td>
+ </tr>
+ <tr>
+ <td valign="top" class="vncellreq"><?= gettext("Type"); ?></td>
+ <td class="vtable">
+ RAID 5 (<?= gettext("rotated block-interleaved parity"); ?>)
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?= gettext("Members of this volume"); ?></td>
+ <td width="78%" class="vtable">
+ <?
+ $i=0;
+ $disable_script="";
+
+ foreach ($a_disk as $diskv) {
+ $r_name="";
+
+ foreach($all_raid as $raid) {
+ if (in_array($diskv['fullname'],(array)$raid['diskr'])) {
+ $r_name=$raid['name'];
+ if ($r_name!=$pconfig['name']) $disable_script.="document.getElementById($i).disabled=1;\n";
+ break;
+ }
+ }
+ echo "<input name='diskr[]' id='$i' type='checkbox' value='$diskv[fullname]'".
+ ((is_array($pconfig['diskr']) && in_array($diskv['fullname'],$pconfig['diskr'])) ? " checked=\"checked\"" : "") .
+ " />$diskv[name] ($diskv[size], $diskv[desc])".(($r_name) ? " - assigned to $r_name" : "")."<br />\n";
+ $i++;
+
+ $i++;
+ }
+
+ if ($disable_script)
+ echo "<script type='text/javascript'><!--\n$disable_script--></script>\n";
+ ?>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <input name="Submit" type="submit" class="formbtn" value="Save" />
+ <?php if (isset($id) && $a_raid[$id]): ?>
+ <input name="id" type="hidden" value="<?=$id;?>" />
+ <?php endif; ?>
+ </td>
+ </tr>
+ </table>
+ </form>
+ </div>
+ </td>
+ </tr>
+</table>
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/freenas/www/disks_raid_gstripe_infos.php b/config/freenas/www/disks_raid_gstripe_infos.php
new file mode 100644
index 00000000..5d8a6de0
--- /dev/null
+++ b/config/freenas/www/disks_raid_gstripe_infos.php
@@ -0,0 +1,143 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ disks_raid_stripe_infos.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+$pgtitle = array(gettext("System"),
+ gettext("Disks"),
+ gettext("GEOM Stripe"),
+ gettext("Information"));
+
+require_once("guiconfig.inc");
+require_once("freenas_guiconfig.inc");
+require_once("freenas_functions.inc");
+
+if (! empty($_POST))
+{
+ /* hash */
+ unset($error_bucket);
+ /* simple error list */
+ unset($input_errors);
+
+ if (is_array($error_bucket))
+ foreach($error_bucket as $elem)
+ $input_errors[] =& $elem["error"];
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($error_bucket)) {
+ input_errors2Ajax(NULL, $error_bucket);
+ exit;
+ }
+
+ if (!$input_errors) {
+ }
+}
+if (!isset($do_action)) {
+}
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc"); ?>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+
+<div id="inputerrors"></div>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Geom Mirror"), false, "disks_raid_gmirror.php");
+ $tab_array[1] = array(gettext("Geom Concat"), false, "disks_raid_gconcat.php");
+ $tab_array[2] = array(gettext("Geom Stripe"), true, "disks_raid_gstripe.php");
+ $tab_array[3] = array(gettext("Geom RAID5"), false, "disks_raid_graid5.php");
+ $tab_array[4] = array(gettext("Geom Vinum"), false, "disks_raid_gvinum.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Manage RAID"), false, "disks_raid_gstripe.php");
+ /* $tab_array[1] = array(gettext("Format RAID"), false, "disks_raid_gconcat_init.php"); */
+ $tab_array[1] = array(gettext("Tools"), false, "disks_raid_gstripe_tools.php");
+ $tab_array[2] = array(gettext("Information"), true, "disks_raid_gstripe_infos.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <form action="disks_raid_gstripe_infos.php" method="post" name="iform" id="iform">
+ <table class="tabcont" align="center" width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="100%" class="vtable">
+ <?php
+ echo "<pre>";
+ echo "<strong>" . gettext("Software RAID information and status") . "</strong><br />";
+
+ exec("/sbin/gstripe list",$rawdata);
+ foreach ($rawdata as $line){
+ echo htmlspecialchars($line) . "<br>";
+ }
+
+ unset ($line);
+ echo "</pre>";
+ ?>
+ </td>
+ </tr>
+ </table>
+ </form>
+ </div>
+ </td>
+ </tr>
+</table>
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/freenas/www/disks_raid_gstripe_tools.php b/config/freenas/www/disks_raid_gstripe_tools.php
new file mode 100644
index 00000000..6bc7891a
--- /dev/null
+++ b/config/freenas/www/disks_raid_gstripe_tools.php
@@ -0,0 +1,187 @@
+<?php
+/*
+ disks_raid_stripe_tools.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+$pgtitle = array(gettext("System"),
+ gettext("Disks"),
+ gettext("GEOM Stripe"),
+ gettext("Tools"));
+
+require_once("freenas_config.inc");
+require_once("guiconfig.inc");
+require_once("freenas_guiconfig.inc");
+require_once("freenas_functions.inc");
+
+if (! empty($_POST))
+{
+ /* hash */
+ unset($error_bucket);
+ /* simple error list */
+ unset($input_errors);
+ unset($do_action);
+
+ $reqdfields = explode(" ", "action object");
+ $reqdfieldsn = explode(",", "Action,Object");
+
+ do_input_validation($_POST, $reqdfields, $reqdfieldsn, &$input_errors);
+
+ if (is_array($error_bucket))
+ foreach($error_bucket as $elem)
+ $input_errors[] =& $elem["error"];
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($error_bucket)) {
+ input_errors2Ajax(NULL, $error_bucket);
+ exit;
+ }
+
+ if (!$input_errors) {
+ $do_action = true;
+ $action = $_POST['action'];
+ $object = $_POST['object'];
+ }
+ }
+ if (!isset($do_action)) {
+ $do_action = false;
+ $action = '';
+ $object = '';
+}
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc"); ?>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+
+<div id="inputerrors"></div>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Geom Mirror"), false, "disks_raid_gmirror.php");
+ $tab_array[1] = array(gettext("Geom Concat"), false, "disks_raid_gconcat.php");
+ $tab_array[2] = array(gettext("Geom Stripe"), true, "disks_raid_gstripe.php");
+ $tab_array[3] = array(gettext("Geom RAID5"), false, "disks_raid_graid5.php");
+ $tab_array[4] = array(gettext("Geom Vinum"), false, "disks_raid_gvinum.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Manage RAID"), false, "disks_raid_gstripe.php");
+ /* $tab_array[1] = array(gettext("Format RAID"), false, "disks_raid_gstripe_init.php"); */
+ $tab_array[1] = array(gettext("Tools"), true, "disks_raid_gstripe_tools.php");
+ $tab_array[2] = array(gettext("Information"), false, "disks_raid_gstripe_infos.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <form action="disks_raid_gstripe_tools.php" method="post" name="iform" id="iform">
+ <table class="tabcont" align="center" width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?=gettext("Object name");?></td>
+ <td width="78%" class="vtable">
+ <input name="object" type="text" class="formfld unknown" id="object" size="20" value="<?=htmlspecialchars($disk);?>" />
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?=gettext("Object name");?></td>
+ <td width="78%" class="vtable">
+ <select name="action" class="formselect" id="action">
+ <option value="list" <?php if ($action == "list") echo "selected"; ?>>list</option>
+ <option value="status" <?php if ($action == "status") echo "selected"; ?>>status</option>
+ <option value="clear" <?php if ($action == "clear") echo "selected"; ?>>clear</option>
+ <option value="stop" <?php if ($action == "stop") echo "selected"; ?>>stop</option>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <input name="Submit" type="submit" class="formbtn" value="Send Command!" />
+ </td>
+ </tr>
+ <tr>
+ <td valign="top" colspan="2">
+ <?
+ if ($do_action) {
+ echo("<strong>" . gettext("GSTRIPE command output:") . "</strong><br />");
+ echo('<pre>');
+ ob_end_flush();
+
+ system("/sbin/gstripe $action " . escapeshellarg($object));
+
+ echo('</pre>');
+ }
+ ?>
+ </td>
+ </tr>
+ <tr>
+ <td align="left" valign="top" colspan="2">
+ <span class="red">
+ <strong>WARNING:</strong><br />
+ </span>
+ <ol>
+ <li><span class="vexpl"><?= gettext("Use these specials actions for debugging only!"); ?></span></li>
+ <li><span class="vexpl"><?= gettext("There is no need of using this menu for start a RAID volume (start automaticaly)."); ?></span></li>
+ </ol>
+ </td>
+ </tr>
+ </table>
+ </form>
+ </div>
+ </td>
+ </tr>
+</table>
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/freenas/www/disks_raid_gvinum.php b/config/freenas/www/disks_raid_gvinum.php
new file mode 100644
index 00000000..134b2fb5
--- /dev/null
+++ b/config/freenas/www/disks_raid_gvinum.php
@@ -0,0 +1,235 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ disks_raid_gvinum.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+$pgtitle = array(gettext("System"),
+ gettext("Disks"),
+ gettext("GEOM Vinum"),
+ gettext("RAID"));
+
+require_once("freenas_config.inc");
+require_once("guiconfig.inc");
+require_once("freenas_guiconfig.inc");
+require_once("freenas_functions.inc");
+
+if (!is_array($freenas_config['gvinum']['vdisk']))
+ $freenas_config['gvinum']['vdisk'] = array();
+
+gvinum_sort();
+
+$raidstatus=get_sraid_disks_list();
+
+$a_raid = &$freenas_config['gvinum']['vdisk'];
+
+if (! empty($_POST))
+{
+ /* hash */
+ unset($error_bucket);
+ /* simple error list */
+ unset($input_errors);
+
+ $pconfig = $_POST;
+
+ if (is_array($error_bucket))
+ foreach($error_bucket as $elem)
+ $input_errors[] =& $elem["error"];
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($error_bucket)) {
+ input_errors2Ajax(NULL, $error_bucket);
+ exit;
+ }
+
+ if ($_POST['apply']) {
+ $retval = 0;
+ if (!file_exists($d_sysrebootreqd_path))
+ {
+ config_lock();
+ /* reload all components that create raid device */
+ disks_raid_gvinum_configure();
+ config_unlock();
+ write_config();
+ }
+ $savemsg = get_std_save_message($retval);
+ if ($retval == 0) {
+ if (file_exists($d_raidconfdirty_path))
+ unlink($d_raidconfdirty_path);
+ }
+ }
+ }
+
+ if ($_GET['act'] == "del") {
+ if ($a_raid[$_GET['id']]) {
+ $raidname=$a_raid[$_GET['id']]['name'];
+ disks_raid_gvinum_delete($raidname);
+ unset($a_raid[$_GET['id']]);
+ write_config();
+ touch($d_raidconfdirty_path);
+ pfSenseHeader("disks_raid_gvinum.php");
+ exit;
+ }
+}
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc"); ?>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+
+<form action="disks_raid_gvinum.php" method="post" name="iform" id="iform">
+<?php if (file_exists($d_diskdirty_path)): ?>
+<?php print_info_box_np(gettext("The Raid configuration has been changed.") . "<br />" .
+ gettext("You must apply the changes in order for them to take effect."));?>
+<?php endif; ?>
+
+<div id="inputerrors"></div>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Geom Mirror"), false, "disks_raid_gmirror.php");
+ $tab_array[1] = array(gettext("Geom Concat"), false, "disks_raid_gconcat.php");
+ $tab_array[2] = array(gettext("Geom Stripe"), false, "disks_raid_gstripe.php");
+ $tab_array[3] = array(gettext("Geom RAID5"), false, "disks_raid_graid5.php");
+ $tab_array[4] = array(gettext("Geom Vinum"), true, "disks_raid_gvinum.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Manage RAID"), true, "disks_raid_gvinum.php");
+ /* $tab_array[1] = array(gettext("Format RAID"), false, "disks_raid_gmirror_init.php"); */
+ $tab_array[1] = array(gettext("Tools"), false, "disks_raid_gvinum_tools.php");
+ $tab_array[2] = array(gettext("Information"), false, "disks_raid_gvinum_infos.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <table class="tabcont" width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="listhdrr"><?=gettext("Volume name");?></td>
+ <td class="listhdrr"><?=gettext("Type");?></td>
+ <td class="listhdrr"><?=gettext("Size");?></td>
+ <td class="listhdrr"><?=gettext("Status");?></td>
+ <td class="list">&nbsp;</td>
+ </tr>
+ <?php $i = 0; foreach ($a_raid as $raid): ?>
+ <tr>
+ <td valign="middle" class="listr">
+ <?=htmlspecialchars($raid['name']);?>
+ </td>
+ <td valign="middle" class="listr">
+ <?=htmlspecialchars($raid['type']);?>
+ </td>
+ <td valign="middle" class="listr">
+ <?php
+ $raidconfiguring = file_exists($d_raidconfdirty_path) &&
+ in_array($raid['name']."\n",file($d_raidconfdirty_path));
+ if ($raidconfiguring)
+ echo gettext("configuring");
+ else {
+ $tempo=$raid['name'];
+ echo "{$raidstatus[$tempo]['size']}";
+ }
+ ?>&nbsp;
+ </td>
+ <td valign="middle" class="listr">
+ <?php
+ if ($raidconfiguring)
+ echo "_CONFIGURING";
+ else {
+ echo "{$raidstatus[$tempo]['desc']}";
+ }
+ ?>&nbsp;
+ </td>
+ <td valign="middle" class="list">
+ <a href="disks_raid_gvinum_edit.php?id=<?=$i;?>">
+ <img src="./themes/<?= $g['theme']; ?>/images/icons/icon_e.gif" title="<?=gettext("edit raid");?>" width="17" height="17" border="0" alt="" />
+ </a>
+ <a href="disks_raid_gvinum.php?act=del&id=<?=$i;?>">
+ <img src="./themes/<?= $g['theme']; ?>/images/icons/icon_x.gif" title="<?=gettext("delete raid");?>" width="17" height="17" border="0" alt="" />
+ </a>
+ </td>
+ </tr>
+ <?php $i++; endforeach; ?>
+ <tr>
+ <td class="list" colspan="4"></td>
+ <td class="list" nowrap>
+ <a href="disks_raid_gvinum_edit.php">
+ <img src="./themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" title="<?=gettext("add disk");?>" width="17" height="17" border="0" alt="" />
+ </a>
+ </td>
+ </tr>
+ <tr>
+ <td align="left" valign="top" colspan="5">
+ <span class="red">
+ <strong><?= gettext("Note:"); ?></strong>
+ </span>
+ <br />
+ <span class="vexpl"><?= gettext("Optional configuration step: Configuring a virtual RAID disk using your"); ?></span>
+ <br />
+ <span class="vexpl"><a href="disks_manage.php"><?= gettext("previsously configured disk."); ?></a></span>
+ <br />
+ <span class="vexpl"><?= gettext("Wait for the \"up\" status before format it and mount it!."); ?></span>
+ </td>
+ </tr>
+ </table>
+ </div>
+ </td>
+ </tr>
+</table>
+</form>
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/freenas/www/disks_raid_gvinum_edit.php b/config/freenas/www/disks_raid_gvinum_edit.php
new file mode 100644
index 00000000..e0245419
--- /dev/null
+++ b/config/freenas/www/disks_raid_gvinum_edit.php
@@ -0,0 +1,277 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ disks_raid_gvinum_edit.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+$pgtitle = array(gettext("System"),
+ gettext("Disks"),
+ gettext("GEOM Vinum"),
+ gettext("RAID"),
+ isset($id) ? gettext("Edit") : gettext("Add"));
+
+require_once("freenas_config.inc");
+require_once("guiconfig.inc");
+require_once("freenas_guiconfig.inc");
+require_once("freenas_functions.inc");
+
+if (!is_array($freenas_config['raid']['vdisk']))
+ $freenas_config['raid']['vdisk'] = array();
+
+gvinum_sort();
+disks_sort();
+
+$a_raid = &$freenas_config['gvinum']['vdisk'];
+$a_disk = get_fstype_disks_list("softraid");
+$all_raid = array_merge((array)$freenas_config['graid5']['vdisk'],(array)$freenas_config['gmirror']['vdisk'],(array)$freenas_config['gvinum']['vdisk'],(array)$freenas_config['gstripe']['vdisk'],(array)$freenas_config['gconcat']['vdisk']);
+
+$id = $_GET['id'];
+if (isset($_POST['id']))
+ $id = $_POST['id'];
+
+if (!sizeof($a_disk)) {
+ $nodisk_errors[] = gettext("You must add disks first.");
+}
+
+if (isset($id) && $a_raid[$id]) {
+ $pconfig['name'] = $a_raid[$id]['name'];
+ $pconfig['fullname'] = $a_raid[$id]['fullname'];
+ $pconfig['type'] = $a_raid[$id]['type'];
+ $pconfig['diskr'] = $a_raid[$id]['diskr'];
+}
+
+if (! empty($_POST))
+{
+ /* hash */
+ unset($error_bucket);
+ /* simple error list */
+ unset($input_errors);
+
+ $reqdfields = explode(" ", "name type");
+ $reqdfieldsn = explode(",", "Name,Type");
+
+ do_input_validation($_POST, $reqdfields, $reqdfieldsn, &$input_errors);
+
+ if (($_POST['name'] && !is_validaliasname($_POST['name'])))
+ {
+ $error_bucket[] = array("error" => gettext("The device name may only consist of the characters a-z, A-Z, 0-9."),
+ "field" => "name");
+ }
+
+ /* check for name conflicts */
+ foreach ($a_raid as $raid)
+ {
+ if (isset($id) && ($a_raid[$id]) && ($a_raid[$id] === $raid))
+ continue;
+
+ if ($raid['name'] == $_POST['name'])
+ {
+ $error_bucket[] = array("error" => gettext("This device already exists in the raid volume list."),
+ "field" => "name");
+ break;
+ }
+ }
+
+ /* check the number of RAID disk for volume */
+
+ switch ($_POST['type'])
+ {
+ case 0:
+ if (count($_POST['diskr']) < 2)
+ $error_bucket[] = array("error" => gettext("There must be a minimum of 2 disks in a RAID 0 volume."),
+ "field" => "diskr");
+ break;
+ case 1:
+ if (count($_POST['diskr']) != 2)
+ $error_bucket[] = array("error" => gettext("There must be 2 disks in a RAID 1 volume."),
+ "field" => "diskr");
+ break;
+ case 5:
+ if (count($_POST['diskr']) < 3)
+ $error_bucket[] = array("error" => gettext("There must be a minimum of 3 disks in a RAID 5 volume."),
+ "field" => "diskr");
+ break;
+ }
+
+ if (is_array($error_bucket))
+ foreach($error_bucket as $elem)
+ $input_errors[] =& $elem["error"];
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($error_bucket)) {
+ input_errors2Ajax(NULL, $error_bucket);
+ exit;
+ }
+
+ if (!$input_errors) {
+ $raid = array();
+ $raid['name'] = $_POST['name'];
+ $raid['type'] = $_POST['type'];
+ $raid['diskr'] = $_POST['diskr'];
+ $raid['desc'] = "Software gvinum RAID {$_POST['type']}";
+ $raid['fullname'] = "/dev/gvinum/{$raid['name']}";
+
+ if (isset($id) && $a_raid[$id])
+ $a_raid[$id] = $raid;
+ else
+ $a_raid[] = $raid;
+
+ $fd = @fopen("$d_raidconfdirty_path", "a");
+ if (!$fd) {
+ echo gettext("ERR Could not save RAID configuration.\n");
+ exit(0);
+ }
+ fwrite($fd, "$raid[name]\n");
+ fclose($fd);
+
+ write_config();
+
+ pfSenseHeader("disks_raid_gvinum.php");
+ exit;
+ }
+}
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc"); ?>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+
+<div id="inputerrors"></div>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Geom Mirror"), false, "disks_raid_gmirror.php");
+ $tab_array[1] = array(gettext("Geom Concat"), false, "disks_raid_gconcat.php");
+ $tab_array[2] = array(gettext("Geom Stripe"), false, "disks_raid_gstripe.php");
+ $tab_array[3] = array(gettext("Geom RAID5"), false, "disks_raid_graid5.php");
+ $tab_array[4] = array(gettext("Geom Vinum"), true, "disks_raid_gvinum.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Manage RAID"), true, "disks_raid_gvinum.php");
+ /* $tab_array[1] = array(gettext("Format RAID"), false, "disks_raid_gmirror_init.php"); */
+ $tab_array[1] = array(gettext("Tools"), false, "disks_raid_gvinum_tools.php");
+ $tab_array[2] = array(gettext("Information"), false, "disks_raid_gvinum_infos.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <form action="disks_raid_gvinum_edit.php" method="post" name="iform" id="iform">
+ <table class="tabcont" align="center" width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?=gettext("Raid name");?></td>
+ <td width="78%" class="vtable">
+ <input name="name" type="text" class="formfld unknown" id="name" size="20" value="<?=htmlspecialchars($pconfig['name']);?>" />
+ </td>
+ </tr>
+ <tr>
+ <td valign="top" class="vncellreq"><?= gettext("Type"); ?></td>
+ <td class="vtable">
+ <select name="type" class="formselect" id="type">
+ <option value="0" <?php if ($pconfig['type'] == 0) echo "selected=\"selected\""; ?>>RAID 0 (<?= gettext("striping"); ?>)</option>
+ <option value="1" <?php if ($pconfig['type'] == 1) echo "selected=\"selected\""; ?>>RAID 1 (<?= gettext("mirroring"); ?>)</option>
+ <option value="5" <?php if ($pconfig['type'] == 5) echo "selected=\"selected\""; ?>>RAID 5 (<?= gettext("rotated block-interleaved parity"); ?>)</option>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?= gettext("Members of this volume"); ?></td>
+ <td width="78%" class="vtable">
+ <?
+ $i=0;
+ $disable_script="";
+
+ foreach ($a_disk as $diskv) {
+ $r_name="";
+
+ if (strcmp($diskv['fstype'],"raid")==0) {
+ foreach($all_raid as $raid) {
+ if (in_array($diskv['name'],$raid['diskr'])) {
+ $r_name=$raid['name'];
+
+ if ($r_name!=$pconfig['name'])
+ $disable_script.="document.getElementById($i).disabled=1;\n";
+ break;
+ }
+ }
+ echo "<input name='diskr[]' id='$i' type='checkbox' value='$diskv[name]'".
+ ((is_array($pconfig['diskr']) && in_array($diskv['name'], $pconfig['diskr'])) ? " checked=\"checked\"" : "").
+ " />$diskv[name] ($diskv[size], $diskv[desc])" . (($r_name) ? " - assigned to $r_name" : "") . "<br>\n";
+ }
+ $i++;
+ }
+ if ($disable_script) echo "<script type='text/javascript'><!--\n$disable_script--></script>\n";
+ ?>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <input name="Submit" type="submit" class="formbtn" value="Save" />
+ <?php if (isset($id) && $a_raid[$id]): ?>
+ <input name="id" type="hidden" value="<?=$id;?>" />
+ <?php endif; ?>
+ </td>
+ </tr>
+ </table>
+ </form>
+ </div>
+ </td>
+ </tr>
+</table>
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/freenas/www/disks_raid_gvinum_infos.php b/config/freenas/www/disks_raid_gvinum_infos.php
new file mode 100644
index 00000000..71a424fa
--- /dev/null
+++ b/config/freenas/www/disks_raid_gvinum_infos.php
@@ -0,0 +1,144 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ disks_raid_gvinum_infos.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+$pgtitle = array(gettext("System"),
+ gettext("Disks"),
+ gettext("GEOM Vinum"),
+ gettext("Information"));
+
+require_once("freenas_config.inc");
+require_once("guiconfig.inc");
+require_once("freenas_guiconfig.inc");
+require_once("freenas_functions.inc");
+
+if (! empty($_POST))
+{
+ /* hash */
+ unset($error_bucket);
+ /* simple error list */
+ unset($input_errors);
+
+ if (is_array($error_bucket))
+ foreach($error_bucket as $elem)
+ $input_errors[] =& $elem["error"];
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($error_bucket)) {
+ input_errors2Ajax(NULL, $error_bucket);
+ exit;
+ }
+
+ if (!$input_errors) {
+ }
+}
+if (!isset($do_action)) {
+}
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc"); ?>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+
+<div id="inputerrors"></div>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Geom Mirror"), false, "disks_raid_gmirror.php");
+ $tab_array[1] = array(gettext("Geom Concat"), false, "disks_raid_gconcat.php");
+ $tab_array[2] = array(gettext("Geom Stripe"), false, "disks_raid_gstripe.php");
+ $tab_array[3] = array(gettext("Geom RAID5"), false, "disks_raid_graid5.php");
+ $tab_array[4] = array(gettext("Geom Vinum"), true, "disks_raid_gvinum.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Manage RAID"), false, "disks_raid_gvinum.php");
+ /* $tab_array[1] = array(gettext("Format RAID"), false, "disks_raid_gmirror_init.php"); */
+ $tab_array[1] = array(gettext("Tools"), false, "disks_raid_gvinum_tools.php");
+ $tab_array[2] = array(gettext("Information"), true, "disks_raid_gvinum_infos.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <form action="disks_raid_gvinum_infos.php" method="post" name="iform" id="iform">
+ <table class="tabcont" align="center" width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="100%" class="vtable">
+ <?php
+ echo "<pre>";
+ echo "<strong>" . gettext("Software RAID information and status") . "</strong><br />";
+
+ exec("/sbin/gvinum list",$rawdata);
+ foreach ($rawdata as $line)
+ {
+ echo htmlspecialchars($line) . "<br>";
+ }
+ unset ($line);
+ echo "</pre>";
+ ?>
+ </td>
+ </tr>
+ </table>
+ </form>
+ </div>
+ </td>
+ </tr>
+</table>
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/freenas/www/disks_raid_gvinum_init.php b/config/freenas/www/disks_raid_gvinum_init.php
new file mode 100644
index 00000000..787c416e
--- /dev/null
+++ b/config/freenas/www/disks_raid_gvinum_init.php
@@ -0,0 +1,181 @@
+<?php
+/* $Id$ */
+/*
+ disks_raid_gmirror_init.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/* == T H I S F I L E I S C U R R E N T L Y N O T U S E D == */
+/* ========================================================================== */
+
+$pgtitle = array(gettext("System"),
+ gettext("Disks"),
+ gettext("GEOM Vinum"),
+ gettext("Initialize"));
+
+require_once("freenas_config.inc");
+require_once("guiconfig.inc");
+require_once("freenas_guiconfig.inc");
+require_once("freenas_functions.inc");
+
+if (! empty($_POST))
+{
+ /* hash */
+ unset($error_bucket);
+ /* simple error list */
+ unset($input_errors);
+
+ $reqdfields = explode(" ", "disk");
+ $reqdfieldsn = explode(",", "Disk");
+
+ do_input_validation($_POST, $reqdfields, $reqdfieldsn, &$input_errors);
+
+ if (is_array($error_bucket))
+ foreach($error_bucket as $elem)
+ $input_errors[] =& $elem["error"];
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($error_bucket)) {
+ input_errors2Ajax(NULL, $error_bucket);
+ exit;
+ }
+
+ if (! $input_errors) {
+ $do_format = true;
+ $disk = $_POST['disk'];
+ }
+}
+
+if (! isset($do_format)) {
+ $do_format = false;
+ $disk = '';
+}
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc"); ?>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+
+<div id="inputerrors"></div>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Geom Mirror"), false, "disks_raid_gmirror.php");
+ $tab_array[1] = array(gettext("Geom Vinum (unstable)"), true, "disks_raid_gvinum.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Manage RAID"), false, "disks_raid_gvinum.php");
+ $tab_array[1] = array(gettext("Format RAID"), true, "disks_raid_gvinum_init.php");
+ $tab_array[2] = array(gettext("Tools"), false, "disks_raid_gvinum_tools.php");
+ $tab_array[3] = array(gettext("Information"), false, "disks_raid_gvinum_infos.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <form action="disks_raid_gvinum_init.php" method="post" name="iform" id="iform">
+ <table class="tabcont" align="center" width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?=gettext("Volume name");?></td>
+ <td width="78%" class="vtable">
+ <input name="disk" type="text" class="formfld" id="disk" size="20" value="<?=htmlspecialchars($disk);?>" />
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <input name="Submit" type="submit" class="formbtn" value="Save" />
+ <?php if (isset($id) && $a_raid[$id]): ?>
+ <input name="id" type="hidden" value="<?=$id;?>" />
+ <?php endif; ?>
+ </td>
+ </tr>
+ <tr>
+ <td valign="top" colspan="2">
+ <?
+ if ($do_format) {
+ echo("<strong>_DISKSRAIDINITPHP_INFO</strong><br />");
+ echo('<pre>');
+ ob_end_flush();
+
+ /* Create filesystem */
+ system("/sbin/newfs -U /dev/gvinum/" . escapeshellarg($disk));
+ /* Do it twice for test the RAID5 bug at reboot*/
+ system("/sbin/newfs -U /dev/gvinum/" . escapeshellarg($disk));
+
+ echo('</pre>');
+ }
+ ?>
+ </td>
+ </tr>
+ <tr>
+ <td align="left" valign="top" colspan="2">
+ <span class="red">
+ <strong>WARNING:</strong><br />
+ </span>
+ <span class="vexpl">
+ <?= gettext("This step will format the RAID volume in Unix FileSystem (UFS)."); ?>
+ </span>
+ </td>
+ </tr>
+ </table>
+ </form>
+ </div>
+ </td>
+ </tr>
+</table>
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/freenas/www/disks_raid_gvinum_tools.php b/config/freenas/www/disks_raid_gvinum_tools.php
new file mode 100644
index 00000000..343fc221
--- /dev/null
+++ b/config/freenas/www/disks_raid_gvinum_tools.php
@@ -0,0 +1,220 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ disks_raid_gvinum_tools.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+$pgtitle = array(gettext("System"),
+ gettext("Disks"),
+ gettext("GEOM Vinum"),
+ gettext("Tools"));
+
+require_once("freenas_config.inc");
+require_once("guiconfig.inc");
+require_once("freenas_guiconfig.inc");
+require_once("freenas_functions.inc");
+
+if (! empty($_POST))
+{
+ /* hash */
+ unset($error_bucket);
+ /* simple error list */
+ unset($input_errors);
+ unset($do_action);
+
+ $reqdfields = explode(" ", "action object");
+ $reqdfieldsn = explode(",", "Action,Object");
+
+ do_input_validation($_POST, $reqdfields, $reqdfieldsn, &$input_errors);
+
+ if (is_array($error_bucket))
+ foreach($error_bucket as $elem)
+ $input_errors[] =& $elem["error"];
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($error_bucket)) {
+ input_errors2Ajax(NULL, $error_bucket);
+ exit;
+ }
+
+ if (!$input_errors) {
+ $do_action = true;
+ $action = $_POST['action'];
+ $object = $_POST['object'];
+ }
+ }
+ if (!isset($do_action)) {
+ $do_action = false;
+ $action = '';
+ $object = '';
+}
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc"); ?>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+
+<div id="inputerrors"></div>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Geom Mirror"), false, "disks_raid_gmirror.php");
+ $tab_array[1] = array(gettext("Geom Concat"), false, "disks_raid_gconcat.php");
+ $tab_array[2] = array(gettext("Geom Stripe"), false, "disks_raid_gstripe.php");
+ $tab_array[3] = array(gettext("Geom RAID5"), false, "disks_raid_graid5.php");
+ $tab_array[4] = array(gettext("Geom Vinum"), true, "disks_raid_gvinum.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Manage RAID"), false, "disks_raid_gvinum.php");
+ /* $tab_array[1] = array(gettext("Format RAID"), false, "disks_raid_gmirror_init.php"); */
+ $tab_array[1] = array(gettext("Tools"), true, "disks_raid_gvinum_tools.php");
+ $tab_array[2] = array(gettext("Information"), false, "disks_raid_gvinum_infos.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <form action="disks_raid_gvinum_tools.php" method="post" name="iform" id="iform">
+ <table class="tabcont" align="center" width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?=gettext("Object name");?></td>
+ <td width="78%" class="vtable">
+ <input name="object" type="text" class="formfld unknown" id="object" size="20" value="<?=htmlspecialchars($disk);?>" />
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?=gettext("Object name");?></td>
+ <td width="78%" class="vtable">
+ <select name="action" class="formselect" id="action">
+ <option value="start" <?php if ($action == "start") echo "selected=\"selected\""; ?>>start</option>
+ <option value="rebuild" <?php if ($action == "rebuild") echo "selected=\"selected\""; ?>>rebuild parity</option>
+ <option value="list" <?php if ($action == "list") echo "selected=\"selected\""; ?>>list</option>
+ <option value="remove" <?php if ($action == "remove") echo "selected=\"selected\""; ?>>remove</option>
+ <option value="forceup" <?php if ($action == "forceup") echo "selected=\"selected\""; ?>>Force State to UP</option>
+ <option value="saveconfig" <?php if ($action == "saveconfig") echo "selected=\"selected\""; ?>>saveconfig</option>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <input name="Submit" type="submit" class="formbtn" value="Send Command!" />
+ <?php if (isset($id) && $a_raid[$id]): ?>
+ <input name="id" type="hidden" value="<?=$id;?>" />
+ <?php endif; ?>
+ </td>
+ </tr>
+ <tr>
+ <td valign="top" colspan="2">
+ <?
+ if ($do_action) {
+ echo("<strong>" . gettext("GVINUM command output:") . "</strong><br />");
+ echo('<pre>');
+ ob_end_flush();
+
+ switch ($action)
+ {
+ case "remove":
+ /* Remove recursivly object */
+ system("/sbin/gvinum rm -r " . escapeshellarg($object));
+ break;
+ case "start":
+ /* Start object */
+ system("/sbin/gvinum start " . escapeshellarg($object));
+ break;
+ case "rebuild":
+ /* Rebuild RAID 5 parity */
+ system("/sbin/gvinum rebuildparity " . escapeshellarg($object));
+ break;
+ case "list":
+ /* Disaply a detailed list of object */
+ system("/sbin/gvinum list " . escapeshellarg($object));
+ break;
+ case "forceup":
+ /* Force object state up */
+ system("/sbin/gvinum setstate -f up " . escapeshellarg($object));
+ break;
+ case "saveconfig":
+ /* Save config */
+ system("/sbin/gvinum saveconfig");
+ break;
+ }
+
+ echo('</pre>');
+ }
+ ?>
+ </td>
+ </tr>
+ <tr>
+ <td align="left" valign="top" colspan="2">
+ <span class="red">
+ <strong>WARNING:</strong><br />
+ </span>
+ <ol>
+ <li><span class="vexpl"><?= gettext("Use these specials actions for debugging only!"); ?></span></li>
+ <li><span class="vexpl"><?= gettext("There is no need of using this menu for start a RAID volume (start automaticaly)."); ?></span></li>
+ </ol>
+ </td>
+ </tr>
+ </table>
+ </form>
+ </div>
+ </td>
+ </tr>
+</table>
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/freenas/www/services_afp.php b/config/freenas/www/services_afp.php
new file mode 100644
index 00000000..2487c6f7
--- /dev/null
+++ b/config/freenas/www/services_afp.php
@@ -0,0 +1,199 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ services_afp.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+$pgtitle = array(gettext("Services"),
+ gettext("AFP"));
+
+require_once("freenas_config.inc");
+require_once("guiconfig.inc");
+require_once("freenas_guiconfig.inc");
+require_once("freenas_functions.inc");
+
+if (!is_array($freenas_config['afp'])) {
+ $freenas_config['afp'] = array();
+}
+
+
+$pconfig['enable'] = isset($freenas_config['afp']['enable']);
+$pconfig['afpname'] = $freenas_config['afp']['afpname'];
+$pconfig['guest'] = isset($freenas_config['afp']['guest']);
+$pconfig['local'] = isset($freenas_config['afp']['local']);
+
+if (! empty($_POST))
+{
+ /* hash */
+ unset($error_bucket);
+ /* simple error list */
+ unset($input_errors);
+ $pconfig = $_POST;
+
+ /* input validation */
+ $reqdfields = split(" ", "afpname");
+ $reqdfieldsn = split(",", "Afpname");
+
+ do_input_validation_new($_POST, $reqdfields, $reqdfieldsn, &$error_bucket);
+
+ if ($_POST['enable'] && !$_POST['guest'])
+ {
+ if (!$_POST['local'])
+ $error_bucket[] = array("error" => gettext("You must select at least one authentication method."),
+ "field" => "local");
+ }
+ if ($_POST['enable'] && !$_POST['local'])
+ {
+ if (!$_POST['guest'])
+ $error_bucket[] = array("error" => gettext("You must select at least one authentication method."),
+ "field" => "name");
+ }
+
+ if (is_array($error_bucket))
+ foreach($error_bucket as $elem)
+ $input_errors[] =& $elem["error"];
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($error_bucket)) {
+ input_errors2Ajax(NULL, $error_bucket);
+ exit;
+ }
+
+ if (!$input_errors)
+ {
+ $freenas_config['afp']['enable'] = $_POST['enable'] ? true : false;
+ $freenas_config['afp']['guest'] = $_POST['guest'] ? true : false;
+ $freenas_config['afp']['local'] = $_POST['local'] ? true : false;
+ $freenas_config['afp']['afpname'] = $_POST['afpname'];
+
+ write_config();
+
+ $retval = 0;
+ if (!file_exists($d_sysrebootreqd_path))
+ {
+ /* nuke the cache file */
+ config_lock();
+ services_afpd_configure();
+ services_zeroconf_configure();
+ config_unlock();
+ }
+
+ $savemsg = get_std_save_message($retval);
+ }
+}
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+
+$jscriptstr = <<<EOD
+<script type="text/javascript">
+<!--
+function enable_change(enable_change) {
+ var endis;
+
+ endis = !(document.iform.enable.checked || enable_change);
+ endis ? color = '#D4D0C8' : color = '#FFFFFF';
+
+ document.iform.guest.disabled = endis;
+ document.iform.local.disabled = endis;
+ document.iform.afpname.disabled = endis;
+ /* color adjustments */
+ document.iform.guest.style.backgroundColor = color;
+ document.iform.local.style.backgroundColor = color;
+ document.iform.afpname.style.backgroundColor = color;
+}
+//-->
+</script>
+
+EOD;
+
+$pfSenseHead->addScript($jscriptstr);
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc"); ?>
+
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+ <div id="inputerrors"></div>
+ <form id="iform" name="iform" action="services_afp.php" method="post">
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="100%" valign="middle" class="listtopic" colspan="2">
+ <span style="vertical-align: middle; position: relative; left: 0px;"><?=gettext("AFP Server");?></span>
+ <span style="vertical-align: middle; position: relative; left: 84%;">
+ <input name="enable" type="checkbox" value="yes" <?php if ($pconfig['enable']) echo "checked=\"checked\""; ?> onClick="enable_change(false)" />&nbsp;<?= gettext("Enable"); ?>
+ </span>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("Server Name");?></td>
+ <td width="78%" class="vtable">
+ <input name="afpname" type="text" class="formfld unknown" id="afpname" size="20" value="<?=htmlspecialchars($pconfig['afpname']);?>" />
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("Authentication");?></td>
+ <td width="78%" class="vtable" align="left" valign="middle">
+ <input name="guest" id="guest" type="checkbox" value="yes" <?php if ($pconfig['guest']) echo "checked=\"checked\""; ?> />
+ <?= gettext("Enable guest access."); ?><br />
+ <input name="local" id="local" type="checkbox" value="yes" <?php if ($pconfig['local']) echo "checked=\"checked\""; ?> />
+ <?= gettext("Enable local user authentication."); ?>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <input id="submit" name="Submit" type="submit" class="formbtn" value="<?=gettext("Save");?>" />
+ </td>
+ </tr>
+ </table>
+ </form>
+<?php include("fend.inc"); ?>
+<?= checkForInputErrors(); ?>
+<script type="text/javascript">
+<!--
+enable_change(false);
+//-->
+</script>
+</body>
+</html>
diff --git a/config/freenas/www/services_ftp.php b/config/freenas/www/services_ftp.php
new file mode 100644
index 00000000..050361e5
--- /dev/null
+++ b/config/freenas/www/services_ftp.php
@@ -0,0 +1,392 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ services_ftp.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+$pgtitle = array(gettext("Services"),
+ gettext("FTP"));
+
+require_once("freenas_config.inc");
+require_once("guiconfig.inc");
+require_once("freenas_guiconfig.inc");
+require_once("freenas_functions.inc");
+
+if (!is_array($freenas_config['ftp']))
+{
+ $freenas_config['ftp'] = array();
+}
+
+$pconfig['enable'] = isset($freenas_config['ftp']['enable']);
+$pconfig['port'] = $freenas_config['ftp']['port'];
+$pconfig['authbackend'] = $freenas_config['ftp']['authentication_backend'];
+$pconfig['numberclients'] = $freenas_config['ftp']['numberclients'];
+$pconfig['maxconperip'] = $freenas_config['ftp']['maxconperip'];
+$pconfig['timeout'] = $freenas_config['ftp']['timeout'];
+$pconfig['anonymous'] = isset($freenas_config['ftp']['anonymous']);
+$pconfig['localuser'] = isset($freenas_config['ftp']['localuser']);
+$pconfig['pasv_max_port'] = $freenas_config['ftp']['pasv_max_port'];
+$pconfig['pasv_min_port'] = $freenas_config['ftp']['pasv_min_port'];
+$pconfig['pasv_address'] = $freenas_config['ftp']['pasv_address'];
+$pconfig['banner'] = $freenas_config['ftp']['banner'];
+$pconfig['natmode'] = isset($freenas_config['ftp']['natmode']);
+$pconfig['passiveip'] = $freenas_config['ftp']['passiveip'];
+$pconfig['fxp'] = isset($freenas_config['ftp']['fxp']);
+
+if (! empty($_POST))
+{
+ /* hash */
+ unset($error_bucket);
+ /* simple error list */
+ unset($input_errors);
+ $pconfig = $_POST;
+
+ /* input validation */
+ if ($_POST['enable']) {
+ $reqdfields = array_merge($reqdfields, explode(" ", "numberclients maxconperip timeout port"));
+ $reqdfieldsn = array_merge($reqdfieldsn, explode(",", "Numberclients,Maxconperip,Timeout,Port"));
+ }
+
+ do_input_validation($_POST, $reqdfields, $reqdfieldsn, &$input_errors);
+
+ if ($_POST['enable'] && !is_port($_POST['port']))
+ {
+ $error_bucket[] = array("error" => gettext("The TCP port must be a valid port number."),
+ "field" => "port");
+ }
+ if ($_POST['enable'] && !is_numericint($_POST['numberclients'])) {
+ $error_bucket[] = array("error" => gettext("The maximum Number of client must be a number."),
+ "field" => "numberclients");
+ }
+
+ if ($_POST['enable'] && !is_numericint($_POST['maxconperip'])) {
+ $error_bucket[] = array("error" => gettext("The max con per ip must be a number."),
+ "field" => "maxconperip");
+ }
+ if ($_POST['enable'] && !is_numericint($_POST['timeout'])) {
+ $error_bucket[] = array("error" => gettext("The maximum idle time be a number."),
+ "field" => "timeout");
+ }
+
+ if ($_POST['enable'] && ($_POST['pasv_address']))
+ {
+ if (!is_ipaddr($_POST['pasv_address']))
+ $error_bucket[] = array("error" => gettext("The pasv address must be a public IP address."),
+ "field" => "pasv_address");
+
+ }
+
+ if ($_POST['enable'] && ($_POST['pasv_max_port']))
+ {
+ if (!is_port($_POST['pasv_max_port']))
+ $error_bucket[] = array("error" => gettext("The pasv_max_port port must be a valid port number."),
+ "field" => "pasv_max_port");
+ }
+
+ if ($_POST['enable'] && ($_POST['pasv_min_port']))
+ {
+ if (!is_port($_POST['pasv_min_port']))
+ $error_bucket[] = array("error" => gettext("The pasv_min_port port must be a valid port number."),
+ "field" => "pasv_min_port");
+
+ }
+
+ if (($_POST['passiveip'] && !is_ipaddr($_POST['passiveip']))) {
+ $error_bucket[] = array("error" => gettext("A valid IP address must be specified."),
+ "field" => "passiveip");
+
+ }
+
+ if (!($_POST['anonymous']) && !($_POST['localuser'])) {
+ $input_errors[] = _SRVFTP_MSGVALIDAUTH;
+ $error_bucket[] = array("error" => gettext("You must select at minium anonymous or/and local user authentication."),
+ "field" => "localuser");
+
+ }
+
+ if (is_array($error_bucket))
+ foreach($error_bucket as $elem)
+ $input_errors[] =& $elem["error"];
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($error_bucket)) {
+ input_errors2Ajax(NULL, $error_bucket);
+ exit;
+ }
+
+ if (!$input_errors)
+ {
+ $freenas_config['ftp']['numberclients'] = $_POST['numberclients'];
+ $freenas_config['ftp']['maxconperip'] = $_POST['maxconperip'];
+ $freenas_config['ftp']['timeout'] = $_POST['timeout'];
+ $freenas_config['ftp']['port'] = $_POST['port'];
+ $freenas_config['ftp']['authentication_backend'] = $_POST['authbackend'];
+ $freenas_config['ftp']['anonymous'] = $_POST['anonymous'] ? true : false;
+ $freenas_config['ftp']['localuser'] = $_POST['localuser'] ? true : false;
+ $freenas_config['ftp']['pasv_max_port'] = $_POST['pasv_max_port'];
+ $freenas_config['ftp']['pasv_min_port'] = $_POST['pasv_min_port'];
+ $freenas_config['ftp']['pasv_address'] = $_POST['pasv_address'];
+ $freenas_config['ftp']['banner'] = $_POST['banner'];
+ $freenas_config['ftp']['passiveip'] = $_POST['passiveip'];
+ $freenas_config['ftp']['fxp'] = $_POST['fxp'] ? true : false;
+ $freenas_config['ftp']['natmode'] = $_POST['natmode'] ? true : false;
+ $freenas_config['ftp']['enable'] = $_POST['enable'] ? true : false;
+
+ write_config();
+
+ $retval = 0;
+ if (!file_exists($d_sysrebootreqd_path)) {
+ /* nuke the cache file */
+ config_lock();
+ services_wzdftpd_configure();
+ services_zeroconf_configure();
+ config_unlock();
+ }
+ $savemsg = get_std_save_message($retval);
+ }
+}
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+
+$jscriptstr = <<<EOD
+<script type="text/javascript">
+<!--
+function enable_change(enable_change) {
+ var endis;
+
+ endis = !(document.iform.enable.checked || enable_change);
+ endis ? color = '#D4D0C8' : color = '#FFFFFF';
+
+ document.iform.port.disabled = endis;
+ document.iform.authbackend.disabled = endis;
+ document.iform.timeout.disabled = endis;
+ document.iform.numberclients.disabled = endis;
+ document.iform.maxconperip.disabled = endis;
+ document.iform.anonymous.disabled = endis;
+ document.iform.localuser.disabled = endis;
+ document.iform.banner.disabled = endis;
+ document.iform.fxp.disabled = endis;
+ document.iform.natmode.disabled = endis;
+ document.iform.passiveip.disabled = endis;
+ document.iform.pasv_max_port.disabled = endis;
+ document.iform.pasv_min_port.disabled = endis;
+ /* color adjustments */
+ document.iform.port.style.backgroundColor = color;
+ document.iform.authbackend.backgroundColor = color;
+ document.iform.timeout.style.backgroundColor = color;
+ document.iform.numberclients.style.backgroundColor = color;
+ document.iform.maxconperip.style.backgroundColor = color;
+ document.iform.anonymous.style.backgroundColor = color;
+ document.iform.localuser.style.backgroundColor = color;
+ document.iform.banner.style.backgroundColor = color;
+ document.iform.fxp.style.backgroundColor = color;
+ document.iform.natmode.style.backgroundColor = color;
+ document.iform.passiveip.style.backgroundColor = color;
+ document.iform.pasv_max_port.style.backgroundColor = color;
+ document.iform.pasv_min_port.style.backgroundColor = color;
+}
+//-->
+</script>
+
+EOD;
+
+$pfSenseHead->addScript($jscriptstr);
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc"); ?>
+
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+ <div id="inputerrors"></div>
+ <form id="iform" name="iform" action="services_ftp.php" method="post">
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="100%" valign="middle" class="listtopic" colspan="2">
+ <span style="vertical-align: middle; position: relative; left: 0px;"><?=gettext("FTP Server");?></span>
+ <span style="vertical-align: middle; position: relative; left: 84%;">
+ <input name="enable" type="checkbox" value="yes" <?php if ($pconfig['enable']) echo "checked=\"checked\""; ?> onClick="enable_change(false)" />&nbsp;<?= gettext("Enable"); ?>
+ </span>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?=gettext("TCP port");?></td>
+ <td width="78%" class="vtable">
+ <input name="port" type="text" class="formfld unknown" id="port" size="20" value="<?=htmlspecialchars($pconfig['port']);?>" />
+ </td>
+ </tr>
+ <?php
+ if (file_exists("/usr/local/sbin/wzdftpd")) {
+ $a_backends = array();
+
+ $dh = opendir("/usr/local/share/wzdftpd/backends");
+ while (false !== ($filename = readdir($dh))) {
+ if (preg_match("/\.so$/", $filename)) {
+ $lastslash = strrpos($filename, "/");
+ $dot = strrpos($filename, ".");
+
+ $backend_name = str_replace("libwzd",
+ "",
+ substr($filename,
+ $lastslash,
+ $dot - $lastslash));
+ $a_backends[] = $backend_name;
+ }
+ }
+ }
+ ?>
+ <?php if (is_array($a_backends)) : ?>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?=gettext("Authentication Backend");?></td>
+ <td width="78%" class="vtable" align="left" valign="middle">
+ <select name="authbackend" id="authbackend" class="formselect">
+ <?php foreach ($a_backends as $backend) : ?>
+ <option value="<?= $backend ?>"><?= $backend ?></option>
+ <?php endforeach; ?>
+ </select><br />
+ <?= gettext("Choose a particular backend, that will be used to authenticate FTP users."); ?>
+ </td>
+ </tr>
+ <?php endif; ?>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?=gettext("Number of clients");?></td>
+ <td width="78%" class="vtable" align="left" valign="middle">
+ <input name="numberclients" type="text" class="formfld unknown" id="numberclients" size="20" value="<?=htmlspecialchars($pconfig['numberclients']);?>" />
+ <br />
+ <?= gettext("Maximum number of simultaneous clients."); ?>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?=gettext("Max conn per ip");?></td>
+ <td width="78%" class="vtable" align="left" valign="middle">
+ <input name="maxconperip" type="text" class="formfld unknown" id="maxconperip" size="20" value="<?=htmlspecialchars($pconfig['maxconperip']);?>" />
+ <br />
+ <?= gettext("Maximum connection per IP address."); ?>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?=gettext("Timeout");?></td>
+ <td width="78%" class="vtable" align="left" valign="middle">
+ <input name="timeout" type="text" class="formfld unknown" id="timeout" size="20" value="<?=htmlspecialchars($pconfig['timeout']);?>" />
+ <br />
+ <?= gettext("Maximum idle time in seconds."); ?>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("Anonymous login");?></td>
+ <td width="78%" class="vtable" align="left" valign="middle">
+ <input name="anonymous" type="checkbox" id="anonymous" value="yes" <?php if ($pconfig['anonymous']) echo "checked=\"checked\""; ?> />
+ <?= gettext("Enable Anonymous login"); ?>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("Local User");?></td>
+ <td width="78%" class="vtable" align="left" valign="middle">
+ <input name="localuser" type="checkbox" id="localuser" value="yes" <?php if ($pconfig['localuser']) echo "checked=\"checked\""; ?> />
+ <?= gettext("Enable local User login"); ?>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("Banner");?></td>
+ <td width="78%" class="vtable" align="left" valign="middle">
+ <textarea name="banner" cols="65" rows="7" id="banner" class="formpre"><?=htmlspecialchars($pconfig['banner']);?></textarea>
+ <br />
+ <?= gettext("Greeting banner displayed by FTP when a connection first comes in."); ?>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("FXP");?></td>
+ <td width="78%" class="vtable" align="left" valign="middle">
+ <input name="fxp" type="checkbox" id="fxp" value="yes" <?php if ($pconfig['fxp']) echo "checked=\"checked\""; ?> />
+ <?= gettext("Enable FXP protocol."); ?>
+ <br />
+ <?= gettext("FXP allows transfers between two remote servers without any file data going to the client asking for the transfer (insecure!)."); ?>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("NAT mode");?></td>
+ <td width="78%" class="vtable" align="left" valign="middle">
+ <input name="natmode" type="checkbox" id="natmode" value="yes" <?php if ($pconfig['natmode']) echo "checked=\"checked\""; ?> />
+ <?= gettext("Force NAT mode"); ?>
+ <br />
+ <?= gettext("Enable it if your FTP server is behind a NAT box that doesn't support applicative FTP proxying"); ?>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("Passive IP address");?></td>
+ <td width="78%" class="vtable" align="left" valign="middle">
+ <input name="passiveip" type="text" class="formfld unknown" id="passiveip" size="30" value="<?=htmlspecialchars($pconfig['passiveip']);?>" />
+ <?= gettext("Use this option to override the IP address that FTP daemon will advertise in response to the PASV command."); ?>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("pasv_min_port");?></td>
+ <td width="78%" class="vtable" align="left" valign="middle">
+ <input name="pasv_min_port" type="text" class="formfld unknown" id="pasv_min_port" size="20" value="<?=htmlspecialchars($pconfig['pasv_min_port']);?>" />
+ <?= gettext("The minimum port to allocate for PASV style data connections."); ?>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("pasv_max_port");?></td>
+ <td width="78%" class="vtable" align="left" valign="middle">
+ <input name="pasv_max_port" type="text" class="formfld unknown" id="pasv_max_port" size="20" value="<?=htmlspecialchars($pconfig['pasv_max_port']);?>" />
+ <?= gettext("The maximum port to allocate for PASV style data connections."); ?>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <input id="submitt" name="Submitt" type="submit" class="formbtn" value="<?=gettext("Save");?>" />
+ </td>
+ </tr>
+ </table>
+ </form>
+<?php include("fend.inc"); ?>
+<?= checkForInputErrors(); ?>
+<script type="text/javascript">
+<!--
+enable_change(false);
+//-->
+</script>
+</body>
+</html>
diff --git a/config/freenas/www/services_nfs.php b/config/freenas/www/services_nfs.php
new file mode 100644
index 00000000..7b4b9a18
--- /dev/null
+++ b/config/freenas/www/services_nfs.php
@@ -0,0 +1,243 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ services_nfs.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+$pgtitle = array(gettext("Services"),
+ gettext("NFS"));
+
+require_once("freenas_config.inc");
+require_once("guiconfig.inc");
+require_once("freenas_guiconfig.inc");
+require_once("freenas_functions.inc");
+
+if (!is_array($freenas_config['nfs']))
+{
+ $freenas_config['nfs'] = array();
+}
+
+$pconfig['enable'] = isset($freenas_config['nfs']['enable']);
+$pconfig['bindto'] = $freenas_config['nfs']['bindto'];
+$pconfig['serveudp'] = isset($freenas_config['nfs']['serveudp']);
+$pconfig['servetcp'] = isset($freenas_config['nfs']['servetcp']);
+
+if (! empty($_POST))
+{
+ /* hash */
+ unset($error_bucket);
+ /* simple error list */
+ unset($input_errors);
+ $pconfig = $_POST;
+
+ /* input validation */
+ $reqdfields = explode(" ", "bindto");
+ $reqdfieldsn = explode(",", "IP address to bind to");
+
+ do_input_validation($_POST, $reqdfields, $reqdfieldsn, &$input_errors);
+
+ if (is_array($error_bucket))
+ foreach($error_bucket as $elem)
+ $input_errors[] =& $elem["error"];
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($error_bucket)) {
+ input_errors2Ajax(NULL, $error_bucket);
+ exit;
+ }
+
+ if (!$input_errors)
+ {
+ $freenas_config['nfs']['enable'] = $_POST['enable'] ? true : false;
+ $freenas_config['nfs']['bindto'] = $_POST['bindto'];
+ if (isset($_POST['servetcp'])) {
+ $freenas_config['nfs']['servetcp'] = $_POST['servetcp'];
+ } else {
+ unset($freenas_config['nfs']['servetcp']);
+ }
+ if (isset($_POST['serveudp'])) {
+ $freenas_config['nfs']['serveudp'] = $_POST['serveudp'];
+ } else {
+ unset($freenas_config['nfs']['serveudp']);
+ }
+
+ write_config();
+
+ $retval = 0;
+ if (!file_exists($d_sysrebootreqd_path))
+ {
+ /* nuke the cache file */
+ config_lock();
+ services_nfs_configure();
+ config_unlock();
+ }
+ $savemsg = get_std_save_message($retval);
+ }
+}
+
+/* if ajax is calling, give them an update message */
+if(isAjax())
+ print_info_box_np($savemsg);
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+
+$jscriptstr = <<<EOD
+<script type="text/javascript">
+<!--
+function enable_change(enable_change) {
+ var endis;
+
+ endis = !(document.iform.enable.checked || enable_change);
+ endis ? color = '#D4D0C8' : color = '#FFFFFF';
+
+ document.iform.servetcp.disabled = endis;
+ document.iform.serveudp.disabled = endis;
+ document.iform.bindto.disabled = endis;
+ /* color adjustments */
+ document.iform.servetcp.style.backgroundColor = color;
+ document.iform.serveudp.style.backgroundColor = color;
+ document.iform.bindto.style.backgroundColor = color;
+}
+//-->
+</script>
+
+EOD;
+
+$pfSenseHead->addScript($jscriptstr);
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc"); ?>
+
+<form id="iform" name="iform" action="services_nfs.php" method="post">
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+<div id="inputerrors"></div>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Settings"), true, "services_nfs.php");
+ $tab_array[1] = array(gettext("Exports"), false, "services_nfs_export.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <table class="tabcont" width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="100%" valign="middle" class="listtopic" colspan="2">
+ <span style="vertical-align: middle; position: relative; left: 0px;"><?=gettext("NFS Server");?></span>
+ <span style="vertical-align: middle; position: relative; left: 84%;">
+ <input name="enable" type="checkbox" value="yes" <?php if ($pconfig['enable']) echo "checked=\"checked\""; ?> onClick="enable_change(false)" />&nbsp;<?= gettext("Enable"); ?>
+ </span>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?=gettext("Bind to IP address");?></td>
+ <td width="78%" class="vtable" align="left" valign="middle">
+ <select name="bindto" id="bindto" class="formselect">
+ <option value="(ANY)"<?php if ($pconfig['bindto'] == "(ANY)") { echo " selected=\"selected\""; } ?>>
+ (ANY)
+ </option>
+ <option value="<?= $config['interfaces']['wan'][ipaddr] ?>"<?php if ($pconfig['bindto'] == $config['interfaces']['wan'][ipaddr]) { echo " selected=\"selected\""; } ?>>
+ <?= $config['interfaces']['wan'][ipaddr] ?>
+ </option>
+ <option value="<?= $config['interfaces']['lan'][ipaddr] ?>"<?php if ($pconfig['bindto'] == $config['interfaces']['lan'][ipaddr]) { echo " selected=\"selected\""; } ?>>
+ <?= $config['interfaces']['lan'][ipaddr] ?>
+ </option>
+ <?php
+ for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++):
+ ?>
+ <option value="<?= $config['interfaces']['opt' . $i][ipaddr] ?>"<?php if ($pconfig['bindto'] == $config['interfaces']['opt' . $i][ipaddr]) { echo " selected=\"selected\""; } ?>>
+ <?= $config['interfaces']['opt' . $i][ipaddr] ?>
+ </option>
+ <?php endfor; ?>
+ </select>
+ <br />
+ <?= gettext("Use an address from the list to make nfsd and rpcbind bind to a specific address."); ?>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?=gettext("Client Types");?></td>
+ <td width="78%" class="vtable" align="left" valign="middle">
+ <p>
+ <input type="checkbox" name="servetcp" id="servetcp" value="on"<?php if ($pconfig['servetcp']) { echo " checked=\"checked\""; } ?>/>
+ <label for="servetcp"><?= gettext("Serve TCP NFS clients"); ?></label>
+ </p>
+ <p>
+ <input type="checkbox" name="serveudp" id="serveudp" value="on"<?php if ($pconfig['serveudp']) { echo " checked=\"checked\""; } ?>/>
+ <label for="serveudp"><?= gettext("Serve UDP NFS clients"); ?></label>
+ </p>
+ <p>
+ <span class="red"><strong><?= gettext("Note"); ?>: </strong></span>
+ <span class="vexpl">
+ <?= gettext("Usually it's save to enable support for both, UDP and TCP client types."); ?>
+ </span>
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <input id="submit" name="Submit" type="submit" class="formbtn" value="<?=gettext("Save");?>" />
+ </td>
+ </tr>
+ </table>
+ </div>
+ </td>
+ </tr>
+</table>
+</form>
+<?php include("fend.inc"); ?>
+<?= checkForInputErrors(); ?>
+<script type="text/javascript">
+<!--
+enable_change(false);
+//-->
+</script>
+</body>
+</html>
diff --git a/config/freenas/www/services_nfs_export.php b/config/freenas/www/services_nfs_export.php
new file mode 100644
index 00000000..c1712762
--- /dev/null
+++ b/config/freenas/www/services_nfs_export.php
@@ -0,0 +1,165 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ services_nfs_export.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+$pgtitle = array(gettext("Services"),
+ gettext("NFS"),
+ gettext("Exports"));
+
+require_once("freenas_config.inc");
+require_once("guiconfig.inc");
+require_once("freenas_guiconfig.inc");
+require_once("freenas_functions.inc");
+
+if (!is_array($freenas_config['mounts']['mount']))
+ $freenas_config['mounts']['mount'] = array();
+
+mount_sort();
+
+$a_mount = &$freenas_config['mounts']['mount'];
+
+if (! empty($_POST))
+{
+ /* hash */
+ unset($error_bucket);
+ /* simple error list */
+ unset($input_errors);
+ $pconfig = $_POST;
+
+ if (is_array($error_bucket))
+ foreach($error_bucket as $elem)
+ $input_errors[] =& $elem["error"];
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($error_bucket)) {
+ input_errors2Ajax(NULL, $error_bucket);
+ exit;
+ }
+
+ if (!$input_errors)
+ {
+ if($_POST['apply']) {
+ $retval = 0;
+ if(!file_exists($d_sysrebootreqd_path)) {
+ config_lock();
+ services_nfs_configure();
+ services_zeroconf_configure();
+ config_unlock();
+ }
+
+ $savemsg = get_std_save_message($retval);
+
+ if(0 == $retval) {
+ if(file_exists($d_nfsexportconfdirty_path))
+ unlink($d_nfsexportconfdirty_path);
+ }
+ }
+ }
+}
+
+if($_GET['act'] == "ret") {
+ pfSenseHeader("services_nfs_export.php");
+ exit;
+}
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc"); ?>
+
+<form id="iform" name="iform" action="services_nfs_export.php" method="post">
+<?php if ($savemsg) print_info_box($savemsg); ?>
+<?php if (file_exists($d_nfsexportconfdirty_path)): ?>
+<?php print_info_box_np(gettext("The exports have been modified.") . "<br />" .
+ gettext("You must apply the changes in order for them to take effect."));?>
+<?php endif; ?>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<div id="inputerrors"></div>
+
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Settings"), false, "services_nfs.php");
+ $tab_array[1] = array(gettext("Exports"), true, "services_nfs_export.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <table class="tabcont" width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td width="20%" class="listhdrr"><?= gettext("Export"); ?></td>
+ <td width="25%" class="listhdrr"><?= gettext("Description"); ?></td>
+ <td width="20%" class="listhdrr"><?= gettext("Export To"); ?></td>
+ <td width="10%" class="list"></td>
+ </tr>
+ <?php $i = 0; foreach($a_mount as $mountv): ?>
+ <tr>
+ <td class="listr">/mnt/<?=htmlspecialchars($mountv['sharename']);?></td>
+ <td class="listr"><?=htmlspecialchars($mountv['desc']);?></td>
+ <td class="listbg" style="color: #FFFFFF;"><?= isset($mountv['nfs']['networks']) ? str_replace(",", "<br />", htmlspecialchars($mountv['nfs']['networks'])) : gettext("None"); ?></td>
+ <td valign="middle" nowrap class="list">
+ <?php if(isset($freenas_config['nfs']['enable']))
+ echo("<a href='services_nfs_export_edit.php?id={$i}'><img src='./themes/" . $g['theme'] . "/images/icons/icon_e.gif' alt='" . gettext("Edit Export") . "' title='" . gettext("Edit Export") . "' width='17' height='17' border='0' /></a>");
+ ?>
+ </td>
+ </tr>
+ <?php $i++; endforeach; ?>
+ </table>
+ </div>
+ </td>
+ </tr>
+</table>
+</form>
+<?php include("fend.inc"); ?>
+<?= checkForInputErrors(); ?>
+</body>
+</html>
diff --git a/config/freenas/www/services_nfs_export_edit.php b/config/freenas/www/services_nfs_export_edit.php
new file mode 100644
index 00000000..f9fd53ea
--- /dev/null
+++ b/config/freenas/www/services_nfs_export_edit.php
@@ -0,0 +1,783 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ services_samba_share_edit.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+$pgtitle = array(gettext("Services"),
+ gettext("NFS"),
+ gettext("Exports"),
+ gettext("Edit"));
+
+require_once("freenas_config.inc");
+require_once("guiconfig.inc");
+require_once("freenas_guiconfig.inc");
+require_once("freenas_functions.inc");
+
+$id = $_GET['id'];
+if (isset($_POST['id']))
+ $id = $_POST['id'];
+
+if (!is_array($freenas_config['mounts']['mount']))
+ $freenas_config['mounts']['mount'] = array();
+
+mount_sort();
+
+$pconfig['mapall'] = $freenas_config['mounts']['mount'][$id]['nfs']['mapall'];
+
+if (! empty($_POST))
+{
+ /* hash */
+ unset($error_bucket);
+ /* simple error list */
+ unset($input_errors);
+ $pconfig = $_POST;
+
+ /* input validation */
+ $reqdfields = explode(" ", "authnetworks");
+ $reqdfieldsn = explode(",", "Destination network");
+
+ do_input_validation($_POST, $reqdfields, $reqdfieldsn, &$input_errors);
+
+ if (isset($_POST['authnetworks']) && is_array($_POST['authnetworks'])) {
+ foreach ($_POST['authnetworks'] as $netel) {
+ list($_POST['network'], $_POST['network_subnet']) = explode('/', $netel);
+
+ if (($_POST['network'] && !is_ipaddr($_POST['network']))) {
+ $error_bucket[] = array("error" => gettext("A valid network must be specified."),
+ "field" => "network");
+ }
+
+ if (($_POST['network_subnet'] && !is_numeric($_POST['network_subnet']))) {
+ $error_bucket[] = array("error" => gettext("A valid network bit count must be specified."),
+ "field" => "network_subnet");
+ }
+
+ $osn[] = gen_subnet($_POST['network'], $_POST['network_subnet']) . "/" . $_POST['network_subnet'];
+ }
+ }
+
+ if (is_array($error_bucket))
+ foreach($error_bucket as $elem)
+ $input_errors[] =& $elem["error"];
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($error_bucket)) {
+ input_errors2Ajax(NULL, $error_bucket);
+ exit;
+ }
+
+ if (!$input_errors)
+ {
+ $freenas_config['mounts']['mount'][$id]['nfs']['networks'] = implode(",", $osn);
+ $freenas_config['mounts']['mount'][$id]['nfs']['mapall'] = $_POST['mapall'];
+
+ touch($d_nfsexportconfdirty_path);
+ write_config();
+ pfSenseHeader("services_nfs_export.php");
+ exit;
+ }
+}
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+
+$addressTransString = gettext("Address");
+$plusimgDescTransString = gettext("add to network list");
+$minusimgDescTransString = gettext("remove from network list");
+$currentnetTransString = gettext("Current networks");
+$networksTypehintTransString = gettext("Network that is authorised to access NFS shares");
+
+$networkCount = count($freenas_config['nfs']['nfsnetwork']);
+$generatedWANSubnet = gen_subnet($config['interfaces']['wan']['ipaddr'],
+ $config['interfaces']['wan']['subnet']);
+$generatedLANSubnet = gen_subnet($config['interfaces']['lan']['ipaddr'],
+ $config['interfaces']['lan']['subnet']);
+
+$jscriptstr = <<<EOD
+<script type="text/javascript">
+<!--
+function network_exists(myValue) {
+ for (i = 0; i < $('authnetworks').options.length; i++) {
+ if ($('authnetworks').options[i].value == myValue) {
+ return true;
+ }
+ }
+
+ return false;
+}
+function selectnetel() {
+ for (i = 0; i < $('authnetworks').options.length; i++) {
+ $('authnetworks').options[i].selected = true;
+ }
+}
+function get_selected_listitems() {
+ var selected = new Array();
+
+ if (!$('authnetworks')) { return; }
+
+ for (i = 0; i < $('authnetworks').options.length; i++) {
+ if ($('authnetworks').childNodes[i].selected == true) {
+ selected.push($('authnetworks').options[i]);
+ }
+ }
+
+ return selected;
+}
+
+function add_selnetwork(net, mask) {
+ var newOption = document.createElement("option");
+ var newOptionText = document.createTextNode(net + '/' + mask);
+ var selectSize = $('authnetworks').size;
+
+ if (!net || !mask) { return; }
+
+ if (network_exists(net + '/' + mask)) {
+ alert('Element already exist in the network list');
+ return;
+ }
+
+ newOption.setAttribute('value', net + '/' + mask);
+ newOption.appendChild(newOptionText);
+
+ /* add the option to the select element */
+ $('authnetworks').appendChild(newOption);
+ $('authnetworks').setAttribute('size', '3');
+
+ /* clear values from HTML fields */
+ if ($('network')) { $('network').value = ''; }
+ if ($('network_subnet')) { $('network_subnet').selectedIndex = 0; }
+}
+
+function remove_selnetwork() {
+ var selectedItems = get_selected_listitems();
+
+ if (selectedItems.length <= 0) {
+ alert('No element selected!');
+ return;
+ }
+
+ for (i = 0; i < selectedItems.length; i++) {
+ $('authnetworks').removeChild(selectedItems[i]);
+ }
+}
+
+function create_authnetworks_tr(selectElement) {
+ var newTR = document.createElement("tr");
+ newTR.setAttribute('id', 'authNetworksTR');
+
+ var newImageTR = document.createElement("tr");
+ newImageTR.setAttribute('id', 'authNetworksImageTR');
+
+ var descTD = document.createElement("td");
+ descTD.setAttribute('align', 'left');
+ descTD.setAttribute('valign', 'top');
+ descTD.setAttribute('style', 'padding-top: 10px; border-top: solid 1px grey;');
+
+ var selectTD = document.createElement("td");
+ selectTD.setAttribute('align', 'left');
+ selectTD.setAttribute('valign', 'middle');
+ selectTD.setAttribute('style', 'padding-top: 10px; border-top: solid 1px grey;');
+
+ var typehintTD = document.createElement("td");
+ typehintTD.setAttribute('align', 'left');
+ typehintTD.setAttribute('valign', 'middle');
+ typehintTD.setAttribute('colspan', '2');
+ typehintTD.setAttribute('style', 'padding-top: 10px; border-top: solid 1px grey;');
+
+ var blankTD = document.createElement("td");
+ blankTD.setAttribute('align', 'left');
+ blankTD.setAttribute('valign', 'top');
+
+ var imageTD = document.createElement("td");
+ imageTD.setAttribute('align', 'left');
+ imageTD.setAttribute('valign', 'middle');
+ imageTD.setAttribute('style', 'vertical-align: middle;');
+ imageTD.setAttribute('colspan', '3');
+
+ var newSpan = document.createElement("span");
+ newSpan.setAttribute('style', 'padding-left: 5px; vertical-align: middle;');
+
+ var newTypehintSpan = document.createElement("span");
+ newTypehintSpan.setAttribute('style', 'padding-left: 5px; vertical-align: middle;');
+
+ var newDescription = document.createTextNode('{$currentnetTransString}:');
+ var newImgDescription = document.createTextNode('{$minusimgDescTransString}');
+ var typehint = document.createTextNode('{$networksTypehintTransString}');
+
+ var newSelect = document.createElement("select");
+ newSelect.setAttribute('name', 'authnetworks[]');
+ newSelect.setAttribute('class', 'formselect');
+ newSelect.setAttribute('id', 'authnetworks');
+ newSelect.setAttribute('multiple', 'multiple');
+ newSelect.setAttribute('size', '{$networkCount}');
+
+ /* divs are used to achieve proper alignement */
+ newImageDiv = document.createElement("div");
+ newImageDiv.setAttribute('style', 'float: left;');
+
+ newImageDescDiv = document.createElement("div");
+ newImageDescDiv.setAttribute('style', 'padding-top: 1px;');
+
+ /* try to add each network to the select element */
+
+EOD;
+
+if (isset($freenas_config['mounts']['mount'][$id]['nfs']['networks'])) {
+ foreach (explode(",", $freenas_config['mounts']['mount'][$id]['nfs']['networks']) as $networkel) {
+ list($netaddress, $netmask) = explode('/', $networkel);
+ $networkSanitized = htmlspecialchars($netaddress);
+
+ $jscriptstr .= <<<EOD
+ var newOption = document.createElement("option");
+ var newOptionText = document.createTextNode('{$networkSanitized}/{$netmask}');
+
+ newOption.setAttribute('value', '{$networkSanitized}/{$netmask}');
+ newOption.appendChild(newOptionText);
+
+ /* add the option to the select element */
+ newSelect.appendChild(newOption);
+
+EOD;
+ } // end if
+} // end foreach
+
+$jscriptstr .= <<<EOD
+ var newImage = document.createElement("img");
+ newImage.setAttribute('src', '/themes/{$g['theme']}/images/misc/bullet_toggle_minus.png');
+ newImage.setAttribute('alt', 'remove network');
+ newImage.setAttribute('border', '0');
+ newImage.setAttribute('style', 'margin-right: 5px; border: solid 1px silver; cursor: pointer;');
+ newImage.setAttribute('onclick', 'remove_selnetwork();');
+
+ /* assemble everything */
+ newTypehintSpan.appendChild(typehint);
+
+ descTD.appendChild(newDescription);
+ selectElement != null ? selectTD.appendChild(selectElement) : selectTD.appendChild(newSelect);
+ typehintTD.appendChild(newTypehintSpan);
+
+ newImageDiv.appendChild(newImage);
+ newImageDescDiv.appendChild(newImgDescription);
+
+ imageTD.appendChild(newImageDiv);
+ imageTD.appendChild(newImageDescDiv);
+
+ newTR.appendChild(descTD);
+ newTR.appendChild(selectTD);
+ newTR.appendChild(typehintTD);
+
+ newImageTR.appendChild(blankTD);
+ newImageTR.appendChild(imageTD);
+
+ $('networkopttab').appendChild(newTR);
+ $('networkopttab').appendChild(newImageTR);
+}
+
+function create_network_tr() {
+ var newTR = document.createElement("tr");
+ newTR.setAttribute('id', 'typeDetailsTR');
+
+ var descTD = document.createElement("td");
+ descTD.setAttribute('align', 'left');
+ descTD.setAttribute('valign', 'top');
+
+ var inputTD = document.createElement("td");
+ inputTD.setAttribute('align', 'left');
+ inputTD.setAttribute('valign', 'top');
+
+ var selectTD = document.createElement("td");
+ selectTD.setAttribute('align', 'left');
+ selectTD.setAttribute('valign', 'middle');
+
+ var imageTD = document.createElement("td");
+ imageTD.setAttribute('align', 'left');
+ imageTD.setAttribute('valign', 'middle');
+
+ var newDescription = document.createTextNode('{$addressTransString}:');
+ var newImgDescription = document.createTextNode('{$plusimgDescTransString}');
+
+ var newInput = document.createElement("input");
+ newInput.setAttribute('name', 'network');
+ newInput.setAttribute('type', 'text');
+ newInput.setAttribute('class', 'formfld host');
+ newInput.setAttribute('id', 'network');
+ newInput.setAttribute('size', '20');
+ newInput.setAttribute('value', '');
+
+ var newSelect = document.createElement("select");
+ newSelect.setAttribute('name', 'network_subnet');
+ newSelect.setAttribute('class', 'formselect');
+ newSelect.setAttribute('id', 'network_subnet');
+
+ var newImage = document.createElement("img");
+ newImage.setAttribute('src', '/themes/{$g['theme']}/images/misc/bullet_toggle_plus.png');
+ newImage.setAttribute('alt', 'add network');
+ newImage.setAttribute('border', '0');
+ newImage.setAttribute('style', 'margin-right: 5px; border: solid 1px silver; cursor: pointer;');
+ newImage.setAttribute('onclick', 'add_selnetwork($("network").value, $("network_subnet").value);');
+
+ /* divs are used to achieve proper alignement */
+ newImageDiv = document.createElement("div");
+ newImageDiv.setAttribute('style', 'float: left;');
+
+ newImageDescDiv = document.createElement("div");
+ newImageDescDiv.setAttribute('style', 'padding-top: 1px;');
+
+ /* add options to select */
+ for (i = 31; i > 0; i--) {
+ var newOption = document.createElement("option");
+ var newOptionText = document.createTextNode(i.toString());
+
+ newOption.setAttribute('value', i);
+ newOption.appendChild(newOptionText);
+
+ /* add the option to the select element */
+ newSelect.appendChild(newOption);
+ }
+
+ /* assemble everything */
+ descTD.appendChild(newDescription);
+ inputTD.appendChild(newInput);
+ selectTD.appendChild(newSelect);
+
+ newImageDiv.appendChild(newImage);
+ newImageDescDiv.appendChild(newImgDescription);
+
+ imageTD.appendChild(newImageDiv);
+ imageTD.appendChild(newImageDescDiv);
+
+ newTR.appendChild(descTD);
+ newTR.appendChild(inputTD);
+ newTR.appendChild(selectTD);
+ newTR.appendChild(imageTD);
+
+ $('networkopttab').appendChild(newTR);
+}
+
+function create_wan_tr() {
+ var wanSubnet = '{$config['interfaces']['wan']['subnet']}';
+
+ var newTR = document.createElement("tr");
+ newTR.setAttribute('id', 'typeDetailsTR');
+
+ var descTD = document.createElement("td");
+ descTD.setAttribute('align', 'left');
+ descTD.setAttribute('valign', 'top');
+
+ var nettextTD = document.createElement("td");
+ nettextTD.setAttribute('align', 'left');
+ nettextTD.setAttribute('valign', 'top');
+
+ var imageTD = document.createElement("td");
+ imageTD.setAttribute('align', 'left');
+ imageTD.setAttribute('valign', 'middle');
+ imageTD.setAttribute('colspan', '2');
+
+ var newDescription = document.createTextNode('{$addressTransString}:');
+ var newWanDescription = document.createTextNode('{$generatedWANSubnet}/' + wanSubnet);
+
+ var newNetTextSpan = document.createElement("span");
+ newNetTextSpan.setAttribute('style', 'font-weight: bold; font-style: italic; vertical-align: middle;');
+
+ var newImage = document.createElement("img");
+ newImage.setAttribute('src', '/themes/{$g['theme']}/images/misc/bullet_toggle_plus.png');
+ newImage.setAttribute('alt', 'add network');
+ newImage.setAttribute('border', '0');
+ newImage.setAttribute('style', 'margin-right: 5px; border: solid 1px silver; cursor: pointer;');
+ newImage.setAttribute('onclick', 'add_selnetwork("{$generatedWANSubnet}", ' + wanSubnet + ');');
+
+ /* divs are used to achieve proper alignement */
+ newImageDiv = document.createElement("div");
+ newImageDiv.setAttribute('style', 'float: left;');
+
+ newImageDescDiv = document.createElement("div");
+ newImageDescDiv.setAttribute('style', 'padding-top: 1px;');
+
+ var newImgDescription = document.createTextNode('{$plusimgDescTransString}');
+
+ /* assemble everything */
+ newNetTextSpan.appendChild(newWanDescription);
+
+ descTD.appendChild(newDescription);
+ nettextTD.appendChild(newNetTextSpan);
+
+ newImageDiv.appendChild(newImage);
+ newImageDescDiv.appendChild(newImgDescription);
+
+ imageTD.appendChild(newImageDiv);
+ imageTD.appendChild(newImageDescDiv);
+
+ newTR.appendChild(descTD);
+ newTR.appendChild(nettextTD);
+ newTR.appendChild(imageTD);
+
+ $('networkopttab').appendChild(newTR);
+}
+
+function create_lan_tr() {
+ var lanSubnet = '{$config['interfaces']['lan']['subnet']}';
+
+ var newTR = document.createElement("tr");
+ newTR.setAttribute('id', 'typeDetailsTR');
+
+ var descTD = document.createElement("td");
+ descTD.setAttribute('align', 'left');
+ descTD.setAttribute('valign', 'top');
+
+ var nettextTD = document.createElement("td");
+ nettextTD.setAttribute('align', 'left');
+ nettextTD.setAttribute('valign', 'top');
+
+ var imageTD = document.createElement("td");
+ imageTD.setAttribute('align', 'left');
+ imageTD.setAttribute('valign', 'middle');
+ imageTD.setAttribute('colspan', '2');
+
+ var newDescription = document.createTextNode('{$addressTransString}:');
+ var newLanDescription = document.createTextNode('{$generatedLANSubnet}/' + lanSubnet);
+
+ var newNetTextSpan = document.createElement("span");
+ newNetTextSpan.setAttribute('style', 'font-weight: bold; font-style: italic; vertical-align: middle;');
+
+ var newImage = document.createElement("img");
+ newImage.setAttribute('src', '/themes/{$g['theme']}/images/misc/bullet_toggle_plus.png');
+ newImage.setAttribute('alt', 'add network');
+ newImage.setAttribute('border', '0');
+ newImage.setAttribute('style', 'margin-right: 5px; border: solid 1px silver; cursor: pointer;');
+ newImage.setAttribute('onclick', 'add_selnetwork("{$generatedLANSubnet}", ' + lanSubnet + ');');
+
+ /* divs are used to achieve proper alignement */
+ newImageDiv = document.createElement("div");
+ newImageDiv.setAttribute('style', 'float: left;');
+
+ newImageDescDiv = document.createElement("div");
+ newImageDescDiv.setAttribute('style', 'padding-top: 1px;');
+
+ var newImgDescription = document.createTextNode('{$plusimgDescTransString}');
+
+ /* assemble everything */
+ newNetTextSpan.appendChild(newLanDescription);
+
+ descTD.appendChild(newDescription);
+ nettextTD.appendChild(newNetTextSpan);
+
+ newImageDiv.appendChild(newImage);
+ newImageDescDiv.appendChild(newImgDescription);
+
+ imageTD.appendChild(newImageDiv);
+ imageTD.appendChild(newImageDescDiv);
+
+ newTR.appendChild(descTD);
+ newTR.appendChild(nettextTD);
+ newTR.appendChild(imageTD);
+
+ $('networkopttab').appendChild(newTR);
+}
+
+function get_optnetwork() {
+ var slashIndex= $('opt_iface_desc').firstChild.nodeValue.indexOf('/');
+ var myNetwork = $('opt_iface_desc').firstChild.nodeValue.substring(0, slashIndex);
+
+ return myNetwork;
+}
+
+function get_optsubnet() {
+ var slashIndex= $('opt_iface_desc').firstChild.nodeValue.indexOf('/');
+ var mySubnet = $('opt_iface_desc').firstChild.nodeValue.substring(slashIndex + 1, $('opt_iface_desc').firstChild.nodeValue.length);
+
+ return mySubnet;
+}
+
+function create_opt_tr() {
+ var newTR = document.createElement("tr");
+ newTR.setAttribute('id', 'typeDetailsTR');
+
+ var descTD = document.createElement("td");
+ descTD.setAttribute('align', 'left');
+ descTD.setAttribute('valign', 'top');
+
+ var nettextTD = document.createElement("td");
+ nettextTD.setAttribute('align', 'left');
+ nettextTD.setAttribute('valign', 'top');
+
+ var imageTD = document.createElement("td");
+ imageTD.setAttribute('align', 'left');
+ imageTD.setAttribute('valign', 'middle');
+ imageTD.setAttribute('colspan', '2');
+
+ var newDescription = document.createTextNode('{$addressTransString}:');
+ var newImgDescription = document.createTextNode('{$plusimgDescTransString}');
+
+ var newImage = document.createElement("img");
+ newImage.setAttribute('src', '/themes/{$g['theme']}/images/misc/bullet_toggle_plus.png');
+ newImage.setAttribute('alt', 'add network');
+ newImage.setAttribute('border', '0');
+ newImage.setAttribute('style', 'margin-right: 5px; border: solid 1px silver; cursor: pointer;');
+ newImage.setAttribute('onclick', 'add_selnetwork(get_optnetwork(), get_optsubnet());');
+
+ /* divs are used to achieve proper alignement */
+ newImageDiv = document.createElement("div");
+ newImageDiv.setAttribute('style', 'float: left;');
+
+ newImageDescDiv = document.createElement("div");
+ newImageDescDiv.setAttribute('style', 'padding-top: 1px;');
+
+ /* add options to select */
+
+EOD;
+
+for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++) {
+ $optSubnet = $config['interfaces']['opt' . $i]['subnet'];
+ $generatedOPTSubnet = gen_subnet($config['interfaces']['opt' . $i]['ipaddr'],
+ $config['interfaces']['opt' . $i]['subnet']);
+
+ if (empty($optSubnet) || empty($generatedOPTSubnet)) { continue; }
+
+ $jscriptstr .= <<<EOD
+ var selOptIndex = $('authnettype').selectedIndex;
+ var optNumber = $('authnettype').options[selOptIndex].value.substr(3, $('authnettype').options[selOptIndex].value.length);
+ var newOptDescription = null;
+ var newNetTextSpan = null;
+
+ if (optNumber == {$i}) {
+ newOptDescription = document.createTextNode('{$generatedOPTSubnet}/{$optSubnet}');
+
+ newNetTextSpan = document.createElement("span");
+ newNetTextSpan.setAttribute('id', 'opt_iface_desc');
+ newNetTextSpan.setAttribute('style', 'font-weight: bold; font-style: italic; vertical-align: middle;');
+ }
+
+EOD;
+}
+
+$jscriptstr .= <<<EOD
+ /* assemble everything */
+ if (newNetTextSpan)
+ newNetTextSpan.appendChild(newOptDescription);
+
+ descTD.appendChild(newDescription);
+ if (newNetTextSpan)
+ nettextTD.appendChild(newNetTextSpan);
+
+ newImageDiv.appendChild(newImage);
+ newImageDescDiv.appendChild(newImgDescription);
+
+ imageTD.appendChild(newImageDiv);
+ imageTD.appendChild(newImageDescDiv);
+
+ newTR.appendChild(descTD);
+ newTR.appendChild(nettextTD);
+ newTR.appendChild(imageTD);
+
+ $('networkopttab').appendChild(newTR);
+}
+
+function authnet_change() {
+ var tmpElement = $('authnetworks');
+
+ if ($('typeDetailsTR')) { $('networkopttab').removeChild($('typeDetailsTR')); }
+ if ($('authNetworksTR')) { $('networkopttab').removeChild($('authNetworksTR')); }
+ if ($('authNetworksImageTR')) { $('networkopttab').removeChild($('authNetworksImageTR')); }
+
+ switch ($('authnettype').selectedIndex) {
+ case 0:
+ /* Network */
+ create_network_tr();
+ break;
+ case 1:
+ /* WAN subnet */
+ create_wan_tr();
+ break;
+ case 2:
+ /* LAN subnet */
+ create_lan_tr();
+ break;
+
+EOD;
+
+for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++) {
+ $case_count = 2 + $i;
+
+ $jscriptstr .= <<<EOD
+ case {$case_count}:
+ /* OPT subnet */
+ create_opt_tr();
+ break;
+
+EOD;
+
+} // end for
+
+$jscriptstr .= <<<EOD
+ } // end switch
+
+ create_authnetworks_tr(tmpElement);
+} // end function authnet_change
+//-->
+</script>
+
+EOD;
+
+$pfSenseHead->addScript($jscriptstr);
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc"); ?>
+
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+ <div id="inputerrors"></div>
+ <form id="iform" name="iform" action="disks_mount_edit.php" method="post">
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="100%" align="left" valign="middle" class="listtopic" colspan="2"><?=gettext("Export Options");?></td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?= gettext("Export Name"); ?></td>
+ <td width="78%" class="vtable">
+ <input type="text" class="formfld file" size="30" value="/mnt/<?=htmlspecialchars($freenas_config['mounts']['mount'][$id]['sharename']);?>" readonly="readonly" />
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?= gettext("Description"); ?></td>
+ <td width="78%" class="vtable">
+ <input type="text" class="formfld unknown" size="30" value="<?=htmlspecialchars($freenas_config['mounts']['mount'][$id]['desc']);?>" readonly="readonly" />
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?=gettext("map all user to root");?></td>
+ <td width="78%" class="vtable">
+ <select name="mapall" class="formselect" id="mapall">
+ <?php
+ $types = explode(",", "Yes,No");
+ $vals = explode(" ", "yes no");
+ $j = 0;
+
+ for ($j = 0; $j < count($vals); $j++):
+ ?>
+ <option value="<?=$vals[$j];?>" <?php if ($vals[$j] == $pconfig['mapall']) echo "selected=\"selected\"";?>>
+ <?=htmlspecialchars($types[$j]);?>
+ </option>
+ <?php endfor; ?>
+ </select>
+ <br />
+ <?= gettext("All users will have the root privilege."); ?>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?=gettext("Authorised network");?></td>
+ <td width="78%" class="vtable" align="left" valign="middle">
+ <table border="0" cellspacing="0" cellpadding="4" id="networkopttab">
+ <tr>
+ <td align="left" valign="middle"><?=gettext("Type");?>:</td>
+ <td align="left" valign="middle" colspan="4">
+ <select name="authnettype" id="authnettype" class="formselect" onchange="authnet_change();">
+ <option value="network">
+ <?=gettext("Network")?>
+ </option>
+ <option value="wan">
+ <?=gettext("WAN subnet");?>
+ </option>
+ <option value="lan">
+ <?=gettext("LAN subnet");?>
+ </option>
+ <?php
+ for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++):
+ ?>
+ <option value="opt<?=$i;?>">
+ <?=htmlspecialchars($config['interfaces']['opt' . $i]['descr']);?>
+ <?=gettext("subnet");?>
+ </option>
+ <?php endfor; ?>
+ </select>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <input id="submit" name="Submit" type="submit" class="formbtn" value="<?=gettext("Save");?>" onmousedown="selectnetel();" onkeydown="selectnetel();" />
+ <?php if(isset($id)): ?>
+ <input id="id" name="id" type="hidden" value="<?=$id;?>" />
+ <?php endif; ?>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <span class="red">
+ <strong><?= gettext("NOTE"); ?>:</strong>
+ </span>
+ <br />
+ <ul>
+ <li>
+ <span class="vexpl">
+ <?= gettext("The name of each exported directory is: /mnt/sharename"); ?>
+ </span>
+ </li>
+ <li>
+ <span class="vexpl">
+ <?= gettext("Try adding networks to the 'current networks' list to authorize each particular network."); ?>
+ </span>
+ </li>
+ <li>
+ <span class="vexpl">
+ <?= gettext("Use ctrl-click (or command-click on the Mac) to select and de-select elements from the 'current networks' list."); ?>
+ </span>
+ </li>
+ </ul>
+ </td>
+ </tr>
+ </table>
+ </form>
+<?php include("fend.inc"); ?>
+<?= checkForInputErrors(); ?>
+<script type="text/javascript">
+<!--
+authnet_change();
+//-->
+</script>
+</body>
+</html>
diff --git a/config/freenas/www/services_rsyncd.php b/config/freenas/www/services_rsyncd.php
new file mode 100644
index 00000000..a31aa229
--- /dev/null
+++ b/config/freenas/www/services_rsyncd.php
@@ -0,0 +1,277 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ services_rsyncd.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+$pgtitle = array(gettext("Services"),
+ gettext("RSYNCD"),
+ gettext("Server"));
+
+require_once("freenas_config.inc");
+require_once("guiconfig.inc");
+require_once("freenas_guiconfig.inc");
+require_once("freenas_functions.inc");
+
+/* TODO: use pfSense users/groups. */
+if (!is_array($freenas_config['system']['user']))
+ $freenas_config['system']['user'] = array();
+
+users_sort();
+
+$a_user = &$freenas_config['system']['user'];
+
+if (!is_array($freenas_config['rsync']))
+{
+ $freenas_config['rsync'] = array();
+}
+
+$pconfig['readonly'] = $freenas_config['rsyncd']['readonly'];
+$pconfig['port'] = $freenas_config['rsyncd']['port'];
+$pconfig['motd'] = $freenas_config['rsyncd']['motd'];
+$pconfig['maxcon'] = $freenas_config['rsyncd']['maxcon'];
+$pconfig['rsyncd_user'] = $freenas_config['rsyncd']['rsyncd_user'];
+$pconfig['enable'] = isset($freenas_config['rsyncd']['enable']);
+
+if (! empty($_POST))
+{
+ /* hash */
+ unset($error_bucket);
+ /* simple error list */
+ unset($input_errors);
+ unset($do_format);
+ $pconfig = $_POST;
+
+ /* input validation */
+ if ($_POST['enable'])
+ {
+ $reqdfields = array_merge($reqdfields, explode(" ", "readonly port"));
+ $reqdfieldsn = array_merge($reqdfieldsn, explode(",", "Readonly,Port"));
+ }
+
+ do_input_validation($_POST, $reqdfields, $reqdfieldsn, &$input_errors);
+
+ if ($_POST['enable']) {
+ if (!is_port($_POST['port']))
+ $error_bucket[] = array("error" => gettext("The TCP port must be a valid port number."),
+ "field" => "port");
+ else if (!is_numericint($_POST['maxcon']))
+ $error_bucket[] = array("error" => gettext("The value provided by the maximum connections field is not a number"),
+ "field" => "maxcon");
+ }
+
+ if (is_array($error_bucket))
+ foreach($error_bucket as $elem)
+ $input_errors[] =& $elem["error"];
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($error_bucket)) {
+ input_errors2Ajax(NULL, $error_bucket);
+ exit;
+ }
+
+ if (!$input_errors)
+ {
+ $freenas_config['rsyncd']['readonly'] = $_POST['readonly'];
+ $freenas_config['rsyncd']['port'] = $_POST['port'];
+ $freenas_config['rsyncd']['motd'] = $_POST['motd'];
+ $freenas_config['rsyncd']['maxcon'] = $_POST['maxcon'];
+ $freenas_config['rsyncd']['enable'] = $_POST['enable'] ? true : false;
+ $freenas_config['rsyncd']['rsyncd_user'] = $_POST['rsyncd_user'];
+
+ write_config();
+
+ $retval = 0;
+ if (!file_exists($d_sysrebootreqd_path))
+ {
+ /* nuke the cache file */
+ config_lock();
+ services_rsyncd_configure();
+ services_zeroconf_configure();
+ config_unlock();
+ }
+ $savemsg = get_std_save_message($retval);
+ }
+}
+
+/* if ajax is calling, give them an update message */
+if(isAjax())
+ print_info_box_np($savemsg);
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+
+$jscriptstr = <<<EOD
+<script type="text/javascript">
+<!--
+function enable_change(enable_change) {
+ var endis;
+
+ endis = !(document.iform.enable.checked || enable_change);
+ endis ? color = '#D4D0C8' : color = '#FFFFFF';
+
+ document.iform.readonly.disabled = endis;
+ document.iform.port.disabled = endis;
+ document.iform.motd.disabled = endis;
+ document.iform.maxcon.disabled = endis;
+ document.iform.rsyncd_user.disabled = endis;
+ /* adjust colors */
+ document.iform.readonly.style.backgroundColor = color;
+ document.iform.port.style.backgroundColor = color;
+ document.iform.motd.style.backgroundColor = color;
+ document.iform.maxcon.style.backgroundColor = color;
+ document.iform.rsyncd_user.style.backgroundColor = color;
+}
+//-->
+</script>
+
+EOD;
+
+$pfSenseHead->addScript($jscriptstr);
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc"); ?>
+
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+<div id="inputerrors"></div>
+<table width="100%" border="0" cellspacing="0" cellpadding="0">
+ <tr>
+ <td>
+ <?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Server"), true, "services_rsyncd.php");
+ $tab_array[1] = array(gettext("Client"), false, "services_rsyncd_client.php");
+ $tab_array[2] = array(gettext("Local"), false, "services_rsyncd_local.php");
+ display_top_tabs($tab_array);
+ ?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <form id="iform" name="iform" action="services_rsyncd.php" method="post">
+ <table class="tabcont" align="center" width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="100%" valign="middle" class="listtopic" colspan="2">
+ <span style="vertical-align: middle; position: relative; left: 0px;"><?=gettext("Rsync Daemon");?></span>
+ <span style="vertical-align: middle; position: relative; left: 81%;">
+ <input name="enable" type="checkbox" value="yes" <?php if ($pconfig['enable']) echo "checked=\"checked\""; ?> onClick="enable_change(false)" />&nbsp;<?= gettext("Enable"); ?>
+ </span>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?= gettext("Read only"); ?></td>
+ <td width="78%" class="vtable">
+ <select name="readonly" class="formselect" id="readonly">
+ <?php
+ $types = explode(",", "Yes,No");
+ $vals = explode(" ", "yes no");
+ $j = 0;
+
+ for ($j = 0; $j < count($vals); $j++):
+ ?>
+ <option value="<?=$vals[$j];?>" <?php if ($vals[$j] == $pconfig['readonly']) echo "selected=\"selected\"";?>>
+ <?=htmlspecialchars($types[$j]);?>
+ </option>
+ <?php endfor; ?>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?= gettext("Map to user"); ?></td>
+ <td width="78%" class="vtable">
+ <select name="rsyncd_user" class="formselect" id="rsyncd_user">
+ <option value="ftp"<?php if ($pconfig['rsyncd_user'] == "ftp") echo "selected";?>>
+ <?php echo htmlspecialchars("guest"); ?>
+ <?php foreach ($a_user as $user): ?>
+ <option value="<?=$user['name'];?>"<?php if ($user['name'] == $pconfig['rsyncd_user']) echo "selected";?>>
+ <?php echo htmlspecialchars($user['name']); ?>
+ </option>
+ <?php endforeach; ?>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?= gettext("TCP port"); ?></td>
+ <td width="78%" class="vtable">
+ <input name="port" type="text" class="formfld unknown" id="port" size="20" value="<?=htmlspecialchars($pconfig['port']);?>" />
+ <br /><?= gettext("Alternate TCP port."); ?>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?= gettext("Maximum connections"); ?></td>
+ <td width="78%" class="vtable">
+ <input name="maxcon" type="text" class="formfld unknown" id="maxcon" size="20" value="<?=htmlspecialchars($pconfig['maxcon']);?>" />
+ <br /><?= gettext("Maximum number of simultaneous connections. Default is 0 (unlimited)"); ?>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?= gettext("MOTD"); ?></td>
+ <td width="78%" class="vtable">
+ <textarea name="motd" cols="65" rows="7" id="motd" class="formpre"><?=htmlspecialchars($pconfig['motd']);?></textarea>
+ <br />
+ <?= gettext("message of the day");?>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <input id="submit" name="Submit" type="submit" class="formbtn" value="<?=gettext("Save");?>" />
+ </td>
+ </tr>
+ </table>
+ </form>
+ </div>
+ </td>
+ </tr>
+</table>
+<?php include("fend.inc"); ?>
+<?= checkForInputErrors(); ?>
+<script type="text/javascript">
+<!--
+enable_change(false);
+//-->
+</script>
+</body>
+</html>
diff --git a/config/freenas/www/services_rsyncd_client.php b/config/freenas/www/services_rsyncd_client.php
new file mode 100644
index 00000000..efb0e870
--- /dev/null
+++ b/config/freenas/www/services_rsyncd_client.php
@@ -0,0 +1,585 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ services_rsyncd_client.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+$pgtitle = array(gettext("Services"),
+ gettext("RSYNCD"),
+ gettext("Client"));
+
+require_once("freenas_config.inc");
+require_once("guiconfig.inc");
+require_once("freenas_guiconfig.inc");
+require_once("freenas_functions.inc");
+
+if (!is_array($freenas_config['rsyncclient']))
+{
+ $freenas_config['rsyncclient'] = array();
+}
+
+$a_months = array("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December");
+$a_weekdays = array("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday");
+$a_mount = array();
+
+$pconfig['readonly'] = $freenas_config['rsyncd']['readonly'];
+$pconfig['port'] = $freenas_config['rsyncd']['port'];
+$pconfig['motd'] = $freenas_config['rsyncd']['motd'];
+$pconfig['maxcon'] = $freenas_config['rsyncd']['maxcon'];
+$pconfig['rsyncd_user'] = $freenas_config['rsyncd']['rsyncd_user'];
+$pconfig['enable'] = isset($freenas_config['rsyncd']['enable']);
+
+if (!is_array($freenas_config['mounts']['mount'])) {
+ $nodisk_errors[] = gettext("You must configure mount point first.");
+} else {
+ if (! empty($_POST))
+ {
+ /* hash */
+ unset($error_bucket);
+ /* simple error list */
+ unset($input_errors);
+ unset($do_format);
+ $pconfig = $_POST;
+
+ /* input validation */
+ if ($_POST['enable']){
+ $reqdfields = array_merge($reqdfields, explode(" ", "rsyncserverip sharetosync"));
+ $reqdfieldsn = array_merge($reqdfieldsn, explode(",", "Rsyncserverip,Sharetosync"));
+ }
+
+ do_input_validation($_POST, $reqdfields, $reqdfieldsn, &$input_errors);
+
+ if ($_POST['enable']) {
+ if (!is_port($_POST['port']))
+ $error_bucket[] = array("error" => gettext("The TCP port must be a valid port number."),
+ "field" => "port");
+ else if (!is_numericint($_POST['maxcon']))
+ $error_bucket[] = array("error" => gettext("The value provided by the maximum connections field is not a number"),
+ "field" => "maxcon");
+ }
+
+ if (!is_array($freenas_config['mounts']['mount'])) {
+ $error_bucket[] = array("error" => gettext("You must configure mount point first."),
+ "field" => "none");
+ }
+
+ if ($_POST['enable'] && !is_ipaddr($_POST['rsyncserverip'])) {
+ $error_bucket[] = array("error" => gettext("A valid IP address must be specified."),
+ "field" => "rsyncserverip");
+ }
+
+ if (is_array($error_bucket))
+ foreach($error_bucket as $elem)
+ $input_errors[] =& $elem["error"];
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($error_bucket)) {
+ input_errors2Ajax(NULL, $error_bucket);
+ exit;
+ }
+
+ if (!$input_errors)
+ {
+ $freenas_config['rsyncclient']['opt_delete'] = $_POST['opt_delete'] ? true : false;;
+ $freenas_config['rsyncclient']['rsyncserverip'] = $_POST['rsyncserverip'];
+ $freenas_config['rsyncclient']['minute'] = $_POST['minutes'];
+ $freenas_config['rsyncclient']['hour'] = $_POST['hours'];
+ $freenas_config['rsyncclient']['day'] = $_POST['days'];
+ $freenas_config['rsyncclient']['month'] = $_POST['months'];
+ $freenas_config['rsyncclient']['weekday'] = $_POST['weekdays'];
+ $freenas_config['rsyncclient']['rsyncshare'] = $_POST['rsyncshare'];
+ $freenas_config['rsyncclient']['enable'] = $_POST['enable'] ? true : false;
+ $freenas_config['rsyncclient']['sharetosync'] = $_POST['sharetosync'];
+ $freenas_config['rsyncclient']['all_mins'] = $_POST['all_mins'];
+ $freenas_config['rsyncclient']['all_hours'] = $_POST['all_hours'];
+ $freenas_config['rsyncclient']['all_days'] = $_POST['all_days'];
+ $freenas_config['rsyncclient']['all_months'] = $_POST['all_months'];
+ $freenas_config['rsyncclient']['all_weekdays'] = $_POST['all_weekdays'];
+
+ write_config();
+
+ $retval = 0;
+
+ if (!file_exists($d_sysrebootreqd_path)){
+ /* nuke the cache file */
+ config_lock();
+ services_rsyncclient_configure();
+ services_cron_configure();
+ config_unlock();
+ }
+
+ $savemsg = get_std_save_message($retval);
+ }
+ }
+
+ mount_sort();
+ $a_mount = &$freenas_config['mounts']['mount'];
+
+ $pconfig['opt_delete'] = isset($freenas_config['rsyncclient']['opt_delete']);
+ $pconfig['enable'] = isset($freenas_config['rsyncclient']['enable']);
+ $pconfig['rsyncserverip'] = $freenas_config['rsyncclient']['rsyncserverip'];
+ $pconfig['rsyncshare'] = $freenas_config['rsyncclient']['rsyncshare'];
+ $pconfig['minute'] = $freenas_config['rsyncclient']['minute'];
+ $pconfig['hour'] = $freenas_config['rsyncclient']['hour'];
+ $pconfig['day'] = $freenas_config['rsyncclient']['day'];
+ $pconfig['month'] = $freenas_config['rsyncclient']['month'];
+ $pconfig['weekday'] = $freenas_config['rsyncclient']['weekday'];
+ $pconfig['sharetosync'] = $freenas_config['rsyncclient']['sharetosync'];
+ $pconfig['all_mins'] = $freenas_config['rsyncclient']['all_mins'];
+ $pconfig['all_hours'] = $freenas_config['rsyncclient']['all_hours'];
+ $pconfig['all_days'] = $freenas_config['rsyncclient']['all_days'];
+ $pconfig['all_months'] = $freenas_config['rsyncclient']['all_months'];
+ $pconfig['all_weekdays'] = $freenas_config['rsyncclient']['all_weekdays'];
+
+ if ($pconfig['all_mins'] == 1){
+ $all_mins_all = " checked";
+ } else {
+ $all_mins_selected = " checked";
+ }
+
+ if ($pconfig['all_hours'] == 1){
+ $all_hours_all = " checked";
+ } else {
+ $all_hours_selected = " checked";
+ }
+
+ if ($pconfig['all_days'] == 1){
+ $all_days_all = " checked";
+ } else {
+ $all_days_selected = " checked";
+ }
+
+ if ($pconfig['all_months'] == 1){
+ $all_months_all = " checked";
+ } else {
+ $all_months_selected = " checked";
+ }
+
+ if ($pconfig['all_weekdays'] == 1){
+ $all_weekdays_all = " checked";
+ } else {
+ $all_weekdays_selected = " checked";
+ }
+}
+
+/* if ajax is calling, give them an update message */
+if(isAjax())
+ print_info_box_np($savemsg);
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+
+$jscriptstr = <<<EOD
+<script type="text/javascript">
+<!--
+function enable_change(enable_change) {
+ var endis;
+
+ endis = !(document.iform.enable.checked || enable_change);
+ endis ? color = '#D4D0C8' : color = '#FFFFFF';
+
+EOD;
+
+$i = 0;
+
+if (is_array($a_mount)) {
+ foreach ($a_mount as $mountv) {
+ $jscriptstr .= " document.iform.share_" . $i . ".disabled = endis;\n";
+ $i++;
+ }
+}
+
+/* Note: In contrast to FreeNAS we are only using
+ * three minutes and one hours field(s)
+ */
+$jscriptstr .= <<<EOD
+
+ document.iform.rsyncserverip.disabled = endis;
+ document.iform.minutes1.disabled = endis;
+ document.iform.minutes2.disabled = endis;
+ document.iform.minutes3.disabled = endis;
+ document.iform.hours1.disabled = endis;
+ /* document.iform.hours2.disabled = endis; */
+ document.iform.days1.disabled = endis;
+ document.iform.days2.disabled = endis;
+ /* document.iform.days3.disabled = endis; */
+ document.iform.months.disabled = endis;
+ document.iform.weekdays.disabled = endis;
+ document.iform.all_mins1.disabled = endis;
+ document.iform.all_mins2.disabled = endis;
+ document.iform.all_hours1.disabled = endis;
+ document.iform.all_hours2.disabled = endis;
+ document.iform.all_days1.disabled = endis;
+ document.iform.all_days2.disabled = endis;
+ document.iform.all_months1.disabled = endis;
+ document.iform.all_months2.disabled = endis;
+ document.iform.all_weekdays1.disabled = endis;
+ document.iform.all_weekdays2.disabled = endis;
+ document.iform.opt_delete.disabled = endis;
+ /* color adjustments */
+ document.iform.rsyncserverip.style.backgroundColor = color;
+ document.iform.minutes1.style.backgroundColor = color;
+ document.iform.minutes2.style.backgroundColor = color;
+ document.iform.minutes3.style.backgroundColor = color;
+ document.iform.hours1.style.backgroundColor = color;
+ /* document.iform.hours2.style.backgroundColor = color; */
+ document.iform.days1.style.backgroundColor = color;
+ document.iform.days2.style.backgroundColor = color;
+ /* document.iform.days3.style.backgroundColor = color; */
+ document.iform.months.style.backgroundColor = color;
+ document.iform.weekdays.style.backgroundColor = color;
+ document.iform.all_mins1.style.backgroundColor = color;
+ document.iform.all_mins2.style.backgroundColor = color;
+ document.iform.all_hours1.style.backgroundColor = color;
+ document.iform.all_hours2.style.backgroundColor = color;
+ document.iform.all_days1.style.backgroundColor = color;
+ document.iform.all_days2.style.backgroundColor = color;
+ document.iform.all_months1.style.backgroundColor = color;
+ document.iform.all_months2.style.backgroundColor = color;
+ document.iform.all_weekdays1.style.backgroundColor = color;
+ document.iform.all_weekdays2.style.backgroundColor = color;
+ document.iform.opt_delete.style.backgroundColor = color;
+}
+//-->
+</script>
+
+EOD;
+
+$pfSenseHead->addScript($jscriptstr);
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc"); ?>
+
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+<div id="inputerrors"></div>
+<table width="100%" border="0" cellspacing="0" cellpadding="0">
+ <tr>
+ <td>
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Server"), false, "services_rsyncd.php");
+ $tab_array[1] = array(gettext("Client"), true, "services_rsyncd_client.php");
+ $tab_array[2] = array(gettext("Local"), false, "services_rsyncd_local.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <form id="iform" name="iform" action="services_rsyncd_client.php" method="post">
+ <table class="tabcont" align="center" width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="100%" valign="middle" class="listtopic" colspan="2">
+ <span style="vertical-align: middle; position: relative; left: 0px;"><?=gettext("Rsync Client Synchronization");?></span>
+ <span style="vertical-align: middle; position: relative; left: 70%;">
+ <input name="enable" type="checkbox" value="yes" <?php if ($pconfig['enable']) echo "checked=\"checked\""; ?> onClick="enable_change(false)" />&nbsp;<?= gettext("Enable"); ?>
+ </span>
+ </td>
+ </tr>
+ <tr>
+ <td width="16%" valign="top" class="vncellreq"><?= gettext("Remote RSYNC Server"); ?></td>
+ <td width="84%" class="vtable">
+ <input name="rsyncserverip" id="rsyncserverip" type="text" class="formfld unknown" size="20" value="<?=htmlspecialchars($pconfig['rsyncserverip']);?>" />
+ <br />
+ <?= gettext("IP address of remote RSYNC server"); ?>
+ </td>
+ </tr>
+ <tr>
+ <td width="16%" valign="top" class="vncellreq"><?= gettext("RSYNC Options"); ?></td>
+ <td width="84%" class="vtable">
+ <input name="opt_delete" id="opt_delete" type="checkbox" value="yes" <?php if ($pconfig['opt_delete']) echo "checked=\"checked\""; ?> />
+ <?= gettext("Delete files that don't exist on sender."); ?>
+ </td>
+ </tr>
+ <tr>
+ <td width="16%" valign="top" class="vncellreq"><?= gettext("Shares to be synchronized"); ?></td>
+ <td width="84%" class="vtable">
+ <?php
+ if (is_array($freenas_config['mounts']['mount'])) {
+ $i=0;
+ foreach ($a_mount as $mountv) {
+ echo "<input name=\"sharetosync[]\" id=\"share_" . $i . "\" type=\"checkbox\" value=\"" . $mountv['sharename'] . "\"";
+ if ($mountv['sharename'] == $pconfig['sharetosync'])
+ echo " checked=\"checked\"";
+ echo" />";
+ echo $mountv['sharename'] . " (" . $mountv['desc'] . ")<br />\n";
+ $i++;
+ }
+ }
+ else
+ echo "You must configure mount point before!";
+ ?>
+ <br />
+ <?= gettext("This same local share must be present on the Remote Server."); ?>
+ </td>
+ </tr>
+ <tr>
+ <td width="16%" valign="top" class="vncellreq"><?= gettext("Synchronization Time"); ?></td>
+ <td width="84%" class="vtable">
+ <table width="100%" border="1" cellpadding="4" cellspacing="0">
+ <tr>
+ <td align="left" valign="top" class="listtopic"><?= gettext("minutes"); ?></td>
+ <td align="left" valign="top" class="listtopic"><?= gettext("hours"); ?></td>
+ <td align="left" valign="top" class="listtopic"><?= gettext("days"); ?></td>
+ <td align="left" valign="top" class="listtopic"><?= gettext("months"); ?></td>
+ <td align="left" valign="top" class="listtopic"><?= gettext("week days"); ?></td>
+ </tr>
+ <tr>
+ <td align="left" valign="top" class="vncell" nowrap="nowrap">
+ <div id="all_min_rdbtns" style="padding-bottom: 10px;" >
+ <input type="radio" name="all_mins" id="all_mins1" value="1"<?php echo $all_mins_all;?> />
+ <label for="all_mins1">All</label><br />
+ <input type="radio" name="all_mins" id="all_mins2" value="0"<?php echo $all_mins_selected;?> />
+ <label for="all_mins2">Selected ...</label>
+ </div>
+ <div id="all_min_select" style="vertical-align: top;">
+ <select multiple="multible" class="formselect" size="24" name="minutes[]" id="minutes1" style="vertical-align: top;">
+ <?php
+ $i = 0;
+ while ($i <= 23){
+ if (isset($pconfig['minute'])) {
+ if (in_array($i, $pconfig['minute'])) {
+ $is_selected = " selected";
+ } else {
+ $is_selected = "";
+ }
+ }
+
+ echo "<option value=\"" . $i . "\"" . $is_selected . ">" . $i . "\n";
+ $i++;
+ }
+ ?>
+ </select>
+ <select multiple="multible" class="formselect" size="24" name="minutes[]" id="minutes2" style="vertical-align: top;">
+ <?php
+ $i = 24;
+ while ($i <= 47) {
+ if (isset($pconfig['minute'])) {
+ if (in_array($i, $pconfig['minute'])) {
+ $is_selected = " selected";
+ } else {
+ $is_selected = "";
+ }
+ }
+
+ echo "<option value=\"" . $i . "\"" . $is_selected . ">" . $i . "\n";
+ $i++;
+ }
+ ?>
+ </select>
+ <select multiple="multible" class="formselect" size="12" name="minutes[]" id="minutes3" style="vertical-align: top;">
+ <?php
+ $i = 48;
+ while ($i <= 59) {
+ if (isset($pconfig['minute'])) {
+ if (in_array($i, $pconfig['minute'])) {
+ $is_selected = " selected";
+ } else {
+ $is_selected = "";
+ }
+ }
+
+ echo "<option value=\"" . $i . "\"" . $is_selected . ">" . $i . "\n";
+ $i++;
+ }
+ ?>
+ </select>
+ </div>
+ </td>
+ <td align="left" valign="top" class="vncell" nowrap="nowrap">
+ <div id="all_hours_rdbtns" style="padding-bottom: 10px;" >
+ <input type="radio" name="all_hours" id="all_hours1" value="1"<?php echo $all_hours_all;?> />
+ <label for="all_hours1">All</label><br />
+ <input type="radio" name="all_hours" id="all_hours2" value="0"<?php echo $all_hours_selected;?> />
+ <label for="all_hours2">Selected ...</label>
+ </div>
+ <div id="all_hours_select" style="vertical-align: top;">
+ <select multiple size="24" name="hours[]" id="hours1" style="vertical-align: top;">
+ <?php
+ $i = 0;
+ while ($i <= 23) {
+ if (isset($pconfig['hour'])) {
+ if (in_array($i, $pconfig['hour'])) {
+ $is_selected = " selected";
+ } else {
+ $is_selected = "";
+ }
+ }
+
+ echo "<option value=\"" . $i . "\"" . $is_selected . ">" . $i . "\n";
+ $i++;
+ }
+ ?>
+ </select>
+ </div>
+ </td>
+ <td align="left" valign="top" class="vncell" nowrap="nowrap">
+ <div id="all_days_rdbtns" style="padding-bottom: 10px;" >
+ <input type="radio" name="all_days" id="all_days1" value="1" <?php echo $all_days_all;?> />
+ <label for="all_days1">All</label><br />
+ <input type="radio" name="all_days" id="all_days2" value="0"<?php echo $all_days_selected;?> />
+ <label for="all_days2">Selected ...</label>
+ </div>
+ <div id="all_days_select" style="vertical-align: top;">
+ <select multiple size="24" name="days[]" id="days1" style="vertical-align: top;">
+ <?php
+ $i = 1;
+ while ($i <= 24) {
+ if (isset($pconfig['day'])) {
+ if (in_array($i, $pconfig['day'])) {
+ $is_selected = " selected";
+ } else {
+ $is_selected = "";
+ }
+ }
+
+ echo "<option value=\"" . $i . "\"" . $is_selected . ">" . $i . "\n";
+ $i++;
+ }
+ ?>
+ </select>
+ <select multiple size="7" name="days[]" id="days2" style="vertical-align: top;">
+ <?php
+ $i = 25;
+ while ($i <= 31) {
+ if (isset($pconfig['day'])) {
+ if (in_array($i, $pconfig['day'])) {
+ $is_selected = " selected";
+ } else {
+ $is_selected = "";
+ }
+ }
+
+ echo "<option value=\"" . $i . "\"" . $is_selected . ">" . $i . "\n";
+ $i++;
+ }
+ ?>
+ </select>
+ </div>
+ </td>
+ <td align="left" valign="top" class="vncell">
+ <div id="all_months_rdbtns" style="padding-bottom: 10px;" >
+ <input type="radio" name="all_months" id="all_months1" value="1"<?php echo $all_months_all;?> />
+ <label for="all_months1">All</label><br />
+ <input type="radio" name="all_months" id="all_months2" value="0"<?php echo $all_months_selected;?> />
+ <label for="all_months2">Selected ...</label>
+ </div>
+ <div id="all_months_select" style="vertical-align: top;">
+ <select multiple size="12" name="months[]" id="months" style="vertical-align: top;">
+ <?php
+ $i=1;
+ foreach ($a_months as $monthv) {
+ if (isset($pconfig['month'])) {
+ if (in_array($i, $pconfig['month'])) {
+ $is_selected = " selected";
+ } else {
+ $is_selected = "";
+ }
+ }
+
+ echo "<option value=\"" . $i . "\"" . $is_selected . ">" . $monthv . "\n";
+ $i++;
+ }
+ ?>
+ </select>
+ </div>
+ </td>
+ <td align="left" valign="top" class="vncell">
+ <div id="all_weekdays_rdbtns" style="padding-bottom: 10px;" >
+ <input type="radio" name="all_weekdays" id="all_weekdays1" value="1"<?php echo $all_weekdays_all;?> />
+ <label for="all_weekdays1">All</label><br />
+ <input type="radio" name="all_weekdays" id="all_weekdays2" value="0"<?php echo $all_weekdays_selected;?> />
+ <label for="all_weekdays2">Selected ...</label>
+ </div>
+ <div id="all_weekdays_select" style="vertical-align: top;">
+ <select multiple size="7" name="weekdays[]" id="weekdays" style="vertical-align: top;">
+ <?php
+ $i=0;
+ foreach ($a_weekdays as $weekdayv) {
+ if (isset($pconfig['weekday'])){
+ if (in_array($i, $pconfig['weekday'])) {
+ $is_selected = " selected";
+ } else {
+ $is_selected = "";
+ }
+ }
+
+ echo "<option value=\"" . $i . "\"" . $is_selected . ">" . $weekdayv . "\n";
+ $i++;
+ }
+ ?>
+ </select>
+ </div>
+ </td>
+ </tr>
+ <tr>
+ <td align="left" valign="top" class="vncell" colspan="5">
+ <?= gettext("Note: Ctrl-click (or command-click on the Mac) to select and de-select minutes, hours, days and months."); ?>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td width="16%" valign="top">&nbsp;</td>
+ <td width="84%">
+ <input id="submit" name="Submit" type="submit" class="formbtn" value="<?=gettext("Save");?>" />
+ </td>
+ </tr>
+ </table>
+ </form>
+ </div>
+ </td>
+ </tr>
+</table>
+<?php include("fend.inc"); ?>
+<?= checkForInputErrors(); ?>
+<script type="text/javascript">
+<!--
+enable_change(false);
+//-->
+</script>
+</body>
+</html>
diff --git a/config/freenas/www/services_rsyncd_local.php b/config/freenas/www/services_rsyncd_local.php
new file mode 100644
index 00000000..df29961a
--- /dev/null
+++ b/config/freenas/www/services_rsyncd_local.php
@@ -0,0 +1,579 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ services_rsyncd_local.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+$pgtitle = array(gettext("Services"),
+ gettext("RSYNCD"),
+ gettext("Local"));
+
+require_once("freenas_config.inc");
+require_once("guiconfig.inc");
+require_once("freenas_guiconfig.inc");
+require_once("freenas_functions.inc");
+
+if (!is_array($freenas_config['rsync_local']))
+{
+ $freenas_config['rsync_local'] = array();
+}
+
+$a_months = array("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December");
+$a_weekdays = array("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday");
+
+$pconfig['readonly'] = $freenas_config['rsyncd']['readonly'];
+$pconfig['port'] = $freenas_config['rsyncd']['port'];
+$pconfig['motd'] = $freenas_config['rsyncd']['motd'];
+$pconfig['maxcon'] = $freenas_config['rsyncd']['maxcon'];
+$pconfig['rsyncd_user'] = $freenas_config['rsyncd']['rsyncd_user'];
+$pconfig['enable'] = isset($freenas_config['rsyncd']['enable']);
+
+if (!is_array($freenas_config['mounts']['mount'])) {
+ $nodisk_errors[] = gettext("You must configure mount point first.");
+} else {
+ if (! empty($_POST))
+ {
+ /* hash */
+ unset($error_bucket);
+ /* simple error list */
+ unset($input_errors);
+
+ $pconfig = $_POST;
+
+ /* input validation */
+ if ($_POST['enable']){
+ $reqdfields = array_merge($reqdfields, explode(" ", "source destination"));
+ $reqdfieldsn = array_merge($reqdfieldsn, explode(",", "Source,Destination"));
+ }
+
+ do_input_validation($_POST, $reqdfields, $reqdfieldsn, &$input_errors);
+
+ if ($_POST['enable'] && (strcmp($_POST['source'],$_POST['destination'])==0)) {
+ $error_bucket[] = array("error" => gettext("You can't have the same mount point for source and destination!"),
+ "field" => "source");
+ }
+
+ if (is_array($error_bucket))
+ foreach($error_bucket as $elem)
+ $input_errors[] =& $elem["error"];
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($error_bucket)) {
+ input_errors2Ajax(NULL, $error_bucket);
+ exit;
+ }
+
+ if (!$input_errors)
+ {
+ $freenas_config['rsync_local']['opt_delete'] = $_POST['opt_delete'] ? true : false;;
+ $freenas_config['rsync_local']['minute'] = $_POST['minutes'];
+ $freenas_config['rsync_local']['hour'] = $_POST['hours'];
+ $freenas_config['rsync_local']['day'] = $_POST['days'];
+ $freenas_config['rsync_local']['month'] = $_POST['months'];
+ $freenas_config['rsync_local']['weekday'] = $_POST['weekdays'];
+ $freenas_config['rsync_local']['source'] = $_POST['source'];
+ $freenas_config['rsync_local']['destination'] = $_POST['destination'];
+ $freenas_config['rsync_local']['enable'] = $_POST['enable'] ? true : false;
+ $freenas_config['rsync_local']['sharetosync'] = $_POST['sharetosync'];
+ $freenas_config['rsync_local']['all_mins'] = $_POST['all_mins'];
+ $freenas_config['rsync_local']['all_hours'] = $_POST['all_hours'];
+ $freenas_config['rsync_local']['all_days'] = $_POST['all_days'];
+ $freenas_config['rsync_local']['all_months'] = $_POST['all_months'];
+ $freenas_config['rsync_local']['all_weekdays'] = $_POST['all_weekdays'];
+
+ write_config();
+
+ $retval = 0;
+
+ if (!file_exists($d_sysrebootreqd_path)){
+ /* nuke the cache file */
+ config_lock();
+ services_rsync_local_configure();
+ services_cron_configure();
+ config_unlock();
+ }
+
+ $savemsg = get_std_save_message($retval);
+ }
+ }
+
+ mount_sort();
+ $a_mount = &$freenas_config['mounts']['mount'];
+
+ $pconfig['opt_delete'] = isset($freenas_config['rsync_local']['opt_delete']);
+ $pconfig['enable'] = isset($freenas_config['rsync_local']['enable']);
+ $pconfig['source'] = $freenas_config['rsync_local']['source'];
+ $pconfig['destination'] = $freenas_config['rsync_local']['destination'];
+ $pconfig['minute'] = $freenas_config['rsync_local']['minute'];
+ $pconfig['hour'] = $freenas_config['rsync_local']['hour'];
+ $pconfig['day'] = $freenas_config['rsync_local']['day'];
+ $pconfig['month'] = $freenas_config['rsync_local']['month'];
+ $pconfig['weekday'] = $freenas_config['rsync_local']['weekday'];
+ $pconfig['sharetosync'] = $freenas_config['rsync_local']['sharetosync'];
+ $pconfig['all_mins'] = $freenas_config['rsync_local']['all_mins'];
+ $pconfig['all_hours'] = $freenas_config['rsync_local']['all_hours'];
+ $pconfig['all_days'] = $freenas_config['rsync_local']['all_days'];
+ $pconfig['all_months'] = $freenas_config['rsync_local']['all_months'];
+ $pconfig['all_weekdays'] = $freenas_config['rsync_local']['all_weekdays'];
+
+ if ($pconfig['all_mins'] == 1){
+ $all_mins_all = " checked";
+ } else {
+ $all_mins_selected = " checked";
+ }
+
+ if ($pconfig['all_hours'] == 1){
+ $all_hours_all = " checked";
+ } else {
+ $all_hours_selected = " checked";
+ }
+
+ if ($pconfig['all_days'] == 1){
+ $all_days_all = " checked";
+ } else {
+ $all_days_selected = " checked";
+ }
+
+ if ($pconfig['all_months'] == 1){
+ $all_months_all = " checked";
+ } else {
+ $all_months_selected = " checked";
+ }
+
+ if ($pconfig['all_weekdays'] == 1){
+ $all_weekdays_all = " checked";
+ } else {
+ $all_weekdays_selected = " checked";
+ }
+}
+
+/* if ajax is calling, give them an update message */
+if(isAjax())
+ print_info_box_np($savemsg);
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+
+$jscriptstr = <<<EOD
+<script type="text/javascript">
+<!--
+function enable_change(enable_change) {
+ var endis;
+
+ endis = !(document.iform.enable.checked || enable_change);
+ endis ? color = '#D4D0C8' : color = '#FFFFFF';
+
+EOD;
+
+/* Note: In contrast to FreeNAS we are only using
+ * three minutes and one hours field(s)
+ */
+$jscriptstr .= <<<EOD
+
+ document.iform.source.disabled = endis;
+ document.iform.destination.disabled = endis;
+ document.iform.minutes1.disabled = endis;
+ document.iform.minutes2.disabled = endis;
+ document.iform.minutes3.disabled = endis;
+ document.iform.hours1.disabled = endis;
+ /* document.iform.hours2.disabled = endis; */
+ document.iform.days1.disabled = endis;
+ document.iform.days2.disabled = endis;
+ /* document.iform.days3.disabled = endis; */
+ document.iform.months.disabled = endis;
+ document.iform.weekdays.disabled = endis;
+ document.iform.all_mins1.disabled = endis;
+ document.iform.all_mins2.disabled = endis;
+ document.iform.all_hours1.disabled = endis;
+ document.iform.all_hours2.disabled = endis;
+ document.iform.all_days1.disabled = endis;
+ document.iform.all_days2.disabled = endis;
+ document.iform.all_months1.disabled = endis;
+ document.iform.all_months2.disabled = endis;
+ document.iform.all_weekdays1.disabled = endis;
+ document.iform.all_weekdays2.disabled = endis;
+ document.iform.opt_delete.disabled = endis;
+ /* color adjustments */
+ document.iform.source.style.backgroundColor = color;
+ document.iform.destination.style.backgroundColor = color;
+ document.iform.minutes1.style.backgroundColor = color;
+ document.iform.minutes2.style.backgroundColor = color;
+ document.iform.minutes3.style.backgroundColor = color;
+ document.iform.hours1.style.backgroundColor = color;
+ /* document.iform.hours2.style.backgroundColor = color; */
+ document.iform.days1.style.backgroundColor = color;
+ document.iform.days2.style.backgroundColor = color;
+ /* document.iform.days3.style.backgroundColor = color; */
+ document.iform.months.style.backgroundColor = color;
+ document.iform.weekdays.style.backgroundColor = color;
+ document.iform.all_mins1.style.backgroundColor = color;
+ document.iform.all_mins2.style.backgroundColor = color;
+ document.iform.all_hours1.style.backgroundColor = color;
+ document.iform.all_hours2.style.backgroundColor = color;
+ document.iform.all_days1.style.backgroundColor = color;
+ document.iform.all_days2.style.backgroundColor = color;
+ document.iform.all_months1.style.backgroundColor = color;
+ document.iform.all_months2.style.backgroundColor = color;
+ document.iform.all_weekdays1.style.backgroundColor = color;
+ document.iform.all_weekdays2.style.backgroundColor = color;
+ document.iform.opt_delete.style.backgroundColor = color;
+}
+//-->
+</script>
+
+EOD;
+
+$pfSenseHead->addScript($jscriptstr);
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc"); ?>
+
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+<div id="inputerrors"></div>
+<table width="100%" border="0" cellspacing="0" cellpadding="0">
+ <tr>
+ <td>
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Server"), false, "services_rsyncd.php");
+ $tab_array[1] = array(gettext("Client"), false, "services_rsyncd_client.php");
+ $tab_array[2] = array(gettext("Local"), true, "services_rsyncd_local.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <form id="iform" name="iform" action="services_rsyncd_local.php" method="post">
+ <table class="tabcont" align="center" width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="100%" valign="middle" class="listtopic" colspan="2">
+ <span style="vertical-align: middle; position: relative; left: 0px;"><?=gettext("Rsync Client Synchronization");?></span>
+ <span style="vertical-align: middle; position: relative; left: 70%;">
+ <input name="enable" type="checkbox" value="yes" <?php if ($pconfig['enable']) echo "checked=\"checked\""; ?> onClick="enable_change(false)" />&nbsp;<?= gettext("Enable"); ?>
+ </span>
+ </td>
+ </tr>
+ <tr>
+ <td width="16%" valign="top" class="vncellreq"><?= gettext("Source"); ?></td>
+ <td width="84%" class="vtable">
+ <select name="source" class="formselect" id="source">
+ <?php
+ if (is_array($freenas_config['mounts']['mount'])) {
+ foreach ($a_mount as $mountv) {
+ echo "<option value=\"{$mountv['sharename']}\"";
+ if (strcmp($mountv['sharename'],$pconfig['source']) == 0)
+ echo " selected";
+ echo">";
+ echo htmlspecialchars($mountv['sharename']);
+ echo "</option>";
+ }
+ }
+ else
+ echo gettext("You must configure mount point first.");
+ ?>
+ </select>
+ <br />
+ <?= gettext("Source Mount Point."); ?>
+ </td>
+ </tr>
+ <tr>
+ <td width="16%" valign="top" class="vncellreq"><?= gettext("Destination"); ?></td>
+ <td width="84%" class="vtable">
+ <select name="destination" class="formselect" id="destination">
+ <?php
+ if (is_array($freenas_config['mounts']['mount'])) {
+ foreach ($a_mount as $mountv) {
+ echo "<option value=\"{$mountv['sharename']}\"";
+ if (strcmp($mountv['sharename'],$pconfig['destination']) == 0)
+ echo " selected";
+ echo">";
+ echo htmlspecialchars($mountv['sharename']);
+ echo "</option>";
+ }
+ }
+ else
+ echo gettext("You must configure mount point first.");
+ ?>
+ </select>
+ <br />
+ <?= gettext("Destination Mount Point."); ?>
+ </td>
+ </tr>
+ <tr>
+ <td width="16%" valign="top" class="vncellreq"><?= gettext("RSYNC Options"); ?></td>
+ <td width="84%" class="vtable">
+ <input name="opt_delete" id="opt_delete" type="checkbox" value="yes" <?php if ($pconfig['opt_delete']) echo "checked=\"checked\""; ?> />
+ <?= gettext("Delete files that don't exist on sender."); ?>
+ </td>
+ </tr>
+ <tr>
+ <td width="16%" valign="top" class="vncellreq"><?= gettext("Synchronization Time"); ?></td>
+ <td width="84%" class="vtable">
+ <table width="100%" border="1" cellpadding="4" cellspacing="0">
+ <tr>
+ <td align="left" valign="top" class="listtopic"><?= gettext("minutes"); ?></td>
+ <td align="left" valign="top" class="listtopic"><?= gettext("hours"); ?></td>
+ <td align="left" valign="top" class="listtopic"><?= gettext("days"); ?></td>
+ <td align="left" valign="top" class="listtopic"><?= gettext("months"); ?></td>
+ <td align="left" valign="top" class="listtopic"><?= gettext("week days"); ?></td>
+ </tr>
+ <tr>
+ <td align="left" valign="top" class="vncell" nowrap="nowrap">
+ <div id="all_min_rdbtns" style="padding-bottom: 10px;" >
+ <input type="radio" name="all_mins" id="all_mins1" value="1"<?php echo $all_mins_all;?> />
+ <label for="all_mins1">All</label><br />
+ <input type="radio" name="all_mins" id="all_mins2" value="0"<?php echo $all_mins_selected;?> />
+ <label for="all_mins2">Selected ...</label>
+ </div>
+ <div id="all_min_select" style="vertical-align: top;">
+ <select multiple="multible" class="formselect" size="24" name="minutes[]" id="minutes1" style="vertical-align: top;">
+ <?php
+ $i = 0;
+ while ($i <= 23){
+ if (isset($pconfig['minute'])) {
+ if (in_array($i, $pconfig['minute'])) {
+ $is_selected = " selected";
+ } else {
+ $is_selected = "";
+ }
+ }
+
+ echo "<option value=\"" . $i . "\"" . $is_selected . ">" . $i . "\n";
+ $i++;
+ }
+ ?>
+ </select>
+ <select multiple="multible" class="formselect" size="24" name="minutes[]" id="minutes2" style="vertical-align: top;">
+ <?php
+ $i = 24;
+ while ($i <= 47) {
+ if (isset($pconfig['minute'])) {
+ if (in_array($i, $pconfig['minute'])) {
+ $is_selected = " selected";
+ } else {
+ $is_selected = "";
+ }
+ }
+
+ echo "<option value=\"" . $i . "\"" . $is_selected . ">" . $i . "\n";
+ $i++;
+ }
+ ?>
+ </select>
+ <select multiple="multible" class="formselect" size="12" name="minutes[]" id="minutes3" style="vertical-align: top;">
+ <?php
+ $i = 48;
+ while ($i <= 59) {
+ if (isset($pconfig['minute'])) {
+ if (in_array($i, $pconfig['minute'])) {
+ $is_selected = " selected";
+ } else {
+ $is_selected = "";
+ }
+ }
+
+ echo "<option value=\"" . $i . "\"" . $is_selected . ">" . $i . "\n";
+ $i++;
+ }
+ ?>
+ </select>
+ </div>
+ </td>
+ <td align="left" valign="top" class="vncell" nowrap="nowrap">
+ <div id="all_hours_rdbtns" style="padding-bottom: 10px;" >
+ <input type="radio" name="all_hours" id="all_hours1" value="1"<?php echo $all_hours_all;?> />
+ <label for="all_hours1">All</label><br />
+ <input type="radio" name="all_hours" id="all_hours2" value="0"<?php echo $all_hours_selected;?> />
+ <label for="all_hours2">Selected ...</label>
+ </div>
+ <div id="all_hours_select" style="vertical-align: top;">
+ <select multiple size="24" name="hours[]" id="hours1" style="vertical-align: top;">
+ <?php
+ $i = 0;
+ while ($i <= 23) {
+ if (isset($pconfig['hour'])) {
+ if (in_array($i, $pconfig['hour'])) {
+ $is_selected = " selected";
+ } else {
+ $is_selected = "";
+ }
+ }
+
+ echo "<option value=\"" . $i . "\"" . $is_selected . ">" . $i . "\n";
+ $i++;
+ }
+ ?>
+ </select>
+ </div>
+ </td>
+ <td align="left" valign="top" class="vncell" nowrap="nowrap">
+ <div id="all_days_rdbtns" style="padding-bottom: 10px;" >
+ <input type="radio" name="all_days" id="all_days1" value="1" <?php echo $all_days_all;?> />
+ <label for="all_days1">All</label><br />
+ <input type="radio" name="all_days" id="all_days2" value="0"<?php echo $all_days_selected;?> />
+ <label for="all_days2">Selected ...</label>
+ </div>
+ <div id="all_days_select" style="vertical-align: top;">
+ <select multiple size="24" name="days[]" id="days1" style="vertical-align: top;">
+ <?php
+ $i = 1;
+ while ($i <= 24) {
+ if (isset($pconfig['day'])) {
+ if (in_array($i, $pconfig['day'])) {
+ $is_selected = " selected";
+ } else {
+ $is_selected = "";
+ }
+ }
+
+ echo "<option value=\"" . $i . "\"" . $is_selected . ">" . $i . "\n";
+ $i++;
+ }
+ ?>
+ </select>
+ <select multiple size="7" name="days[]" id="days2" style="vertical-align: top;">
+ <?php
+ $i = 25;
+ while ($i <= 31) {
+ if (isset($pconfig['day'])) {
+ if (in_array($i, $pconfig['day'])) {
+ $is_selected = " selected";
+ } else {
+ $is_selected = "";
+ }
+ }
+
+ echo "<option value=\"" . $i . "\"" . $is_selected . ">" . $i . "\n";
+ $i++;
+ }
+ ?>
+ </select>
+ </div>
+ </td>
+ <td align="left" valign="top" class="vncell">
+ <div id="all_months_rdbtns" style="padding-bottom: 10px;" >
+ <input type="radio" name="all_months" id="all_months1" value="1"<?php echo $all_months_all;?> />
+ <label for="all_months1">All</label><br />
+ <input type="radio" name="all_months" id="all_months2" value="0"<?php echo $all_months_selected;?> />
+ <label for="all_months2">Selected ...</label>
+ </div>
+ <div id="all_months_select" style="vertical-align: top;">
+ <select multiple size="12" name="months[]" id="months" style="vertical-align: top;">
+ <?php
+ $i=1;
+ foreach ($a_months as $monthv) {
+ if (isset($pconfig['month'])) {
+ if (in_array($i, $pconfig['month'])) {
+ $is_selected = " selected";
+ } else {
+ $is_selected = "";
+ }
+ }
+
+ echo "<option value=\"" . $i . "\"" . $is_selected . ">" . $monthv . "\n";
+ $i++;
+ }
+ ?>
+ </select>
+ </div>
+ </td>
+ <td align="left" valign="top" class="vncell">
+ <div id="all_weekdays_rdbtns" style="padding-bottom: 10px;" >
+ <input type="radio" name="all_weekdays" id="all_weekdays1" value="1"<?php echo $all_weekdays_all;?> />
+ <label for="all_weekdays1">All</label><br />
+ <input type="radio" name="all_weekdays" id="all_weekdays2" value="0"<?php echo $all_weekdays_selected;?> />
+ <label for="all_weekdays2">Selected ...</label>
+ </div>
+ <div id="all_weekdays_select" style="vertical-align: top;">
+ <select multiple size="7" name="weekdays[]" id="weekdays" style="vertical-align: top;">
+ <?php
+ $i=0;
+ foreach ($a_weekdays as $weekdayv) {
+ if (isset($pconfig['weekday'])){
+ if (in_array($i, $pconfig['weekday'])) {
+ $is_selected = " selected";
+ } else {
+ $is_selected = "";
+ }
+ }
+
+ echo "<option value=\"" . $i . "\"" . $is_selected . ">" . $weekdayv . "\n";
+ $i++;
+ }
+ ?>
+ </select>
+ </div>
+ </td>
+ </tr>
+ <tr>
+ <td align="left" valign="top" class="vncell" colspan="5">
+ <?= gettext("Note: Ctrl-click (or command-click on the Mac) to select and de-select minutes, hours, days and months."); ?>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td width="16%" valign="top">&nbsp;</td>
+ <td width="84%">
+ <input id="submit" name="Submit" type="submit" class="formbtn" value="<?=gettext("Save");?>" />
+ </td>
+ </tr>
+ </table>
+ </form>
+ </div>
+ </td>
+ </tr>
+</table>
+<?php include("fend.inc"); ?>
+<?= checkForInputErrors(); ?>
+<script type="text/javascript">
+<!--
+enable_change(false);
+//-->
+</script>
+</body>
+</html>
diff --git a/config/freenas/www/services_samba.php b/config/freenas/www/services_samba.php
new file mode 100644
index 00000000..afd90a08
--- /dev/null
+++ b/config/freenas/www/services_samba.php
@@ -0,0 +1,431 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ services_samba.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+$pgtitle = array(gettext("Services"),
+ gettext("CIFS"));
+
+require_once("freenas_config.inc");
+require_once("guiconfig.inc");
+require_once("freenas_guiconfig.inc");
+require_once("freenas_functions.inc");
+
+if (!is_array($freenas_config['samba']))
+{
+ $freenas_config['samba'] = array();
+}
+
+if (!is_array($freenas_config['mounts']['mount']))
+ $freenas_config['mounts']['mount'] = array();
+
+mount_sort();
+
+$a_mount = &$freenas_config['mounts']['mount'];
+
+$pconfig['netbiosname'] = $freenas_config['samba']['netbiosname'];
+$pconfig['workgroup'] = $freenas_config['samba']['workgroup'];
+$pconfig['serverdesc'] = $freenas_config['samba']['serverdesc'];
+$pconfig['security'] = $freenas_config['samba']['security'];
+$pconfig['localmaster'] = $freenas_config['samba']['localmaster'];
+$pconfig['winssrv'] = $freenas_config['samba']['winssrv'];
+/* $pconfig['hidemount'] = $freenas_config['samba']['hidemount']; */
+$pconfig['timesrv'] = $freenas_config['samba']['timesrv'];
+$pconfig['unixcharset'] = $freenas_config['samba']['unixcharset'];
+$pconfig['doscharset'] = $freenas_config['samba']['doscharset'];
+$pconfig['loglevel'] = $freenas_config['samba']['loglevel'];
+$pconfig['sndbuf'] = $freenas_config['samba']['sndbuf'];
+$pconfig['rcvbuf'] = $freenas_config['samba']['rcvbuf'];
+$pconfig['enable'] = isset($freenas_config['samba']['enable']);
+$pconfig['recyclebin'] = isset($freenas_config['samba']['recyclebin']);
+
+if (! empty($_POST))
+{
+ /* hash */
+ unset($error_bucket);
+ /* simple error list */
+ unset($input_errors);
+ $pconfig = $_POST;
+
+ /* input validation */
+ if ($_POST['enable']) {
+ $reqdfields = array_merge($reqdfields, explode(" ", "netbiosname workgroup security localmaster"));
+ $reqdfieldsn = array_merge($reqdfieldsn, explode(",", "Netbiosname,Workgroup,Security, Localmaster"));
+ }
+
+ do_input_validation($_POST, $reqdfields, $reqdfieldsn, &$input_errors);
+
+ if (($_POST['netbiosname'] && !is_domain($_POST['netbiosname']))) {
+ $error_bucket[] = array("error" => gettext("The Netbios name contains invalid characters."),
+ "field" => "netbiosname");
+ }
+ if (($_POST['workgroup'] && !is_domain($_POST['workgroup']))) {
+ $error_bucket[] = array("error" => gettext("The Workgroup name contains invalid characters."),
+ "field" => "workgroup");
+ }
+ if (($_POST['winssrv'] && !is_ipaddr($_POST['winssrv']))) {
+ $error_bucket[] = array("error" => gettext("The WINS server must be an IP address."),
+ "field" => "winssrv");
+ }
+
+ if (!is_numericint($_POST['sndbuf'])) {
+ $error_bucket[] = array("error" => gettext("PediaXThe SND Buffer value must be a number."),
+ "field" => "sndbuf");
+ }
+
+ if (!is_numericint($_POST['rcvbuf'])) {
+ $error_bucket[] = array("error" => gettext("The RCV Buffer value must be a number."),
+ "field" => "rcvbuf");
+ }
+
+ if (is_array($error_bucket))
+ foreach($error_bucket as $elem)
+ $input_errors[] =& $elem["error"];
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($error_bucket)) {
+ input_errors2Ajax(NULL, $error_bucket);
+ exit;
+ }
+
+ if (!$input_errors)
+ {
+ $freenas_config['samba']['netbiosname'] = $_POST['netbiosname'];
+ $freenas_config['samba']['workgroup'] = $_POST['workgroup'];
+ $freenas_config['samba']['serverdesc'] = $_POST['serverdesc'];
+ $freenas_config['samba']['security'] = $_POST['security'];
+ $freenas_config['samba']['localmaster'] = $_POST['localmaster'];
+ $freenas_config['samba']['winssrv'] = $_POST['winssrv'];
+ /* $freenas_config['samba']['hidemount'] = $_POST['hidemount']; */
+ $freenas_config['samba']['timesrv'] = $_POST['timesrv'];
+ $freenas_config['samba']['doscharset'] = $_POST['doscharset'];
+ $freenas_config['samba']['unixcharset'] = $_POST['unixcharset'];
+ $freenas_config['samba']['loglevel'] = $_POST['loglevel'];
+ $freenas_config['samba']['sndbuf'] = $_POST['sndbuf'];
+ $freenas_config['samba']['rcvbuf'] = $_POST['rcvbuf'];
+ $freenas_config['samba']['recyclebin'] = $_POST['recyclebin'] ? true : false;
+ $freenas_config['samba']['enable'] = $_POST['enable'] ? true : false;
+
+ write_config();
+
+ $retval = 0;
+ if (!file_exists($d_sysrebootreqd_path)) {
+ /* nuke the cache file */
+ config_lock();
+ services_samba_configure();
+ services_zeroconf_configure();
+ config_unlock();
+ }
+ $savemsg = get_std_save_message($retval);
+ }
+}
+
+/* if ajax is calling, give them an update message */
+if(isAjax())
+ print_info_box_np($savemsg);
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+
+$jscriptstr = <<<EOD
+<script type="text/javascript">
+<!--
+function enable_change(enable_change) {
+ var endis;
+
+ endis = !(document.iform.enable.checked || enable_change);
+ endis ? color = '#D4D0C8' : color = '#FFFFFF';
+
+ document.iform.netbiosname.disabled = endis;
+ document.iform.workgroup.disabled = endis;
+ document.iform.localmaster.disabled = endis;
+ document.iform.winssrv.disabled = endis;
+ document.iform.timesrv.disabled = endis;
+ document.iform.serverdesc.disabled = endis;
+ document.iform.doscharset.disabled = endis;
+ document.iform.unixcharset.disabled = endis;
+ document.iform.loglevel.disabled = endis;
+ document.iform.sndbuf.disabled = endis;
+ document.iform.rcvbuf.disabled = endis;
+ document.iform.recyclebin.disabled = endis;
+ document.iform.security.disabled = endis;
+ /* color adjustments */
+ document.iform.netbiosname.style.backgroundColor = color;
+ document.iform.workgroup.style.backgroundColor = color;
+ document.iform.localmaster.style.backgroundColor = color;
+ document.iform.winssrv.style.backgroundColor = color;
+ document.iform.timesrv.style.backgroundColor = color;
+ document.iform.serverdesc.style.backgroundColor = color;
+ document.iform.doscharset.style.backgroundColor = color;
+ document.iform.unixcharset.style.backgroundColor = color;
+ document.iform.loglevel.style.backgroundColor = color;
+ document.iform.sndbuf.style.backgroundColor = color;
+ document.iform.rcvbuf.style.backgroundColor = color;
+ document.iform.recyclebin.style.backgroundColor = color;
+ document.iform.security.style.backgroundColor = color;
+}
+//-->
+</script>
+
+EOD;
+
+$pfSenseHead->addScript($jscriptstr);
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc"); ?>
+
+<form id="iform" name="iform" action="services_samba.php" method="post">
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+<div id="inputerrors"></div>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Settings"), true, "services_samba.php");
+ $tab_array[1] = array(gettext("Shares"), false, "services_samba_share.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <table class="tabcont" width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="100%" valign="middle" class="listtopic" colspan="2">
+ <span style="vertical-align: middle; position: relative; left: 0px;"><?=gettext("CIFS share");?></span>
+ <span style="vertical-align: middle; position: relative; left: 84%;">
+ <input name="enable" type="checkbox" value="yes" <?php if ($pconfig['enable']) echo "checked=\"checked\""; ?> onClick="enable_change(false)" />&nbsp;<?= gettext("Enable"); ?>
+ </span>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?=gettext("Authentication");?></td>
+ <td width="78%" class="vtable">
+ <select name="security" class="formselect" id="security">
+ <?php
+ $types = explode(",", "Anonymous,Local User,Domain");
+ $vals = explode(" ", "share user domain");
+ $j = 0;
+
+ for ($j = 0; $j < count($vals); $j++):
+ ?>
+ <option value="<?=$vals[$j];?>" <?php if ($vals[$j] == $pconfig['security']) echo "selected=\"selected\"";?>>
+ <?=htmlspecialchars($types[$j]);?>
+ </option>
+ <?php endfor; ?>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?=gettext("NetBios name");?></td>
+ <td width="78%" class="vtable" align="left" valign="middle">
+ <input name="netbiosname" type="text" class="formfld unknown" id="netbiosname" size="20" value="<?=htmlspecialchars($pconfig['netbiosname']);?>" />
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?=gettext("Workgroup");?></td>
+ <td width="78%" class="vtable" align="left" valign="middle">
+ <input name="workgroup" type="text" class="formfld unknown" id="workgroup" size="20" value="<?=htmlspecialchars($pconfig['workgroup']);?>" />
+ <br />
+ <?= gettext("Workgroup to be member of.");?>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("Description");?></td>
+ <td width="78%" class="vtable" align="left" valign="middle">
+ <input name="serverdesc" type="text" class="formfld unknown" id="serverdesc" size="30" value="<?=htmlspecialchars($pconfig['serverdesc']);?>" />
+ <br />
+ <?= gettext("Server description. This can usually be left blank.");?>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("Dos charset");?></td>
+ <td width="78%" class="vtable" align="left" valign="middle">
+ <select name="doscharset" class="formselect" id="doscharset">
+ <?php
+ $types = explode(",", "CP850,CP852,CP437,ASCII");
+ $vals = explode(" ", "CP850 CP852 CP437 ASCII");
+ $j = 0;
+
+ for ($j = 0; $j < count($vals); $j++):
+ ?>
+ <option value="<?=$vals[$j];?>" <?php if ($vals[$j] == $pconfig['doscharset']) echo "selected=\"selected\"";?>>
+ <?=htmlspecialchars($types[$j]);?>
+ </option>
+ <?php endfor; ?>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("Unix charset");?></td>
+ <td width="78%" class="vtable" align="left" valign="middle">
+ <select name="unixcharset" class="formselect" id="unixcharset">
+ <?php
+ $types = explode(",", "UTF-8,iso-8859-1,iso-8859-15,gb2312,ASCII");
+ $vals = explode(" ", "UTF-8 iso-8859-1 iso-8859-15 gb2312 ASCII");
+ $j = 0;
+
+ for ($j = 0; $j < count($vals); $j++):
+ ?>
+ <option value="<?=$vals[$j];?>" <?php if ($vals[$j] == $pconfig['unixcharset']) echo "selected=\"selected\"";?>>
+ <?=htmlspecialchars($types[$j]);?>
+ </option>
+ <?php endfor; ?>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("Log level");?></td>
+ <td width="78%" class="vtable" align="left" valign="middle">
+ <select name="loglevel" class="formselect" id="loglevel">
+ <?php
+ $types = explode(",", "Minimum,Normal,Full,Debug");
+ $vals = explode(" ", "1 2 3 10");
+ $j = 0;
+
+ for ($j = 0; $j < count($vals); $j++):
+ ?>
+ <option value="<?=$vals[$j];?>" <?php if ($vals[$j] == $pconfig['loglevel']) echo "selected=\"selected\"";?>>
+ <?=htmlspecialchars($types[$j]);?>
+ </option>
+ <?php endfor; ?>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("Local Master Browser");?></td>
+ <td width="78%" class="vtable" align="left" valign="middle">
+ <select name="localmaster" class="formselect" id="localmaster">
+ <?php
+ $types = explode(",", "Yes,No");
+ $vals = explode(" ", "yes no");
+ $j = 0;
+
+ for ($j = 0; $j < count($vals); $j++):
+ ?>
+ <option value="<?=$vals[$j];?>" <?php if ($vals[$j] == $pconfig['localmaster']) echo "selected=\"selected\"";?>>
+ <?=htmlspecialchars($types[$j]);?>
+ </option>
+ <?php endfor; ?>
+ </select>
+ <br />
+ <?= gettext("Allows FreeNAS to try and become a local master browser."); ?>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("Time Server");?></td>
+ <td width="78%" class="vtable" align="left" valign="middle">
+ <select name="timesrv" class="formselect" id="timesrv">
+ <?php
+ $types = explode(",", "Yes,No");
+ $vals = explode(" ", "yes no");
+ $j = 0;
+
+ for ($j = 0; $j < count($vals); $j++):
+ ?>
+ <option value="<?=$vals[$j];?>" <?php if ($vals[$j] == $pconfig['timesrv']) echo "selected=\"selected\"";?>>
+ <?=htmlspecialchars($types[$j]);?>
+ </option>
+ <?php endfor; ?>
+ </select>
+ <br />
+ <?= gettext("FreeNAS advertises itself as a time server to Windows clients."); ?>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("WINS server");?></td>
+ <td width="78%" class="vtable" align="left" valign="middle">
+ <input name="winssrv" type="text" class="formfld host" id="winssrv" size="30" value="<?=htmlspecialchars($pconfig['winssrv']);?>" />
+ <br />
+ <?= gettext("WINS Server IP address."); ?>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("Recycle Bin");?></td>
+ <td width="78%" class="vtable" align="left" valign="middle">
+ <input name="recyclebin" type="checkbox" id="recyclebin" value="yes" <?php if ($pconfig['recyclebin']) echo "checked=\"checked\""; ?> />
+ <?= gettext("Enable Recycle bin"); ?><br />
+ <?= gettext("This will create a recycle bin on the CIFS shares"); ?>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("Send Buffer Size");?></td>
+ <td width="78%" class="vtable" align="left" valign="middle">
+ <input name="sndbuf" type="text" class="formfld unknown" id="sndbuf" size="30" value="<?=htmlspecialchars($pconfig['sndbuf']);?>" />
+ <br />
+ <?= gettext("Size of send buffer (16384 by default)."); ?>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("Receive Buffer Size");?></td>
+ <td width="78%" class="vtable" align="left" valign="middle">
+ <input name="rcvbuf" type="text" class="formfld unknown" id="rcvbuf" size="30" value="<?=htmlspecialchars($pconfig['rcvbuf']);?>" />
+ <br />
+ <?= gettext("Size of receive buffer (16384 by default)."); ?>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <input id="submit" name="Submit" type="submit" class="formbtn" value="<?=gettext("Save");?>" />
+ </td>
+ </tr>
+ </table>
+ </div>
+ </td>
+ </tr>
+</table>
+</form>
+<?php include("fend.inc"); ?>
+<?= checkForInputErrors(); ?>
+<script type="text/javascript">
+<!--
+enable_change(false);
+//-->
+</script>
+</body>
+</html>
diff --git a/config/freenas/www/services_samba_share.php b/config/freenas/www/services_samba_share.php
new file mode 100644
index 00000000..1545df97
--- /dev/null
+++ b/config/freenas/www/services_samba_share.php
@@ -0,0 +1,165 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ services_samba_share.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+$pgtitle = array(gettext("Services"),
+ gettext("CIFS"),
+ gettext("Shares"));
+
+require_once("freenas_config.inc");
+require_once("guiconfig.inc");
+require_once("freenas_guiconfig.inc");
+require_once("freenas_functions.inc");
+
+if (!is_array($freenas_config['mounts']['mount']))
+ $freenas_config['mounts']['mount'] = array();
+
+mount_sort();
+
+$a_mount = &$freenas_config['mounts']['mount'];
+
+if (! empty($_POST))
+{
+ /* hash */
+ unset($error_bucket);
+ /* simple error list */
+ unset($input_errors);
+ $pconfig = $_POST;
+
+ if (is_array($error_bucket))
+ foreach($error_bucket as $elem)
+ $input_errors[] =& $elem["error"];
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($error_bucket)) {
+ input_errors2Ajax(NULL, $error_bucket);
+ exit;
+ }
+
+ if (!$input_errors)
+ {
+ if($_POST['apply']) {
+ $retval = 0;
+ if(!file_exists($d_sysrebootreqd_path)) {
+ config_lock();
+ services_samba_configure();
+ services_zeroconf_configure();
+ config_unlock();
+ }
+
+ $savemsg = get_std_save_message($retval);
+
+ if(0 == $retval) {
+ if(file_exists($d_smbshareconfdirty_path))
+ unlink($d_smbshareconfdirty_path);
+ }
+ }
+ }
+}
+
+if($_GET['act'] == "ret") {
+ pfSenseHeader("services_samba_share.php");
+ exit;
+}
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc"); ?>
+
+<form id="iform" name="iform" action="services_samba_share.php" method="post">
+<?php if ($savemsg) print_info_box($savemsg); ?>
+<?php if (file_exists($d_smbshareconfdirty_path)): ?>
+<?php print_info_box_np(gettext("The shares has been modified.") . "<br />" .
+ gettext("You must apply the changes in order for them to take effect."));?>
+<?php endif; ?>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<div id="inputerrors"></div>
+
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabnavtbl">
+<?php
+ $tab_array = array();
+ $tab_array[0] = array(gettext("Settings"), false, "services_samba.php");
+ $tab_array[1] = array(gettext("Shares"), true, "services_samba_share.php");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <table class="tabcont" width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td width="20%" class="listhdrr"><?= gettext("Share Name"); ?></td>
+ <td width="25%" class="listhdrr"><?= gettext("Description"); ?></td>
+ <td width="20%" class="listhdrr"><?= gettext("Browseable"); ?></td>
+ <td width="10%" class="list"></td>
+ </tr>
+ <?php $i = 0; foreach($a_mount as $mountv): ?>
+ <tr>
+ <td class="listr"><?=htmlspecialchars($mountv['sharename']);?></td>
+ <td class="listr"><?=htmlspecialchars($mountv['desc']);?></td>
+ <td class="listbg"><?=htmlspecialchars((is_array($freenas_config['samba']['hidemount']) && in_array($mountv['sharename'],$freenas_config['samba']['hidemount']))? gettext("No") : gettext("Yes"));?></td>
+ <td valign="middle" nowrap class="list">
+ <?php if(isset($freenas_config['samba']['enable']))
+ echo("<a href='services_samba_share_edit.php?id={$i}'><img src='./themes/" . $g['theme'] . "/images/icons/icon_e.gif' title='" . gettext("Edit Share") . "' width='17' height='17' border='0'></a>");
+ ?>
+ </td>
+ </tr>
+ <?php $i++; endforeach; ?>
+ </table>
+ </div>
+ </td>
+ </tr>
+</table>
+</form>
+<?php include("fend.inc"); ?>
+<?= checkForInputErrors(); ?>
+</body>
+</html>
diff --git a/config/freenas/www/services_samba_share_edit.php b/config/freenas/www/services_samba_share_edit.php
new file mode 100644
index 00000000..d417fa4c
--- /dev/null
+++ b/config/freenas/www/services_samba_share_edit.php
@@ -0,0 +1,157 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ services_samba_share_edit.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+$pgtitle = array(gettext("Services"),
+ gettext("CIFS"),
+ gettext("Shares"),
+ gettext("Edit"));
+
+require_once("freenas_config.inc");
+require_once("guiconfig.inc");
+require_once("freenas_guiconfig.inc");
+require_once("freenas_functions.inc");
+
+$id = $_GET['id'];
+if (isset($_POST['id']))
+ $id = $_POST['id'];
+
+if (!is_array($freenas_config['mounts']['mount']))
+ $freenas_config['mounts']['mount'] = array();
+
+mount_sort();
+
+if(!is_array($freenas_config['samba']['hidemount']))
+ $freenas_config['samba']['hidemount'] = array();
+
+if (! empty($_POST))
+{
+ /* hash */
+ unset($error_bucket);
+ /* simple error list */
+ unset($input_errors);
+
+ if (is_array($error_bucket))
+ foreach($error_bucket as $elem)
+ $input_errors[] =& $elem["error"];
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($error_bucket)) {
+ input_errors2Ajax(NULL, $error_bucket);
+ exit;
+ }
+
+ if (!$input_errors)
+ {
+ /* TODO: This logic needs to be tested! */
+ if($_POST['browseable'] == gettext("No")) {
+ $freenas_config['samba']['hidemount'] = array_merge($freenas_config['samba']['hidemount'],array($freenas_config['mounts']['mount'][$id]['sharename']));
+ } else {
+ if(is_array($freenas_config['samba']['hidemount']) && in_array($freenas_config['mounts']['mount'][$id]['sharename'],$freenas_config['samba']['hidemount'])) {
+ $freenas_config['samba']['hidemount'] = array_diff($freenas_config['samba']['hidemount'],array($freenas_config['mounts']['mount'][$id]['sharename']));
+ }
+ }
+
+ touch($d_smbshareconfdirty_path);
+ write_config();
+ pfSenseHeader("services_samba_share.php");
+ exit;
+ }
+}
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc"); ?>
+
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+ <div id="inputerrors"></div>
+ <form id="iform" name="iform" action="services_samba_share_edit.php" method="post">
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?= gettext("Share Name"); ?></td>
+ <td width="78%" class="vtable">
+ <input type="text" class="formfld file" size="30" value="<?=htmlspecialchars($freenas_config['mounts']['mount'][$id]['sharename']);?>" disabled="disabled" />
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?= gettext("Description"); ?></td>
+ <td width="78%" class="vtable">
+ <input type="text" class="formfld unknown" size="30" value="<?=htmlspecialchars($freenas_config['mounts']['mount'][$id]['desc']);?>" disabled="disabled">
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?= gettext("Browseable"); ?></td>
+ <td width="78%" class="vtable">
+ <select name="browseable" class="formselect" id="browseable">
+ <?php
+ $text = array(gettext("Yes"),gettext("No"));
+ $vals = explode(" ","1 0"); $j = 0;
+ for($j = 0; $j < count($vals); $j++):
+ ?>
+ <option value="<?=$vals[$j];?>" <?php if(is_array($freenas_config['samba']['hidemount']) && in_array($freenas_config['mounts']['mount'][$id]['sharename'],$freenas_config['samba']['hidemount'])) echo "selected=\"selected\"";?>>
+ <?=htmlspecialchars($text[$j]);?>
+ </option>
+ <?php endfor;?>
+ </select>
+ <br><?= gettext("This controls whether this share is seen in the list of available shares in a net view and in the browse list."); ?>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%"> <input name="Submit" type="submit" class="formbtn" value="<?= gettext("Save"); ?>">
+ <?php if(isset($id)): ?>
+ <input name="id" type="hidden" value="<?=$id;?>">
+ <?php endif; ?>
+ </td>
+ </tr>
+ </table>
+ </form>
+<?php include("fend.inc"); ?>
+<?= checkForInputErrors(); ?>
+</body>
+</html>
diff --git a/config/freenas/www/services_unison.php b/config/freenas/www/services_unison.php
new file mode 100644
index 00000000..eec58865
--- /dev/null
+++ b/config/freenas/www/services_unison.php
@@ -0,0 +1,249 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ services_unison.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+/*
+ *************************
+
+ Unison Installation Notes
+
+ To work, unison requires an environment variable UNISON to point at
+ a writable directory. Unison keeps information there between syncs to
+ speed up the process.
+
+ When a user runs the unison client, it will try to invoke ssh to
+ connect to the this server. Giving the local ssh a UNISON environment
+ variable without compromising ssh turned out to be non-trivial.
+ The solution is to modify the default path found in /etc/login.conf.
+ The path is seeded with "UNISON=/mnt" and this updated by the
+ /etc/inc/services.inc file.
+
+ Todo:
+ * Arguably, a full client install could be done too to
+ allow FreeNAS to FreeNAS syncing.
+
+ *************************
+*/
+
+$pgtitle = array(gettext("Services"),
+ gettext("Unison"));
+
+require_once("freenas_config.inc");
+require_once("guiconfig.inc");
+require_once("freenas_guiconfig.inc");
+require_once("freenas_functions.inc");
+
+if (!is_array($freenas_config['unison'])) {
+ $freenas_config['unison'] = array();
+}
+
+$pconfig['enable'] = isset($freenas_config['unison']['enable']);
+$pconfig['share'] = $freenas_config['unison']['share'];
+$pconfig['workdir'] = isset($freenas_config['unison']['workdir']);
+$pconfig['makedir'] = isset($freenas_config['unison']['makedir']);
+
+if (! empty($_POST))
+{
+ /* hash */
+ unset($error_bucket);
+ /* simple error list */
+ unset($input_errors);
+ $pconfig = $_POST;
+
+ /* input validation */
+ $reqdfields = split(" ", "share workdir");
+ $reqdfieldsn = split(",", "Share,Working Directory");
+
+ do_input_validation_new($_POST, $reqdfields, $reqdfieldsn, &$error_bucket);
+
+ $fullpath = "/mnt/{$_POST['share']}/{$_POST['workdir']}";
+
+ if (!$_POST['makedir'] && ($fullpath) && (!file_exists($fullpath))) {
+ $error_bucket[] = array("error" => gettext("The combination of share and working directory does not exist."),
+ "field" => "workdir");
+ }
+
+ if (is_array($error_bucket))
+ foreach($error_bucket as $elem)
+ $input_errors[] =& $elem["error"];
+
+ /* if this is an AJAX caller then handle via JSON */
+ if(isAjax() && is_array($error_bucket)) {
+ input_errors2Ajax(NULL, $error_bucket);
+ exit;
+ }
+
+ if (!$input_errors)
+ {
+ $freenas_config['unison']['share'] = $_POST['share'];
+ $freenas_config['unison']['workdir'] = $_POST['workdir'];
+ $freenas_config['unison']['enable'] = $_POST['enable'] ? true : false;
+ $freenas_config['unison']['makedir'] = $_POST['makedir'] ? true : false;
+
+ write_config();
+
+ $retval = 0;
+ if (!file_exists($d_sysrebootreqd_path))
+ {
+ /* nuke the cache file */
+ config_lock();
+ services_unison_configure();
+ /* services_zeroconf_configure(); */
+ config_unlock();
+ }
+
+ $savemsg = get_std_save_message($retval);
+ }
+}
+
+/* retrieve mounts to build list of share names */
+if (!is_array($freenas_config['mounts']['mount']))
+ $freenas_config['mounts']['mount'] = array();
+
+mount_sort();
+
+$a_mount = &$freenas_config['mounts']['mount'];
+
+/* if ajax is calling, give them an update message */
+if(isAjax())
+ print_info_box_np($savemsg);
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+
+$jscriptstr = <<<EOD
+<script type="text/javascript">
+<!--
+function enable_change(enable_change) {
+ var endis;
+
+ endis = !(document.iform.enable.checked || enable_change);
+ endis ? color = '#D4D0C8' : color = '#FFFFFF';
+
+ document.iform.share.disabled = endis;
+ document.iform.workdir.disabled = endis;
+ document.iform.makedir.disabled = endis;
+ /* color adjustments */
+ document.iform.share.style.backgroundColor = color;
+ document.iform.workdir.style.backgroundColor = color;
+ document.iform.makedir.style.backgroundColor = color;
+}
+//-->
+</script>
+
+EOD;
+
+$pfSenseHead->addScript($jscriptstr);
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc"); ?>
+
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+ <div id="inputerrors"></div>
+ <form id="iform" name="iform" action="services_unison.php" method="post">
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="100%" valign="middle" class="listtopic" colspan="2">
+ <span style="vertical-align: middle; position: relative; left: 0px;"><?=gettext("Unison File Synchronisation");?></span>
+ <span style="vertical-align: middle; position: relative; left: 72%;">
+ <input name="enable" type="checkbox" value="yes" <?php if ($pconfig['enable']) echo "checked=\"checked\""; ?> onClick="enable_change(false)" />&nbsp;<?= gettext("Enable"); ?>
+ </span>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("Share");?></td>
+ <td width="78%" class="vtable">
+ <select name="share" class="formselect" id="share">
+ <?php foreach ($a_mount as $mount): $tmp=$mount['sharename']; ?>
+ <option value="<?=$tmp;?>"
+ <?php if ($tmp == $pconfig['share']) echo "selected=\"selected\"";?>><?=$tmp?></option>
+ <?php endforeach; ?>
+ </select>
+ <br />
+ <?= gettext("You may need enough space to duplicate all files being synced."); ?>.
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("Working Directory");?></td>
+ <td width="78%" class="vtable" align="left" valign="middle">
+ <input name="workdir" type="text" class="formfld file" id="workdir" size="20" value="<?=htmlspecialchars($pconfig['workdir']);?>" />
+ <?= gettext("Where the working files will be stored"); ?>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("Create");?></td>
+ <td width="78%" class="vtable" align="left" valign="middle">
+ <input name="makedir" type="checkbox" id="makedir" value="yes" <?php if ($pconfig['makedir']) echo "checked=\"checked\""; ?> />
+ <?= gettext("Create work directory if it doesn't exist"); ?>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <input id="submit" name="Submit" type="submit" class="formbtn" value="<?=gettext("Save");?>" />
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <span class="red">
+ <strong><?= gettext("Note"); ?>:</strong>
+ </span>
+ <br />
+ <?= gettext("<a href='/system_advanced.php'>SSHD</a> must be enabled for Unison to work, and the <a href='/system_usermanager.php'>user</a> must have Full Shell enabled."); ?>
+ </td>
+ </tr>
+ </table>
+ </form>
+<?php include("fend.inc"); ?>
+<?= checkForInputErrors(); ?>
+<script type="text/javascript">
+<!--
+enable_change(false);
+//-->
+</script>
+</body>
+</html>
diff --git a/config/freenas/www/status_disks.php b/config/freenas/www/status_disks.php
new file mode 100644
index 00000000..704bc467
--- /dev/null
+++ b/config/freenas/www/status_disks.php
@@ -0,0 +1,127 @@
+<?php
+/* $Id$ */
+/* ========================================================================== */
+/*
+ status_disks.php
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on FreeNAS (http://www.freenas.org)
+ Copyright (C) 2005-2006 Olivier Cochard-Labbé <olivier@freenas.org>.
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+
+$pgtitle = array(gettext("Status"),
+ gettext("Disks"));
+
+require_once("guiconfig.inc");
+require_once("freenas_guiconfig.inc");
+require_once("freenas_functions.inc");
+
+if (!is_array($freenas_config['disks']['disk']))
+ $freenas_config['disks']['disk'] = array();
+
+disks_sort();
+
+$raidstatus=get_sraid_disks_list();
+
+$a_disk_conf = &$freenas_config['disks']['disk'];
+
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+echo $pfSenseHead->getHTML();
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
+<?php include("fbegin.inc"); ?>
+
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+ <div id="inputerrors"></div>
+ <form id="iform" name="iform" action="status_disks.php" method="post">
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="5%" class="listhdrr">Disk</td>
+ <td width="5%" class="listhdrr">Size</td>
+ <td width="60%" class="listhdrr">Description</td>
+ <td width="10%" class="listhdr">Status</td>
+ </tr>
+ <?php foreach ($a_disk_conf as $disk): ?>
+ <tr>
+ <td class="listr">
+ <?=htmlspecialchars($disk['name']);?>
+ </td>
+ <td class="listr">
+ <?=htmlspecialchars($disk['size']);?>
+ </td>
+ <td class="listr">
+ <?=htmlspecialchars($disk['desc']);?>&nbsp;
+ </td>
+ <td class="listr">
+ <?php
+ $stat=disks_status($disk);
+ echo $stat;?>&nbsp;
+ </td>
+ </tr>
+ <?php endforeach; ?>
+ <?php if (isset($raidstatus)): ?>
+ <?php foreach ($raidstatus as $diskk => $diskv): ?>
+ <tr>
+ <td class="listr">
+ <?=htmlspecialchars($diskk);?>
+ </td>
+ <td class="listr">
+ <?=htmlspecialchars($diskv['size']);?>
+ </td>
+ <td class="listr">
+
+ <?=htmlspecialchars("Software RAID volume");?>&nbsp;
+ </td>
+ <td class="listr">
+ <?=htmlspecialchars($diskv['desc']);?>&nbsp;
+ </td>
+ </tr>
+ <?php endforeach; ?>
+ <?php endif; ?>
+ </table>
+ </form>
+<?php include("fend.inc"); ?>
+<?= checkForInputErrors(); ?>
+<script type="text/javascript">
+<!--
+// enable_change(false);
+//-->
+</script>
+</body>
+</html>
diff --git a/config/freeradius.inc b/config/freeradius.inc
new file mode 100644
index 00000000..53a1d695
--- /dev/null
+++ b/config/freeradius.inc
@@ -0,0 +1,527 @@
+<?php
+require_once('config.inc');
+require_once('service-utils.inc');
+
+define('RADDB', '/usr/local/etc/raddb');
+
+function freeradius_deinstall_command() {
+ exec("cd /var/db/pkg && pkg_delete `ls | grep freeradius`");
+ exec("cd /var/db/pkg && pkg_delete `ls | grep libltdl`");
+}
+
+function freeradius_install_command() {
+ global $config;
+
+ $handle = opendir(RADDB);
+ while (false != ($file = readdir($handle))) {
+ if (false != ($pos = strpos($file, '.sample'))) {
+ $newfile = substr($file, 0, $pos);
+ if (copy(RADDB . "/$file", RADDB . "/$newfile"))
+ unlink(RADDB . "/$file");
+ }
+ }
+ closedir($handle);
+
+ freeradius_settings_resync();
+
+ $rcfile = array();
+ $rcfile['file'] = 'radiusd.sh';
+ $rcfile['start'] = 'radiusd -s &';
+ $rcfile['stop'] = 'killall radiusd';
+ write_rcfile($rcfile);
+ start_service("freeradius");
+}
+
+function freeradius_settings_resync() {
+ global $config;
+
+ $settings = $config['installedpackages']['freeradiussettings']['config'][0];
+
+ $iface = ($settings['interface'] ? $settings['interface'] : 'LAN');
+ $iface = convert_friendly_interface_to_real_interface_name($iface);
+ $iface_ip = find_interface_ip($iface);
+ $port = ($settings['port'] != '' ? $settings['port'] : 0);
+ $radiuslogging = $settings['radiuslogging'];
+ $radiuslogbadpass = $settings['radiuslogbadpass'];
+ $radiusloggoodpass = $settings['radiusloggoodpass'];
+
+ // FreeRADIUS's configuration is huge
+ // This is the standard default config file, trimmed down a bit. Somebody might want to implement more options. It should be as simple as editing this, then also providing the settings in each file that was included here (or maybe just put the config inlined here).
+ $conf = <<<EOD
+prefix = /usr/local
+exec_prefix = \${prefix}
+sysconfdir = \${prefix}/etc
+localstatedir = /var
+sbindir = \${exec_prefix}/sbin
+logdir = /var/log
+raddbdir = \${sysconfdir}/raddb
+radacctdir = \${logdir}/radacct
+confdir = \${raddbdir}
+run_dir = \${localstatedir}/run/radiusd
+log_file = \${logdir}/radius.log
+libdir = \${exec_prefix}/lib
+pidfile = \${run_dir}/radiusd.pid
+#user = nobody
+#group = nobody
+max_request_time = 30
+delete_blocked_requests = no
+cleanup_delay = 5
+max_requests = 1024
+bind_address = $iface_ip
+port = $port
+hostname_lookups = no
+allow_core_dumps = no
+regular_expressions = yes
+extended_expressions = yes
+log_stripped_names = no
+log_auth = $radiuslogging
+log_auth_badpass = $radiuslogbadpass
+log_auth_goodpass = $radiusloggoodpass
+usercollide = no
+lower_user = no
+lower_pass = no
+nospace_user = no
+nospace_pass = no
+checkrad = \${sbindir}/checkrad
+
+security {
+ max_attributes = 200
+ reject_delay = 1
+ status_server = no
+}
+
+proxy_requests = yes
+\$INCLUDE \${confdir}/proxy.conf
+
+\$INCLUDE \${confdir}/clients.conf
+
+snmp = no
+\$INCLUDE \${confdir}/snmp.conf
+
+thread pool {
+ start_servers = 5
+ max_servers = 32
+ min_spare_servers = 3
+ max_spare_servers = 10
+ max_requests_per_server = 0
+}
+
+modules {
+ pap {
+ encryption_scheme = crypt
+ }
+
+ chap {
+ authtype = CHAP
+ }
+
+ pam {
+ pam_auth = radiusd
+ }
+
+ unix {
+ cache = no
+ cache_reload = 600
+ radwtmp = \${logdir}/radwtmp
+ }
+
+ \$INCLUDE \${confdir}/eap.conf
+
+ mschap {
+ authtype = MS-CHAP
+ #use_mppe = no
+ #require_encryption = yes
+ #require_strong = yes
+ #with_ntdomain_hack = no
+ #ntlm_auth = "/path/to/ntlm_auth --request-nt-key --username=%{Stripped-User-Name:-%{User-Name:-None}} --challenge=%{mschap:Challenge:-00} --nt-response=%{mschap:NT-Response:-00}"
+ }
+
+ ldap {
+ server = "ldap.your.domain"
+ basedn = "o=My Org,c=UA"
+ filter = "(uid=%{Stripped-User-Name:-%{User-Name}})"
+ #base_filter = "(objectclass=radiusprofile)"
+ start_tls = no
+ #tls_cacertfile = /path/to/cacert.pem
+ #tls_cacertdir = /path/to/ca/dir/
+ #tls_certfile = /path/to/radius.crt
+ #tls_keyfile = /path/to/radius.key
+ #tls_randfile = /path/to/rnd
+ #tls_require_cert = "demand"
+ access_attr = "dialupAccess"
+ dictionary_mapping = \${raddbdir}/ldap.attrmap
+ ldap_connections_number = 5
+ #groupname_attribute = cn
+ #groupmembership_filter = "(|(&(objectClass=GroupOfNames)(member=%{Ldap-UserDn}))(&(objectClass=GroupOfUniqueNames)(uniquemember=%{Ldap-UserDn})))"
+ #groupmembership_attribute = radiusGroupName
+ timeout = 4
+ timelimit = 3
+ net_timeout = 1
+ #compare_check_items = yes
+ #do_xlat = yes
+ #access_attr_used_for_allow = yes
+ }
+
+ realm IPASS {
+ format = prefix
+ delimiter = "/"
+ ignore_default = no
+ ignore_null = no
+ }
+
+ realm suffix {
+ format = suffix
+ delimiter = "@"
+ ignore_default = no
+ ignore_null = no
+ }
+
+ realm realmpercent {
+ format = suffix
+ delimiter = "%"
+ ignore_default = no
+ ignore_null = no
+ }
+
+ realm ntdomain {
+ format = prefix
+ delimiter = "\\"
+ ignore_default = no
+ ignore_null = no
+ }
+
+ checkval {
+ item-name = Calling-Station-Id
+ check-name = Calling-Station-Id
+ data-type = string
+ #notfound-reject = no
+ }
+
+ preprocess {
+ huntgroups = \${confdir}/huntgroups
+ hints = \${confdir}/hints
+ with_ascend_hack = no
+ ascend_channels_per_line = 23
+ with_ntdomain_hack = no
+ with_specialix_jetstream_hack = no
+ with_cisco_vsa_hack = no
+ }
+
+ files {
+ usersfile = \${confdir}/users
+ acctusersfile = \${confdir}/acct_users
+ preproxy_usersfile = \${confdir}/preproxy_users
+ compat = no
+ }
+
+ detail {
+ detailfile = \${radacctdir}/%{Client-IP-Address}/detail-%Y%m%d
+ detailperm = 0600
+ }
+
+ acct_unique {
+ key = "User-Name, Acct-Session-Id, NAS-IP-Address, Client-IP-Address, NAS-Port"
+ }
+
+ \$INCLUDE \${confdir}/sql.conf
+
+ radutmp {
+ filename = \${logdir}/radutmp
+ username = %{User-Name}
+ case_sensitive = yes
+ check_with_nas = yes
+ perm = 0600
+ callerid = "yes"
+ }
+
+ radutmp sradutmp {
+ filename = \${logdir}/sradutmp
+ perm = 0644
+ callerid = "no"
+ }
+
+ attr_filter {
+ attrsfile = \${confdir}/attrs
+ }
+
+ counter daily {
+ filename = \${raddbdir}/db.daily
+ key = User-Name
+ count-attribute = Acct-Session-Time
+ reset = daily
+ counter-name = Daily-Session-Time
+ check-name = Max-Daily-Session
+ allowed-servicetype = Framed-User
+ cache-size = 5000
+ }
+
+ counter weekly {
+ filename = \${raddbdir}/db.weekly
+ key = User-Name
+ count-attribute = Acct-Session-Time
+ reset = weekly
+ counter-name = Weekly-Session-Time
+ check-name = Max-Weekly-Session
+ cache-size = 5000
+ }
+
+ counter monthly {
+ filename = \${raddbdir}/db.monthly
+ key = User-Name
+ count-attribute = Acct-Session-Time
+ reset = monthly
+ counter-name = Monthly-Session-Time
+ check-name = Max-Monthly-Session
+ cache-size = 5000
+ }
+
+ counter forever {
+ filename = \${raddbdir}/db.forever
+ key = User-Name
+ count-attribute = Acct-Session-Time
+ reset = never
+ counter-name = Forever-Session-Time
+ check-name = Max-Forever-Session
+ cache-size = 5000
+ }
+
+ always fail {
+ rcode = fail
+ }
+ always reject {
+ rcode = reject
+ }
+ always ok {
+ rcode = ok
+ simulcount = 0
+ mpp = no
+ }
+
+ expr {
+ }
+
+ digest {
+ }
+
+ exec {
+ wait = yes
+ input_pairs = request
+ }
+
+ exec echo {
+ wait = yes
+ program = "/bin/echo %{User-Name}"
+ input_pairs = request
+ output_pairs = reply
+ #packet_type = Access-Accept
+ }
+
+ ippool main_pool {
+ range-start = 192.168.1.1
+ range-stop = 192.168.3.254
+ netmask = 255.255.255.0
+ cache-size = 800
+ session-db = \${raddbdir}/db.ippool
+ ip-index = \${raddbdir}/db.ipindex
+ override = no
+ maximum-timeout = 0
+ }
+}
+
+instantiate {
+ exec
+ expr
+ daily
+ weekly
+ monthly
+ forever
+}
+
+authorize {
+ preprocess
+ #auth_log
+ #attr_filter
+ chap
+ mschap
+ #digest
+ #IPASS
+ suffix
+ #ntdomain
+ eap
+ files
+ #sql
+ #etc_smbpasswd
+ #ldap
+ daily
+ weekly
+ monthly
+ forever
+ #checkval
+}
+
+authenticate {
+ Auth-Type PAP {
+ pap
+ }
+ Auth-Type CHAP {
+ chap
+ }
+ Auth-Type MS-CHAP {
+ mschap
+ }
+ #digest
+ #pam
+ unix
+ #Auth-Type LDAP {
+ # ldap
+ #}
+ eap
+}
+
+preacct {
+ preprocess
+ acct_unique
+ #IPASS
+ suffix
+ #ntdomain
+ files
+}
+
+accounting {
+ detail
+ daily
+ weekly
+ monthly
+ forever
+ unix
+ radutmp
+ #sradutmp
+ #main_pool
+ #sql
+ #pgsql-voip
+}
+
+session {
+ radutmp
+ #sql
+}
+
+post-auth {
+ #main_pool
+ #reply_log
+ #sql
+ #ldap
+ #Post-Auth-Type REJECT {
+ # insert-module-name-here
+ #}
+}
+
+pre-proxy {
+ #attr_rewrite
+ #files
+ #pre_proxy_log
+}
+
+post-proxy {
+ #post_proxy_log
+ #attr_rewrite
+ #attr_filter
+ eap
+}
+
+EOD;
+ file_put_contents(RADDB . '/radiusd.conf', $conf);
+ restart_service("freeradius");
+}
+
+function freeradius_users_resync() {
+ global $config;
+
+ $conf = '';
+ $users = $config['installedpackages']['freeradius']['config'];
+ if (is_array($users)) {
+ foreach ($users as $user) {
+ $username = $user['username'];
+ $password = $user['password'];
+ $multiconnet = $user['multiconnet'];
+ $ip = $user['ip'];
+ $userexpiration=$user['expiration'];
+ $sessiontime=$user['sessiontime'];
+ $onlinetime=$user['onlinetime'];
+ $vlanid=$user['vlanid'];
+ $additionaloptions=$user['additionaloptions'];
+ $atrib='';
+ $head="$username User-Password == ".'"'.$password.'"';
+ if ($multiconnect <> '') {
+ $head .=", Simultaneous-Use += $multiconnet";
+ }
+ if ($x <> '') {
+ $head .=", Expiration := ".'"'.$userexpiration.'"';
+ }
+ if ($onlinetime <> '') {
+ $head .=", Login-Time := ". '"' . $onlinetime .'"';
+ }
+ if ($ip <> '') {
+ if ($atrib <> '') { $atrib .=","; }
+ $atrib .="\r\n\tFramed-IP-Address = $ip";
+ }
+ if ($sessiontime <> '') {
+ if ($atrib <> '') { $atrib .=","; }
+ $atrib .="\r\n\tSession-Timeout := $sessiontime";
+ }
+ if ($vlanid <> '') {
+ if ($atrib <> '') { $atrib .=","; }
+ $atrib .="\r\n\tTunnel-Type = VLAN,\r\n\tTunnel-Medium-Type = IEEE-802,\r\n\tTunnel-Private-Group-ID = \"$vlanid\"";
+ }
+ if ($additionaloptions <> '') {
+ if ($atrib <> '') { $atrib .=","; }
+ $atrib .="\r\n\t$additionaloptions";
+ }
+
+ $conf .= <<<EOD
+$head
+ $atrib
+
+EOD;
+ }
+ }
+ $filename = RADDB . '/users';
+ file_put_contents($filename, $conf);
+ chmod($filename, 0600);
+
+ restart_service('freeradius');
+}
+
+function freeradius_clients_resync() {
+ global $config;
+
+ $conf = '';
+ $clients = $config['installedpackages']['freeradiusclients']['config'];
+ if (is_array($clients) && !empty($clients)) {
+ foreach ($clients as $item) {
+ $client = $item['client'];
+ $secret = $item['sharedsecret'];
+ $shortname = $item['shortname'];
+ $conf .= <<<EOD
+client $client {
+ secret = $secret
+ shortname = $shortname
+}
+
+EOD;
+ }
+ }
+ else {
+ $conf .= <<<EOD
+client 127.0.0.1 {
+ secret = pfsense
+ shortname = localhost
+}
+
+EOD;
+ }
+
+ file_put_contents(RADDB . '/clients.conf', $conf);
+ restart_service("freeradius");
+}
+?>
diff --git a/config/freeradius.xml b/config/freeradius.xml
new file mode 100644
index 00000000..8f214787
--- /dev/null
+++ b/config/freeradius.xml
@@ -0,0 +1,249 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>freeradius</name>
+ <version>1.1.2</version>
+ <title>FreeRADIUS: Users</title>
+ <include_file>/usr/local/pkg/freeradius.inc</include_file>
+ <menu>
+ <name>FreeRADIUS</name>
+ <tooltiptext>Modify FreeRADIUS users, clients, and settings.</tooltiptext>
+ <section>Services</section>
+ <url>/pkg.php?xml=freeradius.xml</url>
+ </menu>
+ <service>
+ <name>FreeRADIUS</name>
+ <rcfile>radiusd.sh</rcfile>
+ <executable>radiusd</executable>
+ <description>The FreeRADIUS daemon.</description>
+ </service>
+
+ <tabs>
+ <tab>
+ <text>Users</text>
+ <url>/pkg.php?xml=freeradius.xml</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Clients</text>
+ <url>/pkg.php?xml=freeradiusclients.xml</url>
+ </tab>
+ <tab>
+ <text>Settings</text>
+ <url>/pkg_edit.php?xml=freeradiussettings.xml&amp;id=0</url>
+ </tab>
+ </tabs>
+
+ <adddeleteeditpagefields>
+ <columnitem>
+ <fielddescr>Username</fielddescr>
+ <fieldname>username</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Description</fielddescr>
+ <fieldname>description</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>IP address</fielddescr>
+ <fieldname>ip</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Multiple Connection</fielddescr>
+ <fieldname>multiconnet</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Expiration</fielddescr>
+ <fieldname>expiration</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Session time</fielddescr>
+ <fieldname>sessiontime</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Online time</fielddescr>
+ <fieldname>onlinetime</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>VLAN ID</fielddescr>
+ <fieldname>vlanid</fieldname>
+ </columnitem>
+ </adddeleteeditpagefields>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>077</chmod>
+ <item>http://www.pfsense.org/packages/config/freeradiusclients.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>077</chmod>
+ <item>http://www.pfsense.org/packages/config/freeradiussettings.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>077</chmod>
+ <item>http://www.pfsense.org/packages/config/freeradius.inc</item>
+ </additional_files_needed>
+ <fields>
+ <field>
+ <fielddescr>Username</fielddescr>
+ <fieldname>username</fieldname>
+ <description>Enter the username.</description>
+ <type>input</type>
+ <required/>
+ </field>
+ <field>
+ <fielddescr>Password</fielddescr>
+ <fieldname>password</fieldname>
+ <description>Enter the password for this username.</description>
+ <type>password</type>
+ <required/>
+ </field>
+ <field>
+ <fieldname>ip</fieldname>
+ <fielddescr>IP address</fielddescr>
+ <description>If you want this user to be assigned a specific IP address from radius, enter the IP
+address here. Continuous IP address is available with "+" suffix(example:192.168.1.5+. It may help for assigning the
+different IP address to multiple simultaneous connections). IMPORTANT, you MUST ener an IP address here if you checked
+"RADIUS issued IP's" on vpn pptp or vpn pppoe configuration.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fieldname>multiconnet</fieldname>
+ <fielddescr>Number of Multiple connection</fielddescr>
+ <description>The available number of multiple simultaneous connections with this username.</description>
+ <required/>
+ <type>input</type>
+ </field>
+ <field>
+ <fieldname>expiration</fieldname>
+ <fielddescr>Expiration</fielddescr>
+ <description>You may enter the date that this account will stop working here.use Mmm dd yyyy example: 01 Jan 2007 will be Jan 01 2007</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fieldname>sessiontime</fieldname>
+ <fielddescr>Session time</fielddescr>
+ <description>Time this user has until relogin in seconds</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fieldname>onlinetime</fieldname>
+ <fielddescr>Online time</fielddescr>
+ <description>A time string may be a list of simple time strings separated with vertical bars `|' or commas `,'.
+
+Each simple time string must begin either with a day-of-week abbreviation (one of `Su', `Mo', `Tu', `We', `Th', `Fr', `Sa'), or `Wk' for any day from Monday to Friday inclusive, or `Any' or `Al' for any day.
+
+Following the day may be a range of hours separated with a hyphen, using 24-hour time. The range of hours may cross 0; for example `2300-0700' means any time except 7 AM to 11 PM. If no time is given, calls may be made at any time on the specified day(s).
+
+The time string may also be the single word `Never', which does not match any time.
+
+Here are a few sample time strings with an explanation of what they mean.
+
+`Wk2305-0855,Sa,Su2305-1655'
+
+ This means weekdays before 8:55 AM or after 11:05 PM, any time Saturday, or Sunday before 4:55 PM or after 11:05 PM. These are approximately the times during which night rates apply to phone calls in the U.S.A. Note that this time string uses, for example, `2305' rather than `2300'; this will ensure a cheap rate even if the computer clock is running up to five minutes ahead of the real time.
+
+`Wk0905-2255,Su1705-2255'
+
+ This means weekdays from 9:05 AM to 10:55 PM, or Sunday from 5:05 PM to 10:55 PM. This is approximately the opposite of the previous example.
+
+`Any'
+
+ This means any day. Since no time is specified, it means any time on any day. </description>
+
+ <type>input</type>
+ </field>
+ <field>
+ <fieldname>description</fieldname>
+ <fielddescr>Description</fielddescr>
+ <description>You may enter a description here for your reference (not parsed).</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fieldname>vlanid</fieldname>
+ <fielddescr>VLAN ID</fielddescr>
+ <description><![CDATA[
+ Enter the VLAN ID (integer from 1-4095) OR the VLAN name that this user/device should be assigned. In general, this parameter is used in conjunction with switches and access points that support mac-based authentication.<br><br>
+
+ This setting can be used for switches/wireless access points that support the following radius parameters:<br>
+ Tunnel-Type = VLAN<br>
+ Tunnel-Medium-Type = IEEE-802<br>
+ Tunnel-Private-Group-ID = "insert vlan identifier here"<br><br>
+
+ This was implemented and tested with HP Procurve Switches (3500yl, and 2626). HP Procurve switches support using either the VLAN ID or the VLAN name, while other switches will only work using the VLAN ID.
+ ]]>
+ </description>
+ <type>input</type>
+ </field>
+ <field>
+ <fieldname>additionaloptions</fieldname>
+ <fielddescr>Additional RADIUS Options</fielddescr>
+ <description>
+ <![CDATA[
+ Experts only.<br>
+ You may append extra custom RADIUS options to this user account (separated by commas).<br>
+ IMPORTANT: If you don't format this field correctly, FreeRADIUS may not properly start because the users file will contain a syntax error.
+ ]]>
+ </description>
+ <type>textarea</type>
+ <rows>10</rows>
+ <cols>75</cols>
+ </field>
+ </fields>
+ <custom_delete_php_command>
+ freeradius_users_resync();
+ </custom_delete_php_command>
+ <custom_php_resync_config_command>
+ freeradius_users_resync();
+ </custom_php_resync_config_command>
+ <custom_php_install_command>
+ freeradius_install_command();
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ freeradius_deinstall_command();
+ </custom_php_deinstall_command>
+</packagegui>
diff --git a/config/freeradiusclients.xml b/config/freeradiusclients.xml
new file mode 100644
index 00000000..e9417581
--- /dev/null
+++ b/config/freeradiusclients.xml
@@ -0,0 +1,116 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>freeradiusclients</name>
+ <version>none</version>
+ <title>FreeRADIUS: Clients</title>
+ <include_file>freeradius.inc</include_file>
+ <tabs>
+ <tab>
+ <text>Users</text>
+ <url>/pkg.php?xml=freeradius.xml</url>
+ </tab>
+ <tab>
+ <text>Clients</text>
+ <url>/pkg.php?xml=freeradiusclients.xml</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Settings</text>
+ <url>/pkg_edit.php?xml=freeradiussettings.xml&amp;id=0</url>
+ </tab>
+ </tabs>
+ <adddeleteeditpagefields>
+ <columnitem>
+ <fielddescr>Client</fielddescr>
+ <fieldname>client</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Shortname</fielddescr>
+ <fieldname>shortname</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Description</fielddescr>
+ <fieldname>description</fieldname>
+ </columnitem>
+ </adddeleteeditpagefields>
+ <fields>
+ <field>
+ <fielddescr>Client</fielddescr>
+ <fieldname>client</fieldname>
+ <description>Enter the client's IP address.</description>
+ <type>input</type>
+ <required/>
+ </field>
+ <field>
+ <fielddescr>Shortname</fielddescr>
+ <fieldname>shortname</fieldname>
+ <description>Enter the client's shortname.</description>
+ <type>input</type>
+ <required/>
+ </field>
+ <field>
+ <fielddescr>Shared Secret</fielddescr>
+ <fieldname>sharedsecret</fieldname>
+ <description>Enter the client's shared secret here</description>
+ <type>password</type>
+ <required/>
+ </field>
+ <field>
+ <fielddescr>Description</fielddescr>
+ <fieldname>description</fieldname>
+ <description>Enter the description of the user here</description>
+ <type>input</type>
+ </field>
+ </fields>
+ <custom_delete_php_command>
+ freeradius_clients_resync();
+ </custom_delete_php_command>
+ <custom_php_resync_config_command>
+ freeradius_clients_resync();
+ </custom_php_resync_config_command>
+</packagegui>
diff --git a/config/freeradiussettings.xml b/config/freeradiussettings.xml
new file mode 100644
index 00000000..0eb9d9d4
--- /dev/null
+++ b/config/freeradiussettings.xml
@@ -0,0 +1,141 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>freeradiussettings</name>
+ <version>none</version>
+ <title>FreeRADIUS: Settings</title>
+ <aftersaveredirect>pkg_edit.php?xml=freeradiussettings.xml&amp;id=0</aftersaveredirect>
+ <include_file>freeradius.inc</include_file>
+ <tabs>
+ <tab>
+ <text>Users</text>
+ <url>/pkg.php?xml=freeradius.xml</url>
+ </tab>
+ <tab>
+ <text>Clients</text>
+ <url>/pkg.php?xml=freeradiusclients.xml</url>
+ </tab>
+ <tab>
+ <text>Settings</text>
+ <url>/pkg_edit.php?xml=freeradiussettings.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ </tabs>
+ <fields>
+ <field>
+ <fielddescr>Listening Interface(s)</fielddescr>
+ <fieldname>interface</fieldname>
+ <description>Enter the desired listening interface here.</description>
+ <type>interfaces_selection</type>
+ <required/>
+ </field>
+ <field>
+ <fielddescr>Port</fielddescr>
+ <fieldname>port</fieldname>
+ <description>Enter the port the RADIUS server will listen on. Leave blank to default to the system default, i.e., 1892.</description>
+ <type>input</type>
+ <default_value>1892</default_value>
+ </field>
+ <field>
+ <fielddescr>Radius Logging</fielddescr>
+ <fieldname>radiuslogging</fieldname>
+ <description>Enable radius logging to /var/log/radius.log?</description>
+ <type>select</type>
+ <default_value>no</default_value>
+ <options>
+ <option>
+ <name>no</name>
+ <value>no</value>
+ </option>
+ <option>
+ <name>yes</name>
+ <value>yes</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Log bad authentication attempts?</fielddescr>
+ <fieldname>radiuslogbadpass</fieldname>
+ <description>Specifies whether to log bad authentication attempts to the radius.log file. Radius Logging must be enabled for this to work.</description>
+ <type>select</type>
+ <default_value>no</default_value>
+ <options>
+ <option>
+ <name>no</name>
+ <value>no</value>
+ </option>
+ <option>
+ <name>yes</name>
+ <value>yes</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Log good authentication attempts?</fielddescr>
+ <fieldname>radiusloggoodpass</fieldname>
+ <description>Specifies whether to log good authentication attempts to the radius.log file. Radius Logging must be enabled for this to work.</description>
+ <type>select</type>
+ <default_value>no</default_value>
+ <options>
+ <option>
+ <name>no</name>
+ <value>no</value>
+ </option>
+ <option>
+ <name>yes</name>
+ <value>yes</value>
+ </option>
+ </options>
+ </field>
+ </fields>
+ <custom_delete_php_command>
+ freeradius_settings_resync();
+ </custom_delete_php_command>
+ <custom_php_resync_config_command>
+ freeradius_settings_resync();
+ </custom_php_resync_config_command>
+</packagegui>
diff --git a/config/freeswitch/begin_recording.wav b/config/freeswitch/begin_recording.wav
new file mode 100644
index 00000000..9e4992ca
--- /dev/null
+++ b/config/freeswitch/begin_recording.wav
Binary files differ
diff --git a/config/freeswitch/class.phpmailer.tmp b/config/freeswitch/class.phpmailer.tmp
new file mode 100644
index 00000000..2ddc30fd
--- /dev/null
+++ b/config/freeswitch/class.phpmailer.tmp
@@ -0,0 +1,1896 @@
+<?php
+/*~ class.phpmailer.php
+.---------------------------------------------------------------------------.
+| Software: PHPMailer - PHP email class |
+| Version: 2.0.2 |
+| Contact: via sourceforge.net support pages (also www.codeworxtech.com) |
+| Info: http://phpmailer.sourceforge.net |
+| Support: http://sourceforge.net/projects/phpmailer/ |
+| ------------------------------------------------------------------------- |
+| Author: Andy Prevost (project admininistrator) |
+| Author: Brent R. Matzelle (original founder) |
+| Copyright (c) 2004-2007, Andy Prevost. All Rights Reserved. |
+| Copyright (c) 2001-2003, Brent R. Matzelle |
+| ------------------------------------------------------------------------- |
+| License: Distributed under the Lesser General Public License (LGPL) |
+| http://www.gnu.org/copyleft/lesser.html |
+| This program is distributed in the hope that it will be useful - WITHOUT |
+| ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
+| FITNESS FOR A PARTICULAR PURPOSE. |
+| ------------------------------------------------------------------------- |
+| We offer a number of paid services (www.codeworxtech.com): |
+| - Web Hosting on highly optimized fast and secure servers |
+| - Technology Consulting |
+| - Oursourcing (highly qualified programmers and graphic designers) |
+'---------------------------------------------------------------------------'
+
+/**
+ * PHPMailer - PHP email transport class
+ * @package PHPMailer
+ * @author Andy Prevost
+ * @copyright 2004 - 2008 Andy Prevost
+ */
+
+class PHPMailer {
+
+ /////////////////////////////////////////////////
+ // PROPERTIES, PUBLIC
+ /////////////////////////////////////////////////
+
+ /**
+ * Email priority (1 = High, 3 = Normal, 5 = low).
+ * @var int
+ */
+ var $Priority = 3;
+
+ /**
+ * Sets the CharSet of the message.
+ * @var string
+ */
+ var $CharSet = 'iso-8859-1';
+
+ /**
+ * Sets the Content-type of the message.
+ * @var string
+ */
+ var $ContentType = 'text/plain';
+
+ /**
+ * Sets the Encoding of the message. Options for this are "8bit",
+ * "7bit", "binary", "base64", and "quoted-printable".
+ * @var string
+ */
+ var $Encoding = '8bit';
+
+ /**
+ * Holds the most recent mailer error message.
+ * @var string
+ */
+ var $ErrorInfo = '';
+
+ /**
+ * Sets the From email address for the message.
+ * @var string
+ */
+ var $From = 'root@localhost';
+
+ /**
+ * Sets the From name of the message.
+ * @var string
+ */
+ var $FromName = 'Root User';
+
+ /**
+ * Sets the Sender email (Return-Path) of the message. If not empty,
+ * will be sent via -f to sendmail or as 'MAIL FROM' in smtp mode.
+ * @var string
+ */
+ var $Sender = '';
+
+ /**
+ * Sets the Subject of the message.
+ * @var string
+ */
+ var $Subject = '';
+
+ /**
+ * Sets the Body of the message. This can be either an HTML or text body.
+ * If HTML then run IsHTML(true).
+ * @var string
+ */
+ var $Body = '';
+
+ /**
+ * Sets the text-only body of the message. This automatically sets the
+ * email to multipart/alternative. This body can be read by mail
+ * clients that do not have HTML email capability such as mutt. Clients
+ * that can read HTML will view the normal Body.
+ * @var string
+ */
+ var $AltBody = '';
+
+ /**
+ * Sets word wrapping on the body of the message to a given number of
+ * characters.
+ * @var int
+ */
+ var $WordWrap = 0;
+
+ /**
+ * Method to send mail: ("mail", "sendmail", or "smtp").
+ * @var string
+ */
+ var $Mailer = 'mail';
+
+ /**
+ * Sets the path of the sendmail program.
+ * @var string
+ */
+ var $Sendmail = '/usr/sbin/sendmail';
+
+ /**
+ * Path to PHPMailer plugins. This is now only useful if the SMTP class
+ * is in a different directory than the PHP include path.
+ * @var string
+ */
+ var $PluginDir = '';
+
+ /**
+ * Holds PHPMailer version.
+ * @var string
+ */
+ var $Version = "2.0.2";
+
+ /**
+ * Sets the email address that a reading confirmation will be sent.
+ * @var string
+ */
+ var $ConfirmReadingTo = '';
+
+ /**
+ * Sets the hostname to use in Message-Id and Received headers
+ * and as default HELO string. If empty, the value returned
+ * by SERVER_NAME is used or 'localhost.localdomain'.
+ * @var string
+ */
+ var $Hostname = '';
+
+ /**
+ * Sets the message ID to be used in the Message-Id header.
+ * If empty, a unique id will be generated.
+ * @var string
+ */
+ var $MessageID = '';
+
+ /////////////////////////////////////////////////
+ // PROPERTIES FOR SMTP
+ /////////////////////////////////////////////////
+
+ /**
+ * Sets the SMTP hosts. All hosts must be separated by a
+ * semicolon. You can also specify a different port
+ * for each host by using this format: [hostname:port]
+ * (e.g. "smtp1.example.com:25;smtp2.example.com").
+ * Hosts will be tried in order.
+ * @var string
+ */
+ var $Host = 'localhost';
+
+ /**
+ * Sets the default SMTP server port.
+ * @var int
+ */
+ var $Port = 25;
+
+ /**
+ * Sets the SMTP HELO of the message (Default is $Hostname).
+ * @var string
+ */
+ var $Helo = '';
+
+ /**
+ * Sets connection prefix.
+ * Options are "", "ssl" or "tls"
+ * @var string
+ */
+ var $SMTPSecure = "";
+
+ /**
+ * Sets SMTP authentication. Utilizes the Username and Password variables.
+ * @var bool
+ */
+ var $SMTPAuth = false;
+
+ /**
+ * Sets SMTP username.
+ * @var string
+ */
+ var $Username = '';
+
+ /**
+ * Sets SMTP password.
+ * @var string
+ */
+ var $Password = '';
+
+ /**
+ * Sets the SMTP server timeout in seconds. This function will not
+ * work with the win32 version.
+ * @var int
+ */
+ var $Timeout = 10;
+
+ /**
+ * Sets SMTP class debugging on or off.
+ * @var bool
+ */
+ var $SMTPDebug = false;
+
+ /**
+ * Prevents the SMTP connection from being closed after each mail
+ * sending. If this is set to true then to close the connection
+ * requires an explicit call to SmtpClose().
+ * @var bool
+ */
+ var $SMTPKeepAlive = false;
+
+ /**
+ * Provides the ability to have the TO field process individual
+ * emails, instead of sending to entire TO addresses
+ * @var bool
+ */
+ var $SingleTo = false;
+
+ /////////////////////////////////////////////////
+ // PROPERTIES, PRIVATE
+ /////////////////////////////////////////////////
+
+ var $smtp = NULL;
+ var $to = array();
+ var $cc = array();
+ var $bcc = array();
+ var $ReplyTo = array();
+ var $attachment = array();
+ var $CustomHeader = array();
+ var $message_type = '';
+ var $boundary = array();
+ var $language = array();
+ var $error_count = 0;
+ var $LE = "\n";
+ var $sign_key_file = "";
+ var $sign_key_pass = "";
+
+ /////////////////////////////////////////////////
+ // METHODS, VARIABLES
+ /////////////////////////////////////////////////
+
+ /**
+ * Sets message type to HTML.
+ * @param bool $bool
+ * @return void
+ */
+ function IsHTML($bool) {
+ if($bool == true) {
+ $this->ContentType = 'text/html';
+ } else {
+ $this->ContentType = 'text/plain';
+ }
+ }
+
+ /**
+ * Sets Mailer to send message using SMTP.
+ * @return void
+ */
+ function IsSMTP() {
+ $this->Mailer = 'smtp';
+ }
+
+ /**
+ * Sets Mailer to send message using PHP mail() function.
+ * @return void
+ */
+ function IsMail() {
+ $this->Mailer = 'mail';
+ }
+
+ /**
+ * Sets Mailer to send message using the $Sendmail program.
+ * @return void
+ */
+ function IsSendmail() {
+ $this->Mailer = 'sendmail';
+ }
+
+ /**
+ * Sets Mailer to send message using the qmail MTA.
+ * @return void
+ */
+ function IsQmail() {
+ $this->Sendmail = '/var/qmail/bin/sendmail';
+ $this->Mailer = 'sendmail';
+ }
+
+ /////////////////////////////////////////////////
+ // METHODS, RECIPIENTS
+ /////////////////////////////////////////////////
+
+ /**
+ * Adds a "To" address.
+ * @param string $address
+ * @param string $name
+ * @return void
+ */
+ function AddAddress($address, $name = '') {
+ $cur = count($this->to);
+ $this->to[$cur][0] = trim($address);
+ $this->to[$cur][1] = $name;
+ }
+
+ /**
+ * Adds a "Cc" address. Note: this function works
+ * with the SMTP mailer on win32, not with the "mail"
+ * mailer.
+ * @param string $address
+ * @param string $name
+ * @return void
+ */
+ function AddCC($address, $name = '') {
+ $cur = count($this->cc);
+ $this->cc[$cur][0] = trim($address);
+ $this->cc[$cur][1] = $name;
+ }
+
+ /**
+ * Adds a "Bcc" address. Note: this function works
+ * with the SMTP mailer on win32, not with the "mail"
+ * mailer.
+ * @param string $address
+ * @param string $name
+ * @return void
+ */
+ function AddBCC($address, $name = '') {
+ $cur = count($this->bcc);
+ $this->bcc[$cur][0] = trim($address);
+ $this->bcc[$cur][1] = $name;
+ }
+
+ /**
+ * Adds a "Reply-To" address.
+ * @param string $address
+ * @param string $name
+ * @return void
+ */
+ function AddReplyTo($address, $name = '') {
+ $cur = count($this->ReplyTo);
+ $this->ReplyTo[$cur][0] = trim($address);
+ $this->ReplyTo[$cur][1] = $name;
+ }
+
+ /////////////////////////////////////////////////
+ // METHODS, MAIL SENDING
+ /////////////////////////////////////////////////
+
+ /**
+ * Creates message and assigns Mailer. If the message is
+ * not sent successfully then it returns false. Use the ErrorInfo
+ * variable to view description of the error.
+ * @return bool
+ */
+ function Send() {
+ $header = '';
+ $body = '';
+ $result = true;
+
+ if((count($this->to) + count($this->cc) + count($this->bcc)) < 1) {
+ $this->SetError($this->Lang('provide_address'));
+ return false;
+ }
+
+ /* Set whether the message is multipart/alternative */
+ if(!empty($this->AltBody)) {
+ $this->ContentType = 'multipart/alternative';
+ }
+
+ $this->error_count = 0; // reset errors
+ $this->SetMessageType();
+ $header .= $this->CreateHeader();
+ $body = $this->CreateBody();
+
+ if($body == '') {
+ return false;
+ }
+
+ /* Choose the mailer */
+ switch($this->Mailer) {
+ case 'sendmail':
+ $result = $this->SendmailSend($header, $body);
+ break;
+ case 'smtp':
+ $result = $this->SmtpSend($header, $body);
+ break;
+ case 'mail':
+ $result = $this->MailSend($header, $body);
+ break;
+ default:
+ $result = $this->MailSend($header, $body);
+ break;
+ //$this->SetError($this->Mailer . $this->Lang('mailer_not_supported'));
+ //$result = false;
+ //break;
+ }
+
+ return $result;
+ }
+
+ /**
+ * Sends mail using the $Sendmail program.
+ * @access private
+ * @return bool
+ */
+ function SendmailSend($header, $body) {
+ if ($this->Sender != '') {
+ $sendmail = sprintf("%s -oi -f %s -t", escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender));
+ } else {
+ $sendmail = sprintf("%s -oi -t", escapeshellcmd($this->Sendmail));
+ }
+
+ if(!@$mail = popen($sendmail, 'w')) {
+ $this->SetError($this->Lang('execute') . $this->Sendmail);
+ return false;
+ }
+
+ fputs($mail, $header);
+ fputs($mail, $body);
+
+ $result = pclose($mail);
+ if (version_compare(phpversion(), '4.2.3') == -1) {
+ $result = $result >> 8 & 0xFF;
+ }
+ if($result != 0) {
+ $this->SetError($this->Lang('execute') . $this->Sendmail);
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Sends mail using the PHP mail() function.
+ * @access private
+ * @return bool
+ */
+ function MailSend($header, $body) {
+
+ $to = '';
+ for($i = 0; $i < count($this->to); $i++) {
+ if($i != 0) { $to .= ', '; }
+ $to .= $this->AddrFormat($this->to[$i]);
+ }
+
+ $toArr = split(',', $to);
+
+ $params = sprintf("-oi -f %s", $this->Sender);
+ if ($this->Sender != '' && strlen(ini_get('safe_mode')) < 1) {
+ $old_from = ini_get('sendmail_from');
+ ini_set('sendmail_from', $this->Sender);
+ if ($this->SingleTo === true && count($toArr) > 1) {
+ foreach ($toArr as $key => $val) {
+ $rt = @mail($val, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params);
+ }
+ } else {
+ $rt = @mail($to, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params);
+ }
+ } else {
+ if ($this->SingleTo === true && count($toArr) > 1) {
+ foreach ($toArr as $key => $val) {
+ $rt = @mail($val, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params);
+ }
+ } else {
+ $rt = @mail($to, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header);
+ }
+ }
+
+ if (isset($old_from)) {
+ ini_set('sendmail_from', $old_from);
+ }
+
+ if(!$rt) {
+ $this->SetError($this->Lang('instantiate'));
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Sends mail via SMTP using PhpSMTP (Author:
+ * Chris Ryan). Returns bool. Returns false if there is a
+ * bad MAIL FROM, RCPT, or DATA input.
+ * @access private
+ * @return bool
+ */
+ function SmtpSend($header, $body) {
+ include_once($this->PluginDir . 'class.smtp.php');
+ $error = '';
+ $bad_rcpt = array();
+
+ if(!$this->SmtpConnect()) {
+ return false;
+ }
+
+ $smtp_from = ($this->Sender == '') ? $this->From : $this->Sender;
+ if(!$this->smtp->Mail($smtp_from)) {
+ $error = $this->Lang('from_failed') . $smtp_from;
+ $this->SetError($error);
+ $this->smtp->Reset();
+ return false;
+ }
+
+ /* Attempt to send attach all recipients */
+ for($i = 0; $i < count($this->to); $i++) {
+ if(!$this->smtp->Recipient($this->to[$i][0])) {
+ $bad_rcpt[] = $this->to[$i][0];
+ }
+ }
+ for($i = 0; $i < count($this->cc); $i++) {
+ if(!$this->smtp->Recipient($this->cc[$i][0])) {
+ $bad_rcpt[] = $this->cc[$i][0];
+ }
+ }
+ for($i = 0; $i < count($this->bcc); $i++) {
+ if(!$this->smtp->Recipient($this->bcc[$i][0])) {
+ $bad_rcpt[] = $this->bcc[$i][0];
+ }
+ }
+
+ if(count($bad_rcpt) > 0) { // Create error message
+ for($i = 0; $i < count($bad_rcpt); $i++) {
+ if($i != 0) {
+ $error .= ', ';
+ }
+ $error .= $bad_rcpt[$i];
+ }
+ $error = $this->Lang('recipients_failed') . $error;
+ $this->SetError($error);
+ $this->smtp->Reset();
+ return false;
+ }
+
+ if(!$this->smtp->Data($header . $body)) {
+ $this->SetError($this->Lang('data_not_accepted'));
+ $this->smtp->Reset();
+ return false;
+ }
+ if($this->SMTPKeepAlive == true) {
+ $this->smtp->Reset();
+ } else {
+ $this->SmtpClose();
+ }
+
+ return true;
+ }
+
+ /**
+ * Initiates a connection to an SMTP server. Returns false if the
+ * operation failed.
+ * @access private
+ * @return bool
+ */
+ function SmtpConnect() {
+ if($this->smtp == NULL) {
+ $this->smtp = new SMTP();
+ }
+
+ $this->smtp->do_debug = $this->SMTPDebug;
+ $hosts = explode(';', $this->Host);
+ $index = 0;
+ $connection = ($this->smtp->Connected());
+
+ /* Retry while there is no connection */
+ while($index < count($hosts) && $connection == false) {
+ $hostinfo = array();
+ if(eregi('^(.+):([0-9]+)$', $hosts[$index], $hostinfo)) {
+ $host = $hostinfo[1];
+ $port = $hostinfo[2];
+ } else {
+ $host = $hosts[$index];
+ $port = $this->Port;
+ }
+
+ if($this->smtp->Connect(((!empty($this->SMTPSecure))?$this->SMTPSecure.'://':'').$host, $port, $this->Timeout)) {
+ if ($this->Helo != '') {
+ $this->smtp->Hello($this->Helo);
+ } else {
+ $this->smtp->Hello($this->ServerHostname());
+ }
+
+ $connection = true;
+ if($this->SMTPAuth) {
+ if(!$this->smtp->Authenticate($this->Username, $this->Password)) {
+ $this->SetError($this->Lang('authenticate'));
+ $this->smtp->Reset();
+ $connection = false;
+ }
+ }
+ }
+ $index++;
+ }
+ if(!$connection) {
+ $this->SetError($this->Lang('connect_host'));
+ }
+
+ return $connection;
+ }
+
+ /**
+ * Closes the active SMTP session if one exists.
+ * @return void
+ */
+ function SmtpClose() {
+ if($this->smtp != NULL) {
+ if($this->smtp->Connected()) {
+ $this->smtp->Quit();
+ $this->smtp->Close();
+ }
+ }
+ }
+
+ /**
+ * Sets the language for all class error messages. Returns false
+ * if it cannot load the language file. The default language type
+ * is English.
+ * @param string $lang_type Type of language (e.g. Portuguese: "br")
+ * @param string $lang_path Path to the language file directory
+ * @access public
+ * @return bool
+ */
+ function SetLanguage($lang_type, $lang_path = 'language/') {
+ if(file_exists($lang_path.'phpmailer.lang-'.$lang_type.'.php')) {
+ include($lang_path.'phpmailer.lang-'.$lang_type.'.php');
+ } elseif (file_exists($lang_path.'phpmailer.lang-en.php')) {
+ include($lang_path.'phpmailer.lang-en.php');
+ } else {
+ $this->SetError('Could not load language file');
+ return false;
+ }
+ $this->language = $PHPMAILER_LANG;
+
+ return true;
+ }
+
+ /////////////////////////////////////////////////
+ // METHODS, MESSAGE CREATION
+ /////////////////////////////////////////////////
+
+ /**
+ * Creates recipient headers.
+ * @access private
+ * @return string
+ */
+ function AddrAppend($type, $addr) {
+ $addr_str = $type . ': ';
+ $addr_str .= $this->AddrFormat($addr[0]);
+ if(count($addr) > 1) {
+ for($i = 1; $i < count($addr); $i++) {
+ $addr_str .= ', ' . $this->AddrFormat($addr[$i]);
+ }
+ }
+ $addr_str .= $this->LE;
+
+ return $addr_str;
+ }
+
+ /**
+ * Formats an address correctly.
+ * @access private
+ * @return string
+ */
+ function AddrFormat($addr) {
+ if(empty($addr[1])) {
+ $formatted = $this->SecureHeader($addr[0]);
+ } else {
+ $formatted = $this->EncodeHeader($this->SecureHeader($addr[1]), 'phrase') . " <" . $this->SecureHeader($addr[0]) . ">";
+ }
+
+ return $formatted;
+ }
+
+ /**
+ * Wraps message for use with mailers that do not
+ * automatically perform wrapping and for quoted-printable.
+ * Original written by philippe.
+ * @access private
+ * @return string
+ */
+ function WrapText($message, $length, $qp_mode = false) {
+ $soft_break = ($qp_mode) ? sprintf(" =%s", $this->LE) : $this->LE;
+ // If utf-8 encoding is used, we will need to make sure we don't
+ // split multibyte characters when we wrap
+ $is_utf8 = (strtolower($this->CharSet) == "utf-8");
+
+ $message = $this->FixEOL($message);
+ if (substr($message, -1) == $this->LE) {
+ $message = substr($message, 0, -1);
+ }
+
+ $line = explode($this->LE, $message);
+ $message = '';
+ for ($i=0 ;$i < count($line); $i++) {
+ $line_part = explode(' ', $line[$i]);
+ $buf = '';
+ for ($e = 0; $e<count($line_part); $e++) {
+ $word = $line_part[$e];
+ if ($qp_mode and (strlen($word) > $length)) {
+ $space_left = $length - strlen($buf) - 1;
+ if ($e != 0) {
+ if ($space_left > 20) {
+ $len = $space_left;
+ if ($is_utf8) {
+ $len = $this->UTF8CharBoundary($word, $len);
+ } elseif (substr($word, $len - 1, 1) == "=") {
+ $len--;
+ } elseif (substr($word, $len - 2, 1) == "=") {
+ $len -= 2;
+ }
+ $part = substr($word, 0, $len);
+ $word = substr($word, $len);
+ $buf .= ' ' . $part;
+ $message .= $buf . sprintf("=%s", $this->LE);
+ } else {
+ $message .= $buf . $soft_break;
+ }
+ $buf = '';
+ }
+ while (strlen($word) > 0) {
+ $len = $length;
+ if ($is_utf8) {
+ $len = $this->UTF8CharBoundary($word, $len);
+ } elseif (substr($word, $len - 1, 1) == "=") {
+ $len--;
+ } elseif (substr($word, $len - 2, 1) == "=") {
+ $len -= 2;
+ }
+ $part = substr($word, 0, $len);
+ $word = substr($word, $len);
+
+ if (strlen($word) > 0) {
+ $message .= $part . sprintf("=%s", $this->LE);
+ } else {
+ $buf = $part;
+ }
+ }
+ } else {
+ $buf_o = $buf;
+ $buf .= ($e == 0) ? $word : (' ' . $word);
+
+ if (strlen($buf) > $length and $buf_o != '') {
+ $message .= $buf_o . $soft_break;
+ $buf = $word;
+ }
+ }
+ }
+ $message .= $buf . $this->LE;
+ }
+
+ return $message;
+ }
+
+ /**
+ * Finds last character boundary prior to maxLength in a utf-8
+ * quoted (printable) encoded string.
+ * Original written by Colin Brown.
+ * @access private
+ * @param string $encodedText utf-8 QP text
+ * @param int $maxLength find last character boundary prior to this length
+ * @return int
+ */
+ function UTF8CharBoundary($encodedText, $maxLength) {
+ $foundSplitPos = false;
+ $lookBack = 3;
+ while (!$foundSplitPos) {
+ $lastChunk = substr($encodedText, $maxLength - $lookBack, $lookBack);
+ $encodedCharPos = strpos($lastChunk, "=");
+ if ($encodedCharPos !== false) {
+ // Found start of encoded character byte within $lookBack block.
+ // Check the encoded byte value (the 2 chars after the '=')
+ $hex = substr($encodedText, $maxLength - $lookBack + $encodedCharPos + 1, 2);
+ $dec = hexdec($hex);
+ if ($dec < 128) { // Single byte character.
+ // If the encoded char was found at pos 0, it will fit
+ // otherwise reduce maxLength to start of the encoded char
+ $maxLength = ($encodedCharPos == 0) ? $maxLength :
+ $maxLength - ($lookBack - $encodedCharPos);
+ $foundSplitPos = true;
+ } elseif ($dec >= 192) { // First byte of a multi byte character
+ // Reduce maxLength to split at start of character
+ $maxLength = $maxLength - ($lookBack - $encodedCharPos);
+ $foundSplitPos = true;
+ } elseif ($dec < 192) { // Middle byte of a multi byte character, look further back
+ $lookBack += 3;
+ }
+ } else {
+ // No encoded character found
+ $foundSplitPos = true;
+ }
+ }
+ return $maxLength;
+ }
+
+ /**
+ * Set the body wrapping.
+ * @access private
+ * @return void
+ */
+ function SetWordWrap() {
+ if($this->WordWrap < 1) {
+ return;
+ }
+
+ switch($this->message_type) {
+ case 'alt':
+ /* fall through */
+ case 'alt_attachments':
+ $this->AltBody = $this->WrapText($this->AltBody, $this->WordWrap);
+ break;
+ default:
+ $this->Body = $this->WrapText($this->Body, $this->WordWrap);
+ break;
+ }
+ }
+
+ /**
+ * Assembles message header.
+ * @access private
+ * @return string
+ */
+ function CreateHeader() {
+ $result = '';
+
+ /* Set the boundaries */
+ $uniq_id = md5(uniqid(time()));
+ $this->boundary[1] = 'b1_' . $uniq_id;
+ $this->boundary[2] = 'b2_' . $uniq_id;
+
+ $result .= $this->HeaderLine('Date', $this->RFCDate());
+ if($this->Sender == '') {
+ $result .= $this->HeaderLine('Return-Path', trim($this->From));
+ } else {
+ $result .= $this->HeaderLine('Return-Path', trim($this->Sender));
+ }
+
+ /* To be created automatically by mail() */
+ if($this->Mailer != 'mail') {
+ if(count($this->to) > 0) {
+ $result .= $this->AddrAppend('To', $this->to);
+ } elseif (count($this->cc) == 0) {
+ $result .= $this->HeaderLine('To', 'undisclosed-recipients:;');
+ }
+ if(count($this->cc) > 0) {
+ $result .= $this->AddrAppend('Cc', $this->cc);
+ }
+ }
+
+ $from = array();
+ $from[0][0] = trim($this->From);
+ $from[0][1] = $this->FromName;
+ $result .= $this->AddrAppend('From', $from);
+
+ /* sendmail and mail() extract Cc from the header before sending */
+ if((($this->Mailer == 'sendmail') || ($this->Mailer == 'mail')) && (count($this->cc) > 0)) {
+ $result .= $this->AddrAppend('Cc', $this->cc);
+ }
+
+ /* sendmail and mail() extract Bcc from the header before sending */
+ if((($this->Mailer == 'sendmail') || ($this->Mailer == 'mail')) && (count($this->bcc) > 0)) {
+ $result .= $this->AddrAppend('Bcc', $this->bcc);
+ }
+
+ if(count($this->ReplyTo) > 0) {
+ $result .= $this->AddrAppend('Reply-To', $this->ReplyTo);
+ }
+
+ /* mail() sets the subject itself */
+ if($this->Mailer != 'mail') {
+ $result .= $this->HeaderLine('Subject', $this->EncodeHeader($this->SecureHeader($this->Subject)));
+ }
+
+ if($this->MessageID != '') {
+ $result .= $this->HeaderLine('Message-ID',$this->MessageID);
+ } else {
+ $result .= sprintf("Message-ID: <%s@%s>%s", $uniq_id, $this->ServerHostname(), $this->LE);
+ }
+ $result .= $this->HeaderLine('X-Priority', $this->Priority);
+ $result .= $this->HeaderLine('X-Mailer', 'PHPMailer (phpmailer.sourceforge.net) [version ' . $this->Version . ']');
+
+ if($this->ConfirmReadingTo != '') {
+ $result .= $this->HeaderLine('Disposition-Notification-To', '<' . trim($this->ConfirmReadingTo) . '>');
+ }
+
+ // Add custom headers
+ for($index = 0; $index < count($this->CustomHeader); $index++) {
+ $result .= $this->HeaderLine(trim($this->CustomHeader[$index][0]), $this->EncodeHeader(trim($this->CustomHeader[$index][1])));
+ }
+ if (!$this->sign_key_file) {
+ $result .= $this->HeaderLine('MIME-Version', '1.0');
+ $result .= $this->GetMailMIME();
+ }
+
+ return $result;
+ }
+
+ /**
+ * Returns the message MIME.
+ * @access private
+ * @return string
+ */
+ function GetMailMIME() {
+ $result = '';
+ switch($this->message_type) {
+ case 'plain':
+ $result .= $this->HeaderLine('Content-Transfer-Encoding', $this->Encoding);
+ $result .= sprintf("Content-Type: %s; charset=\"%s\"", $this->ContentType, $this->CharSet);
+ break;
+ case 'attachments':
+ /* fall through */
+ case 'alt_attachments':
+ if($this->InlineImageExists()){
+ $result .= sprintf("Content-Type: %s;%s\ttype=\"text/html\";%s\tboundary=\"%s\"%s", 'multipart/related', $this->LE, $this->LE, $this->boundary[1], $this->LE);
+ } else {
+ $result .= $this->HeaderLine('Content-Type', 'multipart/mixed;');
+ $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"');
+ }
+ break;
+ case 'alt':
+ $result .= $this->HeaderLine('Content-Type', 'multipart/alternative;');
+ $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"');
+ break;
+ }
+
+ if($this->Mailer != 'mail') {
+ $result .= $this->LE.$this->LE;
+ }
+
+ return $result;
+ }
+
+ /**
+ * Assembles the message body. Returns an empty string on failure.
+ * @access private
+ * @return string
+ */
+ function CreateBody() {
+ $result = '';
+ if ($this->sign_key_file) {
+ $result .= $this->GetMailMIME();
+ }
+
+ $this->SetWordWrap();
+
+ switch($this->message_type) {
+ case 'alt':
+ $result .= $this->GetBoundary($this->boundary[1], '', 'text/plain', '');
+ $result .= $this->EncodeString($this->AltBody, $this->Encoding);
+ $result .= $this->LE.$this->LE;
+ $result .= $this->GetBoundary($this->boundary[1], '', 'text/html', '');
+ $result .= $this->EncodeString($this->Body, $this->Encoding);
+ $result .= $this->LE.$this->LE;
+ $result .= $this->EndBoundary($this->boundary[1]);
+ break;
+ case 'plain':
+ $result .= $this->EncodeString($this->Body, $this->Encoding);
+ break;
+ case 'attachments':
+ $result .= $this->GetBoundary($this->boundary[1], '', '', '');
+ $result .= $this->EncodeString($this->Body, $this->Encoding);
+ $result .= $this->LE;
+ $result .= $this->AttachAll();
+ break;
+ case 'alt_attachments':
+ $result .= sprintf("--%s%s", $this->boundary[1], $this->LE);
+ $result .= sprintf("Content-Type: %s;%s" . "\tboundary=\"%s\"%s", 'multipart/alternative', $this->LE, $this->boundary[2], $this->LE.$this->LE);
+ $result .= $this->GetBoundary($this->boundary[2], '', 'text/plain', '') . $this->LE; // Create text body
+ $result .= $this->EncodeString($this->AltBody, $this->Encoding);
+ $result .= $this->LE.$this->LE;
+ $result .= $this->GetBoundary($this->boundary[2], '', 'text/html', '') . $this->LE; // Create the HTML body
+ $result .= $this->EncodeString($this->Body, $this->Encoding);
+ $result .= $this->LE.$this->LE;
+ $result .= $this->EndBoundary($this->boundary[2]);
+ $result .= $this->AttachAll();
+ break;
+ }
+
+ if($this->IsError()) {
+ $result = '';
+ } else if ($this->sign_key_file) {
+ $file = tempnam("", "mail");
+ $fp = fopen($file, "w");
+ fwrite($fp, $result);
+ fclose($fp);
+ $signed = tempnam("", "signed");
+
+ if (@openssl_pkcs7_sign($file, $signed, "file://".$this->sign_key_file, array("file://".$this->sign_key_file, $this->sign_key_pass), null)) {
+ $fp = fopen($signed, "r");
+ $result = fread($fp, filesize($this->sign_key_file));
+ fclose($fp);
+ } else {
+ $this->SetError($this->Lang("signing").openssl_error_string());
+ $result = '';
+ }
+
+ unlink($file);
+ unlink($signed);
+ }
+
+ return $result;
+ }
+
+ /**
+ * Returns the start of a message boundary.
+ * @access private
+ */
+ function GetBoundary($boundary, $charSet, $contentType, $encoding) {
+ $result = '';
+ if($charSet == '') {
+ $charSet = $this->CharSet;
+ }
+ if($contentType == '') {
+ $contentType = $this->ContentType;
+ }
+ if($encoding == '') {
+ $encoding = $this->Encoding;
+ }
+ $result .= $this->TextLine('--' . $boundary);
+ $result .= sprintf("Content-Type: %s; charset = \"%s\"", $contentType, $charSet);
+ $result .= $this->LE;
+ $result .= $this->HeaderLine('Content-Transfer-Encoding', $encoding);
+ $result .= $this->LE;
+
+ return $result;
+ }
+
+ /**
+ * Returns the end of a message boundary.
+ * @access private
+ */
+ function EndBoundary($boundary) {
+ return $this->LE . '--' . $boundary . '--' . $this->LE;
+ }
+
+ /**
+ * Sets the message type.
+ * @access private
+ * @return void
+ */
+ function SetMessageType() {
+ if(count($this->attachment) < 1 && strlen($this->AltBody) < 1) {
+ $this->message_type = 'plain';
+ } else {
+ if(count($this->attachment) > 0) {
+ $this->message_type = 'attachments';
+ }
+ if(strlen($this->AltBody) > 0 && count($this->attachment) < 1) {
+ $this->message_type = 'alt';
+ }
+ if(strlen($this->AltBody) > 0 && count($this->attachment) > 0) {
+ $this->message_type = 'alt_attachments';
+ }
+ }
+ }
+
+ /* Returns a formatted header line.
+ * @access private
+ * @return string
+ */
+ function HeaderLine($name, $value) {
+ return $name . ': ' . $value . $this->LE;
+ }
+
+ /**
+ * Returns a formatted mail line.
+ * @access private
+ * @return string
+ */
+ function TextLine($value) {
+ return $value . $this->LE;
+ }
+
+ /////////////////////////////////////////////////
+ // CLASS METHODS, ATTACHMENTS
+ /////////////////////////////////////////////////
+
+ /**
+ * Adds an attachment from a path on the filesystem.
+ * Returns false if the file could not be found
+ * or accessed.
+ * @param string $path Path to the attachment.
+ * @param string $name Overrides the attachment name.
+ * @param string $encoding File encoding (see $Encoding).
+ * @param string $type File extension (MIME) type.
+ * @return bool
+ */
+ function AddAttachment($path, $name = '', $encoding = 'base64', $type = 'application/octet-stream') {
+ if(!@is_file($path)) {
+ $this->SetError($this->Lang('file_access') . $path);
+ return false;
+ }
+
+ $filename = basename($path);
+ if($name == '') {
+ $name = $filename;
+ }
+
+ $cur = count($this->attachment);
+ $this->attachment[$cur][0] = $path;
+ $this->attachment[$cur][1] = $filename;
+ $this->attachment[$cur][2] = $name;
+ $this->attachment[$cur][3] = $encoding;
+ $this->attachment[$cur][4] = $type;
+ $this->attachment[$cur][5] = false; // isStringAttachment
+ $this->attachment[$cur][6] = 'attachment';
+ $this->attachment[$cur][7] = 0;
+
+ return true;
+ }
+
+ /**
+ * Attaches all fs, string, and binary attachments to the message.
+ * Returns an empty string on failure.
+ * @access private
+ * @return string
+ */
+ function AttachAll() {
+ /* Return text of body */
+ $mime = array();
+
+ /* Add all attachments */
+ for($i = 0; $i < count($this->attachment); $i++) {
+ /* Check for string attachment */
+ $bString = $this->attachment[$i][5];
+ if ($bString) {
+ $string = $this->attachment[$i][0];
+ } else {
+ $path = $this->attachment[$i][0];
+ }
+
+ $filename = $this->attachment[$i][1];
+ $name = $this->attachment[$i][2];
+ $encoding = $this->attachment[$i][3];
+ $type = $this->attachment[$i][4];
+ $disposition = $this->attachment[$i][6];
+ $cid = $this->attachment[$i][7];
+
+ $mime[] = sprintf("--%s%s", $this->boundary[1], $this->LE);
+ $mime[] = sprintf("Content-Type: %s; name=\"%s\"%s", $type, $name, $this->LE);
+ $mime[] = sprintf("Content-Transfer-Encoding: %s%s", $encoding, $this->LE);
+
+ if($disposition == 'inline') {
+ $mime[] = sprintf("Content-ID: <%s>%s", $cid, $this->LE);
+ }
+
+ $mime[] = sprintf("Content-Disposition: %s; filename=\"%s\"%s", $disposition, $name, $this->LE.$this->LE);
+
+ /* Encode as string attachment */
+ if($bString) {
+ $mime[] = $this->EncodeString($string, $encoding);
+ if($this->IsError()) {
+ return '';
+ }
+ $mime[] = $this->LE.$this->LE;
+ } else {
+ $mime[] = $this->EncodeFile($path, $encoding);
+ if($this->IsError()) {
+ return '';
+ }
+ $mime[] = $this->LE.$this->LE;
+ }
+ }
+
+ $mime[] = sprintf("--%s--%s", $this->boundary[1], $this->LE);
+
+ return join('', $mime);
+ }
+
+ /**
+ * Encodes attachment in requested format. Returns an
+ * empty string on failure.
+ * @access private
+ * @return string
+ */
+ function EncodeFile ($path, $encoding = 'base64') {
+ if(!@$fd = fopen($path, 'rb')) {
+ $this->SetError($this->Lang('file_open') . $path);
+ return '';
+ }
+ $magic_quotes = get_magic_quotes_runtime();
+ set_magic_quotes_runtime(0);
+ $file_buffer = fread($fd, filesize($path));
+ $file_buffer = $this->EncodeString($file_buffer, $encoding);
+ fclose($fd);
+ set_magic_quotes_runtime($magic_quotes);
+
+ return $file_buffer;
+ }
+
+ /**
+ * Encodes string to requested format. Returns an
+ * empty string on failure.
+ * @access private
+ * @return string
+ */
+ function EncodeString ($str, $encoding = 'base64') {
+ $encoded = '';
+ switch(strtolower($encoding)) {
+ case 'base64':
+ /* chunk_split is found in PHP >= 3.0.6 */
+ $encoded = chunk_split(base64_encode($str), 76, $this->LE);
+ break;
+ case '7bit':
+ case '8bit':
+ $encoded = $this->FixEOL($str);
+ if (substr($encoded, -(strlen($this->LE))) != $this->LE)
+ $encoded .= $this->LE;
+ break;
+ case 'binary':
+ $encoded = $str;
+ break;
+ case 'quoted-printable':
+ $encoded = $this->EncodeQP($str);
+ break;
+ default:
+ $this->SetError($this->Lang('encoding') . $encoding);
+ break;
+ }
+ return $encoded;
+ }
+
+ /**
+ * Encode a header string to best of Q, B, quoted or none.
+ * @access private
+ * @return string
+ */
+ function EncodeHeader ($str, $position = 'text') {
+ $x = 0;
+
+ switch (strtolower($position)) {
+ case 'phrase':
+ if (!preg_match('/[\200-\377]/', $str)) {
+ /* Can't use addslashes as we don't know what value has magic_quotes_sybase. */
+ $encoded = addcslashes($str, "\0..\37\177\\\"");
+ if (($str == $encoded) && !preg_match('/[^A-Za-z0-9!#$%&\'*+\/=?^_`{|}~ -]/', $str)) {
+ return ($encoded);
+ } else {
+ return ("\"$encoded\"");
+ }
+ }
+ $x = preg_match_all('/[^\040\041\043-\133\135-\176]/', $str, $matches);
+ break;
+ case 'comment':
+ $x = preg_match_all('/[()"]/', $str, $matches);
+ /* Fall-through */
+ case 'text':
+ default:
+ $x += preg_match_all('/[\000-\010\013\014\016-\037\177-\377]/', $str, $matches);
+ break;
+ }
+
+ if ($x == 0) {
+ return ($str);
+ }
+
+ $maxlen = 75 - 7 - strlen($this->CharSet);
+ /* Try to select the encoding which should produce the shortest output */
+ if (strlen($str)/3 < $x) {
+ $encoding = 'B';
+ if (function_exists('mb_strlen') && $this->HasMultiBytes($str)) {
+ // Use a custom function which correctly encodes and wraps long
+ // multibyte strings without breaking lines within a character
+ $encoded = $this->Base64EncodeWrapMB($str);
+ } else {
+ $encoded = base64_encode($str);
+ $maxlen -= $maxlen % 4;
+ $encoded = trim(chunk_split($encoded, $maxlen, "\n"));
+ }
+ } else {
+ $encoding = 'Q';
+ $encoded = $this->EncodeQ($str, $position);
+ $encoded = $this->WrapText($encoded, $maxlen, true);
+ $encoded = str_replace('='.$this->LE, "\n", trim($encoded));
+ }
+
+ $encoded = preg_replace('/^(.*)$/m', " =?".$this->CharSet."?$encoding?\\1?=", $encoded);
+ $encoded = trim(str_replace("\n", $this->LE, $encoded));
+
+ return $encoded;
+ }
+
+ /**
+ * Checks if a string contains multibyte characters.
+ * @access private
+ * @param string $str multi-byte text to wrap encode
+ * @return bool
+ */
+ function HasMultiBytes($str) {
+ if (function_exists('mb_strlen')) {
+ return (strlen($str) > mb_strlen($str, $this->CharSet));
+ } else { // Assume no multibytes (we can't handle without mbstring functions anyway)
+ return False;
+ }
+ }
+
+ /**
+ * Correctly encodes and wraps long multibyte strings for mail headers
+ * without breaking lines within a character.
+ * Adapted from a function by paravoid at http://uk.php.net/manual/en/function.mb-encode-mimeheader.php
+ * @access private
+ * @param string $str multi-byte text to wrap encode
+ * @return string
+ */
+ function Base64EncodeWrapMB($str) {
+ $start = "=?".$this->CharSet."?B?";
+ $end = "?=";
+ $encoded = "";
+
+ $mb_length = mb_strlen($str, $this->CharSet);
+ // Each line must have length <= 75, including $start and $end
+ $length = 75 - strlen($start) - strlen($end);
+ // Average multi-byte ratio
+ $ratio = $mb_length / strlen($str);
+ // Base64 has a 4:3 ratio
+ $offset = $avgLength = floor($length * $ratio * .75);
+
+ for ($i = 0; $i < $mb_length; $i += $offset) {
+ $lookBack = 0;
+
+ do {
+ $offset = $avgLength - $lookBack;
+ $chunk = mb_substr($str, $i, $offset, $this->CharSet);
+ $chunk = base64_encode($chunk);
+ $lookBack++;
+ }
+ while (strlen($chunk) > $length);
+
+ $encoded .= $chunk . $this->LE;
+ }
+
+ // Chomp the last linefeed
+ $encoded = substr($encoded, 0, -strlen($this->LE));
+ return $encoded;
+ }
+
+ /**
+ * Encode string to quoted-printable.
+ * @access private
+ * @return string
+ */
+ function EncodeQP( $input = '', $line_max = 76, $space_conv = false ) {
+ $hex = array('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F');
+ $lines = preg_split('/(?:\r\n|\r|\n)/', $input);
+ $eol = "\r\n";
+ $escape = '=';
+ $output = '';
+ while( list(, $line) = each($lines) ) {
+ $linlen = strlen($line);
+ $newline = '';
+ for($i = 0; $i < $linlen; $i++) {
+ $c = substr( $line, $i, 1 );
+ $dec = ord( $c );
+ if ( ( $i == 0 ) && ( $dec == 46 ) ) { // convert first point in the line into =2E
+ $c = '=2E';
+ }
+ if ( $dec == 32 ) {
+ if ( $i == ( $linlen - 1 ) ) { // convert space at eol only
+ $c = '=20';
+ } else if ( $space_conv ) {
+ $c = '=20';
+ }
+ } elseif ( ($dec == 61) || ($dec < 32 ) || ($dec > 126) ) { // always encode "\t", which is *not* required
+ $h2 = floor($dec/16);
+ $h1 = floor($dec%16);
+ $c = $escape.$hex[$h2].$hex[$h1];
+ }
+ if ( (strlen($newline) + strlen($c)) >= $line_max ) { // CRLF is not counted
+ $output .= $newline.$escape.$eol; // soft line break; " =\r\n" is okay
+ $newline = '';
+ // check if newline first character will be point or not
+ if ( $dec == 46 ) {
+ $c = '=2E';
+ }
+ }
+ $newline .= $c;
+ } // end of for
+ $output .= $newline.$eol;
+ } // end of while
+ return trim($output);
+ }
+
+ /**
+ * Encode string to q encoding.
+ * @access private
+ * @return string
+ */
+ function EncodeQ ($str, $position = 'text') {
+ /* There should not be any EOL in the string */
+ $encoded = preg_replace("[\r\n]", '', $str);
+
+ switch (strtolower($position)) {
+ case 'phrase':
+ $encoded = preg_replace("/([^A-Za-z0-9!*+\/ -])/e", "'='.sprintf('%02X', ord('\\1'))", $encoded);
+ break;
+ case 'comment':
+ $encoded = preg_replace("/([\(\)\"])/e", "'='.sprintf('%02X', ord('\\1'))", $encoded);
+ case 'text':
+ default:
+ /* Replace every high ascii, control =, ? and _ characters */
+ $encoded = preg_replace('/([\000-\011\013\014\016-\037\075\077\137\177-\377])/e',
+ "'='.sprintf('%02X', ord('\\1'))", $encoded);
+ break;
+ }
+
+ /* Replace every spaces to _ (more readable than =20) */
+ $encoded = str_replace(' ', '_', $encoded);
+
+ return $encoded;
+ }
+
+ /**
+ * Adds a string or binary attachment (non-filesystem) to the list.
+ * This method can be used to attach ascii or binary data,
+ * such as a BLOB record from a database.
+ * @param string $string String attachment data.
+ * @param string $filename Name of the attachment.
+ * @param string $encoding File encoding (see $Encoding).
+ * @param string $type File extension (MIME) type.
+ * @return void
+ */
+ function AddStringAttachment($string, $filename, $encoding = 'base64', $type = 'application/octet-stream') {
+ /* Append to $attachment array */
+ $cur = count($this->attachment);
+ $this->attachment[$cur][0] = $string;
+ $this->attachment[$cur][1] = $filename;
+ $this->attachment[$cur][2] = $filename;
+ $this->attachment[$cur][3] = $encoding;
+ $this->attachment[$cur][4] = $type;
+ $this->attachment[$cur][5] = true; // isString
+ $this->attachment[$cur][6] = 'attachment';
+ $this->attachment[$cur][7] = 0;
+ }
+
+ /**
+ * Adds an embedded attachment. This can include images, sounds, and
+ * just about any other document. Make sure to set the $type to an
+ * image type. For JPEG images use "image/jpeg" and for GIF images
+ * use "image/gif".
+ * @param string $path Path to the attachment.
+ * @param string $cid Content ID of the attachment. Use this to identify
+ * the Id for accessing the image in an HTML form.
+ * @param string $name Overrides the attachment name.
+ * @param string $encoding File encoding (see $Encoding).
+ * @param string $type File extension (MIME) type.
+ * @return bool
+ */
+ function AddEmbeddedImage($path, $cid, $name = '', $encoding = 'base64', $type = 'application/octet-stream') {
+
+ if(!@is_file($path)) {
+ $this->SetError($this->Lang('file_access') . $path);
+ return false;
+ }
+
+ $filename = basename($path);
+ if($name == '') {
+ $name = $filename;
+ }
+
+ /* Append to $attachment array */
+ $cur = count($this->attachment);
+ $this->attachment[$cur][0] = $path;
+ $this->attachment[$cur][1] = $filename;
+ $this->attachment[$cur][2] = $name;
+ $this->attachment[$cur][3] = $encoding;
+ $this->attachment[$cur][4] = $type;
+ $this->attachment[$cur][5] = false;
+ $this->attachment[$cur][6] = 'inline';
+ $this->attachment[$cur][7] = $cid;
+
+ return true;
+ }
+
+ /**
+ * Returns true if an inline attachment is present.
+ * @access private
+ * @return bool
+ */
+ function InlineImageExists() {
+ $result = false;
+ for($i = 0; $i < count($this->attachment); $i++) {
+ if($this->attachment[$i][6] == 'inline') {
+ $result = true;
+ break;
+ }
+ }
+
+ return $result;
+ }
+
+ /////////////////////////////////////////////////
+ // CLASS METHODS, MESSAGE RESET
+ /////////////////////////////////////////////////
+
+ /**
+ * Clears all recipients assigned in the TO array. Returns void.
+ * @return void
+ */
+ function ClearAddresses() {
+ $this->to = array();
+ }
+
+ /**
+ * Clears all recipients assigned in the CC array. Returns void.
+ * @return void
+ */
+ function ClearCCs() {
+ $this->cc = array();
+ }
+
+ /**
+ * Clears all recipients assigned in the BCC array. Returns void.
+ * @return void
+ */
+ function ClearBCCs() {
+ $this->bcc = array();
+ }
+
+ /**
+ * Clears all recipients assigned in the ReplyTo array. Returns void.
+ * @return void
+ */
+ function ClearReplyTos() {
+ $this->ReplyTo = array();
+ }
+
+ /**
+ * Clears all recipients assigned in the TO, CC and BCC
+ * array. Returns void.
+ * @return void
+ */
+ function ClearAllRecipients() {
+ $this->to = array();
+ $this->cc = array();
+ $this->bcc = array();
+ }
+
+ /**
+ * Clears all previously set filesystem, string, and binary
+ * attachments. Returns void.
+ * @return void
+ */
+ function ClearAttachments() {
+ $this->attachment = array();
+ }
+
+ /**
+ * Clears all custom headers. Returns void.
+ * @return void
+ */
+ function ClearCustomHeaders() {
+ $this->CustomHeader = array();
+ }
+
+ /////////////////////////////////////////////////
+ // CLASS METHODS, MISCELLANEOUS
+ /////////////////////////////////////////////////
+
+ /**
+ * Adds the error message to the error container.
+ * Returns void.
+ * @access private
+ * @return void
+ */
+ function SetError($msg) {
+ $this->error_count++;
+ $this->ErrorInfo = $msg;
+ }
+
+ /**
+ * Returns the proper RFC 822 formatted date.
+ * @access private
+ * @return string
+ */
+ function RFCDate() {
+ $tz = date('Z');
+ $tzs = ($tz < 0) ? '-' : '+';
+ $tz = abs($tz);
+ $tz = (int)($tz/3600)*100 + ($tz%3600)/60;
+ $result = sprintf("%s %s%04d", date('D, j M Y H:i:s'), $tzs, $tz);
+
+ return $result;
+ }
+
+ /**
+ * Returns the appropriate server variable. Should work with both
+ * PHP 4.1.0+ as well as older versions. Returns an empty string
+ * if nothing is found.
+ * @access private
+ * @return mixed
+ */
+ function ServerVar($varName) {
+ global $HTTP_SERVER_VARS;
+ global $HTTP_ENV_VARS;
+
+ if(!isset($_SERVER)) {
+ $_SERVER = $HTTP_SERVER_VARS;
+ if(!isset($_SERVER['REMOTE_ADDR'])) {
+ $_SERVER = $HTTP_ENV_VARS; // must be Apache
+ }
+ }
+
+ if(isset($_SERVER[$varName])) {
+ return $_SERVER[$varName];
+ } else {
+ return '';
+ }
+ }
+
+ /**
+ * Returns the server hostname or 'localhost.localdomain' if unknown.
+ * @access private
+ * @return string
+ */
+ function ServerHostname() {
+ if ($this->Hostname != '') {
+ $result = $this->Hostname;
+ } elseif ($this->ServerVar('SERVER_NAME') != '') {
+ $result = $this->ServerVar('SERVER_NAME');
+ } else {
+ $result = 'localhost.localdomain';
+ }
+
+ return $result;
+ }
+
+ /**
+ * Returns a message in the appropriate language.
+ * @access private
+ * @return string
+ */
+ function Lang($key) {
+ if(count($this->language) < 1) {
+ $this->SetLanguage('en'); // set the default language
+ }
+
+ if(isset($this->language[$key])) {
+ return $this->language[$key];
+ } else {
+ return 'Language string failed to load: ' . $key;
+ }
+ }
+
+ /**
+ * Returns true if an error occurred.
+ * @return bool
+ */
+ function IsError() {
+ return ($this->error_count > 0);
+ }
+
+ /**
+ * Changes every end of line from CR or LF to CRLF.
+ * @access private
+ * @return string
+ */
+ function FixEOL($str) {
+ $str = str_replace("\r\n", "\n", $str);
+ $str = str_replace("\r", "\n", $str);
+ $str = str_replace("\n", $this->LE, $str);
+ return $str;
+ }
+
+ /**
+ * Adds a custom header.
+ * @return void
+ */
+ function AddCustomHeader($custom_header) {
+ $this->CustomHeader[] = explode(':', $custom_header, 2);
+ }
+
+ /**
+ * Evaluates the message and returns modifications for inline images and backgrounds
+ * @access public
+ * @return $message
+ */
+ function MsgHTML($message,$basedir='') {
+ preg_match_all("/(src|background)=\"(.*)\"/Ui", $message, $images);
+ if(isset($images[2])) {
+ foreach($images[2] as $i => $url) {
+ // do not change urls for absolute images (thanks to corvuscorax)
+ if (!preg_match('/^[A-z][A-z]*:\/\//',$url)) {
+ $filename = basename($url);
+ $directory = dirname($url);
+ ($directory == '.')?$directory='':'';
+ $cid = 'cid:' . md5($filename);
+ $fileParts = split("\.", $filename);
+ $ext = $fileParts[1];
+ $mimeType = $this->_mime_types($ext);
+ if ( strlen($basedir) > 1 && substr($basedir,-1) != '/') { $basedir .= '/'; }
+ if ( strlen($directory) > 1 && substr($basedir,-1) != '/') { $directory .= '/'; }
+ $this->AddEmbeddedImage($basedir.$directory.$filename, md5($filename), $filename, 'base64', $mimeType);
+ if ( $this->AddEmbeddedImage($basedir.$directory.$filename, md5($filename), $filename, 'base64',$mimeType) ) {
+ $message = preg_replace("/".$images[1][$i]."=\"".preg_quote($url, '/')."\"/Ui", $images[1][$i]."=\"".$cid."\"", $message);
+ }
+ }
+ }
+ }
+ $this->IsHTML(true);
+ $this->Body = $message;
+ $textMsg = trim(strip_tags(preg_replace('/<(head|title|style|script)[^>]*>.*?<\/\\1>/s','',$message)));
+ if ( !empty($textMsg) && empty($this->AltBody) ) {
+ $this->AltBody = $textMsg;
+ }
+ if ( empty($this->AltBody) ) {
+ $this->AltBody = 'To view this email message, open the email in with HTML compatibility!' . "\n\n";
+ }
+ }
+
+ /**
+ * Gets the mime type of the embedded or inline image
+ * @access private
+ * @return mime type of ext
+ */
+ function _mime_types($ext = '') {
+ $mimes = array(
+ 'hqx' => 'application/mac-binhex40',
+ 'cpt' => 'application/mac-compactpro',
+ 'doc' => 'application/msword',
+ 'bin' => 'application/macbinary',
+ 'dms' => 'application/octet-stream',
+ 'lha' => 'application/octet-stream',
+ 'lzh' => 'application/octet-stream',
+ 'exe' => 'application/octet-stream',
+ 'class' => 'application/octet-stream',
+ 'psd' => 'application/octet-stream',
+ 'so' => 'application/octet-stream',
+ 'sea' => 'application/octet-stream',
+ 'dll' => 'application/octet-stream',
+ 'oda' => 'application/oda',
+ 'pdf' => 'application/pdf',
+ 'ai' => 'application/postscript',
+ 'eps' => 'application/postscript',
+ 'ps' => 'application/postscript',
+ 'smi' => 'application/smil',
+ 'smil' => 'application/smil',
+ 'mif' => 'application/vnd.mif',
+ 'xls' => 'application/vnd.ms-excel',
+ 'ppt' => 'application/vnd.ms-powerpoint',
+ 'wbxml' => 'application/vnd.wap.wbxml',
+ 'wmlc' => 'application/vnd.wap.wmlc',
+ 'dcr' => 'application/x-director',
+ 'dir' => 'application/x-director',
+ 'dxr' => 'application/x-director',
+ 'dvi' => 'application/x-dvi',
+ 'gtar' => 'application/x-gtar',
+ 'php' => 'application/x-httpd-php',
+ 'php4' => 'application/x-httpd-php',
+ 'php3' => 'application/x-httpd-php',
+ 'phtml' => 'application/x-httpd-php',
+ 'phps' => 'application/x-httpd-php-source',
+ 'js' => 'application/x-javascript',
+ 'swf' => 'application/x-shockwave-flash',
+ 'sit' => 'application/x-stuffit',
+ 'tar' => 'application/x-tar',
+ 'tgz' => 'application/x-tar',
+ 'xhtml' => 'application/xhtml+xml',
+ 'xht' => 'application/xhtml+xml',
+ 'zip' => 'application/zip',
+ 'mid' => 'audio/midi',
+ 'midi' => 'audio/midi',
+ 'mpga' => 'audio/mpeg',
+ 'mp2' => 'audio/mpeg',
+ 'mp3' => 'audio/mpeg',
+ 'aif' => 'audio/x-aiff',
+ 'aiff' => 'audio/x-aiff',
+ 'aifc' => 'audio/x-aiff',
+ 'ram' => 'audio/x-pn-realaudio',
+ 'rm' => 'audio/x-pn-realaudio',
+ 'rpm' => 'audio/x-pn-realaudio-plugin',
+ 'ra' => 'audio/x-realaudio',
+ 'rv' => 'video/vnd.rn-realvideo',
+ 'wav' => 'audio/x-wav',
+ 'bmp' => 'image/bmp',
+ 'gif' => 'image/gif',
+ 'jpeg' => 'image/jpeg',
+ 'jpg' => 'image/jpeg',
+ 'jpe' => 'image/jpeg',
+ 'png' => 'image/png',
+ 'tiff' => 'image/tiff',
+ 'tif' => 'image/tiff',
+ 'css' => 'text/css',
+ 'html' => 'text/html',
+ 'htm' => 'text/html',
+ 'shtml' => 'text/html',
+ 'txt' => 'text/plain',
+ 'text' => 'text/plain',
+ 'log' => 'text/plain',
+ 'rtx' => 'text/richtext',
+ 'rtf' => 'text/rtf',
+ 'xml' => 'text/xml',
+ 'xsl' => 'text/xml',
+ 'mpeg' => 'video/mpeg',
+ 'mpg' => 'video/mpeg',
+ 'mpe' => 'video/mpeg',
+ 'qt' => 'video/quicktime',
+ 'mov' => 'video/quicktime',
+ 'avi' => 'video/x-msvideo',
+ 'movie' => 'video/x-sgi-movie',
+ 'doc' => 'application/msword',
+ 'word' => 'application/msword',
+ 'xl' => 'application/excel',
+ 'eml' => 'message/rfc822'
+ );
+ return ( ! isset($mimes[strtolower($ext)])) ? 'application/octet-stream' : $mimes[strtolower($ext)];
+ }
+
+ /**
+ * Set (or reset) Class Objects (variables)
+ *
+ * Usage Example:
+ * $page->set('X-Priority', '3');
+ *
+ * @access public
+ * @param string $name Parameter Name
+ * @param mixed $value Parameter Value
+ * NOTE: will not work with arrays, there are no arrays to set/reset
+ */
+ function set ( $name, $value = '' ) {
+ if ( isset($this->$name) ) {
+ $this->$name = $value;
+ } else {
+ $this->SetError('Cannot set or reset variable ' . $name);
+ return false;
+ }
+ }
+
+ /**
+ * Read a file from a supplied filename and return it.
+ *
+ * @access public
+ * @param string $filename Parameter File Name
+ */
+ function getFile($filename) {
+ $return = '';
+ if ($fp = fopen($filename, 'rb')) {
+ while (!feof($fp)) {
+ $return .= fread($fp, 1024);
+ }
+ fclose($fp);
+ return $return;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Strips newlines to prevent header injection.
+ * @access private
+ * @param string $str String
+ * @return string
+ */
+ function SecureHeader($str) {
+ $str = trim($str);
+ $str = str_replace("\r", "", $str);
+ $str = str_replace("\n", "", $str);
+ return $str;
+ }
+
+ /**
+ * Set the private key file and password to sign the message.
+ *
+ * @access public
+ * @param string $key_filename Parameter File Name
+ * @param string $key_pass Password for private key
+ */
+ function Sign($key_filename, $key_pass) {
+ $this->sign_key_file = $key_filename;
+ $this->sign_key_pass = $key_pass;
+ }
+
+}
+
+?>
diff --git a/config/freeswitch/class.smtp.tmp b/config/freeswitch/class.smtp.tmp
new file mode 100644
index 00000000..398c3ffb
--- /dev/null
+++ b/config/freeswitch/class.smtp.tmp
@@ -0,0 +1,1062 @@
+<?php
+/*~ class.smtp.php
+.---------------------------------------------------------------------------.
+| Software: PHPMailer - PHP email class |
+| Version: 2.0.2 |
+| Contact: via sourceforge.net support pages (also www.codeworxtech.com) |
+| Info: http://phpmailer.sourceforge.net |
+| Support: http://sourceforge.net/projects/phpmailer/ |
+| ------------------------------------------------------------------------- |
+| Author: Andy Prevost (project admininistrator) |
+| Author: Brent R. Matzelle (original founder) |
+| Copyright (c) 2004-2007, Andy Prevost. All Rights Reserved. |
+| Copyright (c) 2001-2003, Brent R. Matzelle |
+| ------------------------------------------------------------------------- |
+| License: Distributed under the Lesser General Public License (LGPL) |
+| http://www.gnu.org/copyleft/lesser.html |
+| This program is distributed in the hope that it will be useful - WITHOUT |
+| ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
+| FITNESS FOR A PARTICULAR PURPOSE. |
+| ------------------------------------------------------------------------- |
+| We offer a number of paid services (www.codeworxtech.com): |
+| - Web Hosting on highly optimized fast and secure servers |
+| - Technology Consulting |
+| - Oursourcing (highly qualified programmers and graphic designers) |
+'---------------------------------------------------------------------------'
+
+/**
+ * SMTP is rfc 821 compliant and implements all the rfc 821 SMTP
+ * commands except TURN which will always return a not implemented
+ * error. SMTP also provides some utility methods for sending mail
+ * to an SMTP server.
+ * @package PHPMailer
+ * @author Chris Ryan
+ */
+
+class SMTP
+{
+ /**
+ * SMTP server port
+ * @var int
+ */
+ var $SMTP_PORT = 25;
+
+ /**
+ * SMTP reply line ending
+ * @var string
+ */
+ var $CRLF = "\r\n";
+
+ /**
+ * Sets whether debugging is turned on
+ * @var bool
+ */
+ var $do_debug; # the level of debug to perform
+
+ /**
+ * Sets VERP use on/off (default is off)
+ * @var bool
+ */
+ var $do_verp = false;
+
+ /**#@+
+ * @access private
+ */
+ var $smtp_conn; # the socket to the server
+ var $error; # error if any on the last call
+ var $helo_rply; # the reply the server sent to us for HELO
+ /**#@-*/
+
+ /**
+ * Initialize the class so that the data is in a known state.
+ * @access public
+ * @return void
+ */
+ function SMTP() {
+ $this->smtp_conn = 0;
+ $this->error = null;
+ $this->helo_rply = null;
+
+ $this->do_debug = 0;
+ }
+
+ /*************************************************************
+ * CONNECTION FUNCTIONS *
+ ***********************************************************/
+
+ /**
+ * Connect to the server specified on the port specified.
+ * If the port is not specified use the default SMTP_PORT.
+ * If tval is specified then a connection will try and be
+ * established with the server for that number of seconds.
+ * If tval is not specified the default is 30 seconds to
+ * try on the connection.
+ *
+ * SMTP CODE SUCCESS: 220
+ * SMTP CODE FAILURE: 421
+ * @access public
+ * @return bool
+ */
+ function Connect($host,$port=0,$tval=30) {
+ # set the error val to null so there is no confusion
+ $this->error = null;
+
+ # make sure we are __not__ connected
+ if($this->connected()) {
+ # ok we are connected! what should we do?
+ # for now we will just give an error saying we
+ # are already connected
+ $this->error = array("error" => "Already connected to a server");
+ return false;
+ }
+
+ if(empty($port)) {
+ $port = $this->SMTP_PORT;
+ }
+
+ #connect to the smtp server
+ $this->smtp_conn = fsockopen($host, # the host of the server
+ $port, # the port to use
+ $errno, # error number if any
+ $errstr, # error message if any
+ $tval); # give up after ? secs
+ # verify we connected properly
+ if(empty($this->smtp_conn)) {
+ $this->error = array("error" => "Failed to connect to server",
+ "errno" => $errno,
+ "errstr" => $errstr);
+ if($this->do_debug >= 1) {
+ echo "SMTP -> ERROR: " . $this->error["error"] .
+ ": $errstr ($errno)" . $this->CRLF;
+ }
+ return false;
+ }
+
+ # sometimes the SMTP server takes a little longer to respond
+ # so we will give it a longer timeout for the first read
+ // Windows still does not have support for this timeout function
+ if(substr(PHP_OS, 0, 3) != "WIN")
+ socket_set_timeout($this->smtp_conn, $tval, 0);
+
+ # get any announcement stuff
+ $announce = $this->get_lines();
+
+ # set the timeout of any socket functions at 1/10 of a second
+ //if(function_exists("socket_set_timeout"))
+ // socket_set_timeout($this->smtp_conn, 0, 100000);
+
+ if($this->do_debug >= 2) {
+ echo "SMTP -> FROM SERVER:" . $this->CRLF . $announce;
+ }
+
+ return true;
+ }
+
+ /**
+ * Performs SMTP authentication. Must be run after running the
+ * Hello() method. Returns true if successfully authenticated.
+ * @access public
+ * @return bool
+ */
+ function Authenticate($username, $password) {
+ // Start authentication
+ fputs($this->smtp_conn,"AUTH LOGIN" . $this->CRLF);
+
+ $rply = $this->get_lines();
+ $code = substr($rply,0,3);
+
+ if($code != 334) {
+ $this->error =
+ array("error" => "AUTH not accepted from server",
+ "smtp_code" => $code,
+ "smtp_msg" => substr($rply,4));
+ if($this->do_debug >= 1) {
+ echo "SMTP -> ERROR: " . $this->error["error"] .
+ ": " . $rply . $this->CRLF;
+ }
+ return false;
+ }
+
+ // Send encoded username
+ fputs($this->smtp_conn, base64_encode($username) . $this->CRLF);
+
+ $rply = $this->get_lines();
+ $code = substr($rply,0,3);
+
+ if($code != 334) {
+ $this->error =
+ array("error" => "Username not accepted from server",
+ "smtp_code" => $code,
+ "smtp_msg" => substr($rply,4));
+ if($this->do_debug >= 1) {
+ echo "SMTP -> ERROR: " . $this->error["error"] .
+ ": " . $rply . $this->CRLF;
+ }
+ return false;
+ }
+
+ // Send encoded password
+ fputs($this->smtp_conn, base64_encode($password) . $this->CRLF);
+
+ $rply = $this->get_lines();
+ $code = substr($rply,0,3);
+
+ if($code != 235) {
+ $this->error =
+ array("error" => "Password not accepted from server",
+ "smtp_code" => $code,
+ "smtp_msg" => substr($rply,4));
+ if($this->do_debug >= 1) {
+ echo "SMTP -> ERROR: " . $this->error["error"] .
+ ": " . $rply . $this->CRLF;
+ }
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Returns true if connected to a server otherwise false
+ * @access private
+ * @return bool
+ */
+ function Connected() {
+ if(!empty($this->smtp_conn)) {
+ $sock_status = socket_get_status($this->smtp_conn);
+ if($sock_status["eof"]) {
+ # hmm this is an odd situation... the socket is
+ # valid but we are not connected anymore
+ if($this->do_debug >= 1) {
+ echo "SMTP -> NOTICE:" . $this->CRLF .
+ "EOF caught while checking if connected";
+ }
+ $this->Close();
+ return false;
+ }
+ return true; # everything looks good
+ }
+ return false;
+ }
+
+ /**
+ * Closes the socket and cleans up the state of the class.
+ * It is not considered good to use this function without
+ * first trying to use QUIT.
+ * @access public
+ * @return void
+ */
+ function Close() {
+ $this->error = null; # so there is no confusion
+ $this->helo_rply = null;
+ if(!empty($this->smtp_conn)) {
+ # close the connection and cleanup
+ fclose($this->smtp_conn);
+ $this->smtp_conn = 0;
+ }
+ }
+
+ /***************************************************************
+ * SMTP COMMANDS *
+ *************************************************************/
+
+ /**
+ * Issues a data command and sends the msg_data to the server
+ * finializing the mail transaction. $msg_data is the message
+ * that is to be send with the headers. Each header needs to be
+ * on a single line followed by a <CRLF> with the message headers
+ * and the message body being seperated by and additional <CRLF>.
+ *
+ * Implements rfc 821: DATA <CRLF>
+ *
+ * SMTP CODE INTERMEDIATE: 354
+ * [data]
+ * <CRLF>.<CRLF>
+ * SMTP CODE SUCCESS: 250
+ * SMTP CODE FAILURE: 552,554,451,452
+ * SMTP CODE FAILURE: 451,554
+ * SMTP CODE ERROR : 500,501,503,421
+ * @access public
+ * @return bool
+ */
+ function Data($msg_data) {
+ $this->error = null; # so no confusion is caused
+
+ if(!$this->connected()) {
+ $this->error = array(
+ "error" => "Called Data() without being connected");
+ return false;
+ }
+
+ fputs($this->smtp_conn,"DATA" . $this->CRLF);
+
+ $rply = $this->get_lines();
+ $code = substr($rply,0,3);
+
+ if($this->do_debug >= 2) {
+ echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
+ }
+
+ if($code != 354) {
+ $this->error =
+ array("error" => "DATA command not accepted from server",
+ "smtp_code" => $code,
+ "smtp_msg" => substr($rply,4));
+ if($this->do_debug >= 1) {
+ echo "SMTP -> ERROR: " . $this->error["error"] .
+ ": " . $rply . $this->CRLF;
+ }
+ return false;
+ }
+
+ # the server is ready to accept data!
+ # according to rfc 821 we should not send more than 1000
+ # including the CRLF
+ # characters on a single line so we will break the data up
+ # into lines by \r and/or \n then if needed we will break
+ # each of those into smaller lines to fit within the limit.
+ # in addition we will be looking for lines that start with
+ # a period '.' and append and additional period '.' to that
+ # line. NOTE: this does not count towards are limit.
+
+ # normalize the line breaks so we know the explode works
+ $msg_data = str_replace("\r\n","\n",$msg_data);
+ $msg_data = str_replace("\r","\n",$msg_data);
+ $lines = explode("\n",$msg_data);
+
+ # we need to find a good way to determine is headers are
+ # in the msg_data or if it is a straight msg body
+ # currently I am assuming rfc 822 definitions of msg headers
+ # and if the first field of the first line (':' sperated)
+ # does not contain a space then it _should_ be a header
+ # and we can process all lines before a blank "" line as
+ # headers.
+ $field = substr($lines[0],0,strpos($lines[0],":"));
+ $in_headers = false;
+ if(!empty($field) && !strstr($field," ")) {
+ $in_headers = true;
+ }
+
+ $max_line_length = 998; # used below; set here for ease in change
+
+ while(list(,$line) = @each($lines)) {
+ $lines_out = null;
+ if($line == "" && $in_headers) {
+ $in_headers = false;
+ }
+ # ok we need to break this line up into several
+ # smaller lines
+ while(strlen($line) > $max_line_length) {
+ $pos = strrpos(substr($line,0,$max_line_length)," ");
+
+ # Patch to fix DOS attack
+ if(!$pos) {
+ $pos = $max_line_length - 1;
+ }
+
+ $lines_out[] = substr($line,0,$pos);
+ $line = substr($line,$pos + 1);
+ # if we are processing headers we need to
+ # add a LWSP-char to the front of the new line
+ # rfc 822 on long msg headers
+ if($in_headers) {
+ $line = "\t" . $line;
+ }
+ }
+ $lines_out[] = $line;
+
+ # now send the lines to the server
+ while(list(,$line_out) = @each($lines_out)) {
+ if(strlen($line_out) > 0)
+ {
+ if(substr($line_out, 0, 1) == ".") {
+ $line_out = "." . $line_out;
+ }
+ }
+ fputs($this->smtp_conn,$line_out . $this->CRLF);
+ }
+ }
+
+ # ok all the message data has been sent so lets get this
+ # over with aleady
+ fputs($this->smtp_conn, $this->CRLF . "." . $this->CRLF);
+
+ $rply = $this->get_lines();
+ $code = substr($rply,0,3);
+
+ if($this->do_debug >= 2) {
+ echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
+ }
+
+ if($code != 250) {
+ $this->error =
+ array("error" => "DATA not accepted from server",
+ "smtp_code" => $code,
+ "smtp_msg" => substr($rply,4));
+ if($this->do_debug >= 1) {
+ echo "SMTP -> ERROR: " . $this->error["error"] .
+ ": " . $rply . $this->CRLF;
+ }
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Expand takes the name and asks the server to list all the
+ * people who are members of the _list_. Expand will return
+ * back and array of the result or false if an error occurs.
+ * Each value in the array returned has the format of:
+ * [ <full-name> <sp> ] <path>
+ * The definition of <path> is defined in rfc 821
+ *
+ * Implements rfc 821: EXPN <SP> <string> <CRLF>
+ *
+ * SMTP CODE SUCCESS: 250
+ * SMTP CODE FAILURE: 550
+ * SMTP CODE ERROR : 500,501,502,504,421
+ * @access public
+ * @return string array
+ */
+ function Expand($name) {
+ $this->error = null; # so no confusion is caused
+
+ if(!$this->connected()) {
+ $this->error = array(
+ "error" => "Called Expand() without being connected");
+ return false;
+ }
+
+ fputs($this->smtp_conn,"EXPN " . $name . $this->CRLF);
+
+ $rply = $this->get_lines();
+ $code = substr($rply,0,3);
+
+ if($this->do_debug >= 2) {
+ echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
+ }
+
+ if($code != 250) {
+ $this->error =
+ array("error" => "EXPN not accepted from server",
+ "smtp_code" => $code,
+ "smtp_msg" => substr($rply,4));
+ if($this->do_debug >= 1) {
+ echo "SMTP -> ERROR: " . $this->error["error"] .
+ ": " . $rply . $this->CRLF;
+ }
+ return false;
+ }
+
+ # parse the reply and place in our array to return to user
+ $entries = explode($this->CRLF,$rply);
+ while(list(,$l) = @each($entries)) {
+ $list[] = substr($l,4);
+ }
+
+ return $list;
+ }
+
+ /**
+ * Sends the HELO command to the smtp server.
+ * This makes sure that we and the server are in
+ * the same known state.
+ *
+ * Implements from rfc 821: HELO <SP> <domain> <CRLF>
+ *
+ * SMTP CODE SUCCESS: 250
+ * SMTP CODE ERROR : 500, 501, 504, 421
+ * @access public
+ * @return bool
+ */
+ function Hello($host="") {
+ $this->error = null; # so no confusion is caused
+
+ if(!$this->connected()) {
+ $this->error = array(
+ "error" => "Called Hello() without being connected");
+ return false;
+ }
+
+ # if a hostname for the HELO was not specified determine
+ # a suitable one to send
+ if(empty($host)) {
+ # we need to determine some sort of appopiate default
+ # to send to the server
+ $host = "localhost";
+ }
+
+ // Send extended hello first (RFC 2821)
+ if(!$this->SendHello("EHLO", $host))
+ {
+ if(!$this->SendHello("HELO", $host))
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Sends a HELO/EHLO command.
+ * @access private
+ * @return bool
+ */
+ function SendHello($hello, $host) {
+ fputs($this->smtp_conn, $hello . " " . $host . $this->CRLF);
+
+ $rply = $this->get_lines();
+ $code = substr($rply,0,3);
+
+ if($this->do_debug >= 2) {
+ echo "SMTP -> FROM SERVER: " . $this->CRLF . $rply;
+ }
+
+ if($code != 250) {
+ $this->error =
+ array("error" => $hello . " not accepted from server",
+ "smtp_code" => $code,
+ "smtp_msg" => substr($rply,4));
+ if($this->do_debug >= 1) {
+ echo "SMTP -> ERROR: " . $this->error["error"] .
+ ": " . $rply . $this->CRLF;
+ }
+ return false;
+ }
+
+ $this->helo_rply = $rply;
+
+ return true;
+ }
+
+ /**
+ * Gets help information on the keyword specified. If the keyword
+ * is not specified then returns generic help, ussually contianing
+ * A list of keywords that help is available on. This function
+ * returns the results back to the user. It is up to the user to
+ * handle the returned data. If an error occurs then false is
+ * returned with $this->error set appropiately.
+ *
+ * Implements rfc 821: HELP [ <SP> <string> ] <CRLF>
+ *
+ * SMTP CODE SUCCESS: 211,214
+ * SMTP CODE ERROR : 500,501,502,504,421
+ * @access public
+ * @return string
+ */
+ function Help($keyword="") {
+ $this->error = null; # to avoid confusion
+
+ if(!$this->connected()) {
+ $this->error = array(
+ "error" => "Called Help() without being connected");
+ return false;
+ }
+
+ $extra = "";
+ if(!empty($keyword)) {
+ $extra = " " . $keyword;
+ }
+
+ fputs($this->smtp_conn,"HELP" . $extra . $this->CRLF);
+
+ $rply = $this->get_lines();
+ $code = substr($rply,0,3);
+
+ if($this->do_debug >= 2) {
+ echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
+ }
+
+ if($code != 211 && $code != 214) {
+ $this->error =
+ array("error" => "HELP not accepted from server",
+ "smtp_code" => $code,
+ "smtp_msg" => substr($rply,4));
+ if($this->do_debug >= 1) {
+ echo "SMTP -> ERROR: " . $this->error["error"] .
+ ": " . $rply . $this->CRLF;
+ }
+ return false;
+ }
+
+ return $rply;
+ }
+
+ /**
+ * Starts a mail transaction from the email address specified in
+ * $from. Returns true if successful or false otherwise. If True
+ * the mail transaction is started and then one or more Recipient
+ * commands may be called followed by a Data command.
+ *
+ * Implements rfc 821: MAIL <SP> FROM:<reverse-path> <CRLF>
+ *
+ * SMTP CODE SUCCESS: 250
+ * SMTP CODE SUCCESS: 552,451,452
+ * SMTP CODE SUCCESS: 500,501,421
+ * @access public
+ * @return bool
+ */
+ function Mail($from) {
+ $this->error = null; # so no confusion is caused
+
+ if(!$this->connected()) {
+ $this->error = array(
+ "error" => "Called Mail() without being connected");
+ return false;
+ }
+
+ $useVerp = ($this->do_verp ? "XVERP" : "");
+ fputs($this->smtp_conn,"MAIL FROM:<" . $from . ">" . $useVerp . $this->CRLF);
+
+ $rply = $this->get_lines();
+ $code = substr($rply,0,3);
+
+ if($this->do_debug >= 2) {
+ echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
+ }
+
+ if($code != 250) {
+ $this->error =
+ array("error" => "MAIL not accepted from server",
+ "smtp_code" => $code,
+ "smtp_msg" => substr($rply,4));
+ if($this->do_debug >= 1) {
+ echo "SMTP -> ERROR: " . $this->error["error"] .
+ ": " . $rply . $this->CRLF;
+ }
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Sends the command NOOP to the SMTP server.
+ *
+ * Implements from rfc 821: NOOP <CRLF>
+ *
+ * SMTP CODE SUCCESS: 250
+ * SMTP CODE ERROR : 500, 421
+ * @access public
+ * @return bool
+ */
+ function Noop() {
+ $this->error = null; # so no confusion is caused
+
+ if(!$this->connected()) {
+ $this->error = array(
+ "error" => "Called Noop() without being connected");
+ return false;
+ }
+
+ fputs($this->smtp_conn,"NOOP" . $this->CRLF);
+
+ $rply = $this->get_lines();
+ $code = substr($rply,0,3);
+
+ if($this->do_debug >= 2) {
+ echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
+ }
+
+ if($code != 250) {
+ $this->error =
+ array("error" => "NOOP not accepted from server",
+ "smtp_code" => $code,
+ "smtp_msg" => substr($rply,4));
+ if($this->do_debug >= 1) {
+ echo "SMTP -> ERROR: " . $this->error["error"] .
+ ": " . $rply . $this->CRLF;
+ }
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Sends the quit command to the server and then closes the socket
+ * if there is no error or the $close_on_error argument is true.
+ *
+ * Implements from rfc 821: QUIT <CRLF>
+ *
+ * SMTP CODE SUCCESS: 221
+ * SMTP CODE ERROR : 500
+ * @access public
+ * @return bool
+ */
+ function Quit($close_on_error=true) {
+ $this->error = null; # so there is no confusion
+
+ if(!$this->connected()) {
+ $this->error = array(
+ "error" => "Called Quit() without being connected");
+ return false;
+ }
+
+ # send the quit command to the server
+ fputs($this->smtp_conn,"quit" . $this->CRLF);
+
+ # get any good-bye messages
+ $byemsg = $this->get_lines();
+
+ if($this->do_debug >= 2) {
+ echo "SMTP -> FROM SERVER:" . $this->CRLF . $byemsg;
+ }
+
+ $rval = true;
+ $e = null;
+
+ $code = substr($byemsg,0,3);
+ if($code != 221) {
+ # use e as a tmp var cause Close will overwrite $this->error
+ $e = array("error" => "SMTP server rejected quit command",
+ "smtp_code" => $code,
+ "smtp_rply" => substr($byemsg,4));
+ $rval = false;
+ if($this->do_debug >= 1) {
+ echo "SMTP -> ERROR: " . $e["error"] . ": " .
+ $byemsg . $this->CRLF;
+ }
+ }
+
+ if(empty($e) || $close_on_error) {
+ $this->Close();
+ }
+
+ return $rval;
+ }
+
+ /**
+ * Sends the command RCPT to the SMTP server with the TO: argument of $to.
+ * Returns true if the recipient was accepted false if it was rejected.
+ *
+ * Implements from rfc 821: RCPT <SP> TO:<forward-path> <CRLF>
+ *
+ * SMTP CODE SUCCESS: 250,251
+ * SMTP CODE FAILURE: 550,551,552,553,450,451,452
+ * SMTP CODE ERROR : 500,501,503,421
+ * @access public
+ * @return bool
+ */
+ function Recipient($to) {
+ $this->error = null; # so no confusion is caused
+
+ if(!$this->connected()) {
+ $this->error = array(
+ "error" => "Called Recipient() without being connected");
+ return false;
+ }
+
+ fputs($this->smtp_conn,"RCPT TO:<" . $to . ">" . $this->CRLF);
+
+ $rply = $this->get_lines();
+ $code = substr($rply,0,3);
+
+ if($this->do_debug >= 2) {
+ echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
+ }
+
+ if($code != 250 && $code != 251) {
+ $this->error =
+ array("error" => "RCPT not accepted from server",
+ "smtp_code" => $code,
+ "smtp_msg" => substr($rply,4));
+ if($this->do_debug >= 1) {
+ echo "SMTP -> ERROR: " . $this->error["error"] .
+ ": " . $rply . $this->CRLF;
+ }
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Sends the RSET command to abort and transaction that is
+ * currently in progress. Returns true if successful false
+ * otherwise.
+ *
+ * Implements rfc 821: RSET <CRLF>
+ *
+ * SMTP CODE SUCCESS: 250
+ * SMTP CODE ERROR : 500,501,504,421
+ * @access public
+ * @return bool
+ */
+ function Reset() {
+ $this->error = null; # so no confusion is caused
+
+ if(!$this->connected()) {
+ $this->error = array(
+ "error" => "Called Reset() without being connected");
+ return false;
+ }
+
+ fputs($this->smtp_conn,"RSET" . $this->CRLF);
+
+ $rply = $this->get_lines();
+ $code = substr($rply,0,3);
+
+ if($this->do_debug >= 2) {
+ echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
+ }
+
+ if($code != 250) {
+ $this->error =
+ array("error" => "RSET failed",
+ "smtp_code" => $code,
+ "smtp_msg" => substr($rply,4));
+ if($this->do_debug >= 1) {
+ echo "SMTP -> ERROR: " . $this->error["error"] .
+ ": " . $rply . $this->CRLF;
+ }
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Starts a mail transaction from the email address specified in
+ * $from. Returns true if successful or false otherwise. If True
+ * the mail transaction is started and then one or more Recipient
+ * commands may be called followed by a Data command. This command
+ * will send the message to the users terminal if they are logged
+ * in.
+ *
+ * Implements rfc 821: SEND <SP> FROM:<reverse-path> <CRLF>
+ *
+ * SMTP CODE SUCCESS: 250
+ * SMTP CODE SUCCESS: 552,451,452
+ * SMTP CODE SUCCESS: 500,501,502,421
+ * @access public
+ * @return bool
+ */
+ function Send($from) {
+ $this->error = null; # so no confusion is caused
+
+ if(!$this->connected()) {
+ $this->error = array(
+ "error" => "Called Send() without being connected");
+ return false;
+ }
+
+ fputs($this->smtp_conn,"SEND FROM:" . $from . $this->CRLF);
+
+ $rply = $this->get_lines();
+ $code = substr($rply,0,3);
+
+ if($this->do_debug >= 2) {
+ echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
+ }
+
+ if($code != 250) {
+ $this->error =
+ array("error" => "SEND not accepted from server",
+ "smtp_code" => $code,
+ "smtp_msg" => substr($rply,4));
+ if($this->do_debug >= 1) {
+ echo "SMTP -> ERROR: " . $this->error["error"] .
+ ": " . $rply . $this->CRLF;
+ }
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Starts a mail transaction from the email address specified in
+ * $from. Returns true if successful or false otherwise. If True
+ * the mail transaction is started and then one or more Recipient
+ * commands may be called followed by a Data command. This command
+ * will send the message to the users terminal if they are logged
+ * in and send them an email.
+ *
+ * Implements rfc 821: SAML <SP> FROM:<reverse-path> <CRLF>
+ *
+ * SMTP CODE SUCCESS: 250
+ * SMTP CODE SUCCESS: 552,451,452
+ * SMTP CODE SUCCESS: 500,501,502,421
+ * @access public
+ * @return bool
+ */
+ function SendAndMail($from) {
+ $this->error = null; # so no confusion is caused
+
+ if(!$this->connected()) {
+ $this->error = array(
+ "error" => "Called SendAndMail() without being connected");
+ return false;
+ }
+
+ fputs($this->smtp_conn,"SAML FROM:" . $from . $this->CRLF);
+
+ $rply = $this->get_lines();
+ $code = substr($rply,0,3);
+
+ if($this->do_debug >= 2) {
+ echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
+ }
+
+ if($code != 250) {
+ $this->error =
+ array("error" => "SAML not accepted from server",
+ "smtp_code" => $code,
+ "smtp_msg" => substr($rply,4));
+ if($this->do_debug >= 1) {
+ echo "SMTP -> ERROR: " . $this->error["error"] .
+ ": " . $rply . $this->CRLF;
+ }
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Starts a mail transaction from the email address specified in
+ * $from. Returns true if successful or false otherwise. If True
+ * the mail transaction is started and then one or more Recipient
+ * commands may be called followed by a Data command. This command
+ * will send the message to the users terminal if they are logged
+ * in or mail it to them if they are not.
+ *
+ * Implements rfc 821: SOML <SP> FROM:<reverse-path> <CRLF>
+ *
+ * SMTP CODE SUCCESS: 250
+ * SMTP CODE SUCCESS: 552,451,452
+ * SMTP CODE SUCCESS: 500,501,502,421
+ * @access public
+ * @return bool
+ */
+ function SendOrMail($from) {
+ $this->error = null; # so no confusion is caused
+
+ if(!$this->connected()) {
+ $this->error = array(
+ "error" => "Called SendOrMail() without being connected");
+ return false;
+ }
+
+ fputs($this->smtp_conn,"SOML FROM:" . $from . $this->CRLF);
+
+ $rply = $this->get_lines();
+ $code = substr($rply,0,3);
+
+ if($this->do_debug >= 2) {
+ echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
+ }
+
+ if($code != 250) {
+ $this->error =
+ array("error" => "SOML not accepted from server",
+ "smtp_code" => $code,
+ "smtp_msg" => substr($rply,4));
+ if($this->do_debug >= 1) {
+ echo "SMTP -> ERROR: " . $this->error["error"] .
+ ": " . $rply . $this->CRLF;
+ }
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * This is an optional command for SMTP that this class does not
+ * support. This method is here to make the RFC821 Definition
+ * complete for this class and __may__ be implimented in the future
+ *
+ * Implements from rfc 821: TURN <CRLF>
+ *
+ * SMTP CODE SUCCESS: 250
+ * SMTP CODE FAILURE: 502
+ * SMTP CODE ERROR : 500, 503
+ * @access public
+ * @return bool
+ */
+ function Turn() {
+ $this->error = array("error" => "This method, TURN, of the SMTP ".
+ "is not implemented");
+ if($this->do_debug >= 1) {
+ echo "SMTP -> NOTICE: " . $this->error["error"] . $this->CRLF;
+ }
+ return false;
+ }
+
+ /**
+ * Verifies that the name is recognized by the server.
+ * Returns false if the name could not be verified otherwise
+ * the response from the server is returned.
+ *
+ * Implements rfc 821: VRFY <SP> <string> <CRLF>
+ *
+ * SMTP CODE SUCCESS: 250,251
+ * SMTP CODE FAILURE: 550,551,553
+ * SMTP CODE ERROR : 500,501,502,421
+ * @access public
+ * @return int
+ */
+ function Verify($name) {
+ $this->error = null; # so no confusion is caused
+
+ if(!$this->connected()) {
+ $this->error = array(
+ "error" => "Called Verify() without being connected");
+ return false;
+ }
+
+ fputs($this->smtp_conn,"VRFY " . $name . $this->CRLF);
+
+ $rply = $this->get_lines();
+ $code = substr($rply,0,3);
+
+ if($this->do_debug >= 2) {
+ echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
+ }
+
+ if($code != 250 && $code != 251) {
+ $this->error =
+ array("error" => "VRFY failed on name '$name'",
+ "smtp_code" => $code,
+ "smtp_msg" => substr($rply,4));
+ if($this->do_debug >= 1) {
+ echo "SMTP -> ERROR: " . $this->error["error"] .
+ ": " . $rply . $this->CRLF;
+ }
+ return false;
+ }
+ return $rply;
+ }
+
+ /*******************************************************************
+ * INTERNAL FUNCTIONS *
+ ******************************************************************/
+
+ /**
+ * Read in as many lines as possible
+ * either before eof or socket timeout occurs on the operation.
+ * With SMTP we can tell if we have more lines to read if the
+ * 4th character is '-' symbol. If it is a space then we don't
+ * need to read anything else.
+ * @access private
+ * @return string
+ */
+ function get_lines() {
+ $data = "";
+ while($str = @fgets($this->smtp_conn,515)) {
+ if($this->do_debug >= 4) {
+ echo "SMTP -> get_lines(): \$data was \"$data\"" .
+ $this->CRLF;
+ echo "SMTP -> get_lines(): \$str is \"$str\"" .
+ $this->CRLF;
+ }
+ $data .= $str;
+ if($this->do_debug >= 4) {
+ echo "SMTP -> get_lines(): \$data is \"$data\"" . $this->CRLF;
+ }
+ # if the 4th character is a space then we are done reading
+ # so just break the loop
+ if(substr($str,3,1) == " ") { break; }
+ }
+ return $data;
+ }
+
+}
+
+
+ ?>
diff --git a/config/freeswitch/freeswitch.inc b/config/freeswitch/freeswitch.inc
new file mode 100644
index 00000000..82fa97b1
--- /dev/null
+++ b/config/freeswitch/freeswitch.inc
@@ -0,0 +1,2234 @@
+<?php
+/* $Id$ */
+/*
+/* ========================================================================== */
+/*
+ freeswitch.inc
+ Copyright (C) 2008 Mark J Crane
+ All rights reserved.
+
+ FreeSWITCH (TM)
+ http://www.freeswitch.org/
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+function guid()
+{
+ if (function_exists('com_create_guid')){
+ return com_create_guid();
+ }else{
+ mt_srand((double)microtime()*10000);//optional for php 4.2.0 and up.
+ $charid = strtoupper(md5(uniqid(rand(), true)));
+ $hyphen = chr(45);// "-"
+ $uuid = chr(123)// "{"
+ .substr($charid, 0, 8).$hyphen
+ .substr($charid, 8, 4).$hyphen
+ .substr($charid,12, 4).$hyphen
+ .substr($charid,16, 4).$hyphen
+ .substr($charid,20,12)
+ .chr(125);// "}"
+ return $uuid;
+ }
+}
+//echo guid();
+
+
+function pkg_is_service_running($servicename)
+{
+ exec("/bin/ps ax | awk '{ print $5 }'", $psout);
+ array_shift($psout);
+ foreach($psout as $line) {
+ $ps[] = trim(array_pop(explode(' ', array_pop(explode('/', $line)))));
+ }
+ if(is_service_running($servicename, $ps) or is_process_running($servicename) ) {
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+
+function event_socket_create($host, $port, $password)
+{
+ //$host has been deprecated
+
+ //build the interface list
+ $i = 0; $ifdescrs = array('wan' => 'WAN', 'lan' => 'LAN');
+ for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++) {
+ $ifdescrs['opt' . $j] = $config['interfaces']['opt' . $j]['descr'];
+ }
+
+ //get the interface ip addresses and try to connect to them
+ foreach ($ifdescrs as $ifdescr => $ifname){
+ $ifinfo = get_interface_info($ifdescr);
+ $interface_ip_address = $ifinfo['ipaddr'];
+
+ if (strlen($interface_ip_address) > 0) {
+
+ $fp = fsockopen($interface_ip_address, $port, $errno, $errdesc, 3);
+ socket_set_blocking($fp,false);
+
+ if (!$fp) {
+ //connection failed continue through the loop testing other addresses
+ //invalid handle
+ }
+ else {
+ //connected to the socket return the handle
+
+ while (!feof($fp)) {
+ $buffer = fgets($fp, 1024);
+ usleep(100); //allow time for reponse
+ if (trim($buffer) == "Content-Type: auth/request") {
+ fputs($fp, "auth $password\n\n");
+ break;
+ }
+ }
+ return $fp;
+ }
+
+ } //end if interface_ip_address
+ } //end foreach
+} //end function
+
+
+function event_socket_request($fp, $cmd)
+{
+ if ($fp) {
+ fputs($fp, $cmd."\n\n");
+ usleep(100); //allow time for reponse
+
+ $response = "";
+ $i = 0;
+ $contentlength = 0;
+ while (!feof($fp)) {
+ $buffer = fgets($fp, 4096);
+ if ($contentlength > 0) {
+ $response .= $buffer;
+ }
+
+ if ($contentlength == 0) { //if contentlenght is already don't process again
+ if (strlen(trim($buffer)) > 0) { //run only if buffer has content
+ $temparray = split(":", trim($buffer));
+ if ($temparray[0] == "Content-Length") {
+ $contentlength = trim($temparray[1]);
+ }
+ }
+ }
+
+ usleep(100); //allow time for reponse
+
+ //optional because of script timeout //don't let while loop become endless
+ if ($i > 10000) { break; }
+
+ if ($contentlength > 0) { //is contentlength set
+ //stop reading if all content has been read.
+ if (strlen($response) >= $contentlength) {
+ break;
+ }
+ }
+ $i++;
+ }
+
+ return $response;
+ }
+ else {
+ echo "no handle";
+ }
+}
+
+
+function event_socket_request_cmd($cmd)
+{
+ global $config;
+ $password = $config['installedpackages']['freeswitchsettings']['config'][0]['event_socket_password'];
+ $port = $config['installedpackages']['freeswitchsettings']['config'][0]['event_socket_port'];
+ $host = $config['interfaces']['lan']['ipaddr'];
+
+ if (pkg_is_service_running('freeswitch')) {
+ $fp = event_socket_create($host, $port, $password);
+ $response = event_socket_request($fp, $cmd);
+ fclose($fp);
+ }
+ unset($host, $port, $password);
+
+}
+
+function byte_convert( $bytes ) {
+
+ if ($bytes<=0)
+ return '0 Byte';
+
+ $convention=1000; //[1000->10^x|1024->2^x]
+ $s=array('B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB');
+ $e=floor(log($bytes,$convention));
+ return round($bytes/pow($convention,$e),2).' '.$s[$e];
+}
+
+function recording_js()
+{
+
+ global $config;
+ $admin_pin = $config['installedpackages']['freeswitchsettings']['config'][0]['admin_pin'];
+
+ $fout = fopen("/usr/local/freeswitch/scripts/recordings.js","w");
+ $tmp = " var pin = \"".$admin_pin."\";\n";
+ $tmp .= " //var pin = \"\"; //don't require a pin\n";
+ $tmp .= " //if you choose not to require a pin then then you may want to add a dialplan condition for a specific caller id\n";
+ $tmp .= "\n";
+ $tmp .= " var digitmaxlength = 0;\n";
+ $tmp .= " var timeoutpin = 7500;\n";
+ $tmp .= " var timeouttransfer = 7500;\n";
+ $tmp .= " var objdate = new Date();\n";
+ $tmp .= "\n";
+ $tmp .= " var adjusthours = 0; //Adjust Server time that is set to GMT 7 hours\n";
+ $tmp .= " var adjustoperator = \"-\"; //+ or -\n";
+ $tmp .= "\n";
+ $tmp .= " if (adjustoperator == \"-\") {\n";
+ $tmp .= " var objdate2 = new Date(objdate.getFullYear(),objdate.getMonth(),objdate.getDate(),(objdate.getHours() - adjusthours),objdate.getMinutes(),objdate.getSeconds());\n";
+ $tmp .= " }\n";
+ $tmp .= " if (adjustoperator == \"+\") {\n";
+ $tmp .= " var objdate2 = new Date(objdate.getFullYear(),objdate.getMonth(),objdate.getDate(),(objdate.getHours() + adjusthours),objdate.getMinutes(),objdate.getSeconds());\n";
+ $tmp .= " }\n";
+ $tmp .= "\n";
+ $tmp .= " var Hours = objdate2.getHours();\n";
+ $tmp .= " var Mins = objdate2.getMinutes();\n";
+ $tmp .= " var Seconds = objdate2.getSeconds();\n";
+ $tmp .= " var Month = objdate2.getMonth() + 1;\n";
+ $tmp .= " var Date = objdate2.getDate();\n";
+ $tmp .= " var Year = objdate2.getYear()\n";
+ $tmp .= " var Day = objdate2.getDay()+1;\n";
+ $tmp .= " var exit = false;\n";
+ $tmp .= "\n";
+ $tmp .= "\n";
+ $tmp .= " function mycb( session, type, data, arg ) {\n";
+ $tmp .= " if ( type == \"dtmf\" ) {\n";
+ $tmp .= " //console_log( \"info\", \"digit: \"+data.digit+\"\\n\" );\n";
+ $tmp .= " if ( data.digit == \"#\" ) {\n";
+ $tmp .= " //console_log( \"info\", \"detected pound sign.\\n\" );\n";
+ $tmp .= " return( true );\n";
+ $tmp .= " }\n";
+ $tmp .= " dtmf.digits += data.digit;\n";
+ $tmp .= "\n";
+ $tmp .= " if ( dtmf.digits.length < digitmaxlength ) {\n";
+ $tmp .= " return( true );\n";
+ $tmp .= " }\n";
+ $tmp .= " }\n";
+ $tmp .= " return( false );\n";
+ $tmp .= " }\n";
+ $tmp .= "\n";
+ $tmp .= " //console_log( \"info\", \"Recording Request\\n\" );\n";
+ $tmp .= "\n";
+ $tmp .= " var dtmf = new Object( );\n";
+ $tmp .= " dtmf.digits = \"\";\n";
+ $tmp .= "\n";
+ $tmp .= " if ( session.ready( ) ) {\n";
+ $tmp .= " session.answer( );\n";
+ $tmp .= "\n";
+
+ $tmp .= "\n";
+ $tmp .= " if (pin.length > 0) {\n";
+ //$tmp .= " session.execute(\"set\", \"tts_engine=flite\");\n";
+ //$tmp .= " session.execute(\"set\", \"tts_voice=kal\");\n";
+ //$tmp .= " session.execute(\"speak\", \"Please enter your pin number now.\");\n";
+ $tmp .= " digitmaxlength = 6;\n";
+ $tmp .= " session.execute(\"set\", \"playback_terminators=#\");\n";
+ $tmp .= " session.streamFile( \"/usr/local/freeswitch/recordings/please_enter_your_pin_number.wav\", mycb, \"dtmf\");\n";
+ $tmp .= " session.collectInput( mycb, dtmf, timeoutpin );\n";
+ $tmp .= " }\n";
+ $tmp .= "\n";
+ $tmp .= " if (dtmf.digits == pin || pin.length == 0) {\n";
+ //$tmp .= " //console_log( \"info\", \"Recordings pin is correct\\n\" );\n";
+ //$tmp .= " session.execute(\"set\", \"tts_engine=flite\");\n";
+ //$tmp .= " session.execute(\"set\", \"tts_voice=kal\");\n";
+ //$tmp .= " session.execute(\"speak\", \"Begin recording.\");\n";
+ $tmp .= " session.streamFile( \"/usr/local/freeswitch/recordings/begin_recording.wav\", mycb, \"dtmf\");\n";
+ $tmp .= " session.execute(\"set\", \"playback_terminators=#\");\n";
+ $tmp .= " session.execute(\"record\", \"/usr/local/freeswitch/recordings/temp\"+Year+Month+Day+Hours+Mins+Seconds+\".wav 180 200\");\n";
+ $tmp .= " }\n";
+ $tmp .= " else {\n";
+ $tmp .= " console_log( \"info\", \"Pin: \" + dtmf.digits + \" is incorrect\\n\" );\n";
+ //$tmp .= " session.execute(\"set\", \"tts_engine=flite\");\n";
+ //$tmp .= " session.execute(\"set\", \"tts_voice=kal\");\n";
+ //$tmp .= " session.execute(\"speak\", \"Your pin number is incorect, goodbye.\");\n";
+ $tmp .= " session.streamFile( \"/usr/local/freeswitch/recordings/your_pin_number_is_incorect_goodbye.wav\", mycb, \"dtmf\");\n";
+ $tmp .= " }\n";
+ $tmp .= " session.hangup();\n";
+ $tmp .= "\n";
+ $tmp .= " }";
+ fwrite($fout, $tmp);
+ unset($tmp);
+ fclose($fout);
+
+}
+
+
+function sync_package_freeswitch_settings()
+{
+
+ global $config;
+ if($config['installedpackages']['freeswitchsettings']['config'] != "") {
+
+ conf_mount_rw();
+ config_unlock();
+
+ foreach($config['installedpackages']['freeswitchsettings']['config'] as $rowhelper) {
+
+ $fout = fopen("/usr/local/freeswitch/conf/directory/default/default.xml","w");
+ $tmpxml = "<include>\n";
+ $tmpxml .= " <user id=\"default\"> <!--if id is numeric mailbox param is not necessary-->\n";
+ $tmpxml .= " <variables>\n";
+ $tmpxml .= " <!--all variables here will be set on all inbound calls that originate from this user -->\n";
+ $tmpxml .= " <!-- set these to take advantage of a dialplan localized to this user -->\n";
+ $tmpxml .= " <variable name=\"numbering_plan\" value=\"" . $rowhelper['numbering_plan'] . "\"/>\n";
+ $tmpxml .= " <variable name=\"default_gateway\" value=\"" . $rowhelper['default_gateway'] . "\"/>\n";
+ $tmpxml .= " <variable name=\"default_area_code\" value=\"" . $rowhelper['default_area_code'] . "\"/>\n";
+ $tmpxml .= " </variables>\n";
+ $tmpxml .= " </user>\n";
+ $tmpxml .= "</include>\n";
+ fwrite($fout, $tmpxml);
+ unset($tmpxml);
+ fclose($fout);
+
+ $fout = fopen("/usr/local/freeswitch/conf/autoload_configs/event_socket.conf.xml","w");
+ $tmpxml = "<configuration name=\"event_socket.conf\" description=\"Socket Client\">\n";
+ $tmpxml .= " <settings>\n";
+ $tmpxml .= " <param name=\"listen-ip\" value=\"0.0.0.0\"/>\n";
+ $tmpxml .= " <param name=\"listen-port\" value=\"" . $rowhelper['event_socket_port'] . "\"/>\n";
+ $tmpxml .= " <param name=\"password\" value=\"" . $rowhelper['event_socket_password'] . "\"/>\n";
+ $tmpxml .= " <!--<param name=\"apply-inbound-acl\" value=\"lan\"/>-->\n";
+ $tmpxml .= " </settings>\n";
+ $tmpxml .= "</configuration>";
+ fwrite($fout, $tmpxml);
+ unset($tmpxml, $event_socket_password);
+ fclose($fout);
+
+ $fout = fopen("/usr/local/freeswitch/conf/autoload_configs/xml_rpc.conf","w");
+ $tmpxml = "<configuration name=\"xml_rpc.conf\" description=\"XML RPC\">\n";
+ $tmpxml .= " <settings>\n";
+ $tmpxml .= " <!-- The port where you want to run the http service (default 8080) -->\n";
+ $tmpxml .= " <param name=\"http-port\" value=\"" . $rowhelper['xml_rpc_http_port'] . "\"/>\n";
+ $tmpxml .= " <!-- if all 3 of the following params exist all http traffic will require auth -->\n";
+ $tmpxml .= " <param name=\"auth-realm\" value=\"" . $rowhelper['xml_rpc_auth_realm'] . "\"/>\n";
+ $tmpxml .= " <param name=\"auth-user\" value=\"" . $rowhelper['xml_rpc_auth_user'] . "\"/>\n";
+ $tmpxml .= " <param name=\"auth-pass\" value=\"" . $rowhelper['xml_rpc_auth_pass'] . "\"/>\n";
+ $tmpxml .= " </settings>\n";
+ $tmpxml .= "</configuration>\n";
+ fwrite($fout, $tmpxml);
+ unset($tmpxml, $event_socket_password);
+ fclose($fout);
+
+ recording_js();
+
+ }
+
+ conf_mount_ro();
+ $cmd = "api reloadxml";
+ //event_socket_request_cmd($cmd);
+ unset($cmd);
+ }
+}
+
+
+function sync_package_freeswitch_dialplan()
+{
+
+ global $config;
+ conf_mount_rw();
+ config_unlock();
+
+ if(strlen($config['installedpackages']['freeswitchdialplan']['config'][0]['dialplan_default_xml']) == 0) {
+ /* dialplan not found in the pfsense config.xml get the default dialplan and save to config.xml. */
+ $filename = "/usr/local/freeswitch/conf/dialplan/default.xml";
+ $fout = fopen($filename,"r");
+ $tmpxml = fread($fout, filesize($filename));
+ $config['installedpackages']['freeswitchdialplan']['config'][0]['dialplan_default_xml'] = base64_encode($tmpxml);
+ unset($filename, $dialplan);
+ fclose($fout);
+ }
+ else {
+ /* found the dialplan in the pfsense config.xml save it to default.xml. */
+ $fout = fopen("/usr/local/freeswitch/conf/dialplan/default.xml","w");
+ $tmpxml = $config['installedpackages']['freeswitchdialplan']['config'][0]['dialplan_default_xml'];
+ fwrite($fout, base64_decode($tmpxml));
+ fclose($fout);
+ unset($tmpxml);
+ }
+
+ conf_mount_ro();
+ $cmd = "api reloadxml";
+ //event_socket_request_cmd($cmd);
+ unset($cmd);
+
+}
+
+
+function sync_package_freeswitch_extensions()
+{
+
+ global $config;
+ if($config['installedpackages']['freeswitchextensions']['config'] != "") {
+
+ conf_mount_rw();
+ config_unlock();
+
+ /* delete all old extensions to prepare for new ones */
+ unlink_if_exists("/usr/local/freeswitch/conf/directory/default/1*.xml");
+ unlink_if_exists("/usr/local/freeswitch/conf/directory/default/2*.xml");
+ unlink_if_exists("/usr/local/freeswitch/conf/directory/default/3*.xml");
+ unlink_if_exists("/usr/local/freeswitch/conf/directory/default/4*.xml");
+ unlink_if_exists("/usr/local/freeswitch/conf/directory/default/5*.xml");
+ unlink_if_exists("/usr/local/freeswitch/conf/directory/default/6*.xml");
+ unlink_if_exists("/usr/local/freeswitch/conf/directory/default/7*.xml");
+ unlink_if_exists("/usr/local/freeswitch/conf/directory/default/8*.xml");
+ unlink_if_exists("/usr/local/freeswitch/conf/directory/default/9*.xml");
+
+ foreach($config['installedpackages']['freeswitchextensions']['config'] as $rowhelper) {
+
+ $fout = fopen("/usr/local/freeswitch/conf/directory/default/".$rowhelper['extension'].".xml","w");
+
+ $tmpxml = "<include>\n";
+ if (strlen($rowhelper['cidr']) == 0) {
+ $tmpxml .= " <user id=\"" . $rowhelper['extension'] . "\" mailbox=\"" . $rowhelper['mailbox'] . "\">\n";
+ }
+ else {
+ $tmpxml .= " <user id=\"" . $rowhelper['extension'] . "\" mailbox=\"" . $rowhelper['mailbox'] . "\" cidr=\"" . $rowhelper['cidr'] . "\">\n";
+ }
+ $tmpxml .= " <params>\n";
+ $tmpxml .= " <param name=\"password\" value=\"" . $rowhelper['password'] . "\"/>\n";
+ $tmpxml .= " <param name=\"vm-password\" value=\"" . $rowhelper['vm-password'] . "\"/>\n";
+ if (strlen($rowhelper['vm-mailto']) > 0) {
+ $tmpxml .= " <param name=\"vm-email-all-messages\" value=\"true\"/>\n";
+
+ switch ($rowhelper['vm-attach-file']) {
+ case "true":
+ $tmpxml .= " <param name=\"vm-attach-file\" value=\"true\"/>\n";
+ break;
+ case "false":
+ $tmpxml .= " <param name=\"vm-attach-file\" value=\"false\"/>\n";
+ break;
+ default:
+ $tmpxml .= " <param name=\"vm-attach-file\" value=\"true\"/>\n";
+ }
+
+ $tmpxml .= " <param name=\"vm-mailto\" value=\"" . $rowhelper['vm-mailto'] . "\"/>\n";
+ }
+ if (strlen($rowhelper['auth-acl']) > 0) {
+ $tmpxml .= " <param name=\"auth-acl\" value=\"" . $rowhelper['auth-acl'] . "\"/>\n";
+ }
+ $tmpxml .= " </params>\n";
+ $tmpxml .= " <variables>\n";
+ $tmpxml .= " <variable name=\"toll_allow\" value=\"domestic,international,local\"/>\n";
+ $tmpxml .= " <variable name=\"accountcode\" value=\"" . $rowhelper['accountcode'] . "\"/>\n";
+ $tmpxml .= " <variable name=\"user_context\" value=\"" . $rowhelper['user_context'] . "\"/>\n";
+ if (strlen($rowhelper['effective_caller_id_number']) > 0) {
+ $tmpxml .= " <variable name=\"effective_caller_id_name\" value=\"" . $rowhelper['effective_caller_id_name'] . "\"/>\n";
+ $tmpxml .= " <variable name=\"effective_caller_id_number\" value=\"" . $rowhelper['effective_caller_id_number'] . "\"/>\n";
+ }
+ if (strlen($rowhelper['outbound_caller_id_number']) > 0) {
+ $tmpxml .= " <variable name=\"outbound_caller_id_name\" value=\"" . $rowhelper['outbound_caller_id_name'] . "\"/>\n";
+ $tmpxml .= " <variable name=\"outbound_caller_id_number\" value=\"" . $rowhelper['outbound_caller_id_number'] . "\"/>\n";
+ }
+ $tmpxml .= " </variables>\n";
+ $tmpxml .= " </user>\n";
+ $tmpxml .= "</include>\n";
+ fwrite($fout, $tmpxml);
+ unset($tmpxml);
+ fclose($fout);
+ }
+
+ conf_mount_ro();
+ $cmd = "api reloadxml";
+ //event_socket_request_cmd($cmd);
+ unset($cmd);
+
+ }
+}
+
+
+function sync_package_freeswitch_gateways()
+{
+
+ global $config;
+ if($config['installedpackages']['freeswitchgateways']['config'] != "") {
+
+ conf_mount_rw();
+ config_unlock();
+
+ /* delete all old gateways to prepare for new ones */
+ unlink_if_exists("/usr/local/freeswitch/conf/sip_profiles/external/*.xml");
+
+ foreach($config['installedpackages']['freeswitchgateways']['config'] as $rowhelper) {
+
+ if ($rowhelper['enabled'] != "false") {
+ $fout = fopen("/usr/local/freeswitch/conf/sip_profiles/external/".$rowhelper['gateway'].".xml","w");
+
+ $tmpxml .= "<include>\n";
+ $tmpxml .= " <gateway name=\"" . $rowhelper['gateway'] . "\">\n";
+ if (strlen($rowhelper['username']) > 0) {
+ $tmpxml .= " <param name=\"username\" value=\"" . $rowhelper['username'] . "\"/>\n";
+ }
+ if (strlen($rowhelper['password']) > 0) {
+ $tmpxml .= " <param name=\"password\" value=\"" . $rowhelper['password'] . "\"/>\n";
+ }
+ if (strlen($rowhelper['realm']) > 0) {
+ $tmpxml .= " <param name=\"realm\" value=\"" . $rowhelper['realm'] . "\"/>\n";
+ }
+ if (strlen($rowhelper['from-user']) > 0) {
+ $tmpxml .= " <param name=\"from-user\" value=\"" . $rowhelper['from-user'] . "\"/>\n";
+ }
+ if (strlen($rowhelper['from-domain']) > 0) {
+ $tmpxml .= " <param name=\"from-domain\" value=\"" . $rowhelper['from-domain'] . "\"/>\n";
+ }
+ if (strlen($rowhelper['proxy']) > 0) {
+ $tmpxml .= " <param name=\"proxy\" value=\"" . $rowhelper['proxy'] . "\"/>\n";
+ }
+ if (strlen($rowhelper['expire-seconds']) > 0) {
+ $tmpxml .= " <param name=\"expire-seconds\" value=\"" . $rowhelper['expire-seconds'] . "\"/>\n";
+ }
+ if (strlen($rowhelper['register']) > 0) {
+ $tmpxml .= " <param name=\"register\" value=\"" . $rowhelper['register'] . "\"/>\n";
+ }
+ if (strlen($rowhelper['register-transport']) > 0) {
+ $tmpxml .= " <param name=\"register-transport\" value=\"" . $rowhelper['register-transport'] . "\"/>\n";
+ }
+ if (strlen($rowhelper['retry-seconds']) > 0) {
+ $tmpxml .= " <param name=\"retry-seconds\" value=\"" . $rowhelper['retry-seconds'] . "\"/>\n";
+ }
+ if (strlen($rowhelper['extension']) > 0) {
+ $tmpxml .= " <param name=\"extension\" value=\"" . $rowhelper['extension'] . "\"/>\n";
+ }
+ if (strlen($rowhelper['context']) > 0) {
+ $tmpxml .= " <param name=\"context\" value=\"" . $rowhelper['context'] . "\"/>\n";
+ }
+ if (strlen($rowhelper['caller-id-in-from']) > 0) {
+ $tmpxml .= " <param name=\"context\" value=\"" . $rowhelper['context'] . "\"/>\n";
+ }
+ if (strlen($rowhelper['supress-cng']) > 0) {
+ $tmpxml .= " <param name=\"context\" value=\"" . $rowhelper['context'] . "\"/>\n";
+ }
+
+ $tmpxml .= " </gateway>\n";
+ $tmpxml .= "</include>";
+
+ fwrite($fout, $tmpxml);
+ unset($tmpxml);
+ fclose($fout);
+ }
+
+ }
+
+ conf_mount_ro();
+ $cmd = "api sofia profile external restart reloadxml";
+ //event_socket_request_cmd($cmd);
+ unset($cmd);
+
+ }
+
+}
+
+
+function sync_package_freeswitch_modules()
+{
+
+ global $config;
+ conf_mount_rw();
+ config_unlock();
+
+ foreach($config['installedpackages']['freeswitchmodules']['config'] as $rowhelper) {
+ $fout = fopen("/usr/local/freeswitch/conf/autoload_configs/modules.conf.xml","w");
+
+ $tmpxml ="";
+ $tmpxml .= "<configuration name=\"modules.conf\" description=\"Modules\">\n";
+ $tmpxml .= " <modules>\n";
+ $tmpxml .= "\n";
+ $tmpxml .= " <!-- Loggers (I'd load these first) -->\n";
+ if ($rowhelper['mod_console'] == "enable"){ $tmpxml .= " <load module=\"mod_console\"/>\n"; }
+ if ($rowhelper['mod_logfile'] == "enable"){ $tmpxml .= " <load module=\"mod_logfile\"/>\n"; }
+ if ($rowhelper['mod_syslog'] == "enable"){ $tmpxml .= " <load module=\"mod_syslog\"/>\n"; }
+ $tmpxml .= "\n";
+ if ($rowhelper['mod_yaml'] == "enable"){ $tmpxml .= " <load module=\"mod_yaml\"/>\n"; }
+ $tmpxml .= "\n";
+ $tmpxml .= " <!-- Multi-Faceted -->\n";
+ $tmpxml .= " <!-- mod_enum is a dialplan interface, an application interface and an api command interface -->\n";
+ if ($rowhelper['mod_enum'] == "enable"){ $tmpxml .= " <load module=\"mod_enum\"/>\n"; }
+ $tmpxml .= "\n";
+ $tmpxml .= " <!-- XML Interfaces -->\n";
+ if ($rowhelper['mod_xml_rpc'] == "enable"){ $tmpxml .= " <load module=\"mod_xml_rpc\"/>\n"; }
+ if ($rowhelper['mod_xml_curl'] == "enable"){ $tmpxml .= " <load module=\"mod_xml_curl\"/>\n"; }
+ if ($rowhelper['mod_xml_cdr'] == "enable"){ $tmpxml .= " <load module=\"mod_xml_cdr\"/>\n"; }
+ $tmpxml .= "\n";
+ $tmpxml .= " <!-- Event Handlers -->\n";
+ if ($rowhelper['mod_cdr_csv'] == "enable"){ $tmpxml .= " <load module=\"mod_cdr_csv\"/>\n"; }
+ if ($rowhelper['mod_event_multicast'] == "enable"){ $tmpxml .= " <load module=\"mod_event_multicast\"/>\n"; }
+ if ($rowhelper['mod_event_socket'] == "enable"){ $tmpxml .= " <load module=\"mod_event_socket\"/>\n"; }
+ if ($rowhelper['mod_zeroconf'] == "enable"){ $tmpxml .= " <load module=\"mod_zeroconf\"/>\n"; }
+ $tmpxml .= "\n";
+ $tmpxml .= " <!-- Directory Interfaces -->\n";
+ if ($rowhelper['mod_ldap'] == "enable"){ $tmpxml .= " <load module=\"mod_ldap\"/>\n"; }
+ $tmpxml .= "\n";
+ $tmpxml .= " <!-- Endpoints -->\n";
+ if ($rowhelper['mod_dingaling'] == "enable"){ $tmpxml .= " <load module=\"mod_dingaling\"/>\n"; }
+ if ($rowhelper['mod_iax'] == "enable"){ $tmpxml .= " <load module=\"mod_iax\"/>\n"; }
+ if ($rowhelper['mod_portaudio'] == "enable"){ $tmpxml .= " <load module=\"mod_portaudio\"/>\n"; }
+ if ($rowhelper['mod_alsa'] == "enable"){ $tmpxml .= " <load module=\"mod_alsa\"/>\n"; }
+ if ($rowhelper['mod_sofia'] == "enable"){ $tmpxml .= " <load module=\"mod_sofia\"/>\n"; }
+ if ($rowhelper['mod_loopback'] == "enable"){ $tmpxml .= " <load module=\"mod_loopback\"/>\n"; }
+ if ($rowhelper['mod_wanpipe'] == "enable"){ $tmpxml .= " <load module=\"mod_wanpipe\"/>\n"; }
+ if ($rowhelper['mod_woomera'] == "enable"){ $tmpxml .= " <load module=\"mod_woomera\"/>\n"; }
+ if ($rowhelper['mod_openzap'] == "enable"){ $tmpxml .= " <load module=\"mod_openzap\"/>\n"; }
+ $tmpxml .= "\n";
+ $tmpxml .= " <!-- Applications -->\n";
+ if ($rowhelper['mod_commands'] == "enable"){ $tmpxml .= " <load module=\"mod_commands\"/>\n"; }
+ if ($rowhelper['mod_conference'] == "enable"){ $tmpxml .= " <load module=\"mod_conference\"/>\n"; }
+ if ($rowhelper['mod_dptools'] == "enable"){ $tmpxml .= " <load module=\"mod_dptools\"/>\n"; }
+ if ($rowhelper['mod_expr'] == "enable"){ $tmpxml .= " <load module=\"mod_expr\"/>\n"; }
+ if ($rowhelper['mod_fax'] == "enable"){ $tmpxml .= " <load module=\"mod_fax\"/>\n"; }
+ if ($rowhelper['mod_fifo'] == "enable"){ $tmpxml .= " <load module=\"mod_fifo\"/>\n"; }
+ if ($rowhelper['mod_voicemail'] == "enable"){ $tmpxml .= " <load module=\"mod_voicemail\"/>\n"; }
+ if ($rowhelper['mod_limit'] == "enable"){ $tmpxml .= " <load module=\"mod_limit\"/>\n"; }
+ if ($rowhelper['mod_esf'] == "enable"){ $tmpxml .= " <load module=\"mod_esf\"/>\n"; }
+ if ($rowhelper['mod_fsv'] == "enable"){ $tmpxml .= " <load module=\"mod_fsv\"/>\n"; }
+ $tmpxml .= "\n";
+ $tmpxml .= " <!-- SNOM Module -->\n";
+ if ($rowhelper['mod_snom'] == "enable"){ $tmpxml .= " <load module=\"mod_snom\"/>\n"; }
+ $tmpxml .= "\n";
+ $tmpxml .= " <!-- Dialplan Interfaces -->\n";
+ if ($rowhelper['mod_dialplan_directory'] == "enable"){ $tmpxml .= " <load module=\"mod_dialplan_directory\"/>\n"; }
+ if ($rowhelper['mod_dialplan_xml'] == "enable"){ $tmpxml .= " <load module=\"mod_dialplan_xml\"/>\n"; }
+ if ($rowhelper['mod_dialplan_asterisk'] == "enable"){ $tmpxml .= " <load module=\"mod_dialplan_asterisk\"/>\n"; }
+ $tmpxml .= "\n";
+ $tmpxml .= " <!-- Codec Interfaces -->\n";
+ if ($rowhelper['mod_voipcodecs'] == "enable"){ $tmpxml .= " <load module=\"mod_voipcodecs\"/>\n"; }
+ if ($rowhelper['mod_g723_1'] == "enable"){ $tmpxml .= " <load module=\"mod_g723_1\"/>\n"; }
+ if ($rowhelper['mod_g729'] == "enable"){ $tmpxml .= " <load module=\"mod_g729\"/>\n"; }
+ if ($rowhelper['mod_amr'] == "enable"){ $tmpxml .= " <load module=\"mod_amr\"/>\n"; }
+ if ($rowhelper['mod_ilbc'] == "enable"){ $tmpxml .= " <load module=\"mod_ilbc\"/>\n"; }
+ if ($rowhelper['mod_speex'] == "enable"){ $tmpxml .= " <load module=\"mod_speex\"/>\n"; }
+ if ($rowhelper['mod_siren'] == "enable"){ $tmpxml .= " <load module=\"mod_siren\"/>\n"; }
+ if ($rowhelper['mod_celt'] == "enable"){ $tmpxml .= " <load module=\"mod_celt\"/>\n"; }
+ if ($rowhelper['mod_h26x'] == "enable"){ $tmpxml .= " <load module=\"mod_h26x\"/>\n"; }
+ $tmpxml .= "\n";
+ $tmpxml .= " <!-- File Format Interfaces -->\n";
+ if ($rowhelper['mod_sndfile'] == "enable"){ $tmpxml .= " <load module=\"mod_sndfile\"/>\n"; }
+ if ($rowhelper['mod_native_file'] == "enable"){ $tmpxml .= " <load module=\"mod_native_file\"/>\n"; }
+ $tmpxml .= " <!--For icecast/mp3 streams/files-->\n";
+ if ($rowhelper['mod_shout'] == "enable"){ $tmpxml .= " <load module=\"mod_shout\"/>\n"; }
+ $tmpxml .= " <!--For local streams (play all the files in a directory)-->\n";
+ if ($rowhelper['mod_local_stream'] == "enable"){ $tmpxml .= " <load module=\"mod_local_stream\"/>\n"; }
+ if ($rowhelper['mod_tone_stream'] == "enable"){ $tmpxml .= " <load module=\"mod_tone_stream\"/>\n"; }
+ $tmpxml .= "\n";
+ $tmpxml .= " <!-- Timers -->\n";
+ $tmpxml .= "\n";
+ $tmpxml .= " <!-- Languages -->\n";
+ if ($rowhelper['mod_spidermonkey'] == "enable"){ $tmpxml .= " <load module=\"mod_spidermonkey\"/>\n"; }
+ if ($rowhelper['mod_perl'] == "enable"){ $tmpxml .= " <load module=\"mod_perl\"/>\n"; }
+ if ($rowhelper['mod_python'] == "enable"){ $tmpxml .= " <load module=\"mod_python\"/>\n"; }
+ if ($rowhelper['mod_java'] == "enable"){ $tmpxml .= " <load module=\"mod_java\"/>\n"; }
+ if ($rowhelper['mod_lua'] == "enable"){ $tmpxml .= " <load module=\"mod_lua\"/>\n"; }
+ $tmpxml .= "\n";
+ $tmpxml .= " <!-- ASR /TTS -->\n";
+ if ($rowhelper['mod_flite'] == "enable"){ $tmpxml .= " <load module=\"mod_flite\"/>\n"; }
+ if ($rowhelper['mod_pocketsphinx'] == "enable"){ $tmpxml .= " <load module=\"mod_pocketsphinx\"/>\n"; }
+ if ($rowhelper['mod_cepstral'] == "enable"){ $tmpxml .= " <load module=\"mod_cepstral\"/>\n"; }
+ if ($rowhelper['mod_openmrcp'] == "enable"){ $tmpxml .= " <load module=\"mod_openmrcp\"/>\n"; }
+ if ($rowhelper['mod_rss'] == "enable"){ $tmpxml .= " <load module=\"mod_rss\"/>\n"; }
+ $tmpxml .= "\n";
+ $tmpxml .= " <!-- Say -->\n";
+ if ($rowhelper['mod_say_en'] == "enable"){ $tmpxml .= " <load module=\"mod_say_en\"/>\n"; }
+ if ($rowhelper['mod_say_zh'] == "enable"){ $tmpxml .= " <load module=\"mod_say_zh\"/>\n"; }
+ $tmpxml .= " </modules>\n";
+ $tmpxml .= "</configuration>";
+
+ fwrite($fout, $tmpxml);
+ unset($tmpxml);
+ fclose($fout);
+ }
+
+ conf_mount_ro();
+ $cmd = "api reloadxml";
+ //event_socket_request_cmd($cmd);
+ unset($cmd);
+
+}
+
+
+function sync_package_freeswitch_public()
+{
+
+ global $config;
+ conf_mount_rw();
+ config_unlock();
+
+ if(strlen($config['installedpackages']['freeswitchpublic']['config'][0]['public_xml']) == 0) {
+ /* dialplan_public_xml not found in the pfsense config.xml get the default public.xml and save to config.xml. */
+ $filename = "/usr/local/freeswitch/conf/dialplan/public.xml";
+ $fout = fopen($filename,"r");
+ $tmpxml = fread($fout, filesize($filename));
+ $tmpxml = str_replace("<anti-action application=\"export\" data=\"domain_name=\${sip_req_host}\"/>", "<!--<anti-action application=\"export\" data=\"domain_name=\${sip_req_host}\"/>-->", $tmpxml);
+ $config['installedpackages']['freeswitchpublic']['config'][0]['public_xml'] = base64_encode($tmpxml);
+ unset($filename, $tmpxml);
+ fclose($fout);
+ }
+ else {
+ /* found dialplan_public_xml in the pfsense config.xml save it to public.xml. */
+ $fout = fopen("/usr/local/freeswitch/conf/dialplan/public.xml","w");
+ $tmpxml = $config['installedpackages']['freeswitchpublic']['config'][0]['public_xml'];
+ fwrite($fout, base64_decode($tmpxml));
+ fclose($fout);
+ unset($tmpxml);
+ }
+
+ conf_mount_ro();
+ //$cmd = "api reloadxml";
+ //event_socket_request_cmd($cmd);
+ unset($cmd);
+
+}
+
+
+function sync_package_freeswitch_vars()
+{
+
+ global $config;
+ conf_mount_rw();
+ config_unlock();
+
+ if(strlen($config['installedpackages']['freeswitchvars']['config'][0]['vars_xml']) == 0) {
+ /* dialplan not found in the pfsense config.xml get the default dialplan and save to config.xml. */
+ $filename = "/usr/local/freeswitch/conf/vars.xml";
+ $fout = fopen($filename,"r");
+ $tmpxml = fread($fout, filesize($filename));
+ $config['installedpackages']['freeswitchvars']['config'][0]['vars_xml'] = base64_encode($tmpxml);
+ unset($filename, $dialplan);
+ fclose($fout);
+ }
+ else {
+ /* found the dialplan in the pfsense config.xml save it to default.xml. */
+ $fout = fopen("/usr/local/freeswitch/conf/vars.xml","w");
+ $tmpxml = $config['installedpackages']['freeswitchvars']['config'][0]['vars_xml'];
+ fwrite($fout, base64_decode($tmpxml));
+ fclose($fout);
+ unset($tmpxml);
+ }
+
+ conf_mount_ro();
+ $cmd = "api reloadxml";
+ //event_socket_request_cmd($cmd);
+ unset($cmd);
+
+}
+
+
+function sync_package_freeswitch_internal()
+{
+ global $config;
+ conf_mount_rw();
+ config_unlock();
+
+ if(strlen($config['installedpackages']['freeswitchinternal']['config'][0]['internal_xml']) == 0) {
+ /* internal_xml not found in the pfsense config.xml get the internal.xml and save to config.xml. */
+ $filename = "/usr/local/freeswitch/conf/sip_profiles/internal.xml";
+ $fout = fopen($filename,"r");
+ $tmpxml = fread($fout, filesize($filename));
+ $config['installedpackages']['freeswitchinternal']['config'][0]['internal_xml'] = base64_encode($tmpxml);
+ unset($filename, $dialplan);
+ fclose($fout);
+ }
+ else {
+ /* found the internal_xml in the pfsense config.xml save it to internal.xml. */
+ $fout = fopen("/usr/local/freeswitch/conf/sip_profiles/internal.xml","w");
+ $tmpxml = $config['installedpackages']['freeswitchinternal']['config'][0]['internal_xml'];
+ fwrite($fout, base64_decode($tmpxml));
+ fclose($fout);
+ unset($tmpxml);
+ }
+
+ conf_mount_ro();
+ $cmd = "api reloadxml";
+ //event_socket_request_cmd($cmd);
+ unset($cmd);
+
+}
+
+
+function sync_package_freeswitch_external()
+{
+ global $config;
+ conf_mount_rw();
+ config_unlock();
+
+ if(strlen($config['installedpackages']['freeswitchexternal']['config'][0]['external_xml']) == 0) {
+ /* external_xml not found in the pfsense config.xml get the external.xml and save to config.xml. */
+ $filename = "/usr/local/freeswitch/conf/sip_profiles/external.xml";
+ $fout = fopen($filename,"r");
+ $tmpxml = fread($fout, filesize($filename));
+ $config['installedpackages']['freeswitchexternal']['config'][0]['external_xml'] = base64_encode($tmpxml);
+ unset($filename, $dialplan);
+ fclose($fout);
+ }
+ else {
+ /* found the external_xml in the pfsense config.xml save it to external.xml. */
+ $fout = fopen("/usr/local/freeswitch/conf/sip_profiles/external.xml","w");
+ $tmpxml = $config['installedpackages']['freeswitchexternal']['config'][0]['external_xml'];
+ fwrite($fout, base64_decode($tmpxml));
+ fclose($fout);
+ unset($tmpxml);
+ }
+
+ conf_mount_ro();
+ $cmd = "api reloadxml";
+ //event_socket_request_cmd($cmd);
+ unset($cmd);
+
+}
+
+
+function get_recording_filename($id)
+{
+ global $config;
+ $a_recordings = &$config['installedpackages']['freeswitchrecordings']['config'];
+ if (count($a_recordings) > 0) {
+ global $config;
+ foreach($a_recordings as $rowhelper) {
+ if ($rowhelper['recordingid'] == $id) {
+ return $rowhelper['filename'];
+ }
+ }
+ }
+}
+
+
+function sync_package_freeswitch_ivr()
+{
+
+ global $config;
+ conf_mount_rw();
+ config_lock();
+
+ $a_ivr = &$config['installedpackages']['freeswitchivr']['config'];
+ if (count($a_ivr) > 0) {
+ foreach($a_ivr as $rowhelper) {
+
+ /*
+ $rowhelper['ivrid']
+ $rowhelper['ivrextension']
+ $rowhelper['ivrname']
+ $rowhelper['recordingid']
+ $rowhelper['ivrtimeout']
+ $rowhelper['ivrcontext']
+ $rowhelper['ivrconditionjs']
+ $rowhelper['ivrdescr']
+ */
+
+ $a_dialplan_includes = &$config['installedpackages']['freeswitchdialplanincludes']['config'];
+ $a_dialplan_include_details = &$config['installedpackages']['freeswitchdialplanincludedetails']['config'];
+
+
+ //add the IVR to the dialplan
+ if (strlen($rowhelper['ivrid']) > 0) {
+ $action = 'add'; //set default action to add
+ $i = 0;
+ if (count($a_dialplan_includes) > 0) {
+ foreach($a_dialplan_includes as $row) {
+
+ //$row['dialplanincludeid'];
+ //$row['extensionname'];
+ //$row['context'];
+ //$row['enabled'];
+ //echo "if (".$row['opt1name']." == \"ivrid\" && ".$row['opt1value']." == ".$rowhelper['ivrid'].") {\n";
+
+ if ($row['opt1name'] == "ivrid" && $row['opt1value'] == $rowhelper['ivrid']) {
+ //update
+ $action = 'update';
+ $dialplanincludeid = $row['dialplanincludeid'];
+ $extensionname = $row['extensionname'];
+ $order = $row['order'];
+ $context = $row['context'];
+ $enabled = $row['enabled'];
+ $descr = $row['descr'];
+ $opt1name = $row['opt1name'];
+ $opt1value = $row['opt1value'];
+ $id = $i;
+ //echo "update".$i."<br />\n";
+
+ }
+ $i++;
+
+ }
+ }
+
+
+ $ent = array();
+ if ($action == 'add') {
+
+ $dialplanincludeid = guid();
+ $ent['dialplanincludeid'] = $dialplanincludeid;
+ $ent['extensionname'] = $rowhelper['ivrextension'];
+ $ent['order'] = '9001'; //if update use the existing order number and extension name and desc
+ $ent['context'] = $rowhelper['ivrcontext'];
+ $ent['enabled'] = 'true';
+ $ent['descr'] = 'IVR';
+ $ent['opt1name'] = 'ivrid';
+ $ent['opt1value'] = $rowhelper['ivrid'];
+
+ //add to the config
+ $a_dialplan_includes[] = $ent;
+ unset($ent);
+
+ $ent = array();
+ $ent['dialplanincludeid'] = $dialplanincludeid;
+ $ent['tag'] = 'condition'; //condition, action, antiaction
+ $ent['fieldtype'] = 'destination_number';
+ $ent['fielddata'] = '^'.$rowhelper['ivrextension'].'$';
+ $a_dialplan_include_details[] = $ent;
+ unset($ent);
+
+ $ivrid = str_replace(array("{", "}"), "", $rowhelper['ivrid']);
+
+ $ent = array();
+ $ent['dialplanincludeid'] = $dialplanincludeid;
+ $ent['tag'] = 'action'; //condition, action, antiaction
+ $ent['fieldtype'] = 'javascript';
+ $ent['fielddata'] = 'ivr_'.$ivrid.'.js';
+ $a_dialplan_include_details[] = $ent;
+ unset($ent);
+
+ unset($ivrid);
+
+ }
+ if ($action == 'update') {
+
+ $ent['dialplanincludeid'] = $dialplanincludeid;
+ $ent['extensionname'] = $rowhelper['ivrextension'];
+ $ent['order'] = $order;
+ $ent['context'] = $context;
+ $ent['enabled'] = $enabled;
+ $ent['descr'] = $descr;
+ $ent['opt1name'] = $opt1name;
+ $ent['opt1value'] = $opt1value;
+
+ //update the config
+ $a_dialplan_includes[$id] = $ent;
+
+ unset($ent);
+ unset($extensionname);
+ unset($order);
+ unset($context);
+ unset($enabled);
+ unset($descr);
+ unset($opt1name);
+ unset($opt1value);
+ unset($id);
+ }
+ write_config();
+
+ sync_package_freeswitch_dialplan_includes();
+ unset($dialplanincludeid);
+
+ } //end if strlen ivrid; add the IVR to the dialplan
+
+ // Build the IVR javascript
+ $recording_action_filename = get_recording_filename($rowhelper['recordingidaction']);
+ $recording_antiaction_filename = get_recording_filename($rowhelper['recordingidantiaction']);
+
+ $password = $config['installedpackages']['freeswitchsettings']['config'][0]['event_socket_password'];
+ $port = $config['installedpackages']['freeswitchsettings']['config'][0]['event_socket_port'];
+ $host = $config['interfaces']['lan']['ipaddr'];
+
+ if (pkg_is_service_running('freeswitch')) {
+ $fp = event_socket_create($host, $port, $password);
+ $cmd = "api global_getvar domain";
+ $domain = trim(event_socket_request($fp, $cmd));
+ }
+
+
+ $tmp = ""; //make sure the variable starts with no value
+ $tmp .= "\n";
+ $tmp .= " var condition = true;\n";
+ $tmp .= "\n";
+ $tmp .= " var domain = \"".$domain."\"; //by default this is the ipv4 address of FreeSWITCH used for transfer to voicemail\n";
+ $tmp .= " var digitmaxlength = 0;\n";
+ $tmp .= " var objdate = new Date();\n";
+ $tmp .= "\n";
+ $tmp .= " var adjusthours = 0; //Adjust Server time that is set to GMT 7 hours\n";
+ $tmp .= " var adjustoperator = \"-\"; //+ or -\n";
+ $tmp .= "\n";
+ $tmp .= " if (adjustoperator == \"-\") {\n";
+ $tmp .= " var objdate2 = new Date(objdate.getFullYear(),objdate.getMonth(),objdate.getDate(),(objdate.getHours() - adjusthours),objdate.getMinutes(),objdate.getSeconds());\n";
+ $tmp .= " }\n";
+ $tmp .= " if (adjustoperator == \"+\") {\n";
+ $tmp .= " var objdate2 = new Date(objdate.getFullYear(),objdate.getMonth(),objdate.getDate(),(objdate.getHours() + adjusthours),objdate.getMinutes(),objdate.getSeconds());\n";
+ $tmp .= " }\n";
+ $tmp .= "\n";
+ $tmp .= " var Hours = objdate2.getHours();\n";
+ $tmp .= " var Mins = objdate2.getMinutes();\n";
+ $tmp .= " var Seconds = objdate2.getSeconds();\n";
+ $tmp .= " var Month = objdate2.getMonth() + 1;\n";
+ $tmp .= " var Date = objdate2.getDate();\n";
+ $tmp .= " var Year = objdate2.getYear()\n";
+ $tmp .= " var Day = objdate2.getDay()+1;\n";
+ $tmp .= " var exit = false;\n";
+ $tmp .= "\n";
+ $tmp .= "//console_log( \"info\", \"IVR Server Time is: \"+Hours+\":\"+Mins+\" \\n\" );\n";
+ $tmp .= "\n";
+ $tmp .= " function mycb( session, type, obj, arg ) {\n";
+ $tmp .= " try {\n";
+ $tmp .= " if ( type == \"dtmf\" ) {\n";
+ $tmp .= " console_log( \"info\", \"digit: \"+obj.digit+\"\\n\" );\n";
+ $tmp .= " if ( obj.digit == \"#\" ) {\n";
+ $tmp .= " //console_log( \"info\", \"detected pound sign.\\n\" );\n";
+ $tmp .= " exit = true;\n";
+ $tmp .= " return( false );\n";
+ $tmp .= " }\n";
+ $tmp .= "\n";
+ $tmp .= " dtmf.digits += obj.digit;\n";
+ $tmp .= "\n";
+ $tmp .= " if ( dtmf.digits.length >= digitmaxlength ) {\n";
+ $tmp .= " exit = true;\n";
+ $tmp .= " return( false );\n";
+ $tmp .= " }\n";
+ $tmp .= " }\n";
+ $tmp .= " } catch (e) {\n";
+ $tmp .= " console_log( \"err\", e+\"\\n\" );\n";
+ $tmp .= " }\n";
+ $tmp .= " return( true );\n";
+ $tmp .= " } //end function mycb\n";
+
+ $tmp .= "\n";
+ $tmp .= base64_decode($rowhelper['ivrconditionjs']);
+ $tmp .= "\n";
+ $tmp .= "\n";
+
+ //$tmp .= " //condition = true; //debugging\n";
+
+ $actiondirect = false;
+ $actioncount = 0;
+ foreach($config['installedpackages']['freeswitchivroptions']['config'] as $row) {
+ //find the correct IVR options with the correct action
+ if ($row['ivrid'] == $rowhelper['ivrid']) {
+ if ($row['optionaction'] == "action") {
+ $actioncount++;
+ if (strtolower($row['optionnumber']) == "n") { //direct the call now don't wait for dtmf
+ $actiondirect = true;
+ $actiondirecttype = $row['optiontype'];
+ $actiondirectdest = $row['optiondest'];
+ }
+ }
+ }
+ }
+ //$tmp .= "action count: ".$actioncount."<br />\n";
+ if ($actioncount > 0) {
+ if ($actiondirect) {
+
+ $tmp .= " if (condition) {\n";
+ $tmp .= " //direct\n";
+ $tmp .= " //console_log( \"info\", \"action direct\\n\" );\n";
+ if ($actiondirecttype == "extension") {
+ $tmp .= " session.execute(\"transfer\", \"".$actiondirectdest." XML default\"); //".$actiondirectdest."\n";
+ }
+ if ($actiondirecttype == "voicemail") {
+ //$tmp .= " session.execute(\"voicemail\", \"".$actiondirectdest." XML default\");\n";
+ $tmp .= " session.execute(\"voicemail\", \"default \"+domain+\" ".$actiondirectdest."\");\n";
+ }
+ $tmp .= "}\n";
+
+ }
+ else {
+ $tmp .= " if (condition) {\n";
+ $tmp .= " //action\n";
+ $tmp .= "\n";
+ $tmp .= " //console_log( \"info\", \"action call now don't wait for dtmf\\n\" );\n";
+ $tmp .= " var dtmf = new Object( );\n";
+ $tmp .= " dtmf.digits = \"\";\n";
+ $tmp .= " if ( session.ready( ) ) {\n";
+ $tmp .= " session.answer( );\n";
+ $tmp .= "\n";
+ $tmp .= " digitmaxlength = 1;\n";
+ $tmp .= " while (session.ready() && ! exit ) {\n";
+ $tmp .= " //session.streamFile( \"C:/Program Files/FreeSWITCH/sounds/".$recording_action_filename."\", mycb, \"dtmf ".$rowhelper['ivrtimeout']."\" );\n";
+ $tmp .= " session.streamFile( \"/usr/local/freeswitch/recordings/".$recording_action_filename."\", mycb, \"dtmf ".$rowhelper['ivrtimeout']."\" );\n";
+ $tmp .= " if (session.ready()) {\n";
+ $tmp .= " if (dtmf.digits == 0) {\n";
+ $tmp .= " dtmf.digits += session.getDigits(1, \"#\", ".($rowhelper['ivrtimeout']*1000)."); // ".$rowhelper['ivrtimeout']." seconds\n";
+ $tmp .= " if (dtmf.digits == 0) {\n";
+ //$tmp .= " console_log( "info", "time out option: " + dtmf.digits + "\n" );\n";
+
+ $a_ivr_options = &$config['installedpackages']['freeswitchivroptions']['config'];
+ //find the timeout IVR options with the correct action
+ if (count($a_ivr_options) > 0) {
+ foreach($a_ivr_options as $row) {
+
+ if ($row['ivrid'] == $rowhelper['ivrid']) {
+
+ if ($row['optionaction'] == "action") {
+ if (strtolower($row['optionnumber']) == "t") {
+ if ($row['optiontype'] == "extension") {
+ $tmp .= " session.execute(\"transfer\", \"".$row['optiondest']." XML default\"); //".$row['optiondescr']."\n";
+ }
+ if ($row['optiontype'] == "voicemail") {
+ //$tmp .= " session.execute(\"voicemail\", \"".$row['optiondest']." XML default\");\n";
+ $tmp .= " session.execute(\"voicemail\", \"default \"+domain+\" ".$row['optiondest']."\");\n";
+ }
+ }
+ } //end anti-action
+
+ } //end ivrid
+
+ } //end for each
+ } //if count
+
+
+ $tmp .= " }\n";
+ $tmp .= " else {\n";
+ $tmp .= " break; //dtmf found end the while loop\n";
+ $tmp .= " }\n";
+ $tmp .= " }\n";
+ $tmp .= " }\n";
+ $tmp .= " }\n";
+ $tmp .= "\n";
+ $tmp .= " //pickup the remaining digits\n";
+ //$tmp .= " //http://wiki.freeswitch.org/wiki/Session_getDigits\n";
+ //$tmp .= " //getDigits(length, terminators, timeout, digit_timeout, abs_timeout)\n";
+ //$tmp .= " //dtmf.digits += session.getDigits(2, \"#\", 3000); //allow up to 3 digits\n";
+ $tmp .= " dtmf.digits += session.getDigits(3, \"#\", 3000); //allow up to 4 digits\n";
+ $tmp .= "\n";
+ $tmp .= "\n";
+ //$tmp .= " console_log( \"info\", \"IVR Digit Pressed: \" + dtmf.digits + \"\\n\" );\n";
+
+
+ //action
+ $tmpaction = "";
+
+ $tmp .= " if ( dtmf.digits.length > \"0\" ) {\n";
+ $x = 0;
+ $a_ivr_options = &$config['installedpackages']['freeswitchivroptions']['config'];
+ if (count($a_ivr_options) > 0) {
+ foreach($a_ivr_options as $row) {
+
+ /*
+ $row['ivrid']
+ $row['optionnumber']
+ $row['optiontype']
+ $row['optionaction']
+ $row['optiondest']
+ $row['optiondescr']
+ */
+
+ $tmpactiondefault = "";
+
+ //find the correct IVR options with the correct action
+ if ($row['ivrid'] == $rowhelper['ivrid']){
+
+ if ($row['optionaction'] == "action") {
+ //$tmpaction .= "\n";
+
+ switch ($row['optionnumber']) {
+ //case "t":
+
+ //if ($row['optiontype'] == "extension") {
+ // $tmpactiondefault .= " session.execute(\"transfer\", \"".$row['optiondest']." XML default\"); //".$row['optiondescr']."\n";
+ //}
+ //if ($row['optiontype'] == "voicemail") {
+ // //$tmpactiondefault .= " session.execute(\"voicemail\", \"".$row['optiondest']." XML default\");\n";
+ // $tmpactiondefault .= " session.execute(\"voicemail\", \"default \"+domain+\" ".$row['optiondest']."\");\n";
+ //}
+
+ //break;
+ default:
+ //$tmpaction .= " //console_log( \"info\", \"IVR Detected 1 digit \\n\" );\n";
+ if ($x == 0) {
+ $tmpaction .= " if ( dtmf.digits == \"".$row['optionnumber']."\" ) { //".$row['optiondescr']."\n";
+ }
+ else {
+ $tmpaction .= " else if ( dtmf.digits == \"".$row['optionnumber']."\" ) { //".$row['optiondescr']."\n";
+ }
+ if ($row['optiontype'] == "extension") {
+ $tmpaction .= " session.execute(\"transfer\", \"".$row['optiondest']." XML default\");\n";
+ }
+ if ($row['optiontype'] == "voicemail") {
+ //$tmpaction .= " session.execute(\"voicemail\", \"".$row['optiondest']." XML default\");\n";
+ $tmpaction .= " session.execute(\"voicemail\", \"default \"+domain+\" ".$row['optiondest']."\");\n";
+ }
+ $tmpaction .= " }\n";
+
+
+ }
+
+ $x++;
+ } //end if action
+
+ } //end ivrid
+
+
+ } //end foreach
+ } //end if count
+
+ $tmp .= $tmpaction;
+ $tmp .= " else {\n";
+ $tmp .= " session.execute(\"transfer\", dtmf.digits+\" XML default\");\n";
+ //$tmp .= $tmpactiondefault;
+ $tmp .= " }\n";
+ $tmp .= "\n";
+ unset($tmpaction);
+
+
+ $tmp .= " } \n";
+ //$tmp .= " else if ( dtmf.digits.length == \"3\" ) {\n";
+ //$tmp .= " //Transfer to the extension the caller chose\n";
+ //$tmp .= " session.execute(\"transfer\", dtmf.digits+\" XML default\");\n";
+ //$tmp .= " } else {\n";
+ //$tmp .= $tmpactiondefault;
+ //$tmp .= " }\n";
+ $tmp .= "\n";
+ $tmp .= " } //end if session.ready\n";
+ $tmp .= "\n";
+ $tmp .= " }\n"; //end if condition
+
+ } //if ($actiondirect) {
+ } //actioncount
+
+ $antiactiondirect = false;
+ $antiactioncount = 0;
+ foreach($config['installedpackages']['freeswitchivroptions']['config'] as $row) {
+ //find the correct IVR options with the correct action
+ if ($row['ivrid'] == $rowhelper['ivrid']) {
+ if ($row['optionaction'] == "anti-action") {
+ $antiactioncount++;
+ if (strtolower($row['optionnumber']) == "n") { //direct the call now don't wait for dtmf
+ $antiactiondirect = true;
+ $antiactiondirecttype = $row['optiontype'];
+ $antiactiondirectdest = $row['optiondest'];
+ }
+ }
+ }
+ }
+ //$tmp .= "anti-action count: ".$antiactioncount."<br />\n";
+
+
+ if ($antiactioncount > 0) {
+ if ($antiactiondirect) {
+ $tmp .= " else {\n";
+ $tmp .= " //anti-action direct\n";
+ $tmp .= " //console_log( \"info\", \"anti-action call now don't wait for dtmf\\n\" );\n";
+ if ($antiactiondirecttype == "extension") {
+ $tmp .= " session.execute(\"transfer\", \"".$antiactiondirectdest." XML default\"); //".$antiactiondirectdest."\n";
+ }
+ if ($antiactiondirecttype == "voicemail") {
+ //$tmp .= " session.execute(\"voicemail\", \"".$antiactiondirectdest." XML default\");\n";
+ $tmp .= " session.execute(\"voicemail\", \"default \"+domain+\" ".$antiactiondirectdest."\");\n";
+ }
+ $tmp .= "}\n";
+ }
+ else {
+ $tmp .= " else {\n";
+ $tmp .= " //anti-action\n";
+ $tmp .= " //console_log( \"info\", \"anti-action options\\n\" );\n";
+ $tmp .= "\n";
+ $tmp .= " var dtmf = new Object( );\n";
+ $tmp .= " dtmf.digits = \"\";\n";
+ $tmp .= " if ( session.ready( ) ) {\n";
+ $tmp .= " session.answer( );\n";
+ $tmp .= "\n";
+ $tmp .= " digitmaxlength = 1;\n";
+ $tmp .= " while (session.ready() && ! exit ) {\n";
+ $tmp .= " session.streamFile( \"/usr/local/freeswitch/recordings/".$recording_antiaction_filename."\", mycb, \"dtmf ".$rowhelper['ivrtimeout']."\" );\n";
+ $tmp .= " if (session.ready()) {\n";
+ $tmp .= " if (dtmf.digits == 0) {\n";
+ $tmp .= " dtmf.digits += session.getDigits(1, \"#\", ".($rowhelper['ivrtimeout']*1000)."); // ".$rowhelper['ivrtimeout']." seconds\n";
+ $tmp .= " if (dtmf.digits == 0) {\n";
+ //$tmp .= " console_log( "info", "time out option: " + dtmf.digits + "\n" );\n";
+
+
+ //find the timeout IVR options with the correct action
+ if (count($a_ivr_options) > 0) {
+ foreach($a_ivr_options as $row) {
+
+ if ($row['ivrid'] == $rowhelper['ivrid']) {
+
+ if ($row['optionaction'] == "anti-action") {
+ if (strtolower($row['optionnumber']) == "t") {
+
+ if ($row['optiontype'] == "extension") {
+ $tmp .= " session.execute(\"transfer\", \"".$row['optiondest']." XML default\"); //".$row['optiondescr']."\n";
+ }
+ if ($row['optiontype'] == "voicemail") {
+ //$tmp .= " session.execute(\"voicemail\", \"".$row['optiondest']." XML default\");\n";
+ $tmp .= " session.execute(\"voicemail\", \"default \"+domain+\" ".$row['optiondest']."\");\n";
+ }
+ }
+
+ } //end anti-action
+
+ } //end ivrid
+
+ } //end for each
+ } //if count
+
+
+ $tmp .= " }\n";
+ $tmp .= " else {\n";
+ $tmp .= " break; //dtmf found end the while loop\n";
+ $tmp .= " }\n";
+
+ $tmp .= " }\n";
+ $tmp .= " }\n";
+ $tmp .= " }\n";
+ $tmp .= "\n";
+ $tmp .= " //pickup the remaining digits\n";
+ $tmp .= " //http://wiki.freeswitch.org/wiki/Session_getDigits\n";
+ $tmp .= " //getDigits(length, terminators, timeout, digit_timeout, abs_timeout)\n";
+ $tmp .= " dtmf.digits += session.getDigits(3, \"#\", 3000);\n";
+ $tmp .= "\n";
+ $tmp .= " console_log( \"info\", \"IVR Digit Pressed: \" + dtmf.digits + \"\\n\" );\n";
+ $tmp .= "\n";
+
+
+
+
+
+ $tmpantiaction = "";
+ $tmp .= " if ( dtmf.digits.length > \"0\" ) {\n";
+
+ $x = 0;
+ if (count($a_ivr_options) > 0) {
+ foreach($a_ivr_options as $row) {
+
+ /*
+ $row['ivrid']
+ $row['optionnumber']
+ $row['optiontype']
+ $row['optionaction']
+ $row['optiondest']
+ $row['optiondescr']
+ */
+ //$tmpantiactiondefault = "";
+
+ //find the correct IVR options with the correct action
+ if ($row['ivrid'] == $rowhelper['ivrid']) {
+
+ if ($row['optionaction'] == "anti-action") {
+
+ switch ($row['optionnumber']) {
+ //case "t":
+
+ //if ($row['optiontype'] == "extension") {
+ // $tmpantiactiondefault .= " session.execute(\"transfer\", \"".$row['optiondest']." XML default\"); //".$row['optiondescr']."\n";
+ //}
+ //if ($row['optiontype'] == "voicemail") {
+ // //$tmpantiactiondefault .= " session.execute(\"voicemail\", \"".$row['optiondest']." XML default\");\n";
+ // $tmpantiactiondefault .= " session.execute(\"voicemail\", \"default \"+domain+\" ".$row['optiondest']."\");\n";
+ //}
+
+ //break;
+ default:
+ //$tmpantiaction .= " //console_log( \"info\", \"IVR Detected 1 digit \\n\" );\n";
+
+ if ($x == 0) {
+ $tmpantiaction .= " if ( dtmf.digits == \"".$row['optionnumber']."\" ) { //".$row['optiondescr']."\n";
+ }
+ else {
+ $tmpantiaction .= " else if ( dtmf.digits == \"".$row['optionnumber']."\" ) { //".$row['optiondescr']."\n";
+ }
+
+ if ($row['optiontype'] == "extension") {
+ $tmpantiaction .= " session.execute(\"transfer\", \"".$row['optiondest']." XML default\");\n";
+ }
+ if ($row['optiontype'] == "voicemail") {
+ //$tmpantiaction .= " session.execute(\"voicemail\", \"".$row['optiondest']." XML default\");\n";
+ $tmpantiaction .= " session.execute(\"voicemail\", \"default \"+domain+\" ".$row['optiondest']."\");\n";
+ }
+ $tmpantiaction .= " }\n";
+
+
+ } //end switch
+
+ $x++;
+ } //end anti-action
+
+ } //end ivrid
+
+
+ } //end for each
+ } //if count
+
+ $tmp .= $tmpantiaction;
+ $tmp .= " else {\n";
+ $tmp .= " session.execute(\"transfer\", dtmf.digits+\" XML default\");\n";
+ //$tmp .= $tmpantiactiondefault;
+ $tmp .= " }\n";
+ $tmp .= "\n";
+ unset($tmpantiaction);
+
+ $tmp .= " } \n";
+ //$tmp .= " else if ( dtmf.digits.length == \"3\" ) {\n";
+ //$tmp .= " //Transfer to the extension the caller chose\n";
+ //$tmp .= " session.execute(\"transfer\", dtmf.digits+\" XML default\"); \n";
+ //$tmp .= " }\n";
+ //$tmp .= " else {\n";
+ //$tmp .= $tmpantiactiondefault;
+ //$tmp .= " }\n";
+ $tmp .= "\n";
+ $tmp .= " } //end if session.ready\n";
+ $tmp .= "\n";
+ $tmp .= " } //end if condition";
+
+ } //if ($antiactiondirect) {
+ } //antiactioncount
+ unset($tmpactiondefault);
+ unset($tmpantiactiondefault);
+
+ if (strlen($rowhelper['ivrid']) > 0) {
+ $ivrfilename = "ivr_".str_replace(array("{", "}"), "", $rowhelper['ivrid']).".js";
+ $fout = fopen("/usr/local/freeswitch/scripts/".$ivrfilename,"w");
+ fwrite($fout, $tmp);
+ unset($ivrfilename);
+ fclose($fout);
+ }
+
+ } //end foreach
+ } //end if count
+ conf_mount_ro();
+ config_unlock();
+
+} //end function
+
+
+
+function sync_package_freeswitch_dialplan_includes()
+{
+
+ global $config;
+ conf_mount_rw();
+ config_lock();
+
+ $a_dialplan_includes = &$config['installedpackages']['freeswitchdialplanincludes']['config'];
+ $a_dialplan_include_details = &$config['installedpackages']['freeswitchdialplanincludedetails']['config'];
+
+ if (count($a_dialplan_includes) > 0) {
+ foreach($config['installedpackages']['freeswitchdialplanincludes']['config'] as $rowhelper) {
+ $tmp = "";
+ $tmp .= "\n";
+
+ //$rowhelper['dialplanincludeid'];
+ //$rowhelper['extensionname'];
+ //$rowhelper['context'];
+ //$rowhelper['enabled'];
+
+ $tmp = "<extension name=\"".$rowhelper['extensionname']."\">\n";
+
+ if (count($a_dialplan_include_details) > 0) {
+
+ $conditioncount = 0;
+ $i = 0;
+ foreach ($a_dialplan_include_details as $ent) {
+ if ($ent['tag'] == "condition" && $rowhelper['dialplanincludeid'] == $ent['dialplanincludeid']) {
+ $conditioncount++;
+ $i++;
+ }
+ }
+
+ $i = 1;
+ foreach ($a_dialplan_include_details as $ent) {
+ if ($ent['tag'] == "condition" && $rowhelper['dialplanincludeid'] == $ent['dialplanincludeid']) {
+ if ($conditioncount == 1) { //single condition
+ //start tag
+ $tmp .= " <condition field=\"".$ent['fieldtype']."\" expression=\"".$ent['fielddata']."\">\n";
+ }
+ else { //more than one condition
+ if ($i < $conditioncount) {
+ //all tags should be self-closing except the last one
+ $tmp .= " <condition field=\"".$ent['fieldtype']."\" expression=\"".$ent['fielddata']."\"/>\n";
+ }
+ else {
+ //for the last tag use the start tag
+ $tmp .= " <condition field=\"".$ent['fieldtype']."\" expression=\"".$ent['fielddata']."\">\n";
+ }
+ }
+ $i++;
+ }
+ } //end for each
+
+ } //end if count
+
+ if (count($a_dialplan_include_details) > 0) {
+ $i = 0;
+ foreach ($a_dialplan_include_details as $ent) {
+ if ($ent['tag'] == "action" && $rowhelper['dialplanincludeid'] == $ent['dialplanincludeid']) {
+ $tmp .= " <action application=\"".$ent['fieldtype']."\" data=\"".$ent['fielddata']."\"/>\n";
+ }
+ $i++;
+ }
+ }
+
+ if (count($a_dialplan_include_details) > 0) {
+ $i = 0;
+ foreach ($a_dialplan_include_details as $ent) {
+ if ($ent['tag'] == "anti-action" && $rowhelper['dialplanincludeid'] == $ent['dialplanincludeid']) {
+ $tmp .= " <anti-action application=\"".$ent['fieldtype']."\" data=\"".$ent['fielddata']."\"/>\n";
+ }
+ $i++;
+ }
+ }
+
+ //if (count($a_dialplan_include_details) > 0) {
+ //foreach ($a_dialplan_include_details as $ent) {
+ // $i = 0;
+ // if ($ent['tag'] == "param" && $rowhelper['dialplanincludeid'] == $ent['dialplanincludeid']) {
+ //$ent['tag']
+ //$ent['fieldtype']
+ //$ent['fielddata']
+ // }
+ // $i++;
+ // }
+ //}
+
+ if ($conditioncount > 0) {
+ $tmp .= " </condition>\n";
+ }
+ unset ($conditioncount);
+ $tmp .= "</extension>\n";
+
+
+ if ($rowhelper['enabled'] == "true") {
+ $dialplanincludefilename = $rowhelper['order']."_".$rowhelper['extensionname'].".xml";
+ $fout = fopen("/usr/local/freeswitch/conf/dialplan/default/".$dialplanincludefilename,"w");
+ fwrite($fout, $tmp);
+ fclose($fout);
+ }
+ unset($dialplanincludefilename);
+ unset($tmp);
+
+
+ } //end foreach
+ } //if array count
+
+ conf_mount_ro();
+ config_unlock();
+
+}
+
+
+function sync_package_freeswitch_public_includes()
+{
+
+ global $config;
+ conf_mount_rw();
+ config_lock();
+
+ $a_public_includes = &$config['installedpackages']['freeswitchpublicincludes']['config'];
+ $a_public_include_details = &$config['installedpackages']['freeswitchpublicincludedetails']['config'];
+
+ if (count($a_public_includes) > 0) {
+ foreach($a_public_includes as $rowhelper) {
+ $tmp = "";
+ $tmp .= "\n";
+
+ //$rowhelper['publicincludeid'];
+ //$rowhelper['extensionname'];
+ //$rowhelper['context'];
+ //$rowhelper['enabled'];
+
+ $tmp = "<extension name=\"".$rowhelper['extensionname']."\">\n";
+
+ if (count($a_public_include_details) > 0) {
+
+ $conditioncount = 0;
+ $i = 0;
+ foreach ($a_public_include_details as $ent) {
+ if ($ent['tag'] == "condition" && $rowhelper['publicincludeid'] == $ent['publicincludeid']) {
+ $conditioncount++;
+ $i++;
+ }
+ }
+
+ $i = 1;
+ foreach ($a_public_include_details as $ent) {
+ if ($ent['tag'] == "condition" && $rowhelper['publicincludeid'] == $ent['publicincludeid']) {
+ if ($conditioncount == 1) { //single condition
+ //start tag
+ $tmp .= " <condition field=\"".$ent['fieldtype']."\" expression=\"".$ent['fielddata']."\">\n";
+ }
+ else { //more than one condition
+ if ($i < $conditioncount) {
+ //all tags should be self-closing except the last one
+ $tmp .= " <condition field=\"".$ent['fieldtype']."\" expression=\"".$ent['fielddata']."\"/>\n";
+ }
+ else {
+ //for the last tag use the start tag
+ $tmp .= " <condition field=\"".$ent['fieldtype']."\" expression=\"".$ent['fielddata']."\">\n";
+ }
+ }
+ $i++;
+ }
+ } //end for each
+
+ } //end if count
+
+
+ if (count($a_public_include_details) > 0) {
+ $i = 0;
+ foreach ($a_public_include_details as $ent) {
+ if ($ent['tag'] == "action" && $rowhelper['publicincludeid'] == $ent['publicincludeid']) {
+ $tmp .= " <action application=\"".$ent['fieldtype']."\" data=\"".$ent['fielddata']."\"/>\n";
+ }
+ $i++;
+ }
+ }
+
+ if (count($a_public_include_details) > 0) {
+ $i = 0;
+ foreach ($a_public_include_details as $ent) {
+ if ($ent['tag'] == "anti-action" && $rowhelper['publicincludeid'] == $ent['publicincludeid']) {
+ $tmp .= " <anti-action application=\"".$ent['fieldtype']."\" data=\"".$ent['fielddata']."\"/>\n";
+ }
+ $i++;
+ }
+ }
+
+ //if (count($a_public_include_details) > 0) {
+ //foreach ($a_public_include_details as $ent) {
+ // $i = 0;
+ // if ($ent['tag'] == "param" && $rowhelper['publicincludeid'] == $ent['publicincludeid']) {
+ //$ent['tag']
+ //$ent['fieldtype']
+ //$ent['fielddata']
+ // }
+ // $i++;
+ // }
+ //}
+
+ if ($conditioncount > 0) {
+ $tmp .= " </condition>\n";
+ }
+ unset ($conditioncount);
+ $tmp .= "</extension>\n";
+
+
+ if ($rowhelper['enabled'] == "true") {
+ $publicincludefilename = $rowhelper['order']."_".$rowhelper['extensionname'].".xml";
+ $fout = fopen("/usr/local/freeswitch/conf/dialplan/public/".$publicincludefilename,"w");
+ fwrite($fout, $tmp);
+ fclose($fout);
+ }
+ unset($publicincludefilename);
+ unset($tmp);
+
+
+ } //end foreach
+ } //end if count
+ conf_mount_ro();
+ config_unlock();
+
+}
+
+
+function sync_package_freeswitch()
+{
+
+ global $config;
+ sync_package_freeswitch_settings();
+ sync_package_freeswitch_dialplan();
+ sync_package_freeswitch_dialplan_includes();
+ sync_package_freeswitch_extensions();
+ sync_package_freeswitch_gateways();
+ sync_package_freeswitch_modules();
+ sync_package_freeswitch_public();
+ sync_package_freeswitch_public_includes();
+ sync_package_freeswitch_vars();
+ sync_package_freeswitch_internal();
+ sync_package_freeswitch_external();
+ //sync_package_freeswitch_recordings();
+ if (pkg_is_service_running('freeswitch')) {
+ sync_package_freeswitch_ivr();
+ }
+
+}
+
+
+function freeswitch_php_install_command()
+{
+
+ global $config;
+ conf_mount_rw();
+ config_lock();
+
+ //needed for mod_fax support
+ system('pkg_add -r spandsp');
+
+ if (!is_dir('/usr/local/www/freeswitch/')) {
+ exec("mkdir /usr/local/www/freeswitch/");
+ }
+
+ exec("tar zxvf /tmp/freeswitch.tgz -C /usr/local/");
+ unlink_if_exists("/tmp/freeswitch.tgz");
+
+ //remove some default config files that are not needed
+ unlink_if_exists("/usr/local/freeswitch/conf/dialplan/default/01_example.com.xml");
+ unlink_if_exists("/usr/local/freeswitch/conf/dialplan/public/00_inbound_did.xml");
+
+ //copy audio files
+ exec("cp /tmp/please_enter_your_pin_number.wav /usr/local/freeswitch/recordings/please_enter_your_pin_number.wav");
+ unlink_if_exists("/tmp/please_enter_your_pin_number.wav");
+
+ exec("cp /tmp/begin_recording.wav /usr/local/freeswitch/recordings/begin_recording.wav");
+ unlink_if_exists("/tmp/begin_recording.wav");
+
+ exec("cp /tmp/your_pin_number_is_incorect_goodbye.wav /usr/local/freeswitch/recordings/your_pin_number_is_incorect_goodbye.wav");
+ unlink_if_exists("/tmp/your_pin_number_is_incorect_goodbye.wav");
+
+
+ //rename .so files from .1 to .so
+ exec("cp /tmp/mod_shout.so.1 /usr/local/freeswitch/mod/mod_shout.so");
+ unlink_if_exists("/tmp/mod_shout.so.tmp");
+
+ exec("cp /tmp/mod_fax.so.1 /usr/local/freeswitch/mod/mod_fax.so");
+ unlink_if_exists("/tmp/mod_shout.so.tmp");
+
+
+ //rename PHP files from .tmp to .php
+ exec("cp /tmp/class.smtp.tmp /usr/local/www/freeswitch/class.smtp.php");
+ unlink_if_exists("/tmp/class.smtp.tmp");
+
+ exec("cp /tmp/class.phpmailer.tmp /usr/local/www/freeswitch/class.phpmailer.php");
+ unlink_if_exists("/tmp/class.phpmailer.tmp");
+
+ exec("cp /tmp/freeswitch_cmd.tmp /usr/local/www/freeswitch/freeswitch_cmd.php");
+ unlink_if_exists("/tmp/freeswitch_cmd.tmp");
+
+ exec("cp /tmp/freeswitch_dialplan_includes_details.tmp /usr/local/www/freeswitch/freeswitch_dialplan_includes_details.php");
+ unlink_if_exists("/tmp/freeswitch_dialplan_includes_details.tmp");
+
+ exec("cp /tmp/freeswitch_dialplan_includes_details_edit.tmp /usr/local/www/freeswitch/freeswitch_dialplan_includes_details_edit.php");
+ unlink_if_exists("/tmp/freeswitch_dialplan_includes_details_edit.tmp");
+
+ exec("cp /tmp/freeswitch_dialplan_includes.tmp /usr/local/www/freeswitch/freeswitch_dialplan_includes.php");
+ unlink_if_exists("/tmp/freeswitch_dialplan_includes.tmp");
+
+ exec("cp /tmp/freeswitch_dialplan_includes_edit.tmp /usr/local/www/freeswitch/freeswitch_dialplan_includes_edit.php");
+ unlink_if_exists("/tmp/freeswitch_dialplan_includes_edit.tmp");
+
+ exec("cp /tmp/freeswitch_extensions.tmp /usr/local/www/freeswitch/freeswitch_extensions.php");
+ unlink_if_exists("/tmp/freeswitch_extensions.tmp");
+
+ exec("cp /tmp/freeswitch_extensions_edit.tmp /usr/local/www/freeswitch/freeswitch_extensions_edit.php");
+ unlink_if_exists("/tmp/freeswitch_extensions_edit.tmp");
+
+ exec("cp /tmp/freeswitch_gateways.tmp /usr/local/www/freeswitch/freeswitch_gateways.php");
+ unlink_if_exists("/tmp/freeswitch_gateways.tmp");
+
+ exec("cp /tmp/freeswitch_gateways_edit.tmp /usr/local/www/freeswitch/freeswitch_gateways_edit.php");
+ unlink_if_exists("/tmp/freeswitch_gateways_edit.tmp");
+
+ exec("cp /tmp/freeswitch_ivr.tmp /usr/local/www/freeswitch/freeswitch_ivr.php");
+ unlink_if_exists("/tmp/freeswitch_ivr.tmp");
+
+ exec("cp /tmp/freeswitch_ivr_edit.tmp /usr/local/www/freeswitch/freeswitch_ivr_edit.php");
+ unlink_if_exists("/tmp/freeswitch_ivr_edit.tmp");
+
+ exec("cp /tmp/freeswitch_ivr_options.tmp /usr/local/www/freeswitch/freeswitch_ivr_options.php");
+ unlink_if_exists("/tmp/freeswitch_ivr_options.tmp");
+
+ exec("cp /tmp/freeswitch_ivr_options_edit.tmp /usr/local/www/freeswitch/freeswitch_ivr_options_edit.php");
+ unlink_if_exists("/tmp/freeswitch_ivr_options_edit.tmp");
+
+ exec("cp /tmp/freeswitch_public_includes.tmp /usr/local/www/freeswitch/freeswitch_public_includes.php");
+ unlink_if_exists("/tmp/freeswitch_public_includes.tmp");
+
+ exec("cp /tmp/freeswitch_public_includes_edit.tmp /usr/local/www/freeswitch/freeswitch_public_includes_edit.php");
+ unlink_if_exists("/tmp/freeswitch_public_includes_edit.tmp");
+
+ exec("cp /tmp/freeswitch_public_includes_details.tmp /usr/local/www/freeswitch/freeswitch_public_includes_details.php");
+ unlink_if_exists("/tmp/freeswitch_public_includes_details.tmp");
+
+ exec("cp /tmp/freeswitch_public_includes_details_edit.tmp /usr/local/www/freeswitch/freeswitch_public_includes_details_edit.php");
+ unlink_if_exists("/tmp/freeswitch_public_includes_details_edit.tmp");
+
+ exec("cp /tmp/freeswitch_mailto.tmp /usr/local/www/freeswitch/freeswitch_mailto.php");
+ unlink_if_exists("/tmp/freeswitch_mailto.tmp");
+
+ exec("cp /tmp/freeswitch_recordings.tmp /usr/local/www/freeswitch/freeswitch_recordings.php");
+ unlink_if_exists("/tmp/freeswitch_recordings.tmp");
+
+ exec("cp /tmp/freeswitch_recordings_edit.tmp /usr/local/www/freeswitch/freeswitch_recordings_edit.php");
+ unlink_if_exists("/tmp/freeswitch_recordings_edit.tmp");
+
+ exec("cp /tmp/freeswitch_recordings_play.tmp /usr/local/www/freeswitch/freeswitch_recordings_play.php");
+ unlink_if_exists("/tmp/freeswitch_recordings_play.tmp");
+
+ exec("cp /tmp/freeswitch_status.tmp /usr/local/www/freeswitch/freeswitch_status.php");
+ unlink_if_exists("/tmp/freeswitch_status.tmp");
+
+ exec("cp /tmp/freeswitch_time_conditions.tmp /usr/local/www/freeswitch/freeswitch_time_conditions.php");
+ unlink_if_exists("/tmp/freeswitch_time_conditions.tmp");
+
+ exec("cp /tmp/freeswitch_time_conditions_edit.tmp /usr/local/www/freeswitch/freeswitch_time_conditions_edit.php");
+ unlink_if_exists("/tmp/freeswitch_time_conditions_edit.tmp");
+
+ exec("cp /usr/local/freeswitch/htdocs/slim.swf /usr/local/www/freeswitch/slim.swf");
+
+ /* freeswitch settings defaults */
+ if (strlen($config['installedpackages']['freeswitchsettings']['config'][0]['numbering_plan']) == 0) {
+ $config['installedpackages']['freeswitchsettings']['config'][0]['numbering_plan'] = "US";
+ }
+ if(strlen($config['installedpackages']['freeswitchsettings']['config'][0]['event_socket_password']) == 0) {
+ $config['installedpackages']['freeswitchsettings']['config'][0]['event_socket_password'] = "ClueCon";
+ }
+ if (strlen($config['installedpackages']['freeswitchsettings']['config'][0]['event_socket_port']) == 0) {
+ $config['installedpackages']['freeswitchsettings']['config'][0]['event_socket_port'] = "8021";
+ }
+ if (strlen($config['installedpackages']['freeswitchsettings']['config'][0]['xml_rpc_http_port']) == 0) {
+ $config['installedpackages']['freeswitchsettings']['config'][0]['xml_rpc_http_port'] = "8787";
+ }
+ if (strlen($config['installedpackages']['freeswitchsettings']['config'][0]['xml_rpc_auth_realm']) == 0) {
+ $config['installedpackages']['freeswitchsettings']['config'][0]['xml_rpc_auth_realm'] = "freeswitch";
+ }
+ if (strlen($config['installedpackages']['freeswitchsettings']['config'][0]['xml_rpc_auth_user']) == 0) {
+ $config['installedpackages']['freeswitchsettings']['config'][0]['xml_rpc_auth_user'] = "freeswitch";
+ }
+ if (strlen($config['installedpackages']['freeswitchsettings']['config'][0]['xml_rpc_auth_pass']) == 0) {
+ $config['installedpackages']['freeswitchsettings']['config'][0]['xml_rpc_auth_pass'] = "works";
+ }
+ if (strlen($config['installedpackages']['freeswitchsettings']['config'][0]['admin_pin']) == 0) {
+ $config['installedpackages']['freeswitchsettings']['config'][0]['admin_pin'] = "7575";
+ }
+
+ $numbering_plan = $config['installedpackages']['freeswitchsettings']['config'][0]['numbering_plan'];
+ $event_socket_password = $config['installedpackages']['freeswitchsettings']['config'][0]['event_socket_password'];
+ $event_socket_port = $config['installedpackages']['freeswitchsettings']['config'][0]['event_socket_port'];
+ $xml_rpc_http_port = $config['installedpackages']['freeswitchsettings']['config'][0]['xml_rpc_http_port'];
+ $xml_rpc_auth_realm = $config['installedpackages']['freeswitchsettings']['config'][0]['xml_rpc_auth_realm'];
+ $xml_rpc_auth_user = $config['installedpackages']['freeswitchsettings']['config'][0]['xml_rpc_auth_user'];
+ $xml_rpc_auth_pass = $config['installedpackages']['freeswitchsettings']['config'][0]['xml_rpc_auth_pass'];
+ $admin_pin = $config['installedpackages']['freeswitchsettings']['config'][0]['admin_pin'];
+
+ //write the recording.js script
+ recording_js();
+
+ //add recording.js to the dialplan
+ $a_dialplan_includes = &$config['installedpackages']['freeswitchdialplanincludes']['config'];
+ $a_dialplan_include_details = &$config['installedpackages']['freeswitchdialplanincludedetails']['config'];
+
+ //delete dialplan recording from the previous install
+ if (count($a_dialplan_includes) > 0) {
+ $i = 0;
+ foreach ($a_dialplan_includes as $ent) {
+ if ($ent['extensionname'] == "Recordings") {
+ unset($a_dialplan_includes[$i]);
+ }
+ $i++;
+ }
+ }
+
+ //delete the recording dialplan details
+ if (count($a_dialplan_include_details) > 0) {
+ $i = 0;
+ foreach ($a_dialplan_include_details as $ent) {
+ if ($ent['fielddata'] == "^732673$") {
+ unset($a_dialplan_include_details[$i]);
+ }
+ if ($ent['fielddata'] == "recordings.js") {
+ unset($a_dialplan_include_details[$i]);
+ }
+ $i++;
+ }
+ }
+
+ $dialplanincludeid = guid();
+
+ $ent = array();
+ $ent['dialplanincludeid'] = $dialplanincludeid;
+ $ent['extensionname'] = 'Recordings';
+ $ent['order'] = '9000';
+ $ent['context'] = 'default';
+ $ent['enabled'] = 'true';
+ $ent['descr'] = 'Default system recordings tool';
+ $a_dialplan_includes[] = $ent;
+ unset($ent);
+
+ $ent = array();
+ $ent['dialplanincludeid'] = $dialplanincludeid;
+ $ent['tag'] = 'condition'; //condition, action, antiaction
+ $ent['fieldtype'] = 'destination_number';
+ $ent['fielddata'] = '^732673$';
+ $a_dialplan_include_details[] = $ent;
+ unset($ent);
+
+ $ent = array();
+ $ent['dialplanincludeid'] = $dialplanincludeid;
+ $ent['tag'] = 'action'; //condition, action, antiaction
+ $ent['fieldtype'] = 'javascript';
+ $ent['fielddata'] = 'recordings.js';
+ $a_dialplan_include_details[] = $ent;
+ unset($ent);
+
+ write_config();
+
+ //prepare switch.conf.xml for voicemail to email
+ $filename = "/usr/local/freeswitch/conf/autoload_configs/switch.conf.xml";
+ $handle = fopen($filename,"rb");
+ $contents = fread($handle, filesize($filename));
+ fclose($handle);
+
+ $handle = fopen($filename,"w");
+ $contents = str_replace("<param name=\"mailer-app\" value=\"sendmail\"/>", "<param name=\"mailer-app\" value=\"/usr/local/bin/php\"/>", $contents);
+ $contents = str_replace("<param name=\"mailer-app-args\" value=\"-t\"/>", "<param name=\"mailer-app-args\" value=\"/usr/local/www/freeswitch/freeswitch_mailto.php\"/>", $contents);
+ fwrite($handle, $contents);
+ unset($contents);
+ fclose($fout);
+ unset($filename);
+
+ //prepare shout.conf.xml for mod_shout
+ $fout = fopen("/usr/local/freeswitch/conf/autoload_configs/shout.conf.xml","w");
+ $tmpxml = "<configuration name=\"shout.conf\" description=\"mod shout config\">\n";
+ $tmpxml .= " <settings>\n";
+ $tmpxml .= " <!-- Don't change these unless you are insane -->\n";
+ $tmpxml .= " <param name=\"decoder\" value=\"i586\"/>\n";
+ $tmpxml .= " <!--<param name=\"volume\" value=\".1\"/>-->\n";
+ $tmpxml .= " <!--<param name=\"outscale\" value=\"8192\"/>-->\n";
+ $tmpxml .= " </settings>\n";
+ $tmpxml .= "</configuration>";
+ fwrite($fout, $tmpxml);
+ unset($tmpxml);
+ fclose($fout);
+
+ $fout = fopen("/usr/local/freeswitch/conf/autoload_configs/event_socket.conf.xml","w");
+ $tmpxml = "<configuration name=\"event_socket.conf\" description=\"Socket Client\">\n";
+ $tmpxml .= " <settings>\n";
+ $tmpxml .= " <param name=\"listen-ip\" value=\"". $config['interfaces']['lan']['ipaddr'] ."\"/>\n";
+ $tmpxml .= " <param name=\"listen-port\" value=\"". $event_socket_port ."\"/>\n";
+ $tmpxml .= " <param name=\"password\" value=\"". $event_socket_password ."\"/>\n";
+ $tmpxml .= " <!--<param name=\"apply-inbound-acl\" value=\"lan\"/>-->\n";
+ $tmpxml .= " </settings>\n";
+ $tmpxml .= "</configuration>";
+ fwrite($fout, $tmpxml);
+ unset($tmpxml);
+ fclose($fout);
+
+ /* freeswitch modules defaults */
+
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_console']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_console'] = "enable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_logfile']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_logfile'] = "enable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_syslog']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_syslog'] = "disable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_yaml']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_yaml'] = "disable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_enum']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_enum'] = "enable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_xml_rpc']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_xml_rpc'] = "disable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_xml_curl']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_xml_curl'] = "disable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_xml_cdr']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_xml_cdr'] = "disable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_cdr_csv']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_cdr_csv'] = "enable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_event_multicast']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_event_multicast'] = "disable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_event_socket']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_event_socket'] = "enable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_zeroconf']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_zeroconf'] = "disable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_ldap']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_ldap'] = "disable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_dingaling']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_dingaling'] = "disable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_iax']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_iax'] = "disable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_portaudio']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_portaudio'] = "disable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_alsa']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_alsa'] = "disable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_sofia']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_sofia'] = "enable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_loopback']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_loopback'] = "enable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_wanpipe']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_wanpipe'] = "disable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_woomera']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_woomera'] = "disable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_openzap']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_openzap'] = "disable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_commands']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_commands'] = "enable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_conference']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_conference'] = "enable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_dptools']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_dptools'] = "enable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_expr']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_expr'] = "enable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_fax']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_fax'] = "enable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_fifo']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_fifo'] = "enable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_voicemail']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_voicemail'] = "enable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_limit']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_limit'] = "enable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_esf']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_esf'] = "enable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_fsv']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_fsv'] = "enable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_snom']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_snom'] = "disable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_dialplan_directory']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_dialplan_directory'] = "disable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_dialplan_xml']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_dialplan_xml'] = "enable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_dialplan_asterisk']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_dialplan_asterisk'] = "enable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_voipcodecs']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_voipcodecs'] = "enable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_g723_1']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_g723_1'] = "enable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_g729']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_g729'] = "enable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_amr']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_amr'] = "enable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_ilbc']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_ilbc'] = "enable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_speex']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_speex'] = "enable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_siren']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_siren'] = "enable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_celt']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_celt'] = "enable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_h26x']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_h26x'] = "enable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_sndfile']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_sndfile'] = "enable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_native_file']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_native_file'] = "enable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_shout']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_shout'] = "disable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_local_stream']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_local_stream'] = "enable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_tone_stream']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_tone_stream'] = "enable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_spidermonkey']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_spidermonkey'] = "enable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_perl']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_perl'] = "disable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_python']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_python'] = "disable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_java']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_java'] = "disable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_lua']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_lua'] = "enable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_flite']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_flite'] = "disable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_pocketsphinx']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_pocketsphinx'] = "disable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_cepstral']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_cepstral'] = "disable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_openmrcp']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_openmrcp'] = "disable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_rss']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_rss'] = "disable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_say_en']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_say_en'] = "enable";
+ }
+ if (strlen($config['installedpackages']['freeswitchmodules']['config'][0]['mod_say_zh']) == 0) {
+ $config['installedpackages']['freeswitchmodules']['config'][0]['mod_say_zh'] = "disable";
+ }
+
+ // if backup file exists restore it
+ $filename = 'freeswitch.bak.tgz';
+
+ //extract a specific directory to /usr/local/freeswitch
+ if (file_exists('/tmp/'.$filename)) {
+ //echo "The file $filename exists";
+
+ //Recommended
+ system('cd /usr/local; tar xvpfz /tmp/'.$filename.' freeswitch/db/');
+ system('cd /usr/local; tar xvpfz /tmp/'.$filename.' freeswitch/log/');
+ system('cd /usr/local; tar xvpfz /tmp/'.$filename.' freeswitch/recordings/');
+ system('cd /usr/local; tar xvpfz /tmp/'.$filename.' freeswitch/scripts/');
+ system('cd /usr/local; tar xvpfz /tmp/'.$filename.' freeswitch/storage/');
+ system('cd /usr/local; tar xvpfz /tmp/'.$filename.' freeswitch/sounds/music/8000/');
+ system('cd /usr/local; tar xvpfz /tmp/'.$filename.' freeswitch/conf/ssl');
+
+ //Optional
+ //system('cd /usr/local; tar xvpfz /tmp/'.$filename.' freeswitch/conf/');
+ //system('cd /usr/local; tar xvpfz /tmp/'.$filename.' freeswitch/grammar/');
+ //system('cd /usr/local; tar xvpfz /tmp/'.$filename.' freeswitch/htdocs/');
+
+ unset($filename);
+ }
+
+ write_rcfile(array(
+ "file" => "freeswitch.sh",
+ "start" => "/usr/local/freeswitch/bin/./freeswitch -nc",
+ "stop" => "/usr/local/freeswitch/bin/./freeswitch -stop"
+ )
+ );
+
+ exec("rm -R /freeswitch");
+ exec("cp /usr/local/freeswitch/conf/directory/default/brian.xml /usr/local/freeswitch/conf/directory/default/brian.xml.noload");
+ unlink_if_exists("/usr/local/freeswitch/conf/directory/default/brian.xml");
+ unlink_if_exists("/usr/local/freeswitch/conf/directory/default/example.com.xml");
+
+ write_rcfile(array(
+ "file" => "freeswitch.sh",
+ "start" => "/usr/local/freeswitch/bin/./freeswitch -nc",
+ "stop" => "/usr/local/freeswitch/bin/./freeswitch -stop"
+ )
+ );
+
+ sync_package_freeswitch();
+ $handle = popen("/usr/local/etc/rc.d/freeswitch.sh start", "r");
+ pclose($handle);
+
+ if (pkg_is_service_running('freeswitch')) {
+ sync_package_freeswitch_ivr();
+ }
+
+ $config['installedpackages']['freeswitchsettings']['config'][0]['freeswitch_version'] = "1.0.2 revision 11245.";
+ $config['installedpackages']['freeswitchsettings']['config'][0]['freeswitch_package_version'] = "0.7";
+
+ conf_mount_ro();
+ config_unlock();
+
+}
+
+
+function freeswitch_deinstall_command()
+{
+
+ conf_mount_rw();
+ config_lock();
+ exec("killall -9 freeswitch");
+ unlink_if_exists("/usr/local/pkg/freeswitch.xml");
+ unlink_if_exists("/usr/local/pkg/freeswitch.inc");
+ unlink_if_exists("/usr/local/pkg/freeswitch_dialplan.xml");
+ unlink_if_exists("/usr/local/pkg/freeswitch_extensions.xml");
+ unlink_if_exists("/usr/local/pkg/freeswitch_external.xml");
+ unlink_if_exists("/usr/local/pkg/freeswitch_internal.xml");
+ unlink_if_exists("/usr/local/pkg/freeswitch_modules.xml");
+ unlink_if_exists("/usr/local/pkg/freeswitch_public.xml");
+ unlink_if_exists("/usr/local/pkg/freeswitch_vars.xml");
+
+ unlink_if_exists("/usr/local/www/freeswitch/class.smtp.php");
+ unlink_if_exists("/usr/local/www/freeswitch/class.phpmailer.php");
+ unlink_if_exists("/usr/local/www/freeswitch/freeswitch_cmd.php");
+ unlink_if_exists("/usr/local/www/freeswitch/freeswitch_dialplan_includes_details.php");
+ unlink_if_exists("/usr/local/www/freeswitch/freeswitch_dialplan_includes_edit.php");
+ unlink_if_exists("/usr/local/www/freeswitch/freeswitch_dialplan_includes.php");
+ unlink_if_exists("/usr/local/www/freeswitch/freeswitch_dialplan_includes_details_edit.php");
+ unlink_if_exists("/usr/local/www/freeswitch/freeswitch_extensions.php");
+ unlink_if_exists("/usr/local/www/freeswitch/freeswitch_extensions_edit.php");
+ unlink_if_exists("/usr/local/www/freeswitch/freeswitch_ivr.php");
+ unlink_if_exists("/usr/local/www/freeswitch/freeswitch_ivr_edit.php");
+ unlink_if_exists("/usr/local/www/freeswitch/freeswitch_ivr_options_edit.php");
+ unlink_if_exists("/usr/local/www/freeswitch/freeswitch_ivr_options.php");
+ unlink_if_exists("/usr/local/www/freeswitch/freeswitch_gateways.php");
+ unlink_if_exists("/usr/local/www/freeswitch/freeswitch_gateways_edit.php");
+ unlink_if_exists("/usr/local/www/freeswitch/freeswitch_mailto.php");
+ unlink_if_exists("/usr/local/www/freeswitch/freeswitch_public_includes_details.php");
+ unlink_if_exists("/usr/local/www/freeswitch/freeswitch_public_includes_edit.php");
+ unlink_if_exists("/usr/local/www/freeswitch/freeswitch_public_includes.php");
+ unlink_if_exists("/usr/local/www/freeswitch/freeswitch_public_includes_details_edit.php");
+ unlink_if_exists("/usr/local/www/freeswitch/freeswitch_recordings.php");
+ unlink_if_exists("/usr/local/www/freeswitch/freeswitch_recordings_edit.php");
+ unlink_if_exists("/usr/local/www/freeswitch/freeswitch_recordings_play.php");
+ unlink_if_exists("/usr/local/www/freeswitch/freeswitch_time_conditions.php");
+ unlink_if_exists("/usr/local/www/freeswitch/freeswitch_time_conditions_edit.php");
+ unlink_if_exists("/usr/local/www/freeswitch/freeswitch_status.php");
+ unlink_if_exists("/usr/local/www/freeswitch/slim.swf");
+
+ exec("rm -R /usr/local/freeswitch/");
+ exec("rm -R /usr/local/www/freeswitch/");
+ unlink_if_exists("/usr/local/etc/rc.d/freeswitch.sh");
+ unlink_if_exists("/tmp/freeswitch.tar.gz");
+ unlink_if_exists("/tmp/pkg_mgr_FreeSWITCH.log");
+ conf_mount_ro();
+ config_unlock();
+
+}
+
+?> \ No newline at end of file
diff --git a/config/freeswitch/freeswitch.xml b/config/freeswitch/freeswitch.xml
new file mode 100644
index 00000000..7c557c30
--- /dev/null
+++ b/config/freeswitch/freeswitch.xml
@@ -0,0 +1,477 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ freeswitch.xml
+ Copyright (C) 2008 Mark J Crane
+ All rights reserved.
+
+ FreeSWITCH (TM)
+ http://www.freeswitch.org/
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>FreeSWITCH is an open source telephony platform designed to facilitate the creation of voice and chat driven products scaling from a soft-phone up to a soft-switch. It can be used as a simple switching engine, a PBX, a media gateway or a media server to host IVR applications using simple scripts or XML to control the callflow.</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>FreeSWITCH Settings</name>
+ <version>0.7</version>
+ <title>FreeSWITCH: Settings</title>
+ <include_file>/usr/local/pkg/freeswitch.inc</include_file>
+ <menu>
+ <name>FreeSWITCH</name>
+ <tooltiptext>Modify FreeSWITCH settings.</tooltiptext>
+ <section>Services</section>
+ <configfile>freeswitch.xml</configfile>
+ <url>/pkg_edit.php?xml=freeswitch.xml&amp;id=0</url>
+ </menu>
+ <service>
+ <name>freeswitch</name>
+ <rcfile>freeswitch.sh</rcfile>
+ <executable>freeswitch</executable>
+ <description>FreeSWITCH is an open source telephony platform designed to facilitate the creation of voice and chat driven products scaling from a soft-phone up to a soft-switch. It can be used as a simple switching engine, a PBX, a media gateway or a media server to host IVR applications using simple scripts or XML to control the callflow. </description>
+ </service>
+ <tabs>
+ <tab>
+ <text>Settings</text>
+ <url>/pkg_edit.php?xml=freeswitch.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Dialplan</text>
+ <url>/freeswitch/freeswitch_dialplan_includes.php</url>
+ </tab>
+ <tab>
+ <text>Extensions</text>
+ <url>/freeswitch/freeswitch_extensions.php</url>
+ </tab>
+ <tab>
+ <text>External</text>
+ <url>/pkg_edit.php?xml=freeswitch_external.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Gateways</text>
+ <url>/freeswitch/freeswitch_gateways.php</url>
+ </tab>
+ <tab>
+ <text>Internal</text>
+ <url>/pkg_edit.php?xml=freeswitch_internal.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>IVR</text>
+ <url>/freeswitch/freeswitch_ivr.php</url>
+ </tab>
+ <tab>
+ <text>Modules</text>
+ <url>/pkg_edit.php?xml=freeswitch_modules.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Public</text>
+ <url>/freeswitch/freeswitch_public_includes.php</url>
+ </tab>
+ <tab>
+ <text>Rec</text>
+ <url>/freeswitch/freeswitch_recordings.php</url>
+ </tab>
+ <tab>
+ <text>Status</text>
+ <url>/freeswitch/freeswitch_status.php</url>
+ </tab>
+ <tab>
+ <text>Vars</text>
+ <url>/pkg_edit.php?xml=freeswitch_vars.xml&amp;id=0</url>
+ </tab>
+ </tabs>
+ <configpath>installedpackages->package->$packagename->configuration->freeswitchsettings</configpath>
+ <additional_files_needed>
+ <prefix>/tmp/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.portableusbapps.com/packages/config/freeswitch/freeswitch.tgz</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freeswitch/freeswitch.inc</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/lib/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freeswitch/libtinfo.so.5.6</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/lib/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freeswitch/libncurses.so.5.6</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/lib/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freeswitch/libogg.so.5.3</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/lib/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freeswitch/libvorbis.so.4</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/tmp/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freeswitch/mod_shout.so.1</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/tmp/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freeswitch/mod_fax.so.1</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/lib/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freeswitch/libspandsp.so.1</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/tmp/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freeswitch/please_enter_your_pin_number.wav</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/tmp/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freeswitch/begin_recording.wav</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/tmp/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freeswitch/your_pin_number_is_incorect_goodbye.wav</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/tmp/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freeswitch/class.smtp.tmp</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/tmp/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freeswitch/class.phpmailer.tmp</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/tmp/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freeswitch/freeswitch_cmd.tmp</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freeswitch/freeswitch_dialplan.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/tmp/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freeswitch/freeswitch_dialplan_includes.tmp</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/tmp/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freeswitch/freeswitch_dialplan_includes_edit.tmp</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/tmp/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freeswitch/freeswitch_dialplan_includes_details.tmp</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/tmp/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freeswitch/freeswitch_dialplan_includes_details_edit.tmp</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/tmp/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freeswitch/freeswitch_extensions.tmp</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/tmp/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freeswitch/freeswitch_extensions_edit.tmp</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freeswitch/freeswitch_external.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/tmp/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freeswitch/freeswitch_gateways.tmp</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/tmp/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freeswitch/freeswitch_gateways_edit.tmp</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freeswitch/freeswitch_internal.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/tmp/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freeswitch/freeswitch_ivr.tmp</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/tmp/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freeswitch/freeswitch_ivr_edit.tmp</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/tmp/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freeswitch/freeswitch_ivr_options_edit.tmp</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/tmp/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freeswitch/freeswitch_ivr_options.tmp</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/tmp/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freeswitch/freeswitch_mailto.tmp</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freeswitch/freeswitch_modules.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freeswitch/freeswitch_public.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/tmp/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freeswitch/freeswitch_public_includes.tmp</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/tmp/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freeswitch/freeswitch_public_includes_edit.tmp</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/tmp/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freeswitch/freeswitch_public_includes_details.tmp</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/tmp/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freeswitch/freeswitch_public_includes_details_edit.tmp</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/tmp/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freeswitch/freeswitch_recordings.tmp</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/tmp/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freeswitch/freeswitch_recordings_edit.tmp</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/tmp/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freeswitch/freeswitch_recordings_play.tmp</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/tmp/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freeswitch/freeswitch_status.tmp</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/tmp/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freeswitch/freeswitch_time_conditions.tmp</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/tmp/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freeswitch/freeswitch_time_conditions_edit.tmp</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/freeswitch/freeswitch_vars.xml</item>
+ </additional_files_needed>
+ <fields>
+ <field>
+ <fielddescr>Numbering Plan</fielddescr>
+ <fieldname>numbering_plan</fieldname>
+ <description>Enter the numbering plan here. example: US</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Default Gateway</fielddescr>
+ <fieldname>default_gateway</fieldname>
+ <description>Enter the default gateway name here. example: asterlink.com</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Default Area Code</fielddescr>
+ <fieldname>default_area_code</fieldname>
+ <description>Enter the area code here. example: 918</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Event Socket Port</fielddescr>
+ <fieldname>event_socket_port</fieldname>
+ <description>Enter the event socket port here. default: 8021</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Event Socket Password</fielddescr>
+ <fieldname>event_socket_password</fieldname>
+ <description>Enter the event socket password here. default: ClueCon</description>
+ <type>password</type>
+ </field>
+ <field>
+ <fielddescr>XML RPC HTTP Port</fielddescr>
+ <fieldname>xml_rpc_http_port</fieldname>
+ <description>Enter the XML RPC HTTP Port here. default: 8787</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>XML RPC Auth Realm</fielddescr>
+ <fieldname>xml_rpc_auth_realm</fieldname>
+ <description>Enter the XML RPC Auth Realm here. default: freeswitch</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>XML RPC Auth User</fielddescr>
+ <fieldname>xml_rpc_auth_user</fieldname>
+ <description>Enter the XML RPC Auth User here. default: freeswitch</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>XML RPC Auth Password</fielddescr>
+ <fieldname>xml_rpc_auth_pass</fieldname>
+ <description>Enter the XML RPC Auth Password here. default: works</description>
+ <type>password</type>
+ </field>
+ <field>
+ <fielddescr>Admin PIN Number</fielddescr>
+ <fieldname>admin_pin</fieldname>
+ <description>Enter a admin pin number. Used to authenticate the admin from the phone.</description>
+ <type>password</type>
+ </field>
+ <field>
+ <fielddescr>SMTP Host</fielddescr>
+ <fieldname>smtphost</fieldname>
+ <description>Enter the SMTP host address. If you using a different port append it on the end with a semi-colon. e.g. smtp.gmail.com:465</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>SMTP Secure</fielddescr>
+ <fieldname>smtpsecure</fieldname>
+ <description>Select the SMTP security. None, TLS, SSL</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>none</name>
+ <value></value>
+ </option>
+ <option>
+ <name>tls</name>
+ <value>tls</value>
+ </option>
+ <option>
+ <name>ssl</name>
+ <value>ssl</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>SMTP Auth</fielddescr>
+ <fieldname>smtpauth</fieldname>
+ <description>Use SMTP Authentication true or false.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>true</name>
+ <value>true</value>
+ </option>
+ <option>
+ <name>false</name>
+ <value>false</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>SMTP Username</fielddescr>
+ <fieldname>smtpusername</fieldname>
+ <description>Enter the SMTP authentication username.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>SMTP Password</fielddescr>
+ <fieldname>smtppassword</fieldname>
+ <description>Enter the SMTP authentication password.</description>
+ <type>password</type>
+ </field>
+ <field>
+ <fielddescr>SMTP From</fielddescr>
+ <fieldname>smtpfrom</fieldname>
+ <description>Enter the SMTP From email address.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>SMTP From Name</fielddescr>
+ <fieldname>smtpfromname</fieldname>
+ <description>Enter the SMTP From Name.</description>
+ <type>input</type>
+ </field>
+ </fields>
+ <custom_add_php_command>
+ </custom_add_php_command>
+ <custom_php_resync_config_command>
+ sync_package_freeswitch_settings();
+ </custom_php_resync_config_command>
+ <custom_delete_php_command>
+ sync_package_freeswitch_settings();
+ </custom_delete_php_command>
+ <custom_php_install_command>
+ freeswitch_php_install_command();
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ freeswitch_deinstall_command();
+ </custom_php_deinstall_command>
+</packagegui> \ No newline at end of file
diff --git a/config/freeswitch/freeswitch_cmd.tmp b/config/freeswitch/freeswitch_cmd.tmp
new file mode 100644
index 00000000..05ae77cf
--- /dev/null
+++ b/config/freeswitch/freeswitch_cmd.tmp
@@ -0,0 +1,49 @@
+<?php
+/* $Id$ */
+/*
+ freeswitch_cmd.php
+ Copyright (C) 2008 Mark J Crane
+ All rights reserved.
+
+ FreeSWITCH (TM)
+ http://www.freeswitch.org/
+
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require("guiconfig.inc");
+require("/usr/local/pkg/freeswitch.inc");
+$cmd = $_GET['cmd'];
+
+
+$password = $config['installedpackages']['freeswitchsettings']['config'][0]['event_socket_password'];
+$port = $config['installedpackages']['freeswitchsettings']['config'][0]['event_socket_port'];
+$host = '';
+
+$fp = event_socket_create($host, $port, $password);
+$response = event_socket_request($fp, $cmd);
+fclose($fp);
+
+header("Location: /freeswitch/freeswitch_status.php?savemsg=".urlencode($response));
+
+?> \ No newline at end of file
diff --git a/config/freeswitch/freeswitch_dialplan.xml b/config/freeswitch/freeswitch_dialplan.xml
new file mode 100644
index 00000000..3ce35570
--- /dev/null
+++ b/config/freeswitch/freeswitch_dialplan.xml
@@ -0,0 +1,136 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ freeswitch_dialplan.xml
+ Copyright (C) 2008 Mark J Crane
+ All rights reserved.
+
+ FreeSWITCH (TM)
+ http://www.freeswitch.org/
+
+
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>FreeSWITCH is an open source telephony platform designed to facilitate the creation of voice and chat driven products scaling from a soft-phone up to a soft-switch. It can be used as a simple switching engine, a PBX, a media gateway or a media server to host IVR applications using simple scripts or XML to control the callflow.</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>freeswitchdialplan</name>
+ <version>0.1</version>
+ <title>FreeSWITCH: Dialplan</title>
+ <aftersaveredirect>pkg_edit.php?xml=freeswitch_dialplan.xml&amp;id=0</aftersaveredirect>
+ <include_file>/usr/local/pkg/freeswitch.inc</include_file>
+ <tabs>
+ <tab>
+ <text>Settings</text>
+ <url>/pkg_edit.php?xml=freeswitch.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Dialplan</text>
+ <url>/freeswitch/freeswitch_dialplan_includes.php</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Extensions</text>
+ <url>/freeswitch/freeswitch_extensions.php</url>
+ </tab>
+ <tab>
+ <text>External</text>
+ <url>/pkg_edit.php?xml=freeswitch_external.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Gateways</text>
+ <url>/freeswitch/freeswitch_gateways.php</url>
+ </tab>
+ <tab>
+ <text>Internal</text>
+ <url>/pkg_edit.php?xml=freeswitch_internal.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>IVR</text>
+ <url>/freeswitch/freeswitch_ivr.php</url>
+ </tab>
+ <tab>
+ <text>Modules</text>
+ <url>/pkg_edit.php?xml=freeswitch_modules.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Public</text>
+ <url>/freeswitch/freeswitch_public_includes.php</url>
+ </tab>
+ <tab>
+ <text>Rec</text>
+ <url>/freeswitch/freeswitch_recordings.php</url>
+ </tab>
+ <tab>
+ <text>Status</text>
+ <url>/freeswitch/freeswitch_status.php</url>
+ </tab>
+ <tab>
+ <text>Vars</text>
+ <url>/pkg_edit.php?xml=freeswitch_vars.xml&amp;id=0</url>
+ </tab>
+ </tabs>
+ <configpath>installedpackages->package->$packagename->configuration->freeswitchdialplan</configpath>
+ <fields>
+ <field>
+ <fielddescr>&lt;b&gt;Default Dialplan&lt;/b&gt; &lt;br /&gt; &lt;br /&gt; The default dialplan is used to setup call destinations based on conditions and context. You can use the dialplan to send calls to gateways, IVRs, external numbers, to scripts, or any destination. </fielddescr>
+ <fieldname>dialplan_default_xml</fieldname>
+ <description>&lt;br /&gt;Path: /usr/local/freeswitch/conf/dialplan/default.xml &lt;br /&gt;&lt;br /&gt;</description>
+ <type>textarea</type>
+ <encoding>base64</encoding>
+ <wrap>off</wrap>
+ <size>30</size>
+ <cols>70</cols>
+ <rows>33</rows>
+ </field>
+ </fields>
+ <custom_php_command_before_form>
+ </custom_php_command_before_form>
+ <custom_php_after_head_command>
+ sync_package_freeswitch_dialplan();
+ </custom_php_after_head_command>
+ <custom_php_after_form_command>
+ </custom_php_after_form_command>
+ <custom_php_validation_command>
+ </custom_php_validation_command>
+ <custom_php_resync_config_command>
+ sync_package_freeswitch_dialplan();
+ </custom_php_resync_config_command>
+</packagegui> \ No newline at end of file
diff --git a/config/freeswitch/freeswitch_dialplan_includes.tmp b/config/freeswitch/freeswitch_dialplan_includes.tmp
new file mode 100644
index 00000000..4b7bacfa
--- /dev/null
+++ b/config/freeswitch/freeswitch_dialplan_includes.tmp
@@ -0,0 +1,271 @@
+<?php
+/* $Id$ */
+/*
+ freeswitch_dialplan_includes.php
+ Copyright (C) 2008 Mark J Crane
+ All rights reserved.
+
+ FreeSWITCH (TM)
+ http://www.freeswitch.org/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require("guiconfig.inc");
+require("/usr/local/pkg/freeswitch.inc");
+
+
+//freeswitchdialplanincludes
+ //dialplanincludeid
+ //extensionname
+ //context
+ //default
+ //enabled
+ //descr
+
+//freeswitchdialplanincludedetails
+
+ //dialplanincludeid
+ //tag
+ //condition
+ //action
+ //antiaction
+ //param
+ //tagorder
+ //1-20
+ //fieldtype
+
+ //fielddata
+
+
+$a_dialplan_includes = &$config['installedpackages']['freeswitchdialplanincludes']['config'];
+$a_dialplan_includes_details = &$config['installedpackages']['freeswitchdialplanincludedetails']['config'];
+
+
+if ($_GET['act'] == "del") {
+ if ($_GET['type'] == 'dialplanincludes') {
+
+ if ($a_dialplan_includes[$_GET['id']]) {
+
+ $dialplanincludeid = $a_dialplan_includes[$_GET['id']][dialplanincludeid];
+
+ $extensionname = $a_dialplan_includes[$_GET['id']][extensionname];
+ $order = $a_dialplan_includes[$_GET['id']][order];
+ $dialplanincludefilename = $order."_".$extensionname.".xml";
+
+ //delete the dialplan include details. aka. child data
+ if (count($a_dialplan_includes_details) > 0) {
+ $i=0;
+ foreach($a_dialplan_includes_details as $row) {
+ if ($row["dialplanincludeid"] == $dialplanincludeid) {
+ //echo "child id: ".$i."<br />\n";
+ unset($a_dialplan_includes_details[$i]);
+ }
+ $i++;
+ }
+ }
+
+ //if the dialplan include xml file exists then delete it
+ if (file_exists("/usr/local/freeswitch/conf/dialplan/default/".$dialplanincludefilename)) {
+ unlink("/usr/local/freeswitch/conf/dialplan/default/".$dialplanincludefilename);
+ }
+
+ unset($dialplanincludefilename);
+ unset($a_dialplan_includes[$_GET['id']]);
+ write_config();
+ sync_package_freeswitch_dialplan_includes();
+ header("Location: freeswitch_dialplan_includes.php");
+ exit;
+ }
+ }
+}
+
+include("head.inc");
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<?php include("fbegin.inc"); ?>
+<p class="pgtitle">FreeSWITCH: Dialplan</p>
+
+<div id="mainlevel">
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+<tr><td class="tabnavtbl">
+<?php
+
+ $tab_array = array();
+ $tab_array[] = array(gettext("Settings"), false, "/pkg_edit.php?xml=freeswitch.xml&amp;id=0");
+ $tab_array[] = array(gettext("Dialplan"), true, "/freeswitch/freeswitch_dialplan_includes.php");
+ $tab_array[] = array(gettext("Extensions"), false, "/freeswitch/freeswitch_extensions.php");
+ $tab_array[] = array(gettext("External"), false, "/pkg_edit.php?xml=freeswitch_external.xml&amp;id=0");
+ $tab_array[] = array(gettext("Gateways"), false, "/freeswitch/freeswitch_gateways.php");
+ $tab_array[] = array(gettext("Internal"), false, "/pkg_edit.php?xml=freeswitch_internal.xml&amp;id=0");
+ $tab_array[] = array(gettext("IVR"), false, "/freeswitch/freeswitch_ivr.php");
+ $tab_array[] = array(gettext("Modules"), false, "/pkg_edit.php?xml=freeswitch_modules.xml&amp;id=0");
+ $tab_array[] = array(gettext("Public"), false, "/freeswitch/freeswitch_public_includes.php");
+ $tab_array[] = array(gettext("Rec"), false, "/freeswitch/freeswitch_recordings.php");
+ $tab_array[] = array(gettext("Status"), false, "/freeswitch/freeswitch_status.php");
+ $tab_array[] = array(gettext("Vars"), false, "/pkg_edit.php?xml=freeswitch_vars.xml&amp;id=0");
+ display_top_tabs($tab_array);
+
+?>
+</td></tr>
+</table>
+
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabcont" >
+
+<form action="freeswitch_dialplan_includes.php" method="post" name="iform" id="iform">
+<?php
+
+
+//echo "<pre>";
+//print_r ($a_dialplan_includes);
+//echo "</pre>";
+
+
+//if ($config_change == 1) {
+// write_config();
+// $config_change = 0;
+//}
+
+//if ($savemsg) print_info_box($savemsg);
+//if (file_exists($d_hostsdirty_path)): echo"<p>";
+//print_info_box_np("This has been changed.<br>You must apply the changes in order for them to take effect.");
+//echo"<br />";
+//endif;
+
+?>
+
+ <br />
+ <br />
+
+ <table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td><span class="vexpl"><span class="red"><strong>Dialplan
+ </strong></span></span>
+ </td>
+ <td align='right'>
+ <input type='button' value='default.xml' onclick="document.location.href='/pkg_edit.php?xml=freeswitch_dialplan.xml&id=0';">
+ </td>
+ </tr>
+ <tr>
+ <td colspan='2'>
+ <span class="vexpl">
+ The dialplan is used to setup call destinations based on conditions and context. You can use the dialplan to send calls to gateways, IVRs, external numbers, to scripts, or any destination.
+ </span>
+ </td>
+
+ </tr>
+ </table>
+
+ <br />
+ <br />
+ <br />
+
+ <table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td width="20%" class="listhdrr">Extension Name</td>
+ <td width="25%" class="listhdrr">Order</td>
+ <td width="25%" class="listhdrr">Enabled</td>
+ <td width="50%" class="listhdr">Description</td>
+ <td width="10%" class="list">
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td width="17"></td>
+ <td valign="middle"><a href="freeswitch_dialplan_includes_edit.php"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" width="17" height="17" border="0"></a></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+
+ <?php
+ $i = 0;
+ if (count($a_dialplan_includes) > 0) {
+ foreach ($a_dialplan_includes as $ent) {
+ ?>
+ <tr>
+ <td class="listlr" ondblclick="document.location='freeswitch_dialplan_includes_edit.php?id=<?=$i;?>'">
+ <?=$ent['extensionname']?>
+ </td>
+ <td class="listlr" ondblclick="document.location='freeswitch_dialplan_includes_edit.php?id=<?=$i;?>'">
+ <?=$ent['order']?>
+ </td>
+ <td class="listr" ondblclick="document.location='freeswitch_dialplan_includes_edit.php?id=<?=$i;?>';">
+ <?=$ent['enabled'];?>&nbsp;
+ </td>
+ <td class="listbg" ondblclick="document.location='freeswitch_dialplan_includes_edit.php?id=<?=$i;?>';">
+ <font color="#FFFFFF"><?=htmlspecialchars($ent['descr']);?>&nbsp;
+ </td>
+ <td valign="middle" nowrap class="list">
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td valign="middle"><a href="freeswitch_dialplan_includes_edit.php?id=<?=$i;?>"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_e.gif" width="17" height="17" border="0"></a></td>
+ <td><a href="freeswitch_dialplan_includes.php?type=dialplanincludes&act=del&id=<?=$i;?>" onclick="return confirm('Do you really want to delete this?')"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_x.gif" width="17" height="17" border="0"></a></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <?php
+ $i++;
+ }
+ }
+ ?>
+ <tr>
+ <td class="list" colspan="4"></td>
+ <td class="list">
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td width="17"></td>
+ <td valign="middle"><a href="freeswitch_dialplan_includes_edit.php"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" width="17" height="17" border="0"></a></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+
+ <tr>
+ <td class="list" colspan="4"></td>
+ <td class="list"></td>
+ </tr>
+ </table>
+
+</form>
+
+/usr/local/freeswitch/conf/dialplan/default/
+<br>
+<br>
+<br>
+<br>
+<br>
+<br>
+
+</td>
+</tr>
+</table>
+
+</div>
+
+
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/freeswitch/freeswitch_dialplan_includes_details.tmp b/config/freeswitch/freeswitch_dialplan_includes_details.tmp
new file mode 100644
index 00000000..7b14dae4
--- /dev/null
+++ b/config/freeswitch/freeswitch_dialplan_includes_details.tmp
@@ -0,0 +1,53 @@
+<?php
+/* $Id$ */
+/*
+ freeswitch_dialplan_includes_details.php
+ Copyright (C) 2008 Mark J Crane
+ All rights reserved.
+
+ FreeSWITCH (TM)
+ http://www.freeswitch.org/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require("guiconfig.inc");
+require("/usr/local/pkg/freeswitch.inc");
+
+
+$a_dialplan_include_details = &$config['installedpackages']['freeswitchdialplanincludedetails']['config'];
+
+
+if ($_GET['act'] == "del") {
+ if ($_GET['type'] == 'dialplanincludedetails') {
+ if ($a_dialplan_include_details[$_GET['id']]) {
+ unset($a_dialplan_include_details[$_GET['id']]);
+ write_config();
+ sync_package_freeswitch_dialplan_includes();
+ //touch($d_hostsdirty_path);
+ header("Location: freeswitch_dialplan_includes_edit.php?id=".$_GET['parentid']);
+ exit;
+ }
+ }
+}
+
+?> \ No newline at end of file
diff --git a/config/freeswitch/freeswitch_dialplan_includes_details_edit.tmp b/config/freeswitch/freeswitch_dialplan_includes_details_edit.tmp
new file mode 100644
index 00000000..391d46d7
--- /dev/null
+++ b/config/freeswitch/freeswitch_dialplan_includes_details_edit.tmp
@@ -0,0 +1,375 @@
+<?php
+/* $Id$ */
+/*
+
+ freeswitch_dialplan_includes_details_edit.php
+ Copyright (C) 2008 Mark J Crane
+ All rights reserved.
+
+ FreeSWITCH (TM)
+ http://www.freeswitch.org/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require("guiconfig.inc");
+require("/usr/local/pkg/freeswitch.inc");
+
+
+$a_dialplan_includes_details = &$config['installedpackages']['freeswitchdialplanincludedetails']['config'];
+
+$id = $_GET['id'];
+if (isset($_POST['id'])) {
+ $id = $_POST['id'];
+}
+
+$parentid = $_GET['parentid'];
+if (isset($_POST['parentid'])) {
+ $parentid = $_POST['parentid'];
+}
+
+$dialplanincludeid = $_GET['dialplanincludeid'];
+if (isset($_POST['dialplanincludeid'])) {
+ $dialplanincludeid = $_POST['dialplanincludeid'];
+}
+
+
+ //dialplanincludeid
+ //tag
+ //condition
+ //action
+ //antiaction
+ //param
+ //tagorder
+ //1-20
+ //fieldtype
+
+ //fielddata
+
+
+if (isset($id) && $a_dialplan_includes_details[$id]) {
+ $pconfig['dialplanincludeid'] = $a_dialplan_includes_details[$id]['dialplanincludeid'];
+ $pconfig['tag'] = $a_dialplan_includes_details[$id]['tag'];
+ //$pconfig['tagorder'] = $a_dialplan_includes_details[$id]['tagorder'];
+ $pconfig['fieldtype'] = $a_dialplan_includes_details[$id]['fieldtype'];
+ $pconfig['fielddata'] = $a_dialplan_includes_details[$id]['fielddata'];
+}
+//else {
+// if (isset($_GET['a'])) {
+// if ($_GET['a'] == "action"){ $pconfig['optionaction'] = "action"; }
+// if ($_GET['a'] == "antiaction"){ $pconfig['optionaction'] = "anti-action"; }
+// }
+//}
+
+
+
+if ($_POST) {
+
+ unset($input_errors);
+ $pconfig = $_POST;
+
+
+ if (!$input_errors) {
+
+ $ent = array();
+ $ent['dialplanincludeid'] = $_POST['dialplanincludeid'];
+ $ent['tag'] = $_POST['tag'];
+ //$ent['tagorder'] = $_POST['tagorder'];
+ $ent['fieldtype'] = $_POST['fieldtype'];
+ $ent['fielddata'] = $_POST['fielddata'];
+
+
+ if (isset($id) && $a_dialplan_includes_details[$id]) {
+ //update
+ $a_dialplan_includes_details[$id] = $ent;
+ }
+ else {
+ //add
+ $a_dialplan_includes_details[] = $ent;
+ }
+
+ write_config();
+ sync_package_freeswitch_dialplan_includes();
+
+ header("Location: freeswitch_dialplan_includes_edit.php?id=".$parentid);
+ exit;
+ }
+}
+
+include("head.inc");
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<?php include("fbegin.inc"); ?>
+<p class="pgtitle">FreeSWITCH: Dialplan: Details: Edit</p>
+
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+
+<div id="mainlevel">
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+<tr><td class="tabnavtbl">
+<?php
+
+ $tab_array = array();
+ $tab_array[] = array(gettext("Settings"), false, "/pkg_edit.php?xml=freeswitch.xml&amp;id=0");
+ $tab_array[] = array(gettext("Dialplan"), true, "/freeswitch/freeswitch_dialplan_includes.php");
+ $tab_array[] = array(gettext("Extensions"), false, "/freeswitch/freeswitch_extensions.php");
+ $tab_array[] = array(gettext("External"), false, "/pkg_edit.php?xml=freeswitch_external.xml&amp;id=0");
+ $tab_array[] = array(gettext("Gateways"), false, "/freeswitch/freeswitch_gateways.php");
+ $tab_array[] = array(gettext("Internal"), false, "/pkg_edit.php?xml=freeswitch_internal.xml&amp;id=0");
+ $tab_array[] = array(gettext("IVR"), false, "/freeswitch/freeswitch_ivr.php");
+ $tab_array[] = array(gettext("Modules"), false, "/pkg_edit.php?xml=freeswitch_modules.xml&amp;id=0");
+ $tab_array[] = array(gettext("Public"), false, "/freeswitch/freeswitch_public_includes.php");
+ $tab_array[] = array(gettext("Rec"), false, "/freeswitch/freeswitch_recordings.php");
+ $tab_array[] = array(gettext("Status"), false, "/freeswitch/freeswitch_status.php");
+ $tab_array[] = array(gettext("Vars"), false, "/pkg_edit.php?xml=freeswitch_vars.xml&amp;id=0");
+ display_top_tabs($tab_array);
+
+?>
+</td></tr>
+</table>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabcont" >
+
+ <form action="freeswitch_dialplan_includes_details_edit.php" method="post" name="iform" id="iform">
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="22%" valign="top" class="vncellreq">Tag</td>
+ <td width="78%" class="vtable">
+ <script type="text/javascript">
+ function dialplan_include_details_tag_onchange() {
+ var tag = document.getElementById("form_tag").value;
+ if (tag == "condition") {
+ document.getElementById("label_fieldtype").innerHTML = "Field";
+ document.getElementById("label_fielddata").innerHTML = "Expression";
+ }
+ else if (tag == "action") {
+ document.getElementById("label_fieldtype").innerHTML = "Application";
+ document.getElementById("label_fielddata").innerHTML = "Data";
+ }
+ else if (tag == "anti-action") {
+ document.getElementById("label_fieldtype").innerHTML = "Application";
+ document.getElementById("label_fielddata").innerHTML = "Data";
+ }
+ else if (tag == "param") {
+ document.getElementById("label_fieldtype").innerHTML = "Name";
+ document.getElementById("label_fielddata").innerHTML = "Value";
+ }
+ if (tag == "") {
+ document.getElementById("label_fieldtype").innerHTML = "Type";
+ document.getElementById("label_fielddata").innerHTML = "Data";
+ }
+ }
+ </script>
+ <?php
+ echo " <select name='tag' class='formfld' id='form_tag' onchange='dialplan_include_details_tag_onchange();'>\n";
+ echo " <option></option>\n";
+ switch (htmlspecialchars($pconfig['tag'])) {
+ case "condition":
+ echo " <option selected='yes'>condition</option>\n";
+ echo " <option>action</option>\n";
+ echo " <option>anti-action</option>\n";
+ //echo " <option>param</option>\n";
+ break;
+ case "action":
+ echo " <option>condition</option>\n";
+ echo " <option selected='yes'>action</option>\n";
+ echo " <option>anti-action</option>\n";
+ //echo " <option>param</option>\n";
+ break;
+ case "anti-action":
+ echo " <option>condition</option>\n";
+ echo " <option>action</option>\n";
+ echo " <option selected='yes'>anti-action</option>\n";
+ //echo " <option>param</option>\n";
+ break;
+ case "param":
+ echo " <option>condition</option>\n";
+ echo " <option>action</option>\n";
+ echo " <option>anti-action</option>\n";
+ //echo " <option selected='yes'>param</option>\n";
+ break;
+ default:
+ echo " <option>condition</option>\n";
+ echo " <option>action</option>\n";
+ echo " <option>anti-action</option>\n";
+ //echo " <option>param</option>\n";
+ }
+ echo " </select>\n";
+
+ //condition
+ //field expression
+ //action
+ //application
+ //data
+ //antiaction
+ //application
+ //data
+ //param
+ //name
+ //value
+
+ ?>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq" id="label_fieldtype">Type</td>
+ <td width="78%" class="vtable">
+ <input name="fieldtype" type="text" class="formfld" id="fieldtype" size="40" value="<?=htmlspecialchars($pconfig['fieldtype']);?>">
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq" id="label_fielddata">Data</td>
+ <td width="78%" class="vtable">
+ <input name="fielddata" type="text" class="formfld" id="fielddata" size="40" value="<?=htmlspecialchars($pconfig['fielddata']);?>">
+ <br> <span class="vexpl"></span></td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <input name="dialplanincludeid" type="hidden" value="<?=$dialplanincludeid;?>">
+ <input name="parentid" type="hidden" value="<?=$parentid;?>">
+ <?php if (isset($id) && $a_dialplan_includes_details[$id]): ?>
+ <input name="id" type="hidden" value="<?=$id;?>">
+ <?php endif; ?>
+ <input name="Submit" type="submit" class="formbtn" value="Save"> <input class="formbtn" type="button" value="Cancel" onclick="history.back()">
+ </td>
+ </tr>
+ </table>
+ </form>
+
+ <br />
+ <br />
+ <b>Additional Information</b>
+ <br />
+ <br />
+ <a href='http://wiki.freeswitch.org/wiki/Dialplan_XML' target='_blank'>http://wiki.freeswitch.org/wiki/Dialplan_XML</a>
+
+ <br />
+ <br />
+ <br />
+ <br />
+
+ <b>Conditions</b>
+ <br />
+ <br />
+ Conditions are pattern matching tags that help FreeSwitch decide if the current call should be processed in this extension or not. When matching conditions against the current call you have several <b>fields</b> that you can compare against.
+ <ul>
+ <li><b>context</b></li>
+ <li><b>rdnis</b> Redirected Number, the directory number to which the call was last presented.</li>
+ <li><b>destination_number</b> Called Number, the number this call is trying to reach (within a given context)</li>
+ <li><b>dialplan</b> Name of the dialplan module that are used, the name is provided by each dialplan module. Example: XML</li>
+ <li><b>caller_id_name</b> Name of the caller (provided by the User Agent that has called us).</li>
+ <li><b>caller_id_number</b> Directory Number of the party who called (callee) -- can be masked (hidden)</li>
+ <li><b>ani</b> Automatic Number Identification, the number of the calling party (callee) -- cannot be masked</li>
+ <li><b>ani2</b> The type of device placing the call [1]</li>
+ <li><b>uuid</b> Unique identifier of the current call? (looks like a GUID)</li>
+ <li><b>source</b> Name of the FreeSwitch module that received the call (e.g. PortAudio)</li>
+ <li><b>chan_name</b> Name of the current channel (Example: PortAudio/1234). Give us examples when this one can be used.</li>
+ <li><b>network_addr</b> IP address of the signalling source for a VoIP call.</li>
+ </ul>
+ In addition to the above you can also do variables using the syntax ${variable} or api functions using the syntax %{api} {args}
+ <br />
+ <br />
+ Variables may be used in either the field or the expression, as follows
+
+ <br />
+ <br />
+ <br />
+ <br />
+
+ <b>Action and Anti-Actions</b>
+ <br />
+ <br />
+ Actions are executed when the <b>condition matches</b>. Anti-Actions are executed when the <b>condition does NOT match</b>.
+ Additional information on applications for Actions and Anti-Actions.<br />
+ <a href='http://wiki.freeswitch.org/wiki/Modules#Applications' target='_blank'>http://wiki.freeswitch.org/wiki/Modules#Applications</a>
+ <br />
+ <a href='http://wiki.freeswitch.org/wiki/Dialplan_Functions' target='_blank'>http://wiki.freeswitch.org/wiki/Dialplan_Functions</a>
+ <br />
+ <br />
+ <br />
+ The following is a partial list of <b>applications</b>.
+ <ul>
+ <li><b>answer</b> answer the call</li>
+ <li><b>bridge</b> bridge the call<li>
+ <li><b>cond</b></li>
+ <li><b>db</b> is a a runtime database either sqlite by default or odbc</li>
+ <li><b>global_set</b> allows setting of global vars similar to the ones found in vars.xml</li>
+ <li><b>group</b> allows grouping of several extensions for things like ring groups</li>
+ <li><b>expr</b></li>
+ <li><b>hangup</b> hangs up the call</li>
+ <li><b>info</b> sends call info to the console</li>
+ <li><b>javascript</b> run javascript .js files</li>
+ <li><b>playback</b></li>
+ <li><b>reject</b> reject the call</li>
+ <li><b>respond</b></li>
+ <li><b>ring_ready</b></li>
+ <li><b>set</b> set a variable</li>
+ <li><b>set_user</b></li>
+ <li><b>sleep</b></li>
+ <li><b>sofia_contact</b></li>
+ <li><b>transfer</b> transfer the call to another extension or number<li>
+ <li><b>voicemail</b> send the call to voicemail</li>
+ </ul>
+
+
+ <br />
+ <br />
+
+ <!--
+ <b>Param</b>
+ Example parameters by name and value
+ <br />
+ <a href='http://wiki.freeswitch.org/wiki/Special:Search?search=param&go=Go' target='_blank'>http://wiki.freeswitch.org/wiki/Special:Search?search=param&go=Go</a>
+ <ul>
+ <li><b>codec-ms</b> 20</li>
+ <li><b>codec-prefs</b> PCMU@20i</li>
+ <li><b>debug</b> 1</li>
+ <li><b>dialplan</b> XML</li>
+ <li><b>dtmf-duration</b> 100</li>
+ <li><b>rfc2833-pt</b>" 101</li>
+ <li><b>sip-port</b> 5060</li>
+ <li><b>use-rtp-timer</b> true</li>
+ </ul>
+ <br />
+ <br />
+ -->
+
+
+ <br />
+ <br />
+ <br />
+ <br />
+ <br />
+
+ </td>
+ </tr>
+</table>
+
+</div>
+
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/freeswitch/freeswitch_dialplan_includes_edit.tmp b/config/freeswitch/freeswitch_dialplan_includes_edit.tmp
new file mode 100644
index 00000000..e838a277
--- /dev/null
+++ b/config/freeswitch/freeswitch_dialplan_includes_edit.tmp
@@ -0,0 +1,524 @@
+<?php
+/* $Id$ */
+/*
+
+ freeswitch_dialplan_includes_edit.php
+ Copyright (C) 2008 Mark J Crane
+ All rights reserved.
+
+ FreeSWITCH (TM)
+ http://www.freeswitch.org/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require("guiconfig.inc");
+require("/usr/local/pkg/freeswitch.inc");
+
+
+//freeswitchdialplanincludes
+ //dialplanincludeid
+ //extensionname
+ //context
+ //default
+ //enabled
+ //descr
+
+//
+
+
+
+$a_dialplan_includes = &$config['installedpackages']['freeswitchdialplanincludes']['config'];
+$a_dialplan_include_details = &$config['installedpackages']['freeswitchdialplanincludedetails']['config'];
+
+$id = $_GET['id'];
+if (isset($_POST['id'])) {
+ $id = $_POST['id'];
+}
+$parentid = $id;
+
+
+if (isset($id) && $a_dialplan_includes[$id]) {
+ $pconfig['dialplanincludeid'] = $a_dialplan_includes[$id]['dialplanincludeid'];
+ $dialplanincludeid = $a_dialplan_includes[$id]['dialplanincludeid'];
+ $pconfig['extensionname'] = $a_dialplan_includes[$id]['extensionname'];
+ $pconfig['order'] = $a_dialplan_includes[$id]['order'];
+ $pconfig['context'] = $a_dialplan_includes[$id]['context'];
+ $pconfig['enabled'] = $a_dialplan_includes[$id]['enabled'];
+ $pconfig['descr'] = $a_dialplan_includes[$id]['descr'];
+ $pconfig['opt1name'] = $a_dialplan_includes[$id]['opt1name'];
+ $pconfig['opt1value'] = $a_dialplan_includes[$id]['opt1value'];
+}
+
+if ($_POST) {
+
+ unset($input_errors);
+ $pconfig = $_POST;
+
+ if ($_GET['act'] == "del") {
+ if ($_GET['type'] == 'dialplanincludedetails') {
+ if ($a_dialplan_include_details[$_GET['id']]) {
+ unset($a_dialplan_include_details[$_GET['id']]);
+ write_config();
+ sync_package_freeswitch_dialplan_includes();
+ header("Location: freeswitch_dialplan_include_edit.php?id=".$_GET['id']);
+ exit;
+ }
+ }
+ }
+
+
+ if (!$input_errors) {
+
+ $ent = array();
+ if (strlen($_POST['dialplanincludeid']) > 0) {
+ //update
+ $ent['dialplanincludeid'] = $_POST['dialplanincludeid'];
+ }
+ else {
+ //add
+ $ent['dialplanincludeid'] = guid();
+ }
+ $ent['extensionname'] = $_POST['extensionname'];
+ $ent['order'] = $_POST['order'];
+ //$ent['context'] = $_POST['context'];
+ $ent['context'] = 'default';
+ $ent['enabled'] = $_POST['enabled'];
+ $ent['descr'] = $_POST['descr'];
+ $ent['opt1name'] = $_POST['opt1name'];
+ $ent['opt1value'] = $_POST['opt1value'];
+
+
+ if (isset($id) && $a_dialplan_includes[$id]) {
+
+ if (count($a_dialplan_includes)>0) {
+ foreach($a_dialplan_includes as $rowhelper) {
+
+ //$rowhelper['dialplanincludeid'];
+ //$rowhelper['extensionname'];
+ //$rowhelper['context'];
+ //$rowhelper['enabled'];
+
+ $filenamechanged = false;
+ if ($rowhelper['dialplanincludeid'] == $_POST['dialplanincludeid']) {
+
+ if ($rowhelper['extensionname'] != $_POST['extensionname']) {
+ //if the extension name has changed then remove the current dialplan xml file
+ //to prepare for the new file
+ $filenamechanged = true;
+ }
+ if ($rowhelper['order'] != $_POST['order']) {
+ //if the order has changed then remove the current dialplan xml file
+ //to prepare for the new file
+ $filenamechanged = true;
+ }
+ if ($_POST['enabled'] == "false") {
+ //if the extension name is disabled then remove the dialplan xml file
+ $filenamechanged = true;
+ }
+ if ($filenamechanged){
+ $dialplanincludefilename = $rowhelper['order']."_".$rowhelper['extensionname'].".xml";
+ if (file_exists("/usr/local/freeswitch/conf/dialplan/default/".$dialplanincludefilename)) {
+ unlink("/usr/local/freeswitch/conf/dialplan/default/".$dialplanincludefilename);
+ }
+ unset($dialplanincludefilename);
+ }
+
+ }
+ unset($filenamechanged);
+
+ } //end foreach
+ } //end count
+
+ //update the config
+ $a_dialplan_includes[$id] = $ent;
+ }
+ else {
+ //add to the config
+ $a_dialplan_includes[] = $ent;
+ }
+
+
+ write_config();
+ sync_package_freeswitch_dialplan_includes();
+
+ header("Location: freeswitch_dialplan_includes.php");
+ exit;
+ }
+}
+
+include("head.inc");
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<?php include("fbegin.inc"); ?>
+<p class="pgtitle">FreeSWITCH: Dialplan: Edit</p>
+
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+
+
+<div id="mainlevel">
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+<tr><td class="tabnavtbl">
+<?php
+
+ $tab_array = array();
+ $tab_array[] = array(gettext("Settings"), false, "/pkg_edit.php?xml=freeswitch.xml&amp;id=0");
+ $tab_array[] = array(gettext("Dialplan"), true, "/freeswitch/freeswitch_dialplan_includes.php");
+ $tab_array[] = array(gettext("Extensions"), false, "/freeswitch/freeswitch_extensions.php");
+ $tab_array[] = array(gettext("External"), false, "/pkg_edit.php?xml=freeswitch_external.xml&amp;id=0");
+ $tab_array[] = array(gettext("Gateways"), false, "/freeswitch/freeswitch_gateways.php");
+ $tab_array[] = array(gettext("Internal"), false, "/pkg_edit.php?xml=freeswitch_internal.xml&amp;id=0");
+ $tab_array[] = array(gettext("IVR"), false, "/freeswitch/freeswitch_ivr.php");
+ $tab_array[] = array(gettext("Modules"), false, "/pkg_edit.php?xml=freeswitch_modules.xml&amp;id=0");
+ $tab_array[] = array(gettext("Public"), false, "/freeswitch/freeswitch_public_includes.php");
+ $tab_array[] = array(gettext("Rec"), false, "/freeswitch/freeswitch_recordings.php");
+ $tab_array[] = array(gettext("Status"), false, "/freeswitch/freeswitch_status.php");
+ $tab_array[] = array(gettext("Vars"), false, "/pkg_edit.php?xml=freeswitch_vars.xml&amp;id=0");
+ display_top_tabs($tab_array);
+
+?>
+</td></tr>
+</table>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabcont" >
+
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td><p><span class="vexpl"><span class="red"><strong>Dialplan:<br>
+ </strong></span>
+ Dialplan Include general settings.
+ </span></p></td>
+ </tr>
+ </table>
+ <br />
+
+ <form action="freeswitch_dialplan_includes_edit.php" method="post" name="iform" id="iform">
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="22%" valign="top" class="vncellreq">Extension Name</td>
+ <td width="78%" class="vtable">
+ <input name="extensionname" type="text" class="formfld" id="extensionname" size="40" value="<?=htmlspecialchars($pconfig['extensionname']);?>">
+ <br />
+ Supported characters are 'a-z', 'A-Z', '0-9', underscore '_', and period '.'.
+ </td>
+ </tr>
+ <!--
+ <tr>
+ <td width="22%" valign="top" class="vncellreq">Context</td>
+ <td width="78%" class="vtable">
+ <input name="context" type="text" class="formfld" id="context" size="40" value="<?=htmlspecialchars($pconfig['context']);?>">
+ <br />
+ e.g. default
+ </td>
+ </tr>
+ -->
+
+ <tr>
+ <td width="22%" valign="top" class="vncellreq">Enabled</td>
+ <td width="78%" class="vtable">
+ <?php
+ echo " <select name='enabled' class='formfld'>\n";
+ echo " <option></option>\n";
+ switch (htmlspecialchars($pconfig['enabled'])) {
+ case "true":
+ echo " <option value='true' selected='yes'>true</option>\n";
+ echo " <option value='false'>false</option>\n";
+ break;
+ case "false":
+ echo " <option value='true'>true</option>\n";
+ echo " <option value='false' selected='yes'>false</option>\n";
+
+ break;
+ default:
+ echo " <option value='true' selected='yes'>true</option>\n";
+ echo " <option value='false'>false</option>\n";
+ }
+ echo " </select>\n";
+ ?>
+ </td>
+ </tr>
+
+ <tr>
+ <td width="22%" valign="top" class="vncellreq">Order</td>
+ <td width="78%" class="vtable">
+ <?php
+
+ echo " <select name='order' class='formfld'>\n";
+ echo " <option></option>\n";
+ if (strlen(htmlspecialchars($pconfig['order']))> 0) {
+ echo " <option selected='yes' value='".htmlspecialchars($pconfig['order'])."'>".htmlspecialchars($pconfig['order'])."</option>\n";
+ }
+ $i=0;
+ while($i<=999) {
+ if (strlen($i) == 1) {
+ echo " <option value='00$i'>00$i</option>\n";
+ }
+ if (strlen($i) == 2) {
+ echo " <option value='0$i'>0$i</option>\n";
+ }
+ if (strlen($i) == 3) {
+ echo " <option value='$i'>$i</option>\n";
+ }
+
+ $i++;
+ }
+ echo " </select>\n";
+ ?>
+ <br />
+ Processing of each dialplan include is determined by this order.
+ </td>
+ </tr>
+
+ <tr>
+ <td width="22%" valign="top" class="vncell">Description</td>
+ <td width="78%" class="vtable">
+ <input name="descr" type="text" class="formfld" id="descr" size="40" value="<?=htmlspecialchars($pconfig['descr']);?>">
+ <br> <span class="vexpl">You may enter a description here
+ for your reference (not parsed).</span></td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <input name="dialplanincludeid" type="hidden" value="<?=htmlspecialchars($pconfig['dialplanincludeid']);?>">
+ <?php
+ if (strlen($id) > 0 && $a_dialplan_includes[$id]) {
+ echo "\n";
+ echo " <input name=\"id\" type=\"hidden\" value=\"$id\">\n";
+ echo " <input name=\"opt1name\" type=\"hidden\" value=\"".htmlspecialchars($pconfig['opt1name'])."\">\n";
+ echo " <input name=\"opt1value\" type=\"hidden\" value=\"".htmlspecialchars($pconfig['opt1value'])."\">\n";
+ }
+ ?>
+ <input name="Submit" type="submit" class="formbtn" value="Save"> <input class="formbtn" type="button" value="Cancel" onclick="history.back()">
+ </td>
+ </tr>
+ </table>
+ </form>
+
+ <br>
+ <br>
+
+ <form action="freeswitch_dialplan_includes_edit.php" method="post" name="iform2" id="iform2">
+ <?php
+
+ //echo "<pre>";
+ //print_r ($a_dialplan_includes);
+ //echo "</pre>";
+
+ //if ($savemsg) print_info_box($savemsg);
+ //if (file_exists($d_hostsdirty_path)): echo"<p>";
+ //print_info_box_np("The FreeSWITCH recordings have been changed.<br>You must apply the changes in order for them to take effect.");
+ //echo"<br />";
+ //endif;
+
+ ?>
+
+
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td><p><span class="vexpl"><span class="red"><strong>Conditions and Actions<br />
+ </strong></span>
+ The following conditions, actions and anti-actions are used in the dialplan to direct call flow. Each is processed in order until you reach the action tag which tells FreeSWITCH what action to perform. You are not limited to only one condition or action tag for a given extension.
+ </span></p></td>
+ </tr>
+ </table>
+ <br />
+
+ <table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td width="20%" class="listhdrr">Tag</td>
+ <td width="20%" class="listhdrr">Type</td>
+ <td width="50%" class="listhdrr">Data</td>
+ <td width="10%" class="list">
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td width="17"></td>
+ <td valign="middle"><a href="freeswitch_dialplan_includes_details_edit.php?parentid=<?=$parentid;?>&dialplanincludeid=<?=$dialplanincludeid;?>&a=action"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" width="17" height="17" border="0"></a></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+
+ <?php
+
+ $i = 0;
+ if (count($a_dialplan_include_details) > 0) {
+
+ foreach ($a_dialplan_include_details as $ent) {
+ if ($ent['tag'] == "condition" && $dialplanincludeid == $ent['dialplanincludeid']) {
+ ?>
+ <tr>
+ <td class="listlr" ondblclick="document.location='freeswitch_dialplan_includes_details_edit.php?id=<?=$i;?>&parentid=<?=$parentid;?>&dialplanincludeid=<?=$dialplanincludeid;?>'">
+ <?=$ent['tag']?>
+ </td>
+ <td class="listr" ondblclick="document.location='freeswitch_dialplan_includes_details_edit.php?id=<?=$i;?>&parentid=<?=$parentid;?>&dialplanincludeid=<?=$dialplanincludeid;?>';">
+ <?=$ent['fieldtype'];?>&nbsp;
+ </td>
+ <td class="listr" ondblclick="document.location='freeswitch_dialplan_includes_details_edit.php?id=<?=$i;?>&parentid=<?=$parentid;?>&dialplanincludeid=<?=$dialplanincludeid;?>';">
+ <?=$ent['fielddata'];?>&nbsp;
+ </td>
+ <td valign="middle" nowrap class="list">
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td valign="middle"><a href="freeswitch_dialplan_includes_details_edit.php?id=<?=$i;?>&parentid=<?=$parentid;?>&dialplanincludeid=<?=$dialplanincludeid;?>"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_e.gif" width="17" height="17" border="0"></a></td>
+ <td><a href="freeswitch_dialplan_includes_details.php?type=dialplanincludedetails&act=del&id=<?=$i;?>&parentid=<?=$parentid;?>&dialplanincludeid=<?=$dialplanincludeid;?>" onclick="return confirm('Do you really want to delete this?')"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_x.gif" width="17" height="17" border="0"></a></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <?php
+ }
+ $i++;
+ }
+ }
+
+ $i = 0;
+ if (count($a_dialplan_include_details) > 0) {
+
+ foreach ($a_dialplan_include_details as $ent) {
+ if ($ent['tag'] == "action" && $dialplanincludeid == $ent['dialplanincludeid']) {
+ ?>
+ <tr>
+ <td class="listlr" ondblclick="document.location='freeswitch_dialplan_includes_details_edit.php?id=<?=$i;?>&parentid=<?=$parentid;?>&dialplanincludeid=<?=$dialplanincludeid;?>'">
+ <?=$ent['tag']?>
+ </td>
+ <td class="listr" ondblclick="document.location='freeswitch_dialplan_includes_details_edit.php?id=<?=$i;?>&parentid=<?=$parentid;?>&dialplanincludeid=<?=$dialplanincludeid;?>';">
+ <?=$ent['fieldtype'];?>&nbsp;
+ </td>
+ <td class="listr" ondblclick="document.location='freeswitch_dialplan_includes_details_edit.php?id=<?=$i;?>&parentid=<?=$parentid;?>&dialplanincludeid=<?=$dialplanincludeid;?>';">
+ <?=$ent['fielddata'];?>&nbsp;
+ </td>
+ <td valign="middle" nowrap class="list">
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td valign="middle"><a href="freeswitch_dialplan_includes_details_edit.php?id=<?=$i;?>&parentid=<?=$parentid;?>&dialplanincludeid=<?=$dialplanincludeid;?>"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_e.gif" width="17" height="17" border="0"></a></td>
+ <td><a href="freeswitch_dialplan_includes_details.php?type=dialplanincludedetails&act=del&id=<?=$i;?>&parentid=<?=$parentid;?>&dialplanincludeid=<?=$dialplanincludeid;?>" onclick="return confirm('Do you really want to delete this?')"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_x.gif" width="17" height="17" border="0"></a></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <?php
+ }
+ $i++;
+ }
+ }
+
+ $i = 0;
+ if (count($a_dialplan_include_details) > 0) {
+
+ foreach ($a_dialplan_include_details as $ent) {
+ if ($ent['tag'] == "anti-action" && $dialplanincludeid == $ent['dialplanincludeid']) {
+ ?>
+ <tr>
+ <td class="listlr" ondblclick="document.location='freeswitch_dialplan_includes_details_edit.php?id=<?=$i;?>&parentid=<?=$parentid;?>&dialplanincludeid=<?=$dialplanincludeid;?>'">
+ <?=$ent['tag']?>
+ </td>
+ <td class="listr" ondblclick="document.location='freeswitch_dialplan_includes_details_edit.php?id=<?=$i;?>&parentid=<?=$parentid;?>&dialplanincludeid=<?=$dialplanincludeid;?>';">
+ <?=$ent['fieldtype'];?>&nbsp;
+ </td>
+ <td class="listr" ondblclick="document.location='freeswitch_dialplan_includes_details_edit.php?id=<?=$i;?>&parentid=<?=$parentid;?>&dialplanincludeid=<?=$dialplanincludeid;?>';">
+ <?=$ent['fielddata'];?>&nbsp;
+ </td>
+ <td valign="middle" nowrap class="list">
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td valign="middle"><a href="freeswitch_dialplan_includes_details_edit.php?id=<?=$i;?>&parentid=<?=$parentid;?>&dialplanincludeid=<?=$dialplanincludeid;?>"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_e.gif" width="17" height="17" border="0"></a></td>
+ <td><a href="freeswitch_dialplan_includes_details.php?type=dialplanincludedetails&act=del&id=<?=$i;?>&parentid=<?=$parentid;?>&dialplanincludeid=<?=$dialplanincludeid;?>" onclick="return confirm('Do you really want to delete this?')"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_x.gif" width="17" height="17" border="0"></a></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <?php
+ }
+ $i++;
+ }
+ }
+
+ $i = 0;
+ if (count($a_dialplan_include_details) > 0) {
+
+ foreach ($a_dialplan_include_details as $ent) {
+ if ($ent['tag'] == "param" && $dialplanincludeid == $ent['dialplanincludeid']) {
+ ?>
+ <tr>
+ <td class="listlr" ondblclick="document.location='freeswitch_dialplan_includes_details_edit.php?id=<?=$i;?>&parentid=<?=$parentid;?>&dialplanincludeid=<?=$dialplanincludeid;?>'">
+ <?=$ent['tag']?>
+ </td>
+ <td class="listr" ondblclick="document.location='freeswitch_dialplan_includes_details_edit.php?id=<?=$i;?>&parentid=<?=$parentid;?>&dialplanincludeid=<?=$dialplanincludeid;?>';">
+ <?=$ent['fieldtype'];?>&nbsp;
+ </td>
+ <td class="listr" ondblclick="document.location='freeswitch_dialplan_includes_details_edit.php?id=<?=$i;?>&parentid=<?=$parentid;?>&dialplanincludeid=<?=$dialplanincludeid;?>';">
+ <?=$ent['fielddata'];?>&nbsp;
+ </td>
+ <td valign="middle" nowrap class="list">
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td valign="middle"><a href="freeswitch_dialplan_includes_details_edit.php?id=<?=$i;?>&parentid=<?=$parentid;?>&dialplanincludeid=<?=$dialplanincludeid;?>"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_e.gif" width="17" height="17" border="0"></a></td>
+ <td><a href="freeswitch_dialplan_includes_details.php?type=dialplanincludedetails&act=del&id=<?=$i;?>&parentid=<?=$parentid;?>&dialplanincludeid=<?=$dialplanincludeid;?>" onclick="return confirm('Do you really want to delete this?')"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_x.gif" width="17" height="17" border="0"></a></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <?php
+ }
+ $i++;
+ }
+ }
+ ?>
+ <tr>
+ <td class="list" colspan="3"></td>
+ <td class="list">
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td width="17"></td>
+ <td valign="middle"><a href="freeswitch_dialplan_includes_details_edit.php?parentid=<?=$parentid;?>&dialplanincludeid=<?=$dialplanincludeid;?>&a=action"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" width="17" height="17" border="0"></a></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+
+
+ <tr>
+ <td class="list" colspan="3"></td>
+ <td class="list"></td>
+ </tr>
+ </table>
+
+ </form>
+
+
+
+
+ <br>
+ <br>
+
+ </td>
+ </tr>
+</table>
+
+</div>
+
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/freeswitch/freeswitch_extensions.tmp b/config/freeswitch/freeswitch_extensions.tmp
new file mode 100644
index 00000000..ca6f3d73
--- /dev/null
+++ b/config/freeswitch/freeswitch_extensions.tmp
@@ -0,0 +1,209 @@
+<?php
+/* $Id$ */
+/*
+ freeswitch_extensions.php
+ Copyright (C) 2008 Mark J Crane
+ All rights reserved.
+
+ FreeSWITCH (TM)
+ http://www.freeswitch.org/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require("guiconfig.inc");
+require("/usr/local/pkg/freeswitch.inc");
+
+$a_extensions = &$config['installedpackages']['freeswitchextensions']['config'];
+
+
+if ($_GET['act'] == "del") {
+ if ($_GET['type'] == 'extensions') {
+ if ($a_extensions[$_GET['id']]) {
+ unset($a_extensions[$_GET['id']]);
+ write_config();
+ header("Location: freeswitch_extensions.php");
+ exit;
+ }
+ }
+}
+
+include("head.inc");
+
+?>
+
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<?php include("fbegin.inc"); ?>
+<p class="pgtitle">FreeSWITCH: Extensions</p>
+
+<div id="mainlevel">
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+<tr><td class="tabnavtbl">
+<?php
+
+ $tab_array = array();
+ $tab_array[] = array(gettext("Settings"), false, "/pkg_edit.php?xml=freeswitch.xml&amp;id=0");
+ $tab_array[] = array(gettext("Dialplan"), false, "/freeswitch/freeswitch_dialplan_includes.php");
+ $tab_array[] = array(gettext("Extensions"), true, "/freeswitch/freeswitch_extensions.php");
+ $tab_array[] = array(gettext("External"), false, "/pkg_edit.php?xml=freeswitch_external.xml&amp;id=0");
+ $tab_array[] = array(gettext("Gateways"), false, "/freeswitch/freeswitch_gateways.php");
+ $tab_array[] = array(gettext("Internal"), false, "/pkg_edit.php?xml=freeswitch_internal.xml&amp;id=0");
+ $tab_array[] = array(gettext("IVR"), false, "/freeswitch/freeswitch_ivr.php");
+ $tab_array[] = array(gettext("Modules"), false, "/pkg_edit.php?xml=freeswitch_modules.xml&amp;id=0");
+ $tab_array[] = array(gettext("Public"), false, "/freeswitch/freeswitch_public_includes.php");
+ $tab_array[] = array(gettext("Rec"), false, "/freeswitch/freeswitch_recordings.php");
+ $tab_array[] = array(gettext("Status"), false, "/freeswitch/freeswitch_status.php");
+ $tab_array[] = array(gettext("Vars"), false, "/pkg_edit.php?xml=freeswitch_vars.xml&amp;id=0");
+ display_top_tabs($tab_array);
+
+?>
+</td></tr>
+</table>
+
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabcont" >
+
+<form action="freeswitch_extensions.php" method="post" name="iform" id="iform">
+<?php
+
+if ($config_change == 1) {
+ write_config();
+ $config_change = 0;
+}
+
+//if ($savemsg) print_info_box($savemsg);
+//if (file_exists($d_hostsdirty_path)): echo"<p>";
+//print_info_box_np("The FreeSWITCH extensions have been changed.<br>You must apply the changes in order for them to take effect.");
+//echo"<br />";
+//endif;
+
+?>
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td><p><span class="vexpl"><span class="red"><strong>Extensions<br>
+ </strong></span>
+ Use this to configure your SIP extensions.
+ </p></td>
+ </tr>
+ </table>
+ <br />
+
+ <table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td width="20%" class="listhdrr">Extension</td>
+ <td width="25%" class="listhdrr">Mail To</td>
+ <td width="25%" class="listhdrr">Call Group</td>
+ <td width="25%" class="listhdr">Description</td>
+ <td width="10%" class="list">
+
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td width="17"></td>
+ <td valign="middle"><a href="freeswitch_extensions_edit.php"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" width="17" height="17" border="0"></a></td>
+ </tr>
+ </table>
+
+ </td>
+ </tr>
+
+
+ <?php
+
+ $i = 0;
+ if (count($a_extensions) > 0) {
+
+ foreach ($a_extensions as $ent) {
+
+ ?>
+ <tr>
+ <td class="listr" ondblclick="document.location='freeswitch_extensions_edit.php?id=<?=$i;?>';">
+ <?=$ent['extension'];?>&nbsp;
+ </td>
+ <td class="listr" ondblclick="document.location='freeswitch_extensions_edit.php?id=<?=$i;?>';">
+ <?=$ent['vm-mailto'];?>&nbsp;
+ </td>
+ <td class="listr" ondblclick="document.location='freeswitch_extensions_edit.php?id=<?=$i;?>';">
+ <?=$ent['callgroup'];?>&nbsp;
+ </td>
+ <td class="listbg" ondblclick="document.location='freeswitch_extensions_edit.php?id=<?=$i;?>';">
+ <font color="#FFFFFF"><?=htmlspecialchars($ent['description']);?>&nbsp;
+ </td>
+ <td valign="middle" nowrap class="list">
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td valign="middle"><a href="freeswitch_extensions_edit.php?id=<?=$i;?>"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_e.gif" width="17" height="17" border="0"></a></td>
+ <td><a href="freeswitch_extensions.php?type=extensions&act=del&id=<?=$i;?>" onclick="return confirm('Do you really want to delete this?')"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_x.gif" width="17" height="17" border="0"></a></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <?php
+
+ $i++;
+ }
+ }
+ ?>
+
+ <tr>
+ <td class="list" colspan="4"></td>
+ <td class="list">
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td width="17"></td>
+ <td valign="middle"><a href="freeswitch_extensions_edit.php"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" width="17" height="17" border="0"></a></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+
+
+ <tr>
+ <td class="list" colspan="4"></td>
+ <td class="list"></td>
+ </tr>
+ </table>
+
+</form>
+
+
+/usr/local/freeswitch/conf/directory/default/
+<br>
+<br>
+<br>
+<br>
+<br>
+<br>
+<br>
+<br>
+
+</td>
+</tr>
+</table>
+
+</div>
+
+
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/freeswitch/freeswitch_extensions.xml b/config/freeswitch/freeswitch_extensions.xml
new file mode 100644
index 00000000..61277e97
--- /dev/null
+++ b/config/freeswitch/freeswitch_extensions.xml
@@ -0,0 +1,225 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+
+ freeswitch_extensions.xml
+ Copyright (C) 2008 Mark J Crane
+ All rights reserved.
+
+ FreeSWITCH (TM)
+ http://www.freeswitch.org/
+
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>FreeSWITCH is an open source telephony platform designed to facilitate the creation of voice and chat driven products scaling from a soft-phone up to a soft-switch. It can be used as a simple switching engine, a PBX, a media gateway or a media server to host IVR applications using simple scripts or XML to control the callflow.</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>freeswitchextensions</name>
+ <version>0.1</version>
+ <title>FreeSWITCH: Extensions</title>
+ <include_file>/usr/local/pkg/freeswitch.inc</include_file>
+ <tabs>
+ <tab>
+ <text>Settings</text>
+ <url>/pkg_edit.php?xml=freeswitch.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Dialplan</text>
+ <url>/freeswitch/freeswitch_dialplan_includes.php</url>
+ </tab>
+ <tab>
+ <text>Extensions</text>
+ <url>/freeswitch/freeswitch_extensions.php</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>External</text>
+ <url>/pkg_edit.php?xml=freeswitch_external.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Gateways</text>
+ <url>/freeswitch/freeswitch_gateways.php</url>
+ </tab>
+ <tab>
+ <text>Internal</text>
+ <url>/pkg_edit.php?xml=freeswitch_internal.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>IVR</text>
+ <url>/freeswitch/freeswitch_ivr.php</url>
+ </tab>
+ <tab>
+ <text>Modules</text>
+ <url>/pkg_edit.php?xml=freeswitch_modules.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Public</text>
+ <url>/freeswitch/freeswitch_public_includes.php</url>
+ </tab>
+ <tab>
+ <text>Rec</text>
+ <url>/freeswitch/freeswitch_recordings.php</url>
+ </tab>
+ <tab>
+ <text>Status</text>
+ <url>/freeswitch/freeswitch_status.php</url>
+ </tab>
+ <tab>
+ <text>Vars</text>
+ <url>/pkg_edit.php?xml=freeswitch_vars.xml&amp;id=0</url>
+ </tab>
+ </tabs>
+ <configpath>installedpackages->package->$packagename->configuration->extensions</configpath>
+ <adddeleteeditpagefields>
+ <columnitem>
+ <fielddescr>Extension</fielddescr>
+ <fieldname>extension</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Mailbox</fielddescr>
+ <fieldname>mailbox</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Description</fielddescr>
+ <fieldname>description</fieldname>
+ </columnitem>
+ </adddeleteeditpagefields>
+ <fields>
+ <field>
+ <fielddescr>Extension</fielddescr>
+ <fieldname>extension</fieldname>
+ <description>Enter the extension here. The default configuration expects extension numbers between 1001 -1019. To use additional numbers for the extensions by adjusting the dialplan. In the in the dialplan under name="Local_Extension" adjust the regular expression="^(10[01][0-9])$".</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Password</fielddescr>
+ <fieldname>password</fieldname>
+ <description>Enter the password here.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Mailbox</fielddescr>
+ <fieldname>mailbox</fieldname>
+ <description>Enter the mailbox here. Example: extension 1001 then mailbox 1001</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Voicemail Password</fielddescr>
+ <fieldname>vm-password</fieldname>
+ <description>Enter the voicemail password here.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Account Code</fielddescr>
+ <fieldname>accountcode</fieldname>
+ <description>Enter the account code here. Example: extension 1001 then accountcode 1001</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Effective Caller ID Name</fielddescr>
+ <fieldname>effective_caller_id_name</fieldname>
+ <description>Enter the effective caller id name here.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Effective Caller ID Number</fielddescr>
+ <fieldname>effective_caller_id_number</fieldname>
+ <description>Enter the effective caller id number here.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Outbound Caller ID Name</fielddescr>
+ <fieldname>outbound_caller_id_name</fieldname>
+ <description>Enter the outbound caller id name here.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Outbound Caller ID Number</fielddescr>
+ <fieldname>outbound_caller_id_number</fieldname>
+ <description>Enter the outbound caller id number here.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Voicemail Mail To</fielddescr>
+ <fieldname>vm-mailto</fieldname>
+ <description>Optional: Enter the email address to send voicemail to.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Voicemail Attach File</fielddescr>
+ <fieldname>vm-attach-file</fieldname>
+ <description>Choose whether to attach the file to the email.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>true</name>
+ <value>true</value>
+ </option>
+ <option>
+ <name>false</name>
+ <value>false</value>
+ </option>
+ </options>
+ </field>
+
+ <field>
+ <fielddescr>User Context</fielddescr>
+ <fieldname>user_context</fieldname>
+ <description>Enter the user context here. Example: default</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Extension Description</fielddescr>
+ <fieldname>description</fieldname>
+ <description>Enter the description of the extension here.</description>
+ <type>input</type>
+ </field>
+ </fields>
+ <custom_add_php_command>
+ </custom_add_php_command>
+ <custom_php_resync_config_command>
+ sync_package_freeswitch_extensions();
+ </custom_php_resync_config_command>
+ <custom_delete_php_command>
+ sync_package_freeswitch_extensions();
+ </custom_delete_php_command>
+ <custom_php_deinstall_command>
+ </custom_php_deinstall_command>
+</packagegui> \ No newline at end of file
diff --git a/config/freeswitch/freeswitch_extensions_edit.tmp b/config/freeswitch/freeswitch_extensions_edit.tmp
new file mode 100644
index 00000000..9b1639f5
--- /dev/null
+++ b/config/freeswitch/freeswitch_extensions_edit.tmp
@@ -0,0 +1,351 @@
+<?php
+/* $Id$ */
+/*
+
+ freeswitch_extensions_edit.php
+ Copyright (C) 2008 Mark J Crane
+ All rights reserved.
+
+ FreeSWITCH (TM)
+ http://www.freeswitch.org/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require("guiconfig.inc");
+require("/usr/local/pkg/freeswitch.inc");
+
+
+$a_extensions = &$config['installedpackages']['freeswitchextensions']['config'];
+
+$id = $_GET['id'];
+if (isset($_POST['id'])) {
+ $id = $_POST['id'];
+}
+
+if (isset($id) && $a_extensions[$id]) {
+
+ $pconfig['extension'] = $a_extensions[$id]['extension'];
+ $pconfig['password'] = $a_extensions[$id]['password'];
+ $pconfig['mailbox'] = $a_extensions[$id]['mailbox'];
+ $pconfig['vm-password'] = $a_extensions[$id]['vm-password'];
+ $pconfig['accountcode'] = $a_extensions[$id]['accountcode'];
+ $pconfig['effective_caller_id_name'] = $a_extensions[$id]['effective_caller_id_name'];
+ $pconfig['effective_caller_id_number'] = $a_extensions[$id]['effective_caller_id_number'];
+ $pconfig['effective_caller_id_number'] = $a_extensions[$id]['effective_caller_id_number'];
+ $pconfig['outbound_caller_id_name'] = $a_extensions[$id]['outbound_caller_id_name'];
+ $pconfig['outbound_caller_id_number'] = $a_extensions[$id]['outbound_caller_id_number'];
+ $pconfig['vm-mailto'] = $a_extensions[$id]['vm-mailto'];
+ $pconfig['vm-attach-file'] = $a_extensions[$id]['vm-attach-file'];
+ $pconfig['user_context'] = $a_extensions[$id]['user_context'];
+ $pconfig['callgroup'] = $a_extensions[$id]['callgroup'];
+ $pconfig['auth-acl'] = $a_extensions[$id]['auth-acl'];
+ $pconfig['cidr'] = $a_extensions[$id]['cidr'];
+ $pconfig['description'] = $a_extensions[$id]['description'];
+
+}
+
+if ($_POST) {
+
+ unset($input_errors);
+ $pconfig = $_POST;
+
+
+ if (!$input_errors) {
+
+ $ent = array();
+ $ent['extension'] = $_POST['extension'];
+ $ent['password'] = $_POST['password'];
+ $ent['mailbox'] = $_POST['mailbox'];
+ $ent['vm-password'] = $_POST['vm-password'];
+ $ent['accountcode'] = $_POST['accountcode'];
+ $ent['effective_caller_id_name'] = $_POST['effective_caller_id_name'];
+ $ent['effective_caller_id_number'] = $_POST['effective_caller_id_number'];
+ $ent['outbound_caller_id_name'] = $_POST['outbound_caller_id_name'];
+ $ent['outbound_caller_id_number'] = $_POST['outbound_caller_id_number'];
+ $ent['vm-mailto'] = $_POST['vm-mailto'];
+ $ent['vm-attach-file'] = $_POST['vm-attach-file'];
+ $ent['user_context'] = $_POST['user_context'];
+ $ent['callgroup'] = $_POST['callgroup'];
+ $ent['auth-acl'] = $_POST['auth-acl'];
+ $ent['cidr'] = $_POST['cidr'];
+
+ $ent['description'] = $_POST['description'];
+
+ if (isset($id) && $a_extensions[$id]) {
+ //update
+ $a_extensions[$id] = $ent;
+ }
+ else {
+ //add
+ $a_extensions[] = $ent;
+ }
+
+ write_config();
+ sync_package_freeswitch_extensions();
+
+ header("Location: freeswitch_extensions.php");
+ exit;
+ }
+}
+
+include("head.inc");
+
+?>
+
+<script type="text/javascript" language="JavaScript">
+
+function show_advanced_config() {
+ document.getElementById("showadvancedbox").innerHTML='';
+ aodiv = document.getElementById('showadvanced');
+ aodiv.style.display = "block";
+}
+
+</script>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<?php include("fbegin.inc"); ?>
+<p class="pgtitle">FreeSWITCH: Extensions: Edit</p>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+
+
+<div id="mainlevel">
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+<tr><td class="tabnavtbl">
+<?php
+
+ $tab_array = array();
+ $tab_array[] = array(gettext("Settings"), false, "/pkg_edit.php?xml=freeswitch.xml&amp;id=0");
+ $tab_array[] = array(gettext("Dialplan"), false, "/freeswitch/freeswitch_dialplan_includes.php");
+ $tab_array[] = array(gettext("Extensions"), true, "/freeswitch/freeswitch_extensions.php");
+ $tab_array[] = array(gettext("External"), false, "/pkg_edit.php?xml=freeswitch_external.xml&amp;id=0");
+ $tab_array[] = array(gettext("Gateways"), false, "/freeswitch/freeswitch_gateways.php");
+ $tab_array[] = array(gettext("Internal"), false, "/pkg_edit.php?xml=freeswitch_internal.xml&amp;id=0");
+ $tab_array[] = array(gettext("IVR"), false, "/freeswitch/freeswitch_ivr.php");
+ $tab_array[] = array(gettext("Modules"), false, "/pkg_edit.php?xml=freeswitch_modules.xml&amp;id=0");
+ $tab_array[] = array(gettext("Public"), false, "/freeswitch/freeswitch_public_includes.php");
+ $tab_array[] = array(gettext("Rec"), false, "/freeswitch/freeswitch_recordings.php");
+ $tab_array[] = array(gettext("Status"), false, "/freeswitch/freeswitch_status.php");
+ $tab_array[] = array(gettext("Vars"), false, "/pkg_edit.php?xml=freeswitch_vars.xml&amp;id=0");
+ display_top_tabs($tab_array);
+
+?>
+</td></tr>
+</table>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabcont" >
+
+
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td><p><span class="vexpl"><span class="red"><strong>Extension Setup<br>
+ </strong></span>
+ /usr/local/freeswitch/conf/directory/default/
+ </p></td>
+ </tr>
+ </table>
+ <br />
+
+ <form action="freeswitch_extensions_edit.php" method="post" name="iform" id="iform">
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+
+ <tr>
+ <td width="25%" valign="top" class="vncellreq">Extension</td>
+ <td width="75%" class="vtable">
+ <input name="extension" type="text" class="formfld" id="extension" size="40" value="<?=htmlspecialchars($pconfig['extension']);?>">
+ <br><span class="vexpl">Enter the extension here. The default configuration expects extension numbers between 1000 -1019. To use 3 digit extensions adjust the dialplan 'default.xml' under name="Local_Extension" change the regular expression="^(10[01][0-9])$" to expression="^(\d{3})$".<br></span>
+ </td>
+ </tr>
+ <tr>
+ <td width="25%" valign="top" class="vncellreq">Password</td>
+ <td width="75%" class="vtable">
+ <input name="password" type="password" class="formfld" id="password" size="40" value="<?=htmlspecialchars($pconfig['password']);?>">
+ <br><span class="vexpl">Enter the password here.<br></span>
+ </td>
+ </tr>
+ <tr>
+ <td width="25%" valign="top" class="vncellreq">Mailbox</td>
+ <td width="75%" class="vtable">
+ <input name="mailbox" type="text" class="formfld" id="mailbox" size="40" value="<?=htmlspecialchars($pconfig['mailbox']);?>">
+ <br><span class="vexpl">Enter the mailbox here. Example: extension 1001 then mailbox 1001<br></span>
+ </td>
+ </tr>
+ <tr>
+ <td width="25%" valign="top" class="vncellreq">Voicemail Password</td>
+ <td width="75%" class="vtable">
+ <input name="vm-password" type="password" class="formfld" id="vm-password" size="40" value="<?=htmlspecialchars($pconfig['vm-password']);?>">
+ <br><span class="vexpl">Enter the voicemail password here.<br></span>
+ </td>
+ </tr>
+ <tr>
+ <td width="25%" valign="top" class="vncellreq">Account Code</td>
+ <td width="75%" class="vtable">
+ <input name="accountcode" type="text" class="formfld" id="accountcode" size="40" value="<?=htmlspecialchars($pconfig['accountcode']);?>">
+ <br><span class="vexpl">Enter the account code here. Example: extension 1001 then accountcode 1001<br></span>
+ </td>
+ </tr>
+ <tr>
+ <td width="25%" valign="top" class="vncellreq" nowrap>Effective Caller ID Name</td>
+ <td width="75%" class="vtable">
+ <input name="effective_caller_id_name" type="text" class="formfld" id="effective_caller_id_name" size="40" value="<?=htmlspecialchars($pconfig['effective_caller_id_name']);?>">
+ <br><span class="vexpl">Enter the effective caller id name here.<br></span>
+ </td>
+ </tr>
+ <tr>
+ <td width="25%" valign="top" class="vncellreq" nowrap>Effective Caller ID Number</td>
+ <td width="75%" class="vtable">
+ <input name="effective_caller_id_number" type="text" class="formfld" id="effective_caller_id_number" size="40" value="<?=htmlspecialchars($pconfig['effective_caller_id_number']);?>">
+ <br><span class="vexpl">Enter the effective caller id number here.<br></span>
+ </td>
+ </tr>
+ <!--
+ <tr>
+ <td width="25%" valign="top" class="vncellreq" nowrap>Outbound Caller ID Name</td>
+ <td width="75%" class="vtable">
+ <input name="outbound_caller_id_name" type="text" class="formfld" id="outbound_caller_id_name" size="40" value="<?=htmlspecialchars($pconfig['outbound_caller_id_name']);?>">
+ <br><span class="vexpl">Enter the outbound caller id name here.<br></span>
+ </td>
+ </tr>
+ <tr>
+ <td width="25%" valign="top" class="vncellreq" nowrap>Outbound Caller ID Number</td>
+ <td width="75%" class="vtable">
+ <input name="outbound_caller_id_number" type="text" class="formfld" id="outbound_caller_id_number" size="40" value="<?=htmlspecialchars($pconfig['outbound_caller_id_number']);?>">
+ <br><span class="vexpl">Enter the outbound caller id number here.<br></span>
+ </td>
+ </tr>
+ -->
+ <tr>
+ <td width="25%" valign="top" class="vncellreq" nowrap>Voicemail Mail To</td>
+ <td width="75%" class="vtable">
+ <input name="vm-mailto" type="text" class="formfld" id="vm-mailto" size="40" value="<?=htmlspecialchars($pconfig['vm-mailto']);?>">
+ <br><span class="vexpl">Optional: Enter the email address to send voicemail to.<br></span>
+ </td>
+ </tr>
+ <tr>
+ <td width="25%" valign="top" class="vncellreq" nowrap>Voicemail Attach File</td>
+ <td width="75%" class="vtable">
+ <?php
+ echo " <select name='vm-attach-file' class='formfld'>\n";
+ echo " <option></option>\n";
+ switch (htmlspecialchars($pconfig['vm-attach-file'])) {
+ case "true":
+ echo " <option value='true' selected='yes'>true</option>\n";
+ echo " <option value='false'>false</option>\n";
+ break;
+ case "false":
+ echo " <option value='true'>true</option>\n";
+ echo " <option value='false' selected='yes'>false</option>\n";
+
+ break;
+ default:
+ echo " <option value='true' selected='yes'>true</option>\n";
+ echo " <option value='false'>false</option>\n";
+ }
+ echo " </select>\n";
+ ?>
+ Choose whether to attach the file to the email.
+ </td>
+ </tr>
+ <tr>
+ <td width="25%" valign="top" class="vncellreq">User Context</td>
+ <td width="75%" class="vtable">
+ <input name="user_context" type="text" class="formfld" id="user_context" size="40" value="<?=htmlspecialchars($pconfig['user_context']);?>">
+ <br><span class="vexpl">Enter the user context here. Example: default<br></span>
+ </td>
+ </tr>
+ <tr>
+ <td width="25%" valign="top" class="vncellreq">Call Group</td>
+ <td width="75%" class="vtable">
+ <input name="callgroup" type="text" class="formfld" id="callgroup" size="40" value="<?=htmlspecialchars($pconfig['callgroup']);?>">
+ <br><span class="vexpl">Enter the user call group here. Example: sales, support<br></span>
+ </td>
+ </tr>
+ </table>
+
+ <div id="showadvancedbox">
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="25%" valign="top" class="vncell">Show Advanced</td>
+ <td width="75%" class="vtable">
+ <input type="button" onClick="show_advanced_config()" value="Advanced"></input></a>
+ </td>
+ </tr>
+ </table>
+ </div>
+ <div id="showadvanced" style="display:none">
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="25%" valign="top" class="vncell">Auth-ACL</td>
+ <td width="75%" class="vtable">
+ <input name="auth-acl" type="text" class="formfld" id="auth-acl" size="40" value="<?=htmlspecialchars($pconfig['auth-acl']);?>">
+ <br> <span class="vexpl">Enter the auth acl here.<br></span>
+ </td>
+ </tr>
+ <tr>
+ <td valign="top" class="vncell">CIDR</td>
+ <td class="vtable">
+ <input name="cidr" type="text" class="formfld" id="cidr" size="40" value="<?=htmlspecialchars($pconfig['cidr']);?>">
+ <br> <span class="vexpl">Enter the cidr here.<br></span>
+ </td>
+ </tr>
+ </table>
+ </div>
+
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="25%" valign="top" class="vncellreq">Extension Description</td>
+ <td width="75%" class="vtable">
+ <input name="description" type="text" class="formfld" id="description" size="40" value="<?=htmlspecialchars($pconfig['description']);?>">
+ <br><span class="vexpl">Enter the description of the extension here.<br></span>
+ </td>
+ </tr>
+ <tr>
+ <td valign="top">&nbsp;</td>
+ <td>
+ <input name="outbound_caller_id_name" type="hidden" class="formfld" id="outbound_caller_id_name" size="40" value="<?=htmlspecialchars($pconfig['outbound_caller_id_name']);?>">
+ <input name="outbound_caller_id_number" type="hidden" class="formfld" id="outbound_caller_id_number" size="40" value="<?=htmlspecialchars($pconfig['outbound_caller_id_number']);?>">
+ <input name="Submit" type="submit" class="formbtn" value="Save"> <input class="formbtn" type="button" value="Cancel" onclick="history.back()">
+ <?php if (isset($id) && $a_extensions[$id]): ?>
+ <input name="id" type="hidden" value="<?=$id;?>">
+ <?php endif; ?>
+ </td>
+ </tr>
+ </table>
+ </form>
+
+ <br>
+ <br>
+ <br>
+ <br>
+ <br>
+ <br>
+
+ </td>
+ </tr>
+</table>
+
+</div>
+
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/freeswitch/freeswitch_external.xml b/config/freeswitch/freeswitch_external.xml
new file mode 100644
index 00000000..62fa9dd3
--- /dev/null
+++ b/config/freeswitch/freeswitch_external.xml
@@ -0,0 +1,136 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+
+ freeswitch_external.xml
+ Copyright (C) 2008 Mark J Crane
+ All rights reserved.
+
+ FreeSWITCH (TM)
+ http://www.freeswitch.org/
+
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>FreeSWITCH is an open source telephony platform designed to facilitate the creation of voice and chat driven products scaling from a soft-phone up to a soft-switch. It can be used as a simple switching engine, a PBX, a media gateway or a media server to host IVR applications using simple scripts or XML to control the callflow.</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>freeswitchexternal</name>
+ <version>0.1</version>
+ <title>FreeSWITCH: External</title>
+ <aftersaveredirect>pkg_edit.php?xml=freeswitch_external.xml&amp;id=0</aftersaveredirect>
+ <include_file>/usr/local/pkg/freeswitch.inc</include_file>
+ <tabs>
+ <tab>
+ <text>Settings</text>
+ <url>/pkg_edit.php?xml=freeswitch.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Dialplan</text>
+ <url>/freeswitch/freeswitch_dialplan_includes.php</url>
+ </tab>
+ <tab>
+ <text>Extensions</text>
+ <url>/freeswitch/freeswitch_extensions.php</url>
+ </tab>
+ <tab>
+ <text>External</text>
+ <url>/pkg_edit.php?xml=freeswitch_external.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Gateways</text>
+ <url>/freeswitch/freeswitch_gateways.php</url>
+ </tab>
+ <tab>
+ <text>Internal</text>
+ <url>/pkg_edit.php?xml=freeswitch_internal.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>IVR</text>
+ <url>/freeswitch/freeswitch_ivr.php</url>
+ </tab>
+ <tab>
+ <text>Modules</text>
+ <url>/pkg_edit.php?xml=freeswitch_modules.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Public</text>
+ <url>/freeswitch/freeswitch_public_includes.php</url>
+ </tab>
+ <tab>
+ <text>Rec</text>
+ <url>/freeswitch/freeswitch_recordings.php</url>
+ </tab>
+ <tab>
+ <text>Status</text>
+ <url>/freeswitch/freeswitch_status.php</url>
+ </tab>
+ <tab>
+ <text>Vars</text>
+ <url>/pkg_edit.php?xml=freeswitch_vars.xml&amp;id=0</url>
+ </tab>
+ </tabs>
+ <configpath>installedpackages->package->$packagename->configuration->freeswitchexternal</configpath>
+ <fields>
+ <field>
+ <fielddescr>&lt;b&gt;External&lt;/b&gt; &lt;br /&gt; &lt;br /&gt;SIP external profile for outbound registrations.</fielddescr>
+ <fieldname>external_xml</fieldname>
+ <description>&lt;br /&gt;Path: /usr/local/freeswitch/conf/sip_profiles/external.xml &lt;br /&gt;&lt;br /&gt;</description>
+ <type>textarea</type>
+ <encoding>base64</encoding>
+ <wrap>off</wrap>
+ <size>30</size>
+ <cols>70</cols>
+ <rows>33</rows>
+ </field>
+ </fields>
+ <custom_php_command_before_form>
+ </custom_php_command_before_form>
+ <custom_php_after_head_command>
+ sync_package_freeswitch_external();
+ </custom_php_after_head_command>
+ <custom_php_after_form_command>
+ </custom_php_after_form_command>
+ <custom_php_validation_command>
+ </custom_php_validation_command>
+ <custom_php_resync_config_command>
+ sync_package_freeswitch_external();
+ </custom_php_resync_config_command>
+</packagegui> \ No newline at end of file
diff --git a/config/freeswitch/freeswitch_gateways.tmp b/config/freeswitch/freeswitch_gateways.tmp
new file mode 100644
index 00000000..75718a7c
--- /dev/null
+++ b/config/freeswitch/freeswitch_gateways.tmp
@@ -0,0 +1,209 @@
+<?php
+/* $Id$ */
+/*
+ freeswitch_gateways.php
+ Copyright (C) 2008 Mark J Crane
+ All rights reserved.
+
+ FreeSWITCH (TM)
+ http://www.freeswitch.org/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require("guiconfig.inc");
+require("/usr/local/pkg/freeswitch.inc");
+
+$a_gateways = &$config['installedpackages']['freeswitchgateways']['config'];
+
+
+if ($_GET['act'] == "del") {
+ if ($_GET['type'] == 'gateways') {
+ if ($a_gateways[$_GET['id']]) {
+ unset($a_gateways[$_GET['id']]);
+ write_config();
+ header("Location: freeswitch_gateways.php");
+ exit;
+ }
+ }
+}
+
+include("head.inc");
+
+?>
+
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<?php include("fbegin.inc"); ?>
+<p class="pgtitle">FreeSWITCH: Gateways</p>
+
+<div id="mainlevel">
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+<tr><td class="tabnavtbl">
+<?php
+
+ $tab_array = array();
+ $tab_array[] = array(gettext("Settings"), false, "/pkg_edit.php?xml=freeswitch.xml&amp;id=0");
+ $tab_array[] = array(gettext("Dialplan"), false, "/freeswitch/freeswitch_dialplan_includes.php");
+ $tab_array[] = array(gettext("Extensions"), false, "/freeswitch/freeswitch_extensions.php");
+ $tab_array[] = array(gettext("External"), false, "/pkg_edit.php?xml=freeswitch_external.xml&amp;id=0");
+ $tab_array[] = array(gettext("Gateways"), true, "/freeswitch/freeswitch_gateways.php");
+ $tab_array[] = array(gettext("Internal"), false, "/pkg_edit.php?xml=freeswitch_internal.xml&amp;id=0");
+ $tab_array[] = array(gettext("IVR"), false, "/freeswitch/freeswitch_ivr.php");
+ $tab_array[] = array(gettext("Modules"), false, "/pkg_edit.php?xml=freeswitch_modules.xml&amp;id=0");
+ $tab_array[] = array(gettext("Public"), false, "/freeswitch/freeswitch_public_includes.php");
+ $tab_array[] = array(gettext("Rec"), false, "/freeswitch/freeswitch_recordings.php");
+ $tab_array[] = array(gettext("Status"), false, "/freeswitch/freeswitch_status.php");
+ $tab_array[] = array(gettext("Vars"), false, "/pkg_edit.php?xml=freeswitch_vars.xml&amp;id=0");
+ display_top_tabs($tab_array);
+
+?>
+</td></tr>
+</table>
+
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabcont" >
+
+<form action="freeswitch_gateways.php" method="post" name="iform" id="iform">
+<?php
+
+if ($config_change == 1) {
+ write_config();
+ $config_change = 0;
+}
+
+//if ($savemsg) print_info_box($savemsg);
+//if (file_exists($d_hostsdirty_path)): echo"<p>";
+//print_info_box_np("The FreeSWITCH gateways have been changed.<br>You must apply the changes in order for them to take effect.");
+//echo"<br />";
+//endif;
+
+?>
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td><p><span class="vexpl"><span class="red"><strong>Gateways<br>
+ </strong></span>
+ Use this to configure your SIP gateways also known as providers.
+ </p></td>
+ </tr>
+ </table>
+ <br />
+
+ <table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td width="20%" class="listhdrr">Gateway</td>
+ <td width="25%" class="listhdrr">Context</td>
+ <td width="25%" class="listhdrr">Enabled</td>
+ <td width="25%" class="listhdr">Description</td>
+ <td width="10%" class="list">
+
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td width="17"></td>
+ <td valign="middle"><a href="freeswitch_gateways_edit.php"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" width="17" height="17" border="0"></a></td>
+ </tr>
+ </table>
+
+ </td>
+ </tr>
+
+
+ <?php
+
+ $i = 0;
+ if (count($a_gateways) > 0) {
+
+ foreach ($a_gateways as $ent) {
+
+ ?>
+ <tr>
+ <td class="listr" ondblclick="document.location='freeswitch_gateways_edit.php?id=<?=$i;?>';">
+ <?=$ent['gateway'];?>&nbsp;
+ </td>
+ <td class="listr" ondblclick="document.location='freeswitch_gateways_edit.php?id=<?=$i;?>';">
+ <?=$ent['context'];?>&nbsp;
+ </td>
+ <td class="listr" ondblclick="document.location='freeswitch_gateways_edit.php?id=<?=$i;?>';">
+ <?=$ent['enabled'];?>&nbsp;
+ </td>
+ <td class="listbg" ondblclick="document.location='freeswitch_gateways_edit.php?id=<?=$i;?>';">
+ <font color="#FFFFFF"><?=htmlspecialchars($ent['description']);?>&nbsp;
+ </td>
+ <td valign="middle" nowrap class="list">
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td valign="middle"><a href="freeswitch_gateways_edit.php?id=<?=$i;?>"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_e.gif" width="17" height="17" border="0"></a></td>
+ <td><a href="freeswitch_gateways.php?type=gateways&act=del&id=<?=$i;?>" onclick="return confirm('Do you really want to delete this?')"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_x.gif" width="17" height="17" border="0"></a></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <?php
+
+ $i++;
+ }
+ }
+ ?>
+
+ <tr>
+ <td class="list" colspan="4"></td>
+ <td class="list">
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td width="17"></td>
+ <td valign="middle"><a href="freeswitch_gateways_edit.php"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" width="17" height="17" border="0"></a></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+
+
+ <tr>
+ <td class="list" colspan="4"></td>
+ <td class="list"></td>
+ </tr>
+ </table>
+
+</form>
+
+
+/usr/local/freeswitch/conf/sip_profiles/external/
+<br>
+<br>
+<br>
+<br>
+<br>
+<br>
+<br>
+<br>
+
+</td>
+</tr>
+</table>
+
+</div>
+
+
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/freeswitch/freeswitch_gateways_edit.tmp b/config/freeswitch/freeswitch_gateways_edit.tmp
new file mode 100644
index 00000000..030f88cf
--- /dev/null
+++ b/config/freeswitch/freeswitch_gateways_edit.tmp
@@ -0,0 +1,596 @@
+<?php
+/* $Id$ */
+/*
+
+ freeswitch_gateways_edit.php
+ Copyright (C) 2008 Mark J Crane
+ All rights reserved.
+
+ FreeSWITCH (TM)
+ http://www.freeswitch.org/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require("guiconfig.inc");
+require("/usr/local/pkg/freeswitch.inc");
+
+
+$a_gateways = &$config['installedpackages']['freeswitchgateways']['config'];
+
+$id = $_GET['id'];
+if (isset($_POST['id'])) {
+ $id = $_POST['id'];
+}
+
+if (isset($id) && $a_gateways[$id]) {
+
+ $pconfig['gatewayid'] = $a_gateways[$id]['gatewayid'];
+ $gatewayid = $a_gateways[$id]['gatewayid'];
+ $pconfig['gateway'] = $a_gateways[$id]['gateway'];
+ $pconfig['username'] = $a_gateways[$id]['username'];
+ $pconfig['password'] = $a_gateways[$id]['password'];
+ $pconfig['realm'] = $a_gateways[$id]['realm'];
+ $pconfig['from-user'] = $a_gateways[$id]['from-user'];
+ $pconfig['from-domain'] = $a_gateways[$id]['from-domain'];
+ $pconfig['proxy'] = $a_gateways[$id]['proxy'];
+ $pconfig['expire-seconds'] = $a_gateways[$id]['expire-seconds'];
+ $pconfig['register'] = $a_gateways[$id]['register'];
+ $pconfig['register-transport'] = $a_gateways[$id]['register-transport'];
+ $pconfig['retry-seconds'] = $a_gateways[$id]['retry-seconds'];
+ $pconfig['extension'] = $a_gateways[$id]['extension'];
+ $pconfig['context'] = $a_gateways[$id]['context'];
+ $pconfig['caller-id-in-from'] = $a_gateways[$id]['caller-id-in-from'];
+ $pconfig['supress-cng'] = $a_gateways[$id]['supress-cng'];
+ $pconfig['enabled'] = $a_gateways[$id]['enabled'];
+ $pconfig['description'] = $a_gateways[$id]['description'];
+}
+
+if ($_POST) {
+
+ unset($input_errors);
+ $pconfig = $_POST;
+
+
+ if (!$input_errors) {
+
+ $ent = array();
+ if (strlen($_POST['ivrid']) > 0) {
+ $ent['gatewayid'] = $_POST['ivrid'];
+ }
+ else {
+ $ent['gatewayid'] = guid();
+ }
+ $ent['gateway'] = $_POST['gateway'];
+ $ent['username'] = $_POST['username'];
+ $ent['password'] = $_POST['password'];
+ $ent['realm'] = $_POST['realm'];
+ $ent['from-user'] = $_POST['from-user'];
+ $ent['from-domain'] = $_POST['from-domain'];
+ $ent['proxy'] = $_POST['proxy'];
+ $ent['expire-seconds'] = $_POST['expire-seconds'];
+ $ent['register'] = $_POST['register'];
+ $ent['register-transport'] = $_POST['register-transport'];
+ $ent['retry-seconds'] = $_POST['retry-seconds'];
+ $ent['extension'] = $_POST['extension'];
+ $ent['context'] = $_POST['context'];
+ $ent['caller-id-in-from'] = $_POST['caller-id-in-from'];
+ $ent['supress-cng'] = $_POST['supress-cng'];
+ $ent['enabled'] = $_POST['enabled'];
+ $ent['description'] = $_POST['description'];
+
+
+ if (isset($id) && $a_gateways[$id]) {
+ //update
+ $a_gateways[$id] = $ent;
+ }
+ else {
+ //add
+ $a_gateways[] = $ent;
+ }
+
+
+
+ if (strlen(trim($_POST['dialplan_expression']))> 0) {
+
+ $gatewayid = $_POST['gatewayid'];
+ $gateway = $_POST['gateway'];
+ $context = $_POST['context'];
+
+ $default_area_code = &$config['installedpackages']['freeswitchsettings']['config'][0]['default_area_code'];
+ $a_dialplan_includes = &$config['installedpackages']['freeswitchdialplanincludes']['config'];
+ $a_dialplan_include_details = &$config['installedpackages']['freeswitchdialplanincludedetails']['config'];
+
+
+ $tmp_array = split("\\\n", $_POST['dialplan_expression']);
+
+ foreach($tmp_array as $dialplan_expression) {
+
+ $dialplan_expression = trim($dialplan_expression);
+ if (strlen($dialplan_expression)>0) {
+
+ switch ($dialplan_expression) {
+ case "^(\d{7})$":
+ $action_data = "sofia/gateway/".$gateway."/1".$default_area_code."\$1";
+ $label = "7 digits";
+ $abbrv = "7d";
+ break;
+ case "^(\d{10})$":
+ $action_data = "sofia/gateway/".$gateway."/1\$1";
+ $label = "10 digits";
+ $abbrv = "10d";
+ break;
+ case "^(\d{11})$":
+ $action_data = "sofia/gateway/".$gateway."/\$1";
+ $label = "11 digits";
+ $abbrv = "11d";
+ break;
+ case "^311$":
+ $action_data = "sofia/gateway/".$gateway."/\$1";
+ $label = "311";
+ $abbrv = "311";
+ break;
+ case "^411$":
+ $action_data = "sofia/gateway/".$gateway."/\$1";
+ $label = "411";
+ $abbrv = "411";
+ break;
+ case "^911$":
+ $action_data = "sofia/gateway/".$gateway."/\$1";
+ $label = "911";
+ $abbrv = "911";
+ break;
+ case "^9(\d{3})$":
+ $action_data = "sofia/gateway/".$gateway."/1".$default_area_code."\$1";
+ $label = "dial 9, 3 digits";
+ $abbrv = "9.3d";
+ break;
+ case "^9(\d{4})$":
+ $action_data = "sofia/gateway/".$gateway."/1".$default_area_code."\$1";
+ $label = "dial 9, 4 digits";
+ $abbrv = "9.4d";
+ break;
+ case "^9(\d{7})$":
+ $action_data = "sofia/gateway/".$gateway."/1".$default_area_code."\$1";
+ $label = "dial 9, 7 digits";
+ $abbrv = "9.7d";
+ break;
+ case "^9(\d{10})$":
+ $action_data = "sofia/gateway/".$gateway."/\$1";
+ $label = "dial 9, 10 digits";
+ $abbrv = "9.10d";
+ break;
+ case "^9(\d{11})$":
+ $action_data = "sofia/gateway/".$gateway."/\$1";
+ $label = "dial 9, 11 digits";
+ $abbrv = "9.11d";
+ break;
+ case "^1?(8(00|55|66|77|88)[2-9]\d{6})$":
+ $action_data = "sofia/gateway/".$gateway."/\$1";
+ $label = "toll free";
+ $abbrv = "tollfree";
+ break;
+ default:
+ $action_data = "sofia/gateway/".$gateway."/\$1";
+ $label = $dialplan_expression;
+ $abbrv = $dialplan_expression;
+ }
+
+ $dialplanincludeid = guid();
+ $ent['dialplanincludeid'] = $dialplanincludeid;
+ $ent['extensionname'] = $gateway.".".$abbrv;
+ $ent['order'] = '9002'; //if update use the existing order number and extension name and desc
+ $ent['context'] = $context;
+ $ent['enabled'] = 'true';
+ $ent['descr'] = $label.' '.$gateway;
+ $ent['opt1name'] = 'gatewayid';
+ $ent['opt1value'] = $gatewayid;
+ $a_dialplan_includes[] = $ent;
+ unset($ent);
+
+ $ent = array();
+ $ent['dialplanincludeid'] = $dialplanincludeid;
+ $ent['tag'] = 'condition'; //condition, action, antiaction
+ $ent['fieldtype'] = 'destination_number';
+ $ent['fielddata'] = $dialplan_expression;
+ $a_dialplan_include_details[] = $ent;
+ unset($ent);
+
+ $ent = array();
+ $ent['dialplanincludeid'] = $dialplanincludeid;
+ $ent['tag'] = 'action'; //condition, action, antiaction
+ $ent['fieldtype'] = 'bridge';
+ $ent['fielddata'] = $action_data;
+ $a_dialplan_include_details[] = $ent;
+ unset($ent);
+
+ unset($label);
+ unset($abbrv);
+ unset($dialplan_expression);
+ unset($action_data);
+ } //if strlen
+ } //end for each
+ }
+
+ write_config();
+ sync_package_freeswitch_gateways();
+ sync_package_freeswitch_dialplan_includes();
+
+ header("Location: freeswitch_gateways.php");
+ exit;
+ }
+}
+
+include("head.inc");
+
+?>
+
+
+<script type="text/javascript" language="JavaScript">
+
+function enable_change(enable_over) {
+ var endis;
+ endis = !(document.iform.enable.checked || enable_over);
+ document.iform.range_from.disabled = endis;
+ document.iform.range_to.disabled = endis;
+}
+
+function show_advanced_config() {
+ document.getElementById("showadvancedbox").innerHTML='';
+ aodiv = document.getElementById('showadvanced');
+ aodiv.style.display = "block";
+}
+
+</script>
+
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<?php include("fbegin.inc"); ?>
+<p class="pgtitle">FreeSWITCH: Gateways: Edit</p>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+
+
+<div id="mainlevel">
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+<tr><td class="tabnavtbl">
+<?php
+
+ $tab_array = array();
+ $tab_array[] = array(gettext("Settings"), false, "/pkg_edit.php?xml=freeswitch.xml&amp;id=0");
+ $tab_array[] = array(gettext("Dialplan"), false, "/freeswitch/freeswitch_dialplan_includes.php");
+ $tab_array[] = array(gettext("Extensions"), false, "/freeswitch/freeswitch_extensions.php");
+ $tab_array[] = array(gettext("External"), false, "/pkg_edit.php?xml=freeswitch_external.xml&amp;id=0");
+ $tab_array[] = array(gettext("Gateways"), true, "/freeswitch/freeswitch_gateways.php");
+ $tab_array[] = array(gettext("Internal"), false, "/pkg_edit.php?xml=freeswitch_internal.xml&amp;id=0");
+ $tab_array[] = array(gettext("IVR"), false, "/freeswitch/freeswitch_ivr.php");
+ $tab_array[] = array(gettext("Modules"), false, "/pkg_edit.php?xml=freeswitch_modules.xml&amp;id=0");
+ $tab_array[] = array(gettext("Public"), false, "/freeswitch/freeswitch_public_includes.php");
+ $tab_array[] = array(gettext("Rec"), false, "/freeswitch/freeswitch_recordings.php");
+ $tab_array[] = array(gettext("Status"), false, "/freeswitch/freeswitch_status.php");
+ $tab_array[] = array(gettext("Vars"), false, "/pkg_edit.php?xml=freeswitch_vars.xml&amp;id=0");
+ display_top_tabs($tab_array);
+
+?>
+</td></tr>
+</table>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabcont" >
+
+
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td><p><span class="vexpl"><span class="red"><strong>Gateway Setup<br>
+ </strong></span>
+ The 'SIP Provider Examples' from the FreeSWITCH wiki can be used as reference to get started. <br />
+ <a href='http://wiki.freeswitch.org/wiki/SIP_Provider_Examples' target='_blank'>http://wiki.freeswitch.org/wiki/SIP_Provider_Examples</a>
+ </p></td>
+ </tr>
+ </table>
+ <br />
+
+ <form action="freeswitch_gateways_edit.php" method="post" name="iform" id="iform">
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="22%" valign="top" class="vncellreq">Gateway</td>
+ <td width="78%" class="vtable">
+ <input name="gateway" type="text" class="formfld" id="gateway" size="40" value="<?=htmlspecialchars($pconfig['gateway']);?>">
+ <br><span class="vexpl">Enter the gateway name here.<br></span>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq">Username</td>
+ <td width="78%" class="vtable">
+ <input name="username" type="text" class="formfld" id="username" size="40" value="<?=htmlspecialchars($pconfig['username']);?>">
+ <br><span class="vexpl">Enter the username here.<br></span>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq">Password</td>
+ <td width="78%" class="vtable">
+ <input name="password" type="password" class="formfld" id="password" size="40" value="<?=htmlspecialchars($pconfig['password']);?>">
+ <br><span class="vexpl">Enter the password here.<br></span>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq">From-user</td>
+ <td width="78%" class="vtable">
+ <input name="from-user" type="text" class="formfld" id="from-user" size="40" value="<?=htmlspecialchars($pconfig['from-user']);?>">
+ <br><span class="vexpl">Enter the from-user here.<br></span>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq">From-domain</td>
+ <td width="78%" class="vtable">
+ <input name="from-domain" type="text" class="formfld" id="from-domain" size="40" value="<?=htmlspecialchars($pconfig['from-domain']);?>">
+ <br><span class="vexpl">Enter the from-domain here.<br></span>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq">Proxy</td>
+ <td width="78%" class="vtable">
+ <input name="proxy" type="text" class="formfld" id="proxy" size="40" value="<?=htmlspecialchars($pconfig['proxy']);?>">
+ <br><span class="vexpl">Enter the proxy here.<br></span>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq">Realm</td>
+ <td width="78%" class="vtable">
+ <input name="realm" type="text" class="formfld" id="realm" size="40" value="<?=htmlspecialchars($pconfig['realm']);?>">
+ <br><span class="vexpl">Enter the realm here.<br></span>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq">Expire-seconds</td>
+ <td width="78%" class="vtable">
+ <input name="expire-seconds" type="text" class="formfld" id="expire-seconds" size="40" value="<?=htmlspecialchars($pconfig['expire-seconds']);?>">
+ <br><span class="vexpl">Enter the expire-seconds here. Example: 600<br></span>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq">Register</td>
+ <td width="78%" class="vtable">
+ <?php
+ echo " <select name='register' class='formfld'>\n";
+ echo " <option></option>\n";
+ switch (htmlspecialchars($pconfig['register'])) {
+ case "true":
+ echo " <option value='true' selected='yes'>true</option>\n";
+ echo " <option value='false'>false</option>\n";
+ break;
+ case "false":
+ echo " <option value='true'>true</option>\n";
+ echo " <option value='false' selected='yes'>false</option>\n";
+
+ break;
+ default:
+ echo " <option value='true' selected='yes'>true</option>\n";
+ echo " <option value='false'>false</option>\n";
+ }
+ echo " </select>\n";
+ ?>
+ Choose whether to register.
+ </td>
+ </tr>
+
+ <tr>
+ <td width="22%" valign="top" class="vncellreq">Retry-seconds</td>
+ <td width="78%" class="vtable">
+ <input name="retry-seconds" type="text" class="formfld" id="retry-seconds" size="40" value="<?=htmlspecialchars($pconfig['retry-seconds']);?>">
+ <br> <span class="vexpl">Enter the retry_seconds here. Example: 30<br></span>
+ </td>
+ </tr>
+
+ <tr>
+ <td width="22%" valign="top" class="vncellreq">Context</td>
+ <td width="78%" class="vtable">
+ <input name="context" type="text" class="formfld" id="context" size="40" value="<?=htmlspecialchars($pconfig['context']);?>">
+ <br> <span class="vexpl">Enter the context here. Example: public<br></span>
+ </td>
+ </tr>
+ </table>
+ <div id="showadvancedbox">
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="22%" valign="top" class="vncell">Show Advanced</td>
+ <td width="78%" class="vtable">
+ <input type="button" onClick="show_advanced_config()" value="Advanced"></input></a>
+ </td>
+ </tr>
+ </table>
+ </div>
+ <div id="showadvanced" style="display:none">
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="22%" valign="top" class="vncell">Register-transport</td>
+ <td width="78%" class="vtable">
+ <?php
+ echo " <select name='register-transport' class='formfld'>\n";
+ echo " <option></option>\n";
+ switch (htmlspecialchars($pconfig['register-transport'])) {
+ case "udp":
+ echo " <option value='udp' selected='yes'>udp</option>\n";
+ echo " <option value='tcp'>tcp</option>\n";
+ break;
+ case "tcp":
+ echo " <option value='udp'>udp</option>\n";
+ echo " <option value='tcp' selected='yes'>tcp</option>\n";
+
+ break;
+ default:
+ echo " <option value='udp'>udp</option>\n";
+ echo " <option value='tcp'>tcp</option>\n";
+ }
+ echo " </select>\n";
+ ?>
+ Choose whether to register-transport.
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Extension</td>
+ <td width="78%" class="vtable">
+ <input name="extension" type="text" class="formfld" id="extension" size="40" value="<?=htmlspecialchars($pconfig['extension']);?>">
+ <br> <span class="vexpl">Enter the extension here.<br></span>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Caller-id-in-from</td>
+ <td width="78%" class="vtable">
+ <?php
+ echo " <select name='caller-id-in-from' class='formfld'>\n";
+ echo " <option></option>\n";
+ switch (htmlspecialchars($pconfig['caller-id-in-from'])) {
+ case "true":
+ echo " <option value='true' selected='yes'>true</option>\n";
+ echo " <option value='false'>false</option>\n";
+ break;
+ case "false":
+ echo " <option value='true'>true</option>\n";
+ echo " <option value='false' selected='yes'>false</option>\n";
+
+ break;
+ default:
+ echo " <option value='true'>true</option>\n";
+ echo " <option value='false'>false</option>\n";
+ }
+ echo " </select>\n";
+ ?>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Supress-cng</td>
+ <td width="78%" class="vtable">
+ <?php
+ echo " <select name='supress-cng' class='formfld'>\n";
+ echo " <option></option>\n";
+ switch (htmlspecialchars($pconfig['supress-cng'])) {
+ case "true":
+ echo " <option value='true' selected='yes'>true</option>\n";
+ echo " <option value='false'>false</option>\n";
+ break;
+ case "false":
+ echo " <option value='true'>true</option>\n";
+ echo " <option value='false' selected='yes'>false</option>\n";
+
+ break;
+ default:
+ echo " <option value='true'>true</option>\n";
+ echo " <option value='false'>false</option>\n";
+ }
+ echo " </select>\n";
+ ?>
+ </td>
+ </tr>
+ </table>
+
+ </div>
+
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="22%" valign="top" class="vncellreq">Enabled</td>
+ <td width="78%" class="vtable">
+ <?php
+ echo " <select name='enabled' class='formfld'>\n";
+ echo " <option></option>\n";
+ switch (htmlspecialchars($pconfig['enabled'])) {
+ case "true":
+ echo " <option value='true' selected='yes'>true</option>\n";
+ echo " <option value='false'>false</option>\n";
+ break;
+ case "false":
+ echo " <option value='true'>true</option>\n";
+ echo " <option value='false' selected='yes'>false</option>\n";
+
+ break;
+ default:
+ echo " <option value='true' selected='yes'>true</option>\n";
+ echo " <option value='false'>false</option>\n";
+ }
+ echo " </select>\n";
+ ?>
+ </td>
+ </tr>
+
+ <tr>
+ <td width="22%" valign="top" class="vncell">Dialplan Expression</td>
+ <td width="78%" class="vtable">
+ <?php
+ echo "<textarea name=\"dialplan_expression\" id=\"dialplan_expression\" cols=\"30\" rows=\"4\" wrap=\"off\"></textarea>\n";
+ ?>
+ <br>
+ <select name='dialplan_expression_select' id='dialplan_expression_select' onchange="document.getElementById('dialplan_expression').value += document.getElementById('dialplan_expression_select').value + '\n';" class='formfld'>
+ <option></option>
+ <option value='^(\d{7})$'>7 digits local</option>
+ <option value='^(\d{10})$'>10 digits long distance</option>
+ <option value='^(\d{11})$'>11 digits long distance</option>
+ <option value='^011(.*)$'>011 International</option>
+ <option value='^311$'>311 information</option>
+ <option value='^411$'>411 information</option>
+ <option value='^911$'>911 emergency</option>
+ <option value='^1?(8(00|55|66|77|88)[2-9]\d{6})$'>toll free</option>
+ <option value='^9(\d{3})$'>Dial 9 then 3 digits</option>
+ <option value='^9(\d{4})$'>Dial 9 then 4 digits</option>
+ <option value='^9(\d{7})$'>Dial 9 then 7 digits</option>
+ <option value='^9(\d{10})$'>Dial 9 then 10 digits</option>
+ <option value='^9(\d{11})$'>Dial 9 then 11 digits</option>
+ </select>
+ <span class="vexpl">
+ <br />
+ Shortcut to create the outbound dialplan entries for this Gateway. The entries are saved to and edited from the 'Dialplan' tab.
+ </span></td>
+ </tr>
+
+ <tr>
+ <td width="22%" valign="top" class="vncell">Gateway Description</td>
+ <td width="78%" class="vtable">
+ <input name="description" type="text" class="formfld" id="description" size="40" value="<?=htmlspecialchars($pconfig['description']);?>">
+ <br> <span class="vexpl">Enter the description of the gateway here.</span></td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <input name="Submit" type="submit" class="formbtn" value="Save"> <input class="formbtn" type="button" value="Cancel" onclick="history.back()">
+ <?php if (isset($id) && $a_gateways[$id]): ?>
+ <input name="id" type="hidden" value="<?=$id;?>">
+ <input name="gatewayid" type="hidden" value="<?=htmlspecialchars($pconfig['gatewayid']);?>">
+ <?php endif; ?>
+ </td>
+ </tr>
+ </table>
+ </form>
+
+ <br>
+ <br>
+ <br>
+ <br>
+ <br>
+ <br>
+
+ </td>
+ </tr>
+</table>
+
+</div>
+
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/freeswitch/freeswitch_internal.xml b/config/freeswitch/freeswitch_internal.xml
new file mode 100644
index 00000000..4ae5848f
--- /dev/null
+++ b/config/freeswitch/freeswitch_internal.xml
@@ -0,0 +1,136 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+
+ freeswitch_internal.xml
+ Copyright (C) 2008 Mark J Crane
+ All rights reserved.
+
+ FreeSWITCH (TM)
+ http://www.freeswitch.org/
+
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>FreeSWITCH is an open source telephony platform designed to facilitate the creation of voice and chat driven products scaling from a soft-phone up to a soft-switch. It can be used as a simple switching engine, a PBX, a media gateway or a media server to host IVR applications using simple scripts or XML to control the callflow.</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>freeswitchinternal</name>
+ <version>0.1</version>
+ <title>FreeSWITCH: Internal</title>
+ <aftersaveredirect>pkg_edit.php?xml=freeswitch_internal.xml&amp;id=0</aftersaveredirect>
+ <include_file>/usr/local/pkg/freeswitch.inc</include_file>
+ <tabs>
+ <tab>
+ <text>Settings</text>
+ <url>/pkg_edit.php?xml=freeswitch.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Dialplan</text>
+ <url>/freeswitch/freeswitch_dialplan_includes.php</url>
+ </tab>
+ <tab>
+ <text>Extensions</text>
+ <url>/freeswitch/freeswitch_extensions.php</url>
+ </tab>
+ <tab>
+ <text>External</text>
+ <url>/pkg_edit.php?xml=freeswitch_external.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Gateways</text>
+ <url>/freeswitch/freeswitch_gateways.php</url>
+ </tab>
+ <tab>
+ <text>Internal</text>
+ <url>/pkg_edit.php?xml=freeswitch_internal.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>IVR</text>
+ <url>/freeswitch/freeswitch_ivr.php</url>
+ </tab>
+ <tab>
+ <text>Modules</text>
+ <url>/pkg_edit.php?xml=freeswitch_modules.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Public</text>
+ <url>/freeswitch/freeswitch_public_includes.php</url>
+ </tab>
+ <tab>
+ <text>Rec</text>
+ <url>/freeswitch/freeswitch_recordings.php</url>
+ </tab>
+ <tab>
+ <text>Status</text>
+ <url>/freeswitch/freeswitch_status.php</url>
+ </tab>
+ <tab>
+ <text>Vars</text>
+ <url>/pkg_edit.php?xml=freeswitch_vars.xml&amp;id=0</url>
+ </tab>
+ </tabs>
+ <configpath>installedpackages->package->$packagename->configuration->freeswitchinternal</configpath>
+ <fields>
+ <field>
+ <fielddescr>&lt;b&gt;Internal&lt;/b&gt; &lt;br /&gt; &lt;br /&gt;SIP internal profile. </fielddescr>
+ <fieldname>internal_xml</fieldname>
+ <description>&lt;br /&gt;Path: /usr/local/freeswitch/conf/sip_profiles/internal.xml &lt;br /&gt;&lt;br /&gt;</description>
+ <type>textarea</type>
+ <encoding>base64</encoding>
+ <wrap>off</wrap>
+ <size>30</size>
+ <cols>70</cols>
+ <rows>33</rows>
+ </field>
+ </fields>
+ <custom_php_command_before_form>
+ </custom_php_command_before_form>
+ <custom_php_after_head_command>
+ sync_package_freeswitch_internal();
+ </custom_php_after_head_command>
+ <custom_php_after_form_command>
+ </custom_php_after_form_command>
+ <custom_php_validation_command>
+ </custom_php_validation_command>
+ <custom_php_resync_config_command>
+ sync_package_freeswitch_internal();
+ </custom_php_resync_config_command>
+</packagegui> \ No newline at end of file
diff --git a/config/freeswitch/freeswitch_ivr.tmp b/config/freeswitch/freeswitch_ivr.tmp
new file mode 100644
index 00000000..d05337ce
--- /dev/null
+++ b/config/freeswitch/freeswitch_ivr.tmp
@@ -0,0 +1,216 @@
+<?php
+/* $Id$ */
+/*
+ freeswitch_ivr.php
+ Copyright (C) 2008 Mark J Crane
+ All rights reserved.
+
+ FreeSWITCH (TM)
+ http://www.freeswitch.org/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require("guiconfig.inc");
+require("/usr/local/pkg/freeswitch.inc");
+
+
+$a_ivr = &$config['installedpackages']['freeswitchivr']['config'];
+
+
+if ($_GET['act'] == "del") {
+ if ($_GET['type'] == 'ivr') {
+ if ($a_ivr[$_GET['id']]) {
+ unset($a_ivr[$_GET['id']]);
+ write_config();
+ sync_package_freeswitch_ivr();
+ header("Location: freeswitch_ivr.php");
+ exit;
+ }
+ }
+}
+
+include("head.inc");
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<?php include("fbegin.inc"); ?>
+<p class="pgtitle">FreeSWITCH: IVR</p>
+
+<div id="mainlevel">
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+<tr><td class="tabnavtbl">
+<?php
+
+ $tab_array = array();
+ $tab_array[] = array(gettext("Settings"), false, "/pkg_edit.php?xml=freeswitch.xml&amp;id=0");
+ $tab_array[] = array(gettext("Dialplan"), false, "/freeswitch/freeswitch_dialplan_includes.php");
+ $tab_array[] = array(gettext("Extensions"), false, "/freeswitch/freeswitch_extensions.php");
+ $tab_array[] = array(gettext("External"), false, "/pkg_edit.php?xml=freeswitch_external.xml&amp;id=0");
+ $tab_array[] = array(gettext("Gateways"), false, "/freeswitch/freeswitch_gateways.php");
+ $tab_array[] = array(gettext("Internal"), false, "/pkg_edit.php?xml=freeswitch_internal.xml&amp;id=0");
+ $tab_array[] = array(gettext("IVR"), true, "/freeswitch/freeswitch_ivr.php");
+ $tab_array[] = array(gettext("Modules"), false, "/pkg_edit.php?xml=freeswitch_modules.xml&amp;id=0");
+ $tab_array[] = array(gettext("Public"), false, "/freeswitch/freeswitch_public_includes.php");
+ $tab_array[] = array(gettext("Rec"), false, "/freeswitch/freeswitch_recordings.php");
+ $tab_array[] = array(gettext("Status"), false, "/freeswitch/freeswitch_status.php");
+ $tab_array[] = array(gettext("Vars"), false, "/pkg_edit.php?xml=freeswitch_vars.xml&amp;id=0");
+ display_top_tabs($tab_array);
+
+?>
+</td></tr>
+</table>
+
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabcont" >
+
+<form action="freeswitch_ivr.php" method="post" name="iform" id="iform">
+<?php
+
+
+//echo "<pre>";
+//print_r ($a_ivr);
+//echo "</pre>";
+
+//build a list of recordings from the config.xml
+//$config_recording_list = '';
+//$i = 0;
+//if (count($a_ivr) > 0) {
+// foreach ($a_ivr as $ivrent) {
+// $config_recording_list .= $ivrent['filename']."|";
+// $i++;
+// }
+//}
+//echo "config recording list: ".$config_recording_list."<br />\n";
+
+
+//if ($config_change == 1) {
+// write_config();
+// $config_change = 0;
+//}
+
+//if ($savemsg) print_info_box($savemsg);
+//if (file_exists($d_hostsdirty_path)): echo"<p>";
+//print_info_box_np("The FreeSWITCH recordings have been changed.<br>You must apply the changes in order for them to take effect.");
+//echo"<br />";
+//endif;
+
+?>
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td><p><span class="vexpl"><span class="red"><strong>IVR<br />
+ </strong></span>
+ An interactive voice response (IVR) often refered to as an Auto Attendant.
+ It associates a recording to multiple options that can be used to direct calls
+ to extensions, voicemail, queues, other IVR applications, and external
+ phone numbers.
+ </span></p></td>
+ </tr>
+ </table>
+ <br />
+
+ <table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td width="20%" class="listhdrr">Extension</td>
+ <td width="25%" class="listhdrr">Name</td>
+ <td width="50%" class="listhdr">Description</td>
+ <td width="10%" class="list">
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td width="17"></td>
+ <td valign="middle"><a href="freeswitch_ivr_edit.php"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" width="17" height="17" border="0"></a></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+
+ <?php
+ $i = 0;
+ if (count($a_ivr) > 0) {
+ foreach ($a_ivr as $ent) {
+ if (strlen($ent['ivrid']) > 0) {
+ ?>
+ <tr>
+ <td class="listlr" ondblclick="document.location='freeswitch_ivr_edit.php?id=<?=$i;?>'">
+ <?=$ent['ivrextension']?>
+ </td>
+ <td class="listr" ondblclick="document.location='freeswitch_ivr_edit.php?id=<?=$i;?>';">
+ <?=$ent['ivrname'];?>&nbsp;
+ </td>
+ <td class="listbg" ondblclick="document.location='freeswitch_ivr_edit.php?id=<?=$i;?>';">
+ <font color="#FFFFFF"><?=htmlspecialchars($ent['ivrdescr']);?>&nbsp;
+ </td>
+ <td valign="middle" nowrap class="list">
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td valign="middle"><a href="freeswitch_ivr_edit.php?id=<?=$i;?>"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_e.gif" width="17" height="17" border="0"></a></td>
+ <td><a href="freeswitch_ivr.php?type=ivr&act=del&id=<?=$i;?>" onclick="return confirm('Do you really want to delete this?')"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_x.gif" width="17" height="17" border="0"></a></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <?php
+ }
+ $i++;
+ }
+ }
+ ?>
+ <tr>
+ <td class="list" colspan="3"></td>
+ <td class="list">
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td width="17"></td>
+ <td valign="middle"><a href="freeswitch_ivr_edit.php"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" width="17" height="17" border="0"></a></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+
+ <tr>
+ <td class="list" colspan="3"></td>
+ <td class="list"></td>
+ </tr>
+ </table>
+
+</form>
+
+<br>
+<br>
+/usr/local/freeswitch/scripts/
+<br>
+<br>
+<br>
+<br>
+
+</td>
+</tr>
+</table>
+
+</div>
+
+
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/freeswitch/freeswitch_ivr_edit.tmp b/config/freeswitch/freeswitch_ivr_edit.tmp
new file mode 100644
index 00000000..f9d4652d
--- /dev/null
+++ b/config/freeswitch/freeswitch_ivr_edit.tmp
@@ -0,0 +1,582 @@
+<?php
+/* $Id$ */
+/*
+
+ freeswitch_ivr_edit.php
+ Copyright (C) 2008 Mark J Crane
+ All rights reserved.
+
+ FreeSWITCH (TM)
+ http://www.freeswitch.org/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require("guiconfig.inc");
+require("/usr/local/pkg/freeswitch.inc");
+
+
+$a_ivr = &$config['installedpackages']['freeswitchivr']['config'];
+$a_ivr_options = &$config['installedpackages']['freeswitchivroptions']['config'];
+
+
+$id = $_GET['id'];
+if (isset($_POST['id'])) {
+ $id = $_POST['id'];
+}
+$parentid = $id;
+
+//set default $ivrconditionjs
+ $ivrconditionjs = "function isholiday( Month, Date ) {\n";
+ $ivrconditionjs .= " var Holiday = 0; //default false\n";
+ $ivrconditionjs .= " if (Month == \"12\" && Date == \"25\") {\n";
+ $ivrconditionjs .= " Holiday = 1; //true\n";
+ $ivrconditionjs .= " }\n";
+ $ivrconditionjs .= " if (Month == \"7\" && Date == \"4\") {\n";
+ $ivrconditionjs .= " Holiday = 1; //true\n";
+ $ivrconditionjs .= " }\n";
+ $ivrconditionjs .= " if (Month == \"1\" && Date == \"1\") {\n";
+ $ivrconditionjs .= " Holiday = 1; //true\n";
+ $ivrconditionjs .= " }\n";
+ $ivrconditionjs .= " if (Holiday == 1) {\n";
+ $ivrconditionjs .= " return true;\n";
+ $ivrconditionjs .= " }\n";
+ $ivrconditionjs .= " else {\n";
+ $ivrconditionjs .= " return false;\n";
+ $ivrconditionjs .= " }\n";
+ $ivrconditionjs .= "}\n";
+ $ivrconditionjs .= "\n";
+ $ivrconditionjs .= "function isweekday( Day ) {\n";
+ $ivrconditionjs .= " if (Day > 1 && Day < 7) {\n";
+ $ivrconditionjs .= " return true;\n";
+ $ivrconditionjs .= " }\n";
+ $ivrconditionjs .= " else {\n";
+ $ivrconditionjs .= " return false;\n";
+ $ivrconditionjs .= " }\n";
+ $ivrconditionjs .= "}\n";
+ $ivrconditionjs .= "\n";
+ $ivrconditionjs .= "function isweekend( Day ) {\n";
+ $ivrconditionjs .= " if (Day > 1 && Day < 7) {\n";
+ $ivrconditionjs .= " return false;\n";
+ $ivrconditionjs .= " }\n";
+ $ivrconditionjs .= " else {\n";
+ $ivrconditionjs .= " return true;\n";
+ $ivrconditionjs .= " }\n";
+ $ivrconditionjs .= "}\n";
+ $ivrconditionjs .= "\n";
+ $ivrconditionjs .= "function isofficehours( Hours ) {\n";
+ $ivrconditionjs .= " if (Hours >= 9 && Hours < 17) {\n";
+ $ivrconditionjs .= " return true;\n";
+ $ivrconditionjs .= " }\n";
+ $ivrconditionjs .= " else {\n";
+ $ivrconditionjs .= " return false;\n";
+ $ivrconditionjs .= " }\n";
+ $ivrconditionjs .= "}\n";
+ $ivrconditionjs .= "\n";
+ $ivrconditionjs .= "function isafterhours( Hours ) {\n";
+ $ivrconditionjs .= " if (Hours >= 9 && Hours < 17) {\n";
+ $ivrconditionjs .= " return false;\n";
+ $ivrconditionjs .= " }\n";
+ $ivrconditionjs .= " else {\n";
+ $ivrconditionjs .= " return true;\n";
+ $ivrconditionjs .= " }\n";
+ $ivrconditionjs .= "}\n";
+ $ivrconditionjs .= "\n";
+ $ivrconditionjs .= "//set default\n";
+ $ivrconditionjs .= "condition = true;\n";
+ $ivrconditionjs .= "\n";
+ $ivrconditionjs .= "//Holiday?\n";
+ $ivrconditionjs .= "if (isholiday( Month, Date )) {\n";
+ $ivrconditionjs .= " console_log( \"info\", \"holiday\\n\" );\n";
+ $ivrconditionjs .= " condition = false;\n";
+ $ivrconditionjs .= "}\n";
+ $ivrconditionjs .= "\n";
+ $ivrconditionjs .= "//Weekend?\n";
+ $ivrconditionjs .= "if (isweekend( Day )) {\n";
+ $ivrconditionjs .= " console_log( \"info\", \"weekend\\n\" );\n";
+ $ivrconditionjs .= " condition = false;\n";
+ $ivrconditionjs .= "}\n";
+ $ivrconditionjs .= "\n";
+ $ivrconditionjs .= "// After Hours?\n";
+ $ivrconditionjs .= "if (isafterhours( Hours )) {\n";
+ $ivrconditionjs .= " console_log( \"info\", \"after hours\\n\" );\n";
+ $ivrconditionjs .= " condition = false;\n";
+ $ivrconditionjs .= "}\n";
+ $ivrconditionjs .= "\n";
+
+
+if (isset($id) && $a_ivr[$id]) {
+ $pconfig['ivrid'] = $a_ivr[$id]['ivrid'];
+ $ivrid = $a_ivr[$id]['ivrid'];
+ $pconfig['ivrextension'] = $a_ivr[$id]['ivrextension'];
+ $pconfig['ivrname'] = $a_ivr[$id]['ivrname'];
+ $pconfig['recordingidaction'] = $a_ivr[$id]['recordingidaction'];
+ $pconfig['recordingidantiaction'] = $a_ivr[$id]['recordingidantiaction'];
+ $pconfig['ivrtimeout'] = $a_ivr[$id]['ivrtimeout'];
+ $pconfig['ivrcontext'] = $a_ivr[$id]['ivrcontext'];
+ $pconfig['ivrconditionjs'] = ($a_ivr[$id]['ivrconditionjs']);
+ $pconfig['ivrdescr'] = $a_ivr[$id]['ivrdescr'];
+}
+
+if ($_POST) {
+
+ unset($input_errors);
+ $pconfig = $_POST;
+
+
+ if ($_GET['act'] == "del") {
+ if ($_GET['type'] == 'options') {
+ if ($a_ivroptions[$_GET['optionid']]) {
+ unset($a_ivr_options[$_GET['optionid']]);
+ write_config();
+ sync_package_freeswitch_ivr();
+ //touch($d_hostsdirty_path);
+ header("Location: freeswitch_ivr_edit.php?id=".$_GET['id']);
+ exit;
+ }
+ }
+ }
+
+
+ if (!$input_errors) {
+
+ $ivrent = array();
+ if (strlen($_POST['ivrid']) > 0) {
+ $ivrent['ivrid'] = $_POST['ivrid'];
+ }
+ else {
+ $ivrent['ivrid'] = guid();
+ }
+ $ivrent['ivrextension'] = $_POST['ivrextension'];
+ $ivrent['ivrname'] = $_POST['ivrname'];
+ $ivrent['recordingidaction'] = $_POST['recordingidaction'];
+ $ivrent['recordingidantiaction'] = $_POST['recordingidantiaction'];
+ $ivrent['ivrtimeout'] = $_POST['ivrtimeout'];
+ $ivrent['ivrcontext'] = $_POST['ivrcontext'];
+ $ivrent['ivrconditionjs'] = base64_encode($_POST['ivrconditionjs']);
+ $ivrent['ivrdescr'] = $_POST['ivrdescr'];
+
+ if (isset($id) && $a_ivr[$id]) {
+ //update
+ $a_ivr[$id] = $ivrent;
+ }
+ else {
+ //add
+ $a_ivr[] = $ivrent;
+ }
+
+ //touch($d_hostsdirty_path);
+ write_config();
+ sync_package_freeswitch_ivr();
+
+ header("Location: freeswitch_ivr.php");
+ exit;
+ }
+}
+
+include("head.inc");
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<?php include("fbegin.inc"); ?>
+<p class="pgtitle">FreeSWITCH: IVR: Edit</p>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+
+
+<div id="mainlevel">
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+<tr><td class="tabnavtbl">
+<?php
+
+ $tab_array = array();
+ $tab_array[] = array(gettext("Settings"), false, "/pkg_edit.php?xml=freeswitch.xml&amp;id=0");
+ $tab_array[] = array(gettext("Dialplan"), false, "/freeswitch/freeswitch_dialplan_includes.php");
+ $tab_array[] = array(gettext("Extensions"), false, "/freeswitch/freeswitch_extensions.php");
+ $tab_array[] = array(gettext("External"), false, "/pkg_edit.php?xml=freeswitch_external.xml&amp;id=0");
+ $tab_array[] = array(gettext("Gateways"), false, "/freeswitch/freeswitch_gateways.php");
+ $tab_array[] = array(gettext("Internal"), false, "/pkg_edit.php?xml=freeswitch_internal.xml&amp;id=0");
+ $tab_array[] = array(gettext("IVR"), true, "/freeswitch/freeswitch_ivr.php");
+ $tab_array[] = array(gettext("Modules"), false, "/pkg_edit.php?xml=freeswitch_modules.xml&amp;id=0");
+ $tab_array[] = array(gettext("Public"), false, "/freeswitch/freeswitch_public_includes.php");
+ $tab_array[] = array(gettext("Rec"), false, "/freeswitch/freeswitch_recordings.php");
+ $tab_array[] = array(gettext("Status"), false, "/freeswitch/freeswitch_status.php");
+ $tab_array[] = array(gettext("Vars"), false, "/pkg_edit.php?xml=freeswitch_vars.xml&amp;id=0");
+ display_top_tabs($tab_array);
+
+?>
+</td></tr>
+</table>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabcont" >
+
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td><p><span class="vexpl"><span class="red"><strong>General Settings:<br>
+ </strong></span>
+ Interactive voice response general settings.
+ </span></p></td>
+ </tr>
+ </table>
+ <br />
+
+ <form action="freeswitch_ivr_edit.php" method="post" name="iform" id="iform">
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="22%" valign="top" class="vncellreq">Extension</td>
+ <td width="78%" class="vtable">
+ <input name="ivrextension" type="text" class="formfld" id="ivrextension" size="40" value="<?=htmlspecialchars($pconfig['ivrextension']);?>">
+ <br> <span class="vexpl">e.g. <em>5002</em></span></td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq">IVR Name</td>
+ <td width="78%" class="vtable">
+ <input name="ivrname" type="text" class="formfld" id="ivrname" size="40" value="<?=htmlspecialchars($pconfig['ivrname']);?>">
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq">Recording Action</td>
+ <td width="78%" class="vtable">
+ <?php
+ $a_recordings = &$config['installedpackages']['freeswitchrecordings']['config'];
+ echo " <select name='recordingidaction' class='formfld'>\n";
+ echo " <option></option>\n";
+ if (count($a_recordings) > 0) {
+ foreach ($a_recordings as $ent) {
+ if (htmlspecialchars($pconfig['recordingidaction']) == $ent['recordingid']) {
+ echo " <option value='".$ent['recordingid']."' selected='yes'>".$ent['recordingname']."</option>\n";
+ }
+ else {
+ echo " <option value='".$ent['recordingid']."'>".$ent['recordingname']."</option>\n";
+ }
+ }
+ }
+ echo " </select>\n";
+ ?>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq">Recording Anti-Action</td>
+ <td width="78%" class="vtable">
+ <?php
+ //$a_recordings = &$config['installedpackages']['freeswitchrecordings']['config'];
+ echo " <select name='recordingidantiaction' class='formfld'>\n";
+ echo " <option></option>\n";
+ if (count($a_recordings) > 0) {
+ foreach ($a_recordings as $ent) {
+ if (htmlspecialchars($pconfig['recordingidantiaction']) == $ent['recordingid']) {
+ echo " <option value='".$ent['recordingid']."' selected='yes'>".$ent['recordingname']."</option>\n";
+ }
+ else {
+ echo " <option value='".$ent['recordingid']."'>".$ent['recordingname']."</option>\n";
+ }
+ }
+ }
+ echo " </select>\n";
+ ?>
+ </td>
+ </tr>
+ <?php
+ if (strlen($pconfig['ivrtimeout']) == 0) {
+ $pconfig['ivrtimeout'] = 10; //set a default timeout
+ }
+ ?>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq">Timeout</td>
+ <td width="78%" class="vtable">
+ <input name="ivrtimeout" type="text" class="formfld" id="ivrtimeout" size="40" value="<?=htmlspecialchars($pconfig['ivrtimeout']);?>">
+ <br><span class="vexpl">After the recording concludes the
+ timeout sets the time in seconds to continue to wait for DTMF.
+ If the DTMF is <br />not detected during that time the 't'
+ timeout option is executed.</span>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Context</td>
+ <td width="78%" class="vtable">
+ <input name="ivrcontext" type="text" class="formfld" id="ivrextension" size="40" value="<?=htmlspecialchars($pconfig['ivrcontext']);?>">
+ <br> <span class="vexpl">e.g. <em>default</em></span></td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Description</td>
+ <td width="78%" class="vtable">
+ <input name="ivrdescr" type="text" class="formfld" id="descr" size="40" value="<?=htmlspecialchars($pconfig['ivrdescr']);?>">
+ <br> <span class="vexpl">You may enter a description here
+ for your reference (not parsed).</span></td>
+ </tr>
+
+
+ <tr>
+ <td width="22%" valign="top" class="vncell">Javascript Condition</td>
+ <td width="78%" class="vtable">
+ <?php
+ if (strlen(htmlspecialchars(base64_decode($pconfig['ivrconditionjs']))) == 0) {
+ echo "<textarea name=\"ivrconditionjs\" cols=\"50\" rows=\"7\" wrap=\"off\">".$ivrconditionjs."</textarea>\n";
+ }
+ else {
+ echo "<textarea name=\"ivrconditionjs\" cols=\"50\" rows=\"7\" wrap=\"off\">".htmlspecialchars(base64_decode($pconfig['ivrconditionjs']))."</textarea>\n";
+ }
+ ?>
+ <br> <span class="vexpl">A simple valid condition is:
+ condition=true; To re-populate the default simply empty the
+ textarea and click on save. The following javascript variables
+ have been defined: Hours, Mins, Seconds, Month, Date, Year,
+ and Day.</span></td>
+ </tr>
+
+
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <input name="Submit" type="submit" class="formbtn" value="Save"> <input class="formbtn" type="button" value="Cancel" onclick="history.back()">
+ <input name="ivrid" type="hidden" value="<?=htmlspecialchars($pconfig['ivrid']);?>">
+ <?php if (isset($id) && $a_ivr[$id]): ?>
+ <input name="id" type="hidden" value="<?=$id;?>">
+ <?php endif; ?>
+ </td>
+ </tr>
+ </table>
+ </form>
+
+ <br>
+ <br>
+
+ <form action="freeswitch_ivr_edit.php" method="post" name="iform2" id="iform2">
+ <?php
+
+
+ //echo "<pre>";
+ //print_r ($a_ivr);
+ //echo "</pre>";
+
+ //if ($savemsg) print_info_box($savemsg);
+ //if (file_exists($d_hostsdirty_path)): echo"<p>";
+ //print_info_box_np("The FreeSWITCH recordings have been changed.<br>You must apply the changes in order for them to take effect.");
+ //echo"<br />";
+ //endif;
+
+ ?>
+
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td><p><span class="vexpl"><span class="red"><strong><br>
+ </strong></span>
+ Options are the choices that are available to the caller when they
+ are calling the auto attendant. If the caller presses 2 then the call
+ is directed to the corresponding destination.
+ </span></p></td>
+ </tr>
+ </table>
+
+
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td><p><span class="vexpl"><span class="red"><strong>Action<br />
+ </strong></span>
+ The options that are executed when the <b>condition matches.</b>
+ </span></p></td>
+ </tr>
+ </table>
+ <br />
+
+ <table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td width="20%" class="listhdrr">Option</td>
+ <td width="25%" class="listhdrr">Type</td>
+ <td width="25%" class="listhdrr">Destination</td>
+ <td width="25%" class="listhdr">Description</td>
+ <td width="10%" class="list">
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td width="17"></td>
+ <td valign="middle"><a href="freeswitch_ivr_options_edit.php?parentid=<?=$parentid;?>&ivrid=<?=$ivrid;?>&a=action"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" width="17" height="17" border="0"></a></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+
+ <?php
+ $i = 0;
+ if (count($a_ivr_options) > 0) {
+ foreach ($a_ivr_options as $ent) {
+ if ($ent['optionaction'] == "action" && $ivrid == $ent['ivrid']) {
+ ?>
+ <tr>
+ <td class="listlr" ondblclick="document.location='freeswitch_ivr_options_edit.php?id=<?=$i;?>&parentid=<?=$parentid;?>&ivrid=<?=$ivrid;?>'">
+ <?=$ent['optionnumber']?>
+ </td>
+ <td class="listr" ondblclick="document.location='freeswitch_ivr_options_edit.php?id=<?=$i;?>&parentid=<?=$parentid;?>&ivrid=<?=$ivrid;?>';">
+ <?=$ent['optiontype'];?>&nbsp;
+ </td>
+ <td class="listr" ondblclick="document.location='freeswitch_ivr_options_edit.php?id=<?=$i;?>&parentid=<?=$parentid;?>&ivrid=<?=$ivrid;?>';">
+ <?=$ent['optiondest'];?>&nbsp;
+ </td>
+ <td class="listbg" ondblclick="document.location='freeswitch_ivr_options_edit.php?id=<?=$id;?>&parentid=<?=$parentid;?>&ivrid=<?=$ivrid;?>';">
+ <font color="#FFFFFF"><?=htmlspecialchars($ent['optiondescr']);?>&nbsp;
+ </td>
+ <td valign="middle" nowrap class="list">
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td valign="middle"><a href="freeswitch_ivr_options_edit.php?id=<?=$i;?>&parentid=<?=$parentid;?>&ivrid=<?=$ivrid;?>"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_e.gif" width="17" height="17" border="0"></a></td>
+ <td><a href="freeswitch_ivr_options.php?type=ivroptions&act=del&id=<?=$i;?>&parentid=<?=$parentid;?>&ivrid=<?=$ivrid;?>" onclick="return confirm('Do you really want to delete this recording?')"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_x.gif" width="17" height="17" border="0"></a></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <?php
+ }
+ $i++;
+ }
+ }
+ ?>
+ <tr>
+ <td class="list" colspan="4"></td>
+ <td class="list">
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td width="17"></td>
+ <td valign="middle"><a href="freeswitch_ivr_options_edit.php?parentid=<?=$parentid;?>&ivrid=<?=$ivrid;?>&a=action"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" width="17" height="17" border="0"></a></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+
+
+ <tr>
+ <td class="list" colspan="4"></td>
+ <td class="list"></td>
+ </tr>
+ </table>
+
+ </form>
+
+
+
+ <form action="freeswitch_ivr_edit.php" method="post" name="iform2" id="iform2">
+ <?php
+
+
+ //echo "<pre>";
+ //print_r ($a_ivr);
+ //echo "</pre>";
+
+ //if ($savemsg) print_info_box($savemsg);
+ //if (file_exists($d_hostsdirty_path)): echo"<p>";
+ //print_info_box_np("The FreeSWITCH recordings have been changed.<br>You must apply the changes in order for them to take effect.");
+ //echo"<br />";
+ //endif;
+
+ ?>
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td><p><span class="vexpl"><span class="red"><strong>Anti-Action<br />
+ </strong></span>
+ The options that are executed when the <b>condition does NOT match.</b>
+ </span></p></td>
+ </tr>
+ </table>
+ <br />
+
+ <table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td width="20%" class="listhdrr">Option</td>
+ <td width="25%" class="listhdrr">Type</td>
+ <td width="25%" class="listhdrr">Destination</td>
+ <td width="25%" class="listhdr">Description</td>
+ <td width="10%" class="list">
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td width="17"></td>
+ <td valign="middle"><a href="freeswitch_ivr_options_edit.php?parentid=<?=$parentid;?>&ivrid=<?=$ivrid;?>&a=antiaction"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" width="17" height="17" border="0"></a></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+
+ <?php
+ $i = 0;
+ if (count($a_ivr_options) > 0) {
+ foreach ($a_ivr_options as $ent) {
+ if ($ent['optionaction'] == "anti-action" && $ivrid == $ent['ivrid']) {
+ ?>
+ <tr>
+ <td class="listlr" ondblclick="document.location='freeswitch_ivr_options_edit.php?id=<?=$i;?>&parentid=<?=$parentid;?>&ivrid=<?=$ivrid;?>'">
+ <?=$ent['optionnumber']?>
+ </td>
+ <td class="listr" ondblclick="document.location='freeswitch_ivr_options_edit.php?id=<?=$i;?>&parentid=<?=$parentid;?>&ivrid=<?=$ivrid;?>';">
+ <?=$ent['optiontype'];?>&nbsp;
+ </td>
+ <td class="listr" ondblclick="document.location='freeswitch_ivr_options_edit.php?id=<?=$i;?>&parentid=<?=$parentid;?>&ivrid=<?=$ivrid;?>';">
+ <?=$ent['optiondest'];?>&nbsp;
+ </td>
+ <td class="listbg" ondblclick="document.location='freeswitch_ivr_options_edit.php?id=<?=$id;?>&parentid=<?=$parentid;?>&ivrid=<?=$ivrid;?>';">
+ <font color="#FFFFFF"><?=htmlspecialchars($ent['optiondescr']);?>&nbsp;
+ </td>
+ <td valign="middle" nowrap class="list">
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td valign="middle"><a href="freeswitch_ivr_options_edit.php?id=<?=$i;?>&parentid=<?=$parentid;?>&ivrid=<?=$ivrid;?>"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_e.gif" width="17" height="17" border="0"></a></td>
+ <td><a href="freeswitch_ivr_options.php?type=ivroptions&act=del&id=<?=$i;?>&parentid=<?=$parentid;?>&ivrid=<?=$ivrid;?>" onclick="return confirm('Do you really want to delete this recording?')"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_x.gif" width="17" height="17" border="0"></a></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <?php
+ }
+ $i++;
+ }
+ }
+ ?>
+ <tr>
+ <td class="list" colspan="4"></td>
+ <td class="list">
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td width="17"></td>
+ <td valign="middle"><a href="freeswitch_ivr_options_edit.php?parentid=<?=$parentid;?>&ivrid=<?=$ivrid;?>&a=antiaction"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" width="17" height="17" border="0"></a></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+
+
+ <tr>
+ <td class="list" colspan="4"></td>
+ <td class="list"></td>
+ </tr>
+ </table>
+
+ </form>
+
+ <br>
+ <br>
+
+ </td>
+ </tr>
+</table>
+
+</div>
+
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/freeswitch/freeswitch_ivr_options.tmp b/config/freeswitch/freeswitch_ivr_options.tmp
new file mode 100644
index 00000000..8356bc58
--- /dev/null
+++ b/config/freeswitch/freeswitch_ivr_options.tmp
@@ -0,0 +1,52 @@
+<?php
+/* $Id$ */
+/*
+ freeswitch_ivr_options.php
+ Copyright (C) 2008 Mark J Crane
+ All rights reserved.
+
+ FreeSWITCH (TM)
+ http://www.freeswitch.org/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require("guiconfig.inc");
+require("/usr/local/pkg/freeswitch.inc");
+
+
+$a_ivr_options = &$config['installedpackages']['freeswitchivroptions']['config'];
+
+
+if ($_GET['act'] == "del") {
+ if ($_GET['type'] == 'ivroptions') {
+ if ($a_ivr_options[$_GET['id']]) {
+ unset($a_ivr_options[$_GET['id']]);
+ write_config();
+ sync_package_freeswitch_ivr();
+ header("Location: freeswitch_ivr_edit.php?id=".$_GET['parentid']);
+ exit;
+ }
+ }
+}
+
+?> \ No newline at end of file
diff --git a/config/freeswitch/freeswitch_ivr_options_edit.tmp b/config/freeswitch/freeswitch_ivr_options_edit.tmp
new file mode 100644
index 00000000..78975a7f
--- /dev/null
+++ b/config/freeswitch/freeswitch_ivr_options_edit.tmp
@@ -0,0 +1,216 @@
+<?php
+/* $Id$ */
+/*
+
+ freeswitch_recordings_edit.php
+ Copyright (C) 2008 Mark J Crane
+ All rights reserved.
+
+ FreeSWITCH (TM)
+ http://www.freeswitch.org/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require("guiconfig.inc");
+require("/usr/local/pkg/freeswitch.inc");
+
+
+$a_ivr_options = &$config['installedpackages']['freeswitchivroptions']['config'];
+
+$id = $_GET['id'];
+if (isset($_POST['id'])) {
+ $id = $_POST['id'];
+}
+
+$parentid = $_GET['parentid'];
+if (isset($_POST['parentid'])) {
+ $parentid = $_POST['parentid'];
+}
+
+$ivrid = $_GET['ivrid'];
+if (isset($_POST['ivrid'])) {
+ $ivrid = $_POST['ivrid'];
+}
+
+
+if (isset($id) && $a_ivr_options[$id]) {
+ $pconfig['optionaction'] = $a_ivr_options[$id]['optionaction'];
+ $pconfig['optionnumber'] = $a_ivr_options[$id]['optionnumber'];
+ $pconfig['optiontype'] = $a_ivr_options[$id]['optiontype'];
+ $pconfig['optiondest'] = $a_ivr_options[$id]['optiondest'];
+ $pconfig['optiondescr'] = $a_ivr_options[$id]['optiondescr'];
+}
+else {
+ if (isset($_GET['a'])) {
+ if ($_GET['a'] == "action"){ $pconfig['optionaction'] = "action"; }
+ if ($_GET['a'] == "antiaction"){ $pconfig['optionaction'] = "anti-action"; }
+ }
+}
+
+
+if ($_POST) {
+
+ unset($input_errors);
+ $pconfig = $_POST;
+
+
+ if (!$input_errors) {
+
+ $ivroptionent = array();
+ $ivroptionent['ivrid'] = $_POST['ivrid'];
+ $ivroptionent['optionnumber'] = $_POST['optionnumber'];
+ $ivroptionent['optiontype'] = $_POST['optiontype'];
+ $ivroptionent['optionaction'] = $_POST['optionaction'];
+ $ivroptionent['optiondest'] = $_POST['optiondest'];
+ $ivroptionent['optiondescr'] = $_POST['optiondescr'];
+
+ if (isset($id) && $a_ivr_options[$id]) {
+ //update
+ $a_ivr_options[$id] = $ivroptionent;
+ }
+ else {
+ //add
+ $a_ivr_options[] = $ivroptionent;
+ }
+
+
+ write_config();
+ sync_package_freeswitch_ivr();
+
+ header("Location: freeswitch_ivr_edit.php?id=".$parentid);
+ exit;
+ }
+}
+
+include("head.inc");
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<?php include("fbegin.inc"); ?>
+<p class="pgtitle">FreeSWITCH: IVR: Options: Edit</p>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+
+<div id="mainlevel">
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+<tr><td class="tabnavtbl">
+<?php
+
+ $tab_array = array();
+ $tab_array[] = array(gettext("Settings"), false, "/pkg_edit.php?xml=freeswitch.xml&amp;id=0");
+ $tab_array[] = array(gettext("Dialplan"), false, "/freeswitch/freeswitch_dialplan_includes.php");
+ $tab_array[] = array(gettext("Extensions"), false, "/freeswitch/freeswitch_extensions.php");
+ $tab_array[] = array(gettext("External"), false, "/pkg_edit.php?xml=freeswitch_external.xml&amp;id=0");
+ $tab_array[] = array(gettext("Gateways"), false, "/freeswitch/freeswitch_gateways.php");
+ $tab_array[] = array(gettext("Internal"), false, "/pkg_edit.php?xml=freeswitch_internal.xml&amp;id=0");
+ $tab_array[] = array(gettext("IVR"), true, "/freeswitch/freeswitch_ivr.php");
+ $tab_array[] = array(gettext("Modules"), false, "/pkg_edit.php?xml=freeswitch_modules.xml&amp;id=0");
+ $tab_array[] = array(gettext("Public"), false, "/freeswitch/freeswitch_public_includes.php");
+ $tab_array[] = array(gettext("Rec"), false, "/freeswitch/freeswitch_recordings.php");
+ $tab_array[] = array(gettext("Status"), false, "/freeswitch/freeswitch_status.php");
+ $tab_array[] = array(gettext("Vars"), false, "/pkg_edit.php?xml=freeswitch_vars.xml&amp;id=0");
+ display_top_tabs($tab_array);
+
+?>
+</td></tr>
+</table>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabcont" >
+
+ <form action="freeswitch_ivr_options_edit.php" method="post" name="iform" id="iform">
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="22%" valign="top" class="vncellreq">Option Number</td>
+ <td width="78%" class="vtable">
+ <input name="optionnumber" type="text" class="formfld" id="optionnumber" size="40" value="<?=htmlspecialchars($pconfig['optionnumber']);?>">
+ <br> <span class="vexpl">Option Number<br>
+ e.g. <em>1</em></span></td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq">Type</td>
+ <td width="78%" class="vtable">
+ <?php
+ echo " <select name='optiontype' class='formfld'>\n";
+ echo " <option></option>\n";
+ if (htmlspecialchars($pconfig['optiontype']) == "extension") {
+ echo " <option selected='yes'>extension</option>\n";
+ }
+ else {
+ echo " <option>extension</option>\n";
+ }
+ if (htmlspecialchars($pconfig['optiontype']) == "voicemail") {
+ echo " <option selected='yes'>voicemail</option>\n";
+ }
+ else {
+ echo " <option>voicemail</option>\n";
+ }
+ echo " </select>\n";
+ ?>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq">Destination</td>
+ <td width="78%" class="vtable">
+ <input name="optiondest" type="text" class="formfld" id="optiondest" size="40" value="<?=htmlspecialchars($pconfig['optiondest']);?>">
+ <br> <span class="vexpl">Destination<br>
+ e.g. <em>1001</em></span></td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Description</td>
+ <td width="78%" class="vtable">
+ <input name="optiondescr" type="text" class="formfld" id="optiondescr" size="40" value="<?=htmlspecialchars($pconfig['optiondescr']);?>">
+ <br> <span class="vexpl">You may enter a description here
+ for your reference (not parsed).</span></td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <input name="ivrid" type="hidden" value="<?=$ivrid;?>">
+ <input name="parentid" type="hidden" value="<?=$parentid;?>">
+ <input name="optionaction" type="hidden" value="<?=$pconfig['optionaction'];?>">
+ <?php if (isset($id) && $a_ivr_options[$id]): ?>
+ <input name="id" type="hidden" value="<?=$id;?>">
+ <?php endif; ?>
+ <input name="Submit" type="submit" class="formbtn" value="Save"> <input class="formbtn" type="button" value="Cancel" onclick="history.back()">
+ </td>
+ </tr>
+ </table>
+ </form>
+
+ <br>
+ <br>
+ <br>
+ <br>
+ <br>
+ <br>
+
+ </td>
+ </tr>
+</table>
+
+</div>
+
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/freeswitch/freeswitch_mailto.tmp b/config/freeswitch/freeswitch_mailto.tmp
new file mode 100644
index 00000000..23645570
--- /dev/null
+++ b/config/freeswitch/freeswitch_mailto.tmp
@@ -0,0 +1,240 @@
+<?php
+/* $Id$ */
+/*
+ freeswitch_mailto.php
+ Copyright (C) 2008 Mark J Crane
+ All rights reserved.
+
+ FreeSWITCH (TM)
+ http://www.freeswitch.org/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require_once("config.inc");
+require_once("/usr/local/pkg/freeswitch.inc");
+global $config;
+
+$tmp_smtphost = $config['installedpackages']['freeswitchsettings']['config'][0]['smtphost'];
+$tmp_smtpsecure = $config['installedpackages']['freeswitchsettings']['config'][0]['smtpsecure']; //options "", "TLS", "SSL"
+$tmp_smtpsecure = strtolower($tmp_smtpsecure);
+$tmp_smtpauth = $config['installedpackages']['freeswitchsettings']['config'][0]['smtpauth']; // SMTP authentication: true or false
+$tmp_smtpusername = $config['installedpackages']['freeswitchsettings']['config'][0]['smtpusername'];
+$tmp_smtppassword = $config['installedpackages']['freeswitchsettings']['config'][0]['smtppassword'];
+$tmp_smtpfrom = $config['installedpackages']['freeswitchsettings']['config'][0]['smtpfrom'];
+$tmp_smtpfromname = $config['installedpackages']['freeswitchsettings']['config'][0]['smtpfromname'];
+
+
+ini_set(max_execution_time,900); //15 minutes
+ini_set('memory_limit', '96M');
+$fd = fopen("php://stdin", "r");
+
+$email = file_get_contents ("php://stdin");
+
+fclose($fd);
+
+if($fd){
+ $fp = fopen("/tmp/voicemailtoemail.txt", "w");
+}
+
+
+ob_end_clean();
+ob_start();
+
+
+//get main header and body
+ $tmparray = split("\n\n", $email);
+ $mainheader = $tmparray[0];
+ $maincontent = substr($email, strlen($mainheader), strlen($email));
+
+//get the boundary
+ $tmparray = split("\n", $mainheader);
+ $contenttmp = $tmparray[1]; //Content-Type: multipart/mixed; boundary="XXXX_boundary_XXXX"
+ $tmparray = split('; ', $contenttmp); //boundary="XXXX_boundary_XXXX"
+ $contenttmp = $tmparray[1];
+ $tmparray = split('=', $contenttmp); //"XXXX_boundary_XXXX"
+ $boundary = $tmparray[1];
+ $boundary = trim($boundary,'"');
+ //echo "boundary: $boundary\n";
+
+//put the main headers into an array
+ $mainheaderarray = split("\n", $mainheader);
+ //print_r($mainheaderarray);
+ foreach ($mainheaderarray as $val) {
+ $tmparray = split(': ', $val);
+ //print_r($tmparray);
+ $var[$tmparray[0]] = trim($tmparray[1]);
+ }
+
+ $var['To'] = str_replace("<", "", $var['To']);
+ $var['To'] = str_replace(">", "", $var['To']);
+
+ echo "To: ".$var['To']."\n";
+ echo "From: ".$var['From']."\n";
+ echo "Subject: ".$var['Subject']."\n";
+ //print_r($var);
+ echo "\n\n";
+
+
+// split mime type multi-part into each part
+ $maincontent = str_replace($boundary."--", $boundary, $maincontent);
+ $tmparray = split("--".$boundary, $maincontent);
+
+// loop through each mime part
+ $i=0;
+ foreach ($tmparray as $mimepart) {
+
+ $mimearray = split("\n\n", $mimepart);
+ $subheader = $mimearray[0];
+ $headermimearray = split("\n", trim($subheader));
+
+ $x=0;
+ foreach ($headermimearray as $val) {
+ if(stristr($val, ':') === FALSE) {
+ $tmparray = split('=', $val); //':' not found
+ if (trim($tmparray[0]) == "boundary") {
+ $subboundary = $tmparray[1];
+ $subboundary = trim($subboundary,'"');
+ //echo "subboundary: ".$subboundary."\n";
+ }
+ }
+ else {
+ $tmparray = split(':', $val); //':' found
+ }
+
+ //print_r($tmparray);
+ $var[trim($tmparray[0])] = trim($tmparray[1]);
+ }
+ //print_r($var);
+
+
+ $contenttypearray = split(' ', $headermimearray[0]);
+
+ if ($contenttypearray[0] == "Content-Type:") {
+ $contenttype = trim($contenttypearray[1]);
+
+ switch ($contenttype) {
+ case "multipart/alternative;":
+
+ //echo "type: ".$contenttype."\n";
+ $content = trim(substr($mimepart, strlen($subheader), strlen($mimepart)));
+
+ $content = str_replace($subboundary."--", $subboundary, $content);
+ $tmpsubarray = split("--".$subboundary, $content);
+ foreach ($tmpsubarray as $mimesubsubpart) {
+
+ $mimesubsubarray = split("\n\n", $mimesubsubpart);
+ $subsubheader = $mimesubsubarray[0];
+
+ $headersubsubmimeearray = split("\n", trim($subsubheader));
+ $subsubcontenttypearray = split(' ', $headersubsubmimeearray[0]);
+ //echo "subsubcontenttypearray[0] ".$subsubcontenttypearray[0]."\n";
+
+ if ($subsubcontenttypearray[0] == "Content-Type:") {
+ $subsubcontenttype = trim($subsubcontenttypearray[1]);
+ switch ($subsubcontenttype) {
+ case "text/plain;":
+ $textplain = trim(substr($mimesubsubpart, strlen($subsubheader), strlen($mimesubsubpart)));
+ //echo "text/plain: $textplain\n";
+ break;
+ case "text/html;":
+ $texthtml = trim(substr($mimesubsubpart, strlen($subsubheader), strlen($mimesubsubpart)));
+ //echo "text/html: $texthtml\n";
+ break;
+ }
+ } //end if
+
+
+ } //end foreach
+
+ break;
+ case "audio/wav;":
+ //echo "type: ".$contenttype."\n";
+ $strwav = trim(substr($mimepart, strlen($subheader), strlen($mimepart)));
+ //echo "\n*** begin wav ***\n".$strwav."\n*** end wav ***\n";
+ break;
+
+ }//end switch
+ } //end if
+
+ $i++;
+
+ } //end foreach
+
+
+//send the email
+
+ include "class.phpmailer.php";
+ include "class.smtp.php"; ; // optional, gets called from within class.phpmailer.php if not already loaded
+
+ $mail = new PHPMailer();
+
+ $mail->IsSMTP(); // set mailer to use SMTP
+ $mail->SMTPAuth = $tmp_smtpauth; // turn on/off SMTP authentication
+ $mail->Host = $tmp_smtphost;
+ if (strlen($tmp_smtpsecure)>0) {
+ $mail->SMTPSecure = $tmp_smtpsecure;
+ }
+ if ($tmp_smtpauth) {
+ $mail->Username = $tmp_smtpusername;
+ $mail->Password = $tmp_smtppassword;
+ }
+
+
+ $mail->From = $tmp_smtpfrom;
+ $mail->FromName = $tmp_smtpfromname;
+ $mail->Subject = $var['Subject'];
+ $mail->AltBody = $textplain; // optional, comment out and test
+ $mail->MsgHTML($texthtml);
+
+
+ $tmp_to = $var['To'];
+ $tmp_to = str_replace(";", ",", $tmp_to);
+ $tmp_to_array = split(",", $tmp_to);
+ foreach($tmp_to_array as $tmp_to_row) {
+ if (strlen($tmp_to_row) > 0) {
+ $mail->AddAddress($tmp_to_row);
+ }
+ }
+
+ if (strlen($strwav) > 0) {
+ //$mail->AddAttachment("/usr/local/freeswitch/data/domain/example.wav"); // attachment
+ $filename='voicemail.wav'; $encoding = "base64"; $type = "audio/wav";
+ $mail->AddStringAttachment(base64_decode($strwav),$filename,$encoding,$type);
+ }
+ unset($strwav);
+
+ if(!$mail->Send()) {
+ echo "Mailer Error: " . $mail->ErrorInfo;
+ }
+ else {
+ echo "Message sent!";
+ }
+
+
+$content = ob_get_contents(); //get the output from the buffer
+ob_end_clean(); //clean the buffer
+
+fwrite($fp, $content);
+fclose($fp);
+
+?> \ No newline at end of file
diff --git a/config/freeswitch/freeswitch_modules.xml b/config/freeswitch/freeswitch_modules.xml
new file mode 100644
index 00000000..91620ac9
--- /dev/null
+++ b/config/freeswitch/freeswitch_modules.xml
@@ -0,0 +1,1216 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ freeswitch_modules.xml
+ Copyright (C) 2008 Mark J Crane
+ All rights reserved.
+
+ FreeSWITCH (TM)
+ http://www.freeswitch.org/
+
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>FreeSWITCH is an open source telephony platform designed to facilitate the creation of voice and chat driven products scaling from a soft-phone up to a soft-switch. It can be used as a simple switching engine, a PBX, a media gateway or a media server to host IVR applications using simple scripts or XML to control the callflow.</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>FreeSWITCH Modules</name>
+ <version>0.2</version>
+ <title>FreeSWITCH: Modules</title>
+ <include_file>/usr/local/pkg/freeswitch.inc</include_file>
+ <menu>
+ <name>FreeSWITCH</name>
+ <tooltiptext>Modify FreeSWITCH Modules.</tooltiptext>
+ <section>Services</section>
+ <configfile>freeswitch.xml</configfile>
+ <url>/pkg_edit.php?xml=freeswitch.xml&amp;id=0</url>
+ </menu>
+ <service>
+ <name>freeswitch</name>
+ <rcfile>freeswitch.sh</rcfile>
+ <executable>freeswitch</executable>
+ <description>FreeSWITCH is an open source telephony platform designed to facilitate the creation of voice and chat driven products scaling from a soft-phone up to a soft-switch. It can be used as a simple switching engine, a PBX, a media gateway or a media server to host IVR applications using simple scripts or XML to control the callflow.</description>
+ </service>
+ <tabs>
+ <tab>
+ <text>Settings</text>
+ <url>/pkg_edit.php?xml=freeswitch.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Dialplan</text>
+ <url>/freeswitch/freeswitch_dialplan_includes.php</url>
+ </tab>
+ <tab>
+ <text>Extensions</text>
+ <url>/freeswitch/freeswitch_extensions.php</url>
+ </tab>
+ <tab>
+ <text>External</text>
+ <url>/pkg_edit.php?xml=freeswitch_external.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Gateways</text>
+ <url>/freeswitch/freeswitch_gateways.php</url>
+ </tab>
+ <tab>
+ <text>Internal</text>
+ <url>/pkg_edit.php?xml=freeswitch_internal.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>IVR</text>
+ <url>/freeswitch/freeswitch_ivr.php</url>
+ </tab>
+ <tab>
+ <text>Modules</text>
+ <url>/pkg_edit.php?xml=freeswitch_modules.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Public</text>
+ <url>/freeswitch/freeswitch_public_includes.php</url>
+ </tab>
+ <tab>
+ <text>Rec</text>
+ <url>/freeswitch/freeswitch_recordings.php</url>
+ </tab>
+ <tab>
+ <text>Status</text>
+ <url>/freeswitch/freeswitch_status.php</url>
+ </tab>
+ <tab>
+ <text>Vars</text>
+ <url>/pkg_edit.php?xml=freeswitch_vars.xml&amp;id=0</url>
+ </tab>
+ </tabs>
+ <configpath>installedpackages->package->$packagename->configuration->freeswitchmodules</configpath>
+ <fields>
+ <field>
+ <fielddescr>&lt;b&gt;Loggers&lt;/b&gt;</fielddescr>
+ <fieldname>loggers</fieldname>
+ <description></description>
+ <type>listtopic</type>
+ </field>
+ <field>
+ <fielddescr>mod_console</fielddescr>
+ <fieldname>mod_console</fieldname>
+ <description>Send logs to the console.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>mod_logfile</fielddescr>
+ <fieldname>mod_logfile</fieldname>
+ <description>Send logs to the local file system.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>mod_syslog</fielddescr>
+ <fieldname>mod_syslog</fieldname>
+ <description>Send logs to a remote syslog server.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>&lt;b&gt;Multi-Faceted&lt;/b&gt;</fielddescr>
+ <fieldname>multi-faceted</fieldname>
+ <description></description>
+ <type>listtopic</type>
+ </field>
+ <field>
+ <fielddescr>mod_enum</fielddescr>
+ <fieldname>mod_enum</fieldname>
+ <description>Route PSTN numbers over internet according to ENUM servers, such as e164.org.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>&lt;b&gt;XML Interfaces&lt;/b&gt;</fielddescr>
+ <fieldname>xml_interfaces</fieldname>
+ <description></description>
+ <type>listtopic</type>
+ </field>
+ <field>
+ <fielddescr>mod_xml_rpc</fielddescr>
+ <fieldname>mod_xml_rpc</fieldname>
+ <description>XML Remote Procedure Calls. Issue commands from your web application.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>mod_xml_curl</fielddescr>
+ <fieldname>mod_xml_curl</fieldname>
+ <description>XML Gateway Code. Configure FreeSWITCH from a web server on boot and on the fly.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>mod_xml_cdr</fielddescr>
+ <fieldname>mod_xml_cdr</fieldname>
+ <description>XML based call detail record handler.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>&lt;b&gt;Event Handlers&lt;/b&gt;</fielddescr>
+ <fieldname>event_handlers</fieldname>
+ <description></description>
+ <type>listtopic</type>
+ </field>
+ <field>
+ <fielddescr>mod_cdr_csv</fielddescr>
+ <fieldname>mod_cdr_csv</fieldname>
+ <description>CSV call detail record handler.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>mod_event_multicast</fielddescr>
+ <fieldname>mod_event_multicast</fieldname>
+ <description>Broadcasts events to netmask.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>mod_event_socket</fielddescr>
+ <fieldname>mod_event_socket</fieldname>
+ <description>Sends events via a single socket.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>mod_zeroconf</fielddescr>
+ <fieldname>mod_zeroconf</fieldname>
+ <description>Support for zeroconf.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>&lt;b&gt;Directory Interfaces&lt;/b&gt;</fielddescr>
+ <fieldname>directory_interfaces</fieldname>
+ <description></description>
+ <type>listtopic</type>
+ </field>
+ <field>
+ <fielddescr>mod_ldap</fielddescr>
+ <fieldname>mod_ldap</fieldname>
+ <description>LDAP module made to obtain dialplans, user accounts, etc.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>&lt;b&gt;Endpoints&lt;/b&gt;</fielddescr>
+ <fieldname>endpoints</fieldname>
+ <description></description>
+ <type>listtopic</type>
+ </field>
+ <field>
+ <fielddescr>mod_dingaling</fielddescr>
+ <fieldname>mod_dingaling</fieldname>
+ <description>Jabber/GoogleTalk Talk integration module.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>mod_iax</fielddescr>
+ <fieldname>mod_iax</fieldname>
+ <description>IAX2.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>mod_portaudio</fielddescr>
+ <fieldname>mod_portaudio</fieldname>
+ <description>Voice through a local soundcard.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>mod_alsa</fielddescr>
+ <fieldname>mod_alsa</fieldname>
+ <description></description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>mod_sofia</fielddescr>
+ <fieldname>mod_sofia</fieldname>
+ <description>SIP module.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>mod_loopback</fielddescr>
+ <fieldname>mod_loopback</fieldname>
+ <description>A loopback channel driver to make an outbound call as an inbound call.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>mod_wanpipe</fielddescr>
+ <fieldname>mod_wanpipe</fieldname>
+ <description>T1/E1 Sangoma Card module.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>mod_woomera</fielddescr>
+ <fieldname>mod_woomera</fieldname>
+ <description>H.323/Woomera module.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>mod_openzap</fielddescr>
+ <fieldname>mod_openzap</fieldname>
+ <description>Interface to Zaptel hardware.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>&lt;b&gt;Applications&lt;/b&gt;</fielddescr>
+ <fieldname>applications</fieldname>
+ <description></description>
+ <type>listtopic</type>
+ </field>
+ <field>
+ <fielddescr>mod_commands</fielddescr>
+ <fieldname>mod_commands</fieldname>
+ <description>A mass plethora of API interface commands.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>mod_conference</fielddescr>
+ <fieldname>mod_conference</fieldname>
+ <description>Conference room module.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>mod_dptools</fielddescr>
+ <fieldname>mod_dptools</fieldname>
+ <description>Dialplan Tools: provides a number of apps and utilities for the dialplan.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>mod_expr</fielddescr>
+ <fieldname>mod_expr</fieldname>
+ <description>Brian Allen Vanderburgs expression evaluation library.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>mod_fax</fielddescr>
+ <fieldname>mod_fax</fieldname>
+ <description>FAX provides fax send and receive.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>mod_fifo</fielddescr>
+ <fieldname>mod_fifo</fieldname>
+ <description>FIFO provides custom call queues including call park.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>mod_voicemail</fielddescr>
+ <fieldname>mod_voicemail</fieldname>
+ <description>Full featured voicemail module.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>mod_limit</fielddescr>
+ <fieldname>mod_limit</fieldname>
+ <description>Resource limitation module.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>mod_esf</fielddescr>
+ <fieldname>mod_esf</fieldname>
+ <description>Holds the multi cast paging application for SIP.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>mod_fsv</fielddescr>
+ <fieldname>mod_fsv</fieldname>
+ <description>FreeSWITCH Video application (Recording and playback).</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>&lt;b&gt;SNOM Module&lt;/b&gt;</fielddescr>
+ <fieldname>snom_module</fieldname>
+ <description></description>
+ <type>listtopic</type>
+ </field>
+ <field>
+ <fielddescr>mod_snom</fielddescr>
+ <fieldname>mod_snom</fieldname>
+ <description></description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>&lt;b&gt;Dialplan Interfaces&lt;/b&gt;</fielddescr>
+ <fieldname>dialplan_interfaces</fieldname>
+ <description></description>
+ <type>listtopic</type>
+ </field>
+ <field>
+ <fielddescr>mod_dialplan_directory</fielddescr>
+ <fieldname>mod_dialplan_directory</fieldname>
+ <description>Allows you to obtain a dialplan from a directory resource.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>mod_dialplan_xml</fielddescr>
+ <fieldname>mod_dialplan_xml</fieldname>
+ <description>Allows you to program dialplans in XML format.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>mod_dialplan_asterisk</fielddescr>
+ <fieldname>mod_dialplan_asterisk</fieldname>
+ <description>Allows you to create dialplans the old-fashioned way.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>mod_yaml</fielddescr>
+ <fieldname>mod_yaml</fieldname>
+ <description>Allows you to program dialplans in YAML format.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>&lt;b&gt;Codec Interfaces&lt;/b&gt;</fielddescr>
+ <fieldname>codec_interfaces</fieldname>
+ <description></description>
+ <type>listtopic</type>
+ </field>
+ <field>
+ <fielddescr>mod_voipcodecs</fielddescr>
+ <fieldname>mod_voipcodecs</fieldname>
+ <description></description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>mod_g723_1</fielddescr>
+ <fieldname>mod_g723_1</fieldname>
+ <description>G.723.1 codec.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>mod_g729</fielddescr>
+ <fieldname>mod_g729</fieldname>
+ <description>G729 codec is only supported in passthrough mode.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>mod_amr</fielddescr>
+ <fieldname>mod_amr</fieldname>
+ <description>amr codec.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>mod_ilbc</fielddescr>
+ <fieldname>mod_ilbc</fieldname>
+ <description>ILBC codec.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>mod_speex</fielddescr>
+ <fieldname>mod_speex</fieldname>
+ <description>Speex codec.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>mod_siren</fielddescr>
+ <fieldname>mod_siren</fieldname>
+ <description>Siren codec.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>mod_celt</fielddescr>
+ <fieldname>mod_celt</fieldname>
+ <description>Celt codec.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>mod_h26x</fielddescr>
+ <fieldname>mod_h26x</fieldname>
+ <description>H26X signed linear codec. Video Pass-thru.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>&lt;b&gt;File Format Interfaces&lt;/b&gt;</fielddescr>
+ <fieldname>file_format_interfaces</fieldname>
+ <description></description>
+ <type>listtopic</type>
+ </field>
+ <field>
+ <fielddescr>mod_sndfile</fielddescr>
+ <fieldname>mod_sndfile</fieldname>
+ <description>Multi-format file format transcoder (WAV, etc).</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>mod_native_file</fielddescr>
+ <fieldname>mod_native_file</fieldname>
+ <description>File interface for codec specific file formats.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>&lt;b&gt;Streams/Files&lt;/b&gt;</fielddescr>
+ <fieldname>streams_files</fieldname>
+ <description></description>
+ <type>listtopic</type>
+ </field>
+ <field>
+ <fielddescr>mod_shout</fielddescr>
+ <fieldname>mod_shout</fieldname>
+ <description>mp3 files and shoutcast streams.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>mod_local_stream</fielddescr>
+ <fieldname>mod_local_stream</fieldname>
+ <description>For local streams (play all the files in a directory).</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>mod_tone_stream</fielddescr>
+ <fieldname>mod_tone_stream</fieldname>
+ <description>Generate tone streams.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>&lt;b&gt;Languages&lt;/b&gt;</fielddescr>
+ <fieldname>languages</fieldname>
+ <description></description>
+ <type>listtopic</type>
+ </field>
+ <field>
+ <fielddescr>mod_spidermonkey</fielddescr>
+ <fieldname>mod_spidermonkey</fieldname>
+ <description>JavaScript support.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>mod_perl</fielddescr>
+ <fieldname>mod_perl</fieldname>
+ <description>Perl support.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>mod_python</fielddescr>
+ <fieldname>mod_python</fieldname>
+ <description>Python support.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>mod_java</fielddescr>
+ <fieldname>mod_java</fieldname>
+ <description>Java support.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>mod_lua</fielddescr>
+ <fieldname>mod_lua</fieldname>
+ <description>Lua support.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>&lt;b&gt;ASR /TTS&lt;/b&gt;</fielddescr>
+ <fieldname>asr_tts</fieldname>
+ <description></description>
+ <type>listtopic</type>
+ </field>
+ <field>
+ <fielddescr>mod_flite</fielddescr>
+ <fieldname>mod_flite</fieldname>
+ <description>Free open source Text to Speech.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>mod_pocketsphinx</fielddescr>
+ <fieldname>mod_pocketsphinx</fieldname>
+ <description>Free open source Speech Recognition.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>mod_cepstral</fielddescr>
+ <fieldname>mod_cepstral</fieldname>
+ <description>Links into Cepstral for dynamic sound output. Not available on this build.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>mod_openmrcp</fielddescr>
+ <fieldname>mod_openmrcp</fieldname>
+ <description>Module for an open MRCP implementation.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>mod_rss</fielddescr>
+ <fieldname>mod_rss</fieldname>
+ <description>Reads RSS feeds via a TTS engine.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>&lt;b&gt;Say&lt;/b&gt;</fielddescr>
+ <fieldname>say</fieldname>
+ <description></description>
+ <type>listtopic</type>
+ </field>
+ <field>
+ <fielddescr>mod_say_en</fielddescr>
+ <fieldname>mod_say_en</fieldname>
+ <description></description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>mod_say_zh</fielddescr>
+ <fieldname>mod_say_zh</fieldname>
+ <description></description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>enable</name>
+ <value>enable</value>
+ </option>
+ <option>
+ <name>disable</name>
+ <value>disable</value>
+ </option>
+ </options>
+ </field>
+ </fields>
+ <custom_add_php_command>
+ </custom_add_php_command>
+ <custom_php_resync_config_command>
+ sync_package_freeswitch_modules();
+ </custom_php_resync_config_command>
+ <custom_delete_php_command>
+ sync_package_freeswitch_modules();
+ </custom_delete_php_command>
+ <custom_php_deinstall_command>
+ </custom_php_deinstall_command>
+</packagegui> \ No newline at end of file
diff --git a/config/freeswitch/freeswitch_public.xml b/config/freeswitch/freeswitch_public.xml
new file mode 100644
index 00000000..fab77635
--- /dev/null
+++ b/config/freeswitch/freeswitch_public.xml
@@ -0,0 +1,135 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ freeswitch_public.xml
+ Copyright (C) 2008 Mark J Crane
+ All rights reserved.
+
+ FreeSWITCH (TM)
+ http://www.freeswitch.org/
+
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>FreeSWITCH is an open source telephony platform designed to facilitate the creation of voice and chat driven products scaling from a soft-phone up to a soft-switch. It can be used as a simple switching engine, a PBX, a media gateway or a media server to host IVR applications using simple scripts or XML to control the callflow.</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>freeswitchpublic</name>
+ <version>0.1</version>
+ <title>FreeSWITCH: Public</title>
+ <aftersaveredirect>pkg_edit.php?xml=freeswitch_public.xml&amp;id=0</aftersaveredirect>
+ <include_file>/usr/local/pkg/freeswitch.inc</include_file>
+ <tabs>
+ <tab>
+ <text>Settings</text>
+ <url>/pkg_edit.php?xml=freeswitch.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Dialplan</text>
+ <url>/freeswitch/freeswitch_dialplan_includes.php</url>
+ </tab>
+ <tab>
+ <text>Extensions</text>
+ <url>/freeswitch/freeswitch_extensions.php</url>
+ </tab>
+ <tab>
+ <text>External</text>
+ <url>/pkg_edit.php?xml=freeswitch_external.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Gateways</text>
+ <url>/freeswitch/freeswitch_gateways.php</url>
+ </tab>
+ <tab>
+ <text>Internal</text>
+ <url>/pkg_edit.php?xml=freeswitch_internal.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>IVR</text>
+ <url>/freeswitch/freeswitch_ivr.php</url>
+ </tab>
+ <tab>
+ <text>Modules</text>
+ <url>/pkg_edit.php?xml=freeswitch_modules.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Public</text>
+ <url>/freeswitch/freeswitch_public_includes.php</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Rec</text>
+ <url>/freeswitch/freeswitch_recordings.php</url>
+ </tab>
+ <tab>
+ <text>Status</text>
+ <url>/freeswitch/freeswitch_status.php</url>
+ </tab>
+ <tab>
+ <text>Vars</text>
+ <url>/pkg_edit.php?xml=freeswitch_vars.xml&amp;id=0</url>
+ </tab>
+ </tabs>
+ <configpath>installedpackages->package->$packagename->configuration->freeswitchpublic</configpath>
+ <fields>
+ <field>
+ <fielddescr>&lt;b&gt;Public&lt;/b&gt; &lt;br /&gt; &lt;br /&gt;Directs inbound calls to extensions, IVRs, external numbers, and scripts. </fielddescr>
+ <fieldname>public_xml</fieldname>
+ <description>&lt;br /&gt;Path: /usr/local/freeswitch/conf/dialplan/public.xml &lt;br /&gt;&lt;br /&gt;</description>
+ <type>textarea</type>
+ <encoding>base64</encoding>
+ <wrap>off</wrap>
+ <size>30</size>
+ <cols>70</cols>
+ <rows>33</rows>
+ </field>
+ </fields>
+ <custom_php_command_before_form>
+ </custom_php_command_before_form>
+ <custom_php_after_head_command>
+ sync_package_freeswitch_public();
+ </custom_php_after_head_command>
+ <custom_php_after_form_command>
+ </custom_php_after_form_command>
+ <custom_php_validation_command>
+ </custom_php_validation_command>
+ <custom_php_resync_config_command>
+ sync_package_freeswitch_public();
+ </custom_php_resync_config_command>
+</packagegui> \ No newline at end of file
diff --git a/config/freeswitch/freeswitch_public_includes.tmp b/config/freeswitch/freeswitch_public_includes.tmp
new file mode 100644
index 00000000..66f733b3
--- /dev/null
+++ b/config/freeswitch/freeswitch_public_includes.tmp
@@ -0,0 +1,275 @@
+<?php
+/* $Id$ */
+/*
+ freeswitch_public_includes.php
+ Copyright (C) 2008 Mark J Crane
+ All rights reserved.
+
+ FreeSWITCH (TM)
+ http://www.freeswitch.org/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require("guiconfig.inc");
+require("/usr/local/pkg/freeswitch.inc");
+
+
+//freeswitchpublicincludes
+ //publicincludeid
+ //extensionname
+ //context
+ //default
+ //enabled
+ //descr
+
+//freeswitchpublicincludedetails
+
+ //publicincludeid
+ //tag
+ //condition
+ //action
+ //antiaction
+ //param
+ //tagorder
+ //1-20
+ //fieldtype
+
+ //fielddata
+
+
+$a_public_includes = &$config['installedpackages']['freeswitchpublicincludes']['config'];
+$a_public_includes_details = &$config['installedpackages']['freeswitchpublicincludedetails']['config'];
+
+
+if ($_GET['act'] == "del") {
+ if ($_GET['type'] == 'publicincludes') {
+
+ if ($a_public_includes[$_GET['id']]) {
+
+ $publicincludeid = $a_public_includes[$_GET['id']][publicincludeid];
+
+ $extensionname = $a_public_includes[$_GET['id']][extensionname];
+ $order = $a_public_includes[$_GET['id']][order];
+ $publicincludefilename = $order."_".$extensionname.".xml";
+
+ //delete the public include details. aka. child data
+ if (count($a_public_includes_details) > 0) {
+ $i=0;
+ if (count($a_public_includes_details) > 0) {
+ foreach($a_public_includes_details as $row) {
+ if ($row["publicincludeid"] == $publicincludeid) {
+ //echo "child id: ".$i."<br />\n";
+ unset($a_public_includes_details[$i]);
+ }
+ $i++;
+ }
+ }
+ }
+
+ //if the public include xml file exists then delete it
+ if (file_exists("/usr/local/freeswitch/conf/public/default/".$publicincludefilename)) {
+ unlink("/usr/local/freeswitch/conf/public/default/".$publicincludefilename);
+ }
+
+ unset($publicincludefilename);
+ unset($a_public_includes[$_GET['id']]);
+ write_config();
+ sync_package_freeswitch_public_includes();
+ header("Location: freeswitch_public_includes.php");
+ exit;
+ }
+ }
+}
+
+include("head.inc");
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<?php include("fbegin.inc"); ?>
+<p class="pgtitle">FreeSWITCH: Public</p>
+
+<div id="mainlevel">
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+<tr><td class="tabnavtbl">
+<?php
+
+ $tab_array = array();
+ $tab_array[] = array(gettext("Settings"), false, "/pkg_edit.php?xml=freeswitch.xml&amp;id=0");
+ $tab_array[] = array(gettext("Dialplan"), false, "/freeswitch/freeswitch_dialplan_includes.php");
+ $tab_array[] = array(gettext("Extensions"), false, "/freeswitch/freeswitch_extensions.php");
+ $tab_array[] = array(gettext("External"), false, "/pkg_edit.php?xml=freeswitch_external.xml&amp;id=0");
+ $tab_array[] = array(gettext("Gateways"), false, "/freeswitch/freeswitch_gateways.php");
+ $tab_array[] = array(gettext("Internal"), false, "/pkg_edit.php?xml=freeswitch_internal.xml&amp;id=0");
+ $tab_array[] = array(gettext("IVR"), false, "/freeswitch/freeswitch_ivr.php");
+ $tab_array[] = array(gettext("Modules"), false, "/pkg_edit.php?xml=freeswitch_modules.xml&amp;id=0");
+ $tab_array[] = array(gettext("Public"), true, "/freeswitch/freeswitch_public_includes.php");
+ $tab_array[] = array(gettext("Rec"), false, "/freeswitch/freeswitch_recordings.php");
+ $tab_array[] = array(gettext("Status"), false, "/freeswitch/freeswitch_status.php");
+ $tab_array[] = array(gettext("Vars"), false, "/pkg_edit.php?xml=freeswitch_vars.xml&amp;id=0");
+ display_top_tabs($tab_array);
+
+?>
+</td></tr>
+</table>
+
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabcont" >
+
+<form action="freeswitch_public_includes.php" method="post" name="iform" id="iform">
+<?php
+
+
+//echo "<pre>";
+//print_r ($a_public_includes);
+//echo "</pre>";
+
+
+//if ($config_change == 1) {
+// write_config();
+// $config_change = 0;
+//}
+
+//if ($savemsg) print_info_box($savemsg);
+//if (file_exists($d_hostsdirty_path)): echo"<p>";
+//print_info_box_np("The FreeSWITCH recordings have been changed.<br>You must apply the changes in order for them to take effect.");
+//echo"<br />";
+//endif;
+
+?>
+
+ <br />
+ <br />
+
+ <table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td><span class="vexpl"><span class="red"><strong>Public
+ </strong></span></span>
+ </td>
+ <td align='right'>
+ <input type='button' value='public.xml' alt='' onclick="document.location.href='/pkg_edit.php?xml=freeswitch_public.xml&id=0';">
+ </td>
+ </tr>
+ <tr>
+ <td colspan='2'>
+ <span class="vexpl">
+ The public dialplan is used to route incoming calls to destinations based on conditions and context. It can send incoming calls to IVRs, extensions, external numbers, and scripts.
+ </span>
+ </td>
+
+ </tr>
+ </table>
+
+ <br />
+ <br />
+ <br />
+
+ <table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td width="20%" class="listhdrr">Extension Name</td>
+ <td width="25%" class="listhdrr">Order</td>
+ <td width="25%" class="listhdrr">Enabled</td>
+ <td width="50%" class="listhdr">Description</td>
+ <td width="10%" class="list">
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td width="17"></td>
+ <td valign="middle"><a href="freeswitch_public_includes_edit.php"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" width="17" height="17" border="0"></a></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+
+ <?php
+ $i = 0;
+ if (count($a_public_includes) > 0) {
+ foreach ($a_public_includes as $ent) {
+ if (strlen($ent['extensionname'].$ent['enabled']) > 0) {
+ ?>
+ <tr>
+ <td class="listlr" ondblclick="document.location='freeswitch_public_includes_edit.php?id=<?=$i;?>'">
+ <?=$ent['extensionname']?>
+ </td>
+ <td class="listlr" ondblclick="document.location='freeswitch_public_includes_edit.php?id=<?=$i;?>'">
+ <?=$ent['order']?>
+ </td>
+ <td class="listr" ondblclick="document.location='freeswitch_public_includes_edit.php?id=<?=$i;?>';">
+ <?=$ent['enabled'];?>&nbsp;
+ </td>
+ <td class="listbg" ondblclick="document.location='freeswitch_public_includes_edit.php?id=<?=$i;?>';">
+ <font color="#FFFFFF"><?=htmlspecialchars($ent['descr']);?>&nbsp;
+ </td>
+ <td valign="middle" nowrap class="list">
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td valign="middle"><a href="freeswitch_public_includes_edit.php?id=<?=$i;?>"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_e.gif" width="17" height="17" border="0"></a></td>
+ <td><a href="freeswitch_public_includes.php?type=publicincludes&act=del&id=<?=$i;?>" onclick="return confirm('Do you really want to delete this?')"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_x.gif" width="17" height="17" border="0"></a></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <?php
+ } //end if strlen
+ $i++;
+ } //end for each
+ } //end if count
+ ?>
+ <tr>
+ <td class="list" colspan="4"></td>
+ <td class="list">
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td width="17"></td>
+ <td valign="middle"><a href="freeswitch_public_includes_edit.php"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" width="17" height="17" border="0"></a></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+
+ <tr>
+ <td class="list" colspan="4"></td>
+ <td class="list"></td>
+ </tr>
+ </table>
+
+</form>
+
+/usr/local/freeswitch/conf/dialplan/public/
+<br>
+<br>
+<br>
+<br>
+<br>
+<br>
+
+</td>
+</tr>
+</table>
+
+</div>
+
+
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/freeswitch/freeswitch_public_includes_details.tmp b/config/freeswitch/freeswitch_public_includes_details.tmp
new file mode 100644
index 00000000..c28a7647
--- /dev/null
+++ b/config/freeswitch/freeswitch_public_includes_details.tmp
@@ -0,0 +1,53 @@
+<?php
+/* $Id$ */
+/*
+ freeswitch_public_includes_details.php
+ Copyright (C) 2008 Mark J Crane
+ All rights reserved.
+
+ FreeSWITCH (TM)
+ http://www.freeswitch.org/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require("guiconfig.inc");
+require("/usr/local/pkg/freeswitch.inc");
+
+
+$a_public_include_details = &$config['installedpackages']['freeswitchpublicincludedetails']['config'];
+
+
+if ($_GET['act'] == "del") {
+ if ($_GET['type'] == 'publicincludedetails') {
+ if ($a_public_include_details[$_GET['id']]) {
+ unset($a_public_include_details[$_GET['id']]);
+ write_config();
+ sync_package_freeswitch_public_includes();
+ //touch($d_hostsdirty_path);
+ header("Location: freeswitch_public_includes_edit.php?id=".$_GET['parentid']);
+ exit;
+ }
+ }
+}
+
+?> \ No newline at end of file
diff --git a/config/freeswitch/freeswitch_public_includes_details_edit.tmp b/config/freeswitch/freeswitch_public_includes_details_edit.tmp
new file mode 100644
index 00000000..821d9097
--- /dev/null
+++ b/config/freeswitch/freeswitch_public_includes_details_edit.tmp
@@ -0,0 +1,410 @@
+<?php
+/* $Id$ */
+/*
+
+ freeswitch_public_includes_details_edit.php
+ Copyright (C) 2008 Mark J Crane
+ All rights reserved.
+
+ FreeSWITCH (TM)
+ http://www.freeswitch.org/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require("guiconfig.inc");
+require("/usr/local/pkg/freeswitch.inc");
+
+
+$a_public_includes_details = &$config['installedpackages']['freeswitchpublicincludedetails']['config'];
+
+$id = $_GET['id'];
+if (isset($_POST['id'])) {
+ $id = $_POST['id'];
+}
+
+$parentid = $_GET['parentid'];
+if (isset($_POST['parentid'])) {
+ $parentid = $_POST['parentid'];
+}
+
+$publicincludeid = $_GET['publicincludeid'];
+if (isset($_POST['publicincludeid'])) {
+ $publicincludeid = $_POST['publicincludeid'];
+}
+
+
+ //publicincludeid
+ //tag
+ //condition
+ //action
+ //antiaction
+ //param
+ //tagorder
+ //1-20
+ //fieldtype
+
+ //fielddata
+
+
+if (isset($id) && $a_public_includes_details[$id]) {
+ $pconfig['publicincludeid'] = $a_public_includes_details[$id]['publicincludeid'];
+ $pconfig['tag'] = $a_public_includes_details[$id]['tag'];
+ //$pconfig['tagorder'] = $a_public_includes_details[$id]['tagorder'];
+ $pconfig['fieldtype'] = $a_public_includes_details[$id]['fieldtype'];
+ $pconfig['fielddata'] = $a_public_includes_details[$id]['fielddata'];
+}
+//else {
+// if (isset($_GET['a'])) {
+// if ($_GET['a'] == "action"){ $pconfig['optionaction'] = "action"; }
+// if ($_GET['a'] == "antiaction"){ $pconfig['optionaction'] = "anti-action"; }
+// }
+//}
+
+
+
+if ($_POST) {
+
+ unset($input_errors);
+ $pconfig = $_POST;
+
+
+ if (!$input_errors) {
+
+ $ent = array();
+ $ent['publicincludeid'] = $_POST['publicincludeid'];
+ $ent['tag'] = $_POST['tag'];
+ //$ent['tagorder'] = $_POST['tagorder'];
+ $ent['fieldtype'] = $_POST['fieldtype'];
+ $ent['fielddata'] = $_POST['fielddata'];
+
+
+ if (isset($id) && $a_public_includes_details[$id]) {
+ //update
+ $a_public_includes_details[$id] = $ent;
+ }
+ else {
+ //add
+ $a_public_includes_details[] = $ent;
+ }
+
+ //touch($d_hostsdirty_path);
+ write_config();
+ sync_package_freeswitch_public_includes();
+
+ header("Location: freeswitch_public_includes_edit.php?id=".$parentid);
+ exit;
+ }
+}
+
+include("head.inc");
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<?php include("fbegin.inc"); ?>
+<p class="pgtitle">FreeSWITCH: Public: Details: Edit</p>
+
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+
+<div id="mainlevel">
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+<tr><td class="tabnavtbl">
+<?php
+
+ $tab_array = array();
+ $tab_array[] = array(gettext("Settings"), false, "/pkg_edit.php?xml=freeswitch.xml&amp;id=0");
+ $tab_array[] = array(gettext("Dialplan"), false, "/freeswitch/freeswitch_dialplan_includes.php");
+ $tab_array[] = array(gettext("Extensions"), false, "/freeswitch/freeswitch_extensions.php");
+ $tab_array[] = array(gettext("External"), false, "/pkg_edit.php?xml=freeswitch_external.xml&amp;id=0");
+ $tab_array[] = array(gettext("Gateways"), false, "/freeswitch/freeswitch_gateways.php");
+ $tab_array[] = array(gettext("Internal"), false, "/pkg_edit.php?xml=freeswitch_internal.xml&amp;id=0");
+ $tab_array[] = array(gettext("IVR"), false, "/freeswitch/freeswitch_ivr.php");
+ $tab_array[] = array(gettext("Modules"), false, "/pkg_edit.php?xml=freeswitch_modules.xml&amp;id=0");
+ $tab_array[] = array(gettext("Public"), true, "/freeswitch/freeswitch_public_includes.php");
+ $tab_array[] = array(gettext("Rec"), false, "/freeswitch/freeswitch_recordings.php");
+ $tab_array[] = array(gettext("Status"), false, "/freeswitch/freeswitch_status.php");
+ $tab_array[] = array(gettext("Vars"), false, "/pkg_edit.php?xml=freeswitch_vars.xml&amp;id=0");
+ display_top_tabs($tab_array);
+
+?>
+</td></tr>
+</table>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabcont" >
+
+ <form action="freeswitch_public_includes_details_edit.php" method="post" name="iform" id="iform">
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="22%" valign="top" class="vncellreq">Tag</td>
+ <td width="78%" class="vtable">
+ <script type="text/javascript">
+ function public_include_details_tag_onchange() {
+ var tag = document.getElementById("form_tag").value;
+ if (tag == "condition") {
+ document.getElementById("label_fieldtype").innerHTML = "Field";
+ document.getElementById("label_fielddata").innerHTML = "Expression";
+ }
+ else if (tag == "action") {
+ document.getElementById("label_fieldtype").innerHTML = "Application";
+ document.getElementById("label_fielddata").innerHTML = "Data";
+ }
+ else if (tag == "anti-action") {
+ document.getElementById("label_fieldtype").innerHTML = "Application";
+ document.getElementById("label_fielddata").innerHTML = "Data";
+ }
+ else if (tag == "param") {
+ document.getElementById("label_fieldtype").innerHTML = "Name";
+ document.getElementById("label_fielddata").innerHTML = "Value";
+ }
+ if (tag == "") {
+ document.getElementById("label_fieldtype").innerHTML = "Type";
+ document.getElementById("label_fielddata").innerHTML = "Data";
+ }
+ }
+ </script>
+ <?php
+ echo " <select name='tag' class='formfld' id='form_tag' onchange='public_include_details_tag_onchange();'>\n";
+ echo " <option></option>\n";
+ switch (htmlspecialchars($pconfig['tag'])) {
+ case "condition":
+ echo " <option selected='yes'>condition</option>\n";
+ echo " <option>action</option>\n";
+ echo " <option>anti-action</option>\n";
+ //echo " <option>param</option>\n";
+ break;
+ case "action":
+ echo " <option>condition</option>\n";
+ echo " <option selected='yes'>action</option>\n";
+ echo " <option>anti-action</option>\n";
+ //echo " <option>param</option>\n";
+ break;
+ case "anti-action":
+ echo " <option>condition</option>\n";
+ echo " <option>action</option>\n";
+ echo " <option selected='yes'>anti-action</option>\n";
+ //echo " <option>param</option>\n";
+ break;
+ case "param":
+ echo " <option>condition</option>\n";
+ echo " <option>action</option>\n";
+ echo " <option>anti-action</option>\n";
+ //echo " <option selected='yes'>param</option>\n";
+ break;
+ default:
+ echo " <option>condition</option>\n";
+ echo " <option>action</option>\n";
+ echo " <option>anti-action</option>\n";
+ //echo " <option>param</option>\n";
+ }
+ echo " </select>\n";
+
+ //condition
+ //field expression
+ //action
+ //application
+ //data
+ //antiaction
+ //application
+ //data
+ //param
+ //name
+ //value
+
+ ?>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq" id="label_fieldtype">Type</td>
+ <td width="78%" class="vtable">
+ <input name="fieldtype" type="text" class="formfld" id="fieldtype" size="40" value="<?=htmlspecialchars($pconfig['fieldtype']);?>">
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq" id="label_fielddata">Data</td>
+ <td width="78%" class="vtable">
+ <input name="fielddata" type="text" class="formfld" id="fielddata" size="40" value="<?=htmlspecialchars($pconfig['fielddata']);?>">
+ <br> <span class="vexpl"></span></td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <input name="publicincludeid" type="hidden" value="<?=$publicincludeid;?>">
+ <input name="parentid" type="hidden" value="<?=$parentid;?>">
+ <?php if (isset($id) && $a_public_includes_details[$id]): ?>
+ <input name="id" type="hidden" value="<?=$id;?>">
+ <?php endif; ?>
+ <input name="Submit" type="submit" class="formbtn" value="Save"> <input class="formbtn" type="button" value="Cancel" onclick="history.back()">
+ </td>
+ </tr>
+ </table>
+ </form>
+
+
+ <br />
+ <br />
+ <b>Example</b>
+ <br />
+ <br />
+ If the inbound call matches the DID 12085551234 then proceed to the action.
+ <br />
+ <br />
+ <table cellpadding='3'>
+ <tr><th class="vncellreq" width='75' align="left">Tag:</th><td class="vtable">condition</td></tr>
+ <tr><th class="vncellreq" align="left">Type:</th><td class="vtable">destination_number</td></tr>
+ <tr><th class="vncellreq" align="left">Data:</th><td class="vtable">^(12085551234)$</td></tr>
+ </table>
+
+ <br />
+ <br />
+
+ Transfer the inbound call to an IVR with extension of 5000.
+ <br />
+ <br />
+ <table cellpadding='3'>
+ <tr><th class="vncellreq" width='75' align="left">Tag:</th><td class="vtable">action</td></tr>
+ <tr><th class="vncellreq" align="left">Application:</th><td class="vtable">transfer</td></tr>
+ <tr><th class="vncellreq" align="left">Data:</th><td class="vtable">5000 XML default</td></tr>
+ </table>
+
+ <br />
+ <br />
+
+ Or transfer the inbound call to extension 1001.
+ <br />
+ <br />
+ <table cellpadding='3'>
+ <tr><th class="vncellreq" width='75' align="left">Tag:</th><td class="vtable">action</td></tr>
+ <tr><th class="vncellreq" align="left">Application:</th><td class="vtable">transfer</td></tr>
+ <tr><th class="vncellreq" align="left">Data:</th><td class="vtable">1001 XML default</td></tr>
+ </table>
+
+
+ <br />
+ <br />
+ <br />
+ <br />
+
+
+ <b>Conditions</b>
+ <br />
+ <br />
+ Conditions are pattern matching tags that help FreeSwitch decide if the current call should be processed in this extension or not. When matching conditions against the current call you have several <b>fields</b> that you can compare against.
+ <ul>
+ <li><b>context</b></li>
+ <li><b>rdnis</b> Redirected Number, the directory number to which the call was last presented.</li>
+ <li><b>destination_number</b> Called Number, the number this call is trying to reach (within a given context)</li>
+ <li><b>public</b> Name of the public module that are used, the name is provided by each public module. Example: XML</li>
+ <li><b>caller_id_name</b> Name of the caller (provided by the User Agent that has called us).</li>
+ <li><b>caller_id_number</b> Directory Number of the party who called (callee) -- can be masked (hidden)</li>
+ <li><b>ani</b> Automatic Number Identification, the number of the calling party (callee) -- cannot be masked</li>
+ <li><b>ani2</b> The type of device placing the call [1]</li>
+ <li><b>uuid</b> Unique identifier of the current call? (looks like a GUID)</li>
+ <li><b>source</b> Name of the FreeSwitch module that received the call (e.g. PortAudio)</li>
+ <li><b>chan_name</b> Name of the current channel (Example: PortAudio/1234). Give us examples when this one can be used.</li>
+ <li><b>network_addr</b> IP address of the signalling source for a VoIP call.</li>
+ </ul>
+ In addition to the above you can also do variables using the syntax ${variable} or api functions using the syntax %{api} {args}
+ <br />
+ <br />
+ Variables may be used in either the field or the expression, as follows
+
+ <br />
+ <br />
+ <br />
+ <br />
+
+ <b>Action and Anti-Actions</b>
+ <br />
+ <br />
+ Actions are executed when the <b>condition matches</b>. Anti-Actions are executed when the <b>condition does NOT match</b>.
+ Additional information on applications for Actions and Anti-Actions.<br />
+ <a href='http://wiki.freeswitch.org/wiki/Modules#Applications' target='_blank'>http://wiki.freeswitch.org/wiki/Modules#Applications</a>
+ <br />
+ <a href='http://wiki.freeswitch.org/wiki/public_Functions' target='_blank'>http://wiki.freeswitch.org/wiki/public_Functions</a>
+ <br />
+ <br />
+ <br />
+ The following is a partial list of <b>applications</b>.
+ <ul>
+ <li><b>answer</b> answer the call</li>
+ <li><b>bridge</b> bridge the call<li>
+ <li><b>cond</b></li>
+ <li><b>db</b> is a a runtime database either sqlite by default or odbc</li>
+ <li><b>global_set</b> allows setting of global vars similar to the ones found in vars.xml</li>
+ <li><b>group</b> allows grouping of several extensions for things like ring groups</li>
+ <li><b>expr</b></li>
+ <li><b>hangup</b> hangs up the call</li>
+ <li><b>info</b> sends call info to the console</li>
+ <li><b>javascript</b> run javascript .js files</li>
+ <li><b>playback</b></li>
+ <li><b>reject</b> reject the call</li>
+ <li><b>respond</b></li>
+ <li><b>ring_ready</b></li>
+ <li><b>set</b> set a variable</li>
+ <li><b>set_user</b></li>
+ <li><b>sleep</b></li>
+ <li><b>sofia_contact</b></li>
+ <li><b>transfer</b> transfer the call to another extension or number<li>
+ <li><b>voicemail</b> send the call to voicemail</li>
+ </ul>
+
+
+ <br />
+ <br />
+
+ <!--
+ <b>Param</b>
+ Example parameters by name and value
+ <br />
+ <a href='http://wiki.freeswitch.org/wiki/Special:Search?search=param&go=Go' target='_blank'>http://wiki.freeswitch.org/wiki/Special:Search?search=param&go=Go</a>
+ <ul>
+ <li><b>codec-ms</b> 20</li>
+ <li><b>codec-prefs</b> PCMU@20i</li>
+ <li><b>debug</b> 1</li>
+ <li><b>public</b> XML</li>
+ <li><b>dtmf-duration</b> 100</li>
+ <li><b>rfc2833-pt</b>" 101</li>
+ <li><b>sip-port</b> 5060</li>
+ <li><b>use-rtp-timer</b> true</li>
+ </ul>
+ <br />
+ <br />
+ -->
+
+
+ <br />
+ <br />
+ <br />
+ <br />
+ <br />
+
+ </td>
+ </tr>
+</table>
+
+</div>
+
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/freeswitch/freeswitch_public_includes_edit.tmp b/config/freeswitch/freeswitch_public_includes_edit.tmp
new file mode 100644
index 00000000..94454fd3
--- /dev/null
+++ b/config/freeswitch/freeswitch_public_includes_edit.tmp
@@ -0,0 +1,524 @@
+<?php
+/* $Id$ */
+/*
+
+ freeswitch_public_includes_edit.php
+ Copyright (C) 2008 Mark J Crane
+ All rights reserved.
+
+ FreeSWITCH (TM)
+ http://www.freeswitch.org/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require("guiconfig.inc");
+require("/usr/local/pkg/freeswitch.inc");
+
+
+
+//freeswitchpublicincludes
+ //publicincludeid
+ //extensionname
+ //context
+ //default
+ //enabled
+ //descr
+
+//
+
+
+
+$a_public_includes = &$config['installedpackages']['freeswitchpublicincludes']['config'];
+$a_public_include_details = &$config['installedpackages']['freeswitchpublicincludedetails']['config'];
+
+$id = $_GET['id'];
+if (isset($_POST['id'])) {
+ $id = $_POST['id'];
+}
+$parentid = $id;
+
+
+
+if (isset($id) && $a_public_includes[$id]) {
+ $pconfig['publicincludeid'] = $a_public_includes[$id]['publicincludeid'];
+ $publicincludeid = $a_public_includes[$id]['publicincludeid'];
+ $pconfig['extensionname'] = $a_public_includes[$id]['extensionname'];
+ $pconfig['order'] = $a_public_includes[$id]['order'];
+ $pconfig['context'] = $a_public_includes[$id]['context'];
+ $pconfig['enabled'] = $a_public_includes[$id]['enabled'];
+ $pconfig['descr'] = $a_public_includes[$id]['descr'];
+ $pconfig['opt1name'] = $a_public_includes[$id]['opt1name'];
+ $pconfig['opt1value'] = $a_public_includes[$id]['opt1value'];
+}
+
+if ($_POST) {
+
+ unset($input_errors);
+ $pconfig = $_POST;
+
+ if ($_GET['act'] == "del") {
+ if ($_GET['type'] == 'publicincludedetails') {
+ if ($a_public_include_details[$_GET['id']]) {
+ unset($a_public_include_details[$_GET['id']]);
+ write_config();
+ sync_package_freeswitch_public_includes();
+ header("Location: freeswitch_public_include_edit.php?id=".$_GET['id']);
+ exit;
+ }
+ }
+ }
+
+
+ if (!$input_errors) {
+
+ $ent = array();
+ if (strlen($_POST['publicincludeid']) > 0) {
+ //update
+ $ent['publicincludeid'] = $_POST['publicincludeid'];
+ }
+ else {
+ //add
+ $ent['publicincludeid'] = guid();
+ }
+ $ent['extensionname'] = $_POST['extensionname'];
+ $ent['order'] = $_POST['order'];
+ //$ent['context'] = $_POST['context'];
+ $ent['context'] = 'default';
+ $ent['enabled'] = $_POST['enabled'];
+ $ent['descr'] = $_POST['descr'];
+ $ent['opt1name'] = $_POST['opt1name'];
+ $ent['opt1value'] = $_POST['opt1value'];
+
+
+
+ if (isset($id) && $a_public_includes[$id]) {
+ $a_public_includes = $config['installedpackages']['freeswitchpublicincludes']['config'];
+ if (count($a_public_includes) > 0) {
+ foreach($a_public_includes as $rowhelper) {
+
+ //$rowhelper['publicincludeid'];
+ //$rowhelper['extensionname'];
+ //$rowhelper['context'];
+ //$rowhelper['enabled'];
+
+ $filenamechanged = false;
+ if ($rowhelper['publicincludeid'] == $_POST['publicincludeid']) {
+
+ if ($rowhelper['extensionname'] != $_POST['extensionname']) {
+ //if the extension name has changed then remove the current public xml file
+ //to prepare for the new file
+ $filenamechanged = true;
+ }
+ if ($rowhelper['order'] != $_POST['order']) {
+ //if the order has changed then remove the current public xml file
+ //to prepare for the new file
+ $filenamechanged = true;
+ }
+ if ($_POST['enabled'] == "false") {
+ //if the extension name is disabled then remove the public xml file
+ $filenamechanged = true;
+ }
+ if ($filenamechanged){
+ $publicincludefilename = $rowhelper['order']."_".$rowhelper['extensionname'].".xml";
+ if (file_exists("/usr/local/freeswitch/conf/dialplan/public/".$publicincludefilename)) {
+ unlink("/usr/local/freeswitch/conf/dialplan/public/".$publicincludefilename);
+ }
+ unset($publicincludefilename);
+ }
+
+ }
+ unset($filenamechanged);
+
+ } //end foreach
+ } //end if count
+
+ //update the config
+ $a_public_includes[$id] = $ent;
+ }
+ else {
+ //add to the config
+ $a_public_includes[] = $ent;
+ }
+
+
+ write_config();
+ sync_package_freeswitch_public_includes();
+
+ header("Location: freeswitch_public_includes.php");
+ exit;
+ }
+}
+
+include("head.inc");
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<?php include("fbegin.inc"); ?>
+<p class="pgtitle">FreeSWITCH: Public: Edit</p>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+
+
+<div id="mainlevel">
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+<tr><td class="tabnavtbl">
+<?php
+
+ $tab_array = array();
+ $tab_array[] = array(gettext("Settings"), false, "/pkg_edit.php?xml=freeswitch.xml&amp;id=0");
+ $tab_array[] = array(gettext("Dialplan"), false, "/freeswitch/freeswitch_dialplan_includes.php");
+ $tab_array[] = array(gettext("Extensions"), false, "/freeswitch/freeswitch_extensions.php");
+ $tab_array[] = array(gettext("External"), false, "/pkg_edit.php?xml=freeswitch_external.xml&amp;id=0");
+ $tab_array[] = array(gettext("Gateways"), false, "/freeswitch/freeswitch_gateways.php");
+ $tab_array[] = array(gettext("Internal"), false, "/pkg_edit.php?xml=freeswitch_internal.xml&amp;id=0");
+ $tab_array[] = array(gettext("IVR"), false, "/freeswitch/freeswitch_ivr.php");
+ $tab_array[] = array(gettext("Modules"), false, "/pkg_edit.php?xml=freeswitch_modules.xml&amp;id=0");
+ $tab_array[] = array(gettext("Public"), true, "/freeswitch/freeswitch_public_includes.php");
+ $tab_array[] = array(gettext("Rec"), false, "/freeswitch/freeswitch_recordings.php");
+ $tab_array[] = array(gettext("Status"), false, "/freeswitch/freeswitch_status.php");
+ $tab_array[] = array(gettext("Vars"), false, "/pkg_edit.php?xml=freeswitch_vars.xml&amp;id=0");
+ display_top_tabs($tab_array);
+
+?>
+</td></tr>
+</table>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabcont" >
+
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td><p><span class="vexpl"><span class="red"><strong>Public:<br>
+ </strong></span>
+ Public Include general settings.
+ </span></p></td>
+ </tr>
+ </table>
+ <br />
+
+ <form action="freeswitch_public_includes_edit.php" method="post" name="iform" id="iform">
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="22%" valign="top" class="vncellreq">Extension Name</td>
+ <td width="78%" class="vtable">
+ <input name="extensionname" type="text" class="formfld" id="extensionname" size="40" value="<?=htmlspecialchars($pconfig['extensionname']);?>">
+ <br />
+ Supported characters are 'a-z', 'A-Z', '0-9', underscore '_', and period '.'.
+ </td>
+ </tr>
+ <!--
+ <tr>
+ <td width="22%" valign="top" class="vncellreq">Context</td>
+ <td width="78%" class="vtable">
+ <input name="context" type="text" class="formfld" id="context" size="40" value="<?=htmlspecialchars($pconfig['context']);?>">
+ <br />
+ e.g. default
+ </td>
+ </tr>
+ -->
+
+ <tr>
+ <td width="22%" valign="top" class="vncellreq">Enabled</td>
+ <td width="78%" class="vtable">
+ <?php
+ echo " <select name='enabled' class='formfld'>\n";
+ echo " <option></option>\n";
+ switch (htmlspecialchars($pconfig['enabled'])) {
+ case "true":
+ echo " <option value='true' selected='yes'>true</option>\n";
+ echo " <option value='false'>false</option>\n";
+ break;
+ case "false":
+ echo " <option value='true'>true</option>\n";
+ echo " <option value='false' selected='yes'>false</option>\n";
+
+ break;
+ default:
+ echo " <option value='true' selected='yes'>true</option>\n";
+ echo " <option value='false'>false</option>\n";
+ }
+ echo " </select>\n";
+ ?>
+ </td>
+ </tr>
+
+ <tr>
+ <td width="22%" valign="top" class="vncellreq">Order</td>
+ <td width="78%" class="vtable">
+ <?php
+
+ echo " <select name='order' class='formfld'>\n";
+ echo " <option></option>\n";
+ if (strlen(htmlspecialchars($pconfig['order']))> 0) {
+ echo " <option selected='yes' value='".htmlspecialchars($pconfig['order'])."'>".htmlspecialchars($pconfig['order'])."</option>\n";
+ }
+ $i=0;
+ while($i<=999) {
+ if (strlen($i) == 1) {
+ echo " <option value='00$i'>00$i</option>\n";
+ }
+ if (strlen($i) == 2) {
+ echo " <option value='0$i'>0$i</option>\n";
+ }
+ if (strlen($i) == 3) {
+ echo " <option value='$i'>$i</option>\n";
+ }
+
+ $i++;
+ }
+ echo " </select>\n";
+ ?>
+ <br />
+ Processing of each public include is determined by this order.
+ </td>
+ </tr>
+
+ <tr>
+ <td width="22%" valign="top" class="vncell">Description</td>
+ <td width="78%" class="vtable">
+ <input name="descr" type="text" class="formfld" id="descr" size="40" value="<?=htmlspecialchars($pconfig['descr']);?>">
+ <br> <span class="vexpl">You may enter a description here
+ for your reference (not parsed).</span></td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <input name="publicincludeid" type="hidden" value="<?=htmlspecialchars($pconfig['publicincludeid']);?>">
+ <?php
+ if (strlen($id) > 0 && $a_public_includes[$id]) {
+ echo "\n";
+ echo " <input name=\"id\" type=\"hidden\" value=\"$id\">\n";
+ echo " <input name=\"opt1name\" type=\"hidden\" value=\"".htmlspecialchars($pconfig['opt1name'])."\">\n";
+ echo " <input name=\"opt1value\" type=\"hidden\" value=\"".htmlspecialchars($pconfig['opt1value'])."\">\n";
+ }
+ ?>
+ <input name="Submit" type="submit" class="formbtn" value="Save"> <input class="formbtn" type="button" value="Cancel" onclick="history.back()">
+ </td>
+ </tr>
+ </table>
+ </form>
+
+ <br>
+ <br>
+
+ <form action="freeswitch_public_includes_edit.php" method="post" name="iform2" id="iform2">
+ <?php
+
+ //echo "<pre>";
+ //print_r ($a_public_includes);
+ //echo "</pre>";
+
+ //if ($savemsg) print_info_box($savemsg);
+ //if (file_exists($d_hostsdirty_path)): echo"<p>";
+ //print_info_box_np("The FreeSWITCH recordings have been changed.<br>You must apply the changes in order for them to take effect.");
+ //echo"<br />";
+ //endif;
+
+ ?>
+
+
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td><p><span class="vexpl"><span class="red"><strong>Conditions and Actions<br />
+ </strong></span>
+ The following conditions, actions and anti-actions are used in the public to direct call flow. Each is processed in order until you reach the action tag which tells FreeSWITCH what action to perform. You are not limited to only one condition or action tag for a given extension.
+ </span></p></td>
+ </tr>
+ </table>
+ <br />
+
+ <table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td width="20%" class="listhdrr">Tag</td>
+ <td width="20%" class="listhdrr">Type</td>
+ <td width="50%" class="listhdrr">Data</td>
+ <td width="10%" class="list">
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td width="17"></td>
+ <td valign="middle"><a href="freeswitch_public_includes_details_edit.php?parentid=<?=$parentid;?>&publicincludeid=<?=$publicincludeid;?>&a=action"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" width="17" height="17" border="0"></a></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+
+ <?php
+
+ $i = 0;
+ if (count($a_public_include_details) > 0) {
+
+ foreach ($a_public_include_details as $ent) {
+ if ($ent['tag'] == "condition" && $publicincludeid == $ent['publicincludeid']) {
+ ?>
+ <tr>
+ <td class="listlr" ondblclick="document.location='freeswitch_public_includes_details_edit.php?id=<?=$i;?>&parentid=<?=$parentid;?>&publicincludeid=<?=$publicincludeid;?>'">
+ <?=$ent['tag']?>
+ </td>
+ <td class="listr" ondblclick="document.location='freeswitch_public_includes_details_edit.php?id=<?=$i;?>&parentid=<?=$parentid;?>&publicincludeid=<?=$publicincludeid;?>';">
+ <?=$ent['fieldtype'];?>&nbsp;
+ </td>
+ <td class="listr" ondblclick="document.location='freeswitch_public_includes_details_edit.php?id=<?=$i;?>&parentid=<?=$parentid;?>&publicincludeid=<?=$publicincludeid;?>';">
+ <?=$ent['fielddata'];?>&nbsp;
+ </td>
+ <td valign="middle" nowrap class="list">
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td valign="middle"><a href="freeswitch_public_includes_details_edit.php?id=<?=$i;?>&parentid=<?=$parentid;?>&publicincludeid=<?=$publicincludeid;?>"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_e.gif" width="17" height="17" border="0"></a></td>
+ <td><a href="freeswitch_public_includes_details.php?type=publicincludedetails&act=del&id=<?=$i;?>&parentid=<?=$parentid;?>&publicincludeid=<?=$publicincludeid;?>" onclick="return confirm('Do you really want to delete this?')"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_x.gif" width="17" height="17" border="0"></a></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <?php
+ }
+ $i++;
+ }
+ }
+
+ $i = 0;
+ if (count($a_public_include_details) > 0) {
+
+ foreach ($a_public_include_details as $ent) {
+ if ($ent['tag'] == "action" && $publicincludeid == $ent['publicincludeid']) {
+ ?>
+ <tr>
+ <td class="listlr" ondblclick="document.location='freeswitch_public_includes_details_edit.php?id=<?=$i;?>&parentid=<?=$parentid;?>&publicincludeid=<?=$publicincludeid;?>'">
+ <?=$ent['tag']?>
+ </td>
+ <td class="listr" ondblclick="document.location='freeswitch_public_includes_details_edit.php?id=<?=$i;?>&parentid=<?=$parentid;?>&publicincludeid=<?=$publicincludeid;?>';">
+ <?=$ent['fieldtype'];?>&nbsp;
+ </td>
+ <td class="listr" ondblclick="document.location='freeswitch_public_includes_details_edit.php?id=<?=$i;?>&parentid=<?=$parentid;?>&publicincludeid=<?=$publicincludeid;?>';">
+ <?=$ent['fielddata'];?>&nbsp;
+ </td>
+ <td valign="middle" nowrap class="list">
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td valign="middle"><a href="freeswitch_public_includes_details_edit.php?id=<?=$i;?>&parentid=<?=$parentid;?>&publicincludeid=<?=$publicincludeid;?>"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_e.gif" width="17" height="17" border="0"></a></td>
+ <td><a href="freeswitch_public_includes_details.php?type=publicincludedetails&act=del&id=<?=$i;?>&parentid=<?=$parentid;?>&publicincludeid=<?=$publicincludeid;?>" onclick="return confirm('Do you really want to delete this?')"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_x.gif" width="17" height="17" border="0"></a></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <?php
+ }
+ $i++;
+ }
+ }
+
+ $i = 0;
+ if (count($a_public_include_details) > 0) {
+
+ foreach ($a_public_include_details as $ent) {
+ if ($ent['tag'] == "anti-action" && $publicincludeid == $ent['publicincludeid']) {
+ ?>
+ <tr>
+ <td class="listlr" ondblclick="document.location='freeswitch_public_includes_details_edit.php?id=<?=$i;?>&parentid=<?=$parentid;?>&publicincludeid=<?=$publicincludeid;?>'">
+ <?=$ent['tag']?>
+ </td>
+ <td class="listr" ondblclick="document.location='freeswitch_public_includes_details_edit.php?id=<?=$i;?>&parentid=<?=$parentid;?>&publicincludeid=<?=$publicincludeid;?>';">
+ <?=$ent['fieldtype'];?>&nbsp;
+ </td>
+ <td class="listr" ondblclick="document.location='freeswitch_public_includes_details_edit.php?id=<?=$i;?>&parentid=<?=$parentid;?>&publicincludeid=<?=$publicincludeid;?>';">
+ <?=$ent['fielddata'];?>&nbsp;
+ </td>
+ <td valign="middle" nowrap class="list">
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td valign="middle"><a href="freeswitch_public_includes_details_edit.php?id=<?=$i;?>&parentid=<?=$parentid;?>&publicincludeid=<?=$publicincludeid;?>"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_e.gif" width="17" height="17" border="0"></a></td>
+ <td><a href="freeswitch_public_includes_details.php?type=publicincludedetails&act=del&id=<?=$i;?>&parentid=<?=$parentid;?>&publicincludeid=<?=$publicincludeid;?>" onclick="return confirm('Do you really want to delete this?')"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_x.gif" width="17" height="17" border="0"></a></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <?php
+ }
+ $i++;
+ }
+ }
+
+ $i = 0;
+ if (count($a_public_include_details) > 0) {
+
+ foreach ($a_public_include_details as $ent) {
+ if ($ent['tag'] == "param" && $publicincludeid == $ent['publicincludeid']) {
+ ?>
+ <tr>
+ <td class="listlr" ondblclick="document.location='freeswitch_public_includes_details_edit.php?id=<?=$i;?>&parentid=<?=$parentid;?>&publicincludeid=<?=$publicincludeid;?>'">
+ <?=$ent['tag']?>
+ </td>
+ <td class="listr" ondblclick="document.location='freeswitch_public_includes_details_edit.php?id=<?=$i;?>&parentid=<?=$parentid;?>&publicincludeid=<?=$publicincludeid;?>';">
+ <?=$ent['fieldtype'];?>&nbsp;
+ </td>
+ <td class="listr" ondblclick="document.location='freeswitch_public_includes_details_edit.php?id=<?=$i;?>&parentid=<?=$parentid;?>&publicincludeid=<?=$publicincludeid;?>';">
+ <?=$ent['fielddata'];?>&nbsp;
+ </td>
+ <td valign="middle" nowrap class="list">
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td valign="middle"><a href="freeswitch_public_includes_details_edit.php?id=<?=$i;?>&parentid=<?=$parentid;?>&publicincludeid=<?=$publicincludeid;?>"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_e.gif" width="17" height="17" border="0"></a></td>
+ <td><a href="freeswitch_public_includes_details.php?type=publicincludedetails&act=del&id=<?=$i;?>&parentid=<?=$parentid;?>&publicincludeid=<?=$publicincludeid;?>" onclick="return confirm('Do you really want to delete this?')"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_x.gif" width="17" height="17" border="0"></a></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <?php
+ }
+ $i++;
+ }
+ }
+ ?>
+ <tr>
+ <td class="list" colspan="3"></td>
+ <td class="list">
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td width="17"></td>
+ <td valign="middle"><a href="freeswitch_public_includes_details_edit.php?parentid=<?=$parentid;?>&publicincludeid=<?=$publicincludeid;?>&a=action"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" width="17" height="17" border="0"></a></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+
+
+ <tr>
+ <td class="list" colspan="3"></td>
+ <td class="list"></td>
+ </tr>
+ </table>
+
+ </form>
+
+
+ <br>
+ <br>
+
+ </td>
+ </tr>
+</table>
+
+</div>
+
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/freeswitch/freeswitch_recordings.tmp b/config/freeswitch/freeswitch_recordings.tmp
new file mode 100644
index 00000000..7d9b539d
--- /dev/null
+++ b/config/freeswitch/freeswitch_recordings.tmp
@@ -0,0 +1,499 @@
+<?php
+/* $Id$ */
+/*
+ freeswitch_recordings.php
+ Copyright (C) 2008 Mark J Crane
+ All rights reserved.
+
+ FreeSWITCH (TM)
+ http://www.freeswitch.org/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require("guiconfig.inc");
+require("/usr/local/pkg/freeswitch.inc");
+
+$a_recordings = &$config['installedpackages']['freeswitchrecordings']['config'];
+$dir_recordings = '/usr/local/freeswitch/recordings/';
+$dir_music_on_hold_8000 = '/usr/local/freeswitch/sounds/music/8000/';
+
+if ($_GET['a'] == "download") {
+
+ session_cache_limiter('public');
+
+ if ($_GET['type'] = "rec") {
+ if (file_exists($dir_recordings.$_GET['filename'])) {
+ $fd = fopen($dir_recordings.$_GET['filename'], "rb");
+ if ($_GET['t'] == "bin") {
+ header("Content-Type: application/force-download");
+ header("Content-Type: application/octet-stream");
+ header("Content-Type: application/download");
+ header("Content-Description: File Transfer");
+ header('Content-Disposition: attachment; filename="'.$_GET['filename'].'"');
+ }
+ else {
+ $file_ext = substr($_GET['filename'], -3);
+ if ($file_ext == "wav") {
+ header("Content-Type: audio/x-wav");
+ }
+ if ($file_ext == "mp3") {
+ header("Content-Type: audio/mp3");
+ }
+ }
+ header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
+ header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past
+ header("Content-Length: " . filesize($dir_recordings.$_GET['filename']));
+ fpassthru($fd);
+ }
+ }
+
+ if ($_GET['type'] = "moh") {
+ if (file_exists($dir_music_on_hold_8000.$_GET['filename'])) {
+ $fd = fopen($dir_music_on_hold_8000.$_GET['filename'], "rb");
+ if ($_GET['t'] == "bin") {
+ header("Content-Type: application/force-download");
+ header("Content-Type: application/octet-stream");
+ header("Content-Type: application/download");
+ header("Content-Description: File Transfer");
+ header('Content-Disposition: attachment; filename="'.$_GET['filename'].'"');
+ }
+ else {
+ $file_ext = substr($_GET['filename'], -3);
+ if ($file_ext == "wav") {
+ header("Content-Type: audio/x-wav");
+ }
+ if ($file_ext == "mp3") {
+ header("Content-Type: audio/mp3");
+ }
+ }
+ header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
+ header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past
+ header("Content-Length: " . filesize($dir_music_on_hold_8000.$_GET['filename']));
+ fpassthru($fd);
+ }
+ }
+
+ exit;
+}
+else {
+ //echo $dir_recordings.$_GET['filename'];
+}
+
+if (($_POST['submit'] == "Upload") && is_uploaded_file($_FILES['ulfile']['tmp_name'])) {
+
+ if ($_POST['type'] == 'moh') {
+ move_uploaded_file($_FILES['ulfile']['tmp_name'], $dir_music_on_hold_8000 . $_FILES['ulfile']['name']);
+ $savemsg = "Uploaded file to $dir_music_on_hold_8000" . htmlentities($_FILES['ulfile']['name']);
+ //system('chmod -R 744 $dir_music_on_hold_8000*');
+ unset($_POST['txtCommand']);
+ }
+ if ($_POST['type'] == 'rec') {
+ move_uploaded_file($_FILES['ulfile']['tmp_name'], $dir_recordings . $_FILES['ulfile']['name']);
+ $savemsg = "Uploaded file to $dir_recordings" . htmlentities($_FILES['ulfile']['name']);
+ //system('chmod -R 744 $dir_recordings*');
+ unset($_POST['txtCommand']);
+ }
+}
+
+
+
+
+if ($_GET['act'] == "del") {
+ if ($_GET['type'] == 'rec') {
+ if ($a_recordings[$_GET['id']]) {
+ unlink_if_exists('/usr/local/freeswitch/recordings/'.$a_recordings[$_GET['id']]['filename']);
+ unset($a_recordings[$_GET['id']]);
+ write_config();
+ header("Location: freeswitch_recordings.php");
+ exit;
+ }
+ }
+
+ if ($_GET['type'] == 'moh') {
+ unlink_if_exists($dir_music_on_hold_8000.$_GET['filename']);
+ header("Location: freeswitch_recordings.php");
+ exit;
+ }
+
+}
+
+
+
+include("head.inc");
+
+?>
+
+<script>
+function EvalSound(soundobj) {
+ var thissound= eval("document."+soundobj);
+ thissound.Play();
+}
+</script>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<?php include("fbegin.inc"); ?>
+<p class="pgtitle">FreeSWITCH: Recordings</p>
+
+<div id="mainlevel">
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+<tr><td class="tabnavtbl">
+<?php
+
+ $tab_array = array();
+ $tab_array[] = array(gettext("Settings"), false, "/pkg_edit.php?xml=freeswitch.xml&amp;id=0");
+ $tab_array[] = array(gettext("Dialplan"), false, "/freeswitch/freeswitch_dialplan_includes.php");
+ $tab_array[] = array(gettext("Extensions"), false, "/freeswitch/freeswitch_extensions.php");
+ $tab_array[] = array(gettext("External"), false, "/pkg_edit.php?xml=freeswitch_external.xml&amp;id=0");
+ $tab_array[] = array(gettext("Gateways"), false, "/freeswitch/freeswitch_gateways.php");
+ $tab_array[] = array(gettext("Internal"), false, "/pkg_edit.php?xml=freeswitch_internal.xml&amp;id=0");
+ $tab_array[] = array(gettext("IVR"), false, "/freeswitch/freeswitch_ivr.php");
+ $tab_array[] = array(gettext("Modules"), false, "/pkg_edit.php?xml=freeswitch_modules.xml&amp;id=0");
+ $tab_array[] = array(gettext("Public"), false, "/freeswitch/freeswitch_public_includes.php");
+ $tab_array[] = array(gettext("Rec"), true, "/freeswitch/freeswitch_recordings.php");
+ $tab_array[] = array(gettext("Status"), false, "/freeswitch/freeswitch_status.php");
+ $tab_array[] = array(gettext("Vars"), false, "/pkg_edit.php?xml=freeswitch_vars.xml&amp;id=0");
+ display_top_tabs($tab_array);
+
+?>
+</td></tr>
+</table>
+
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabcont" >
+
+<?php
+
+
+//build a list of recordings from the config.xml
+$config_recording_list = '';
+$i = 0;
+if (count($a_recordings) > 0) {
+ foreach ($a_recordings as $recordingent) {
+ $config_recording_list .= $recordingent['filename']."|";
+ $i++;
+ }
+}
+
+
+
+$config_change = 0;
+if (is_dir($dir_recordings)) {
+ if ($dh = opendir($dir_recordings)) {
+ while (($file = readdir($dh)) !== false) {
+ if (filetype($dir_recordings . $file) == "file") {
+
+ if (strpos($config_recording_list, $file) === false) {
+
+ //$handle = fopen($dir_recordings.$file,'rb');
+ //$file_content = fread($handle,filesize($dir_recordings.$file));
+ //fclose($handle);
+
+ $a_file = split("\.", $file);
+
+ $recordingent = array();
+ $recordingent['filename'] = $file;
+ $recordingent['recordingname'] = $a_file[0];
+ $recordingent['recordingid'] = guid();
+ //$recordingent['filecontent'] = base64_encode($file_content);
+ $recordingent['descr'] = 'Auto';
+
+ $a_recordings[] = $recordingent;
+ write_config();
+
+ unset($file_content);
+
+ }
+ else {
+ //echo "The file was found.<br/>";
+ }
+
+ }
+ }
+ closedir($dh);
+ }
+}
+
+
+
+//saved for future use if and when config.xml scales well
+ //enough to save the files inside it
+//$i = 0;
+//if (count($a_recordings) > 0) {
+// foreach ($a_recordings as $recordingent) {
+
+// if (!is_file($dir_recordings.$recordingent['filename'])) {
+ //echo "not found: ".$recordingent['filename']."<br />";
+
+ //recording not found restore the file from the config.xml
+ //$file_content = $recordingent['filecontent'];
+ //$handle = fopen($dir_recordings.$recordingent['filename'],'w');
+ //fwrite ($handle, base64_decode($file_content));
+ //unset($file_content);
+ //fclose($handle);
+ //$recordingent['filecontent'] = base64_encode($file_content);
+
+ // loop through recordings in the config.xml
+ // if the file does not exist remove it from the file system.
+ //unset($a_recordings[$i]);
+
+// $config_change = 1;
+// }
+// else {
+ //echo "found: ".$recordingent['filename']."<br />";
+// }
+
+// $i++;
+// }
+//}
+
+if ($config_change == 1) {
+ write_config();
+ $config_change = 0;
+}
+
+//if ($savemsg) print_info_box($savemsg);
+//if (file_exists($d_hostsdirty_path)): echo"<p>";
+//print_info_box_np("The FreeSWITCH recordings have been changed.<br>You must apply the changes in order for them to take effect.");
+//echo"<br />";
+//endif;
+
+?>
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td><p><span class="vexpl"><span class="red"><strong>Recordings:<br>
+ </strong></span>
+ To make a recording dial extension 732673 (record) or you can make a
+ 16bit 8khz/16khz Mono WAV file then copy it to the
+ following directory then refresh the page to play it back.
+ Click on the 'Filename' to download it or the 'Recording Name' to
+ play the audio.
+ </span></p></td>
+ </tr>
+ </table>
+
+ <br />
+
+ <div id="niftyOutter">
+ <form action="" method="POST" enctype="multipart/form-data" name="frmUpload" onSubmit="">
+ <table border='0'>
+ <tr>
+ <td width='50%'><b>location:</b> <?php echo $dir_recordings; ?></td>
+ <td valign="top" class="label">
+ <input name="type" type="hidden" value="rec">
+ </td>
+ <td align="right">File to upload:</td>
+ <td valign="top" class="label">
+ <input name="ulfile" type="file" class="button" id="ulfile">
+ <input name="submit" type="submit" class="button" id="upload" value="Upload">
+ </td>
+ </tr>
+ </table>
+ </div>
+ </form>
+
+ <table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td width="30%" class="listhdrr">Filename (download)</td>
+ <td width="30%" class="listhdrr">Recording Name (play)</td>
+ <td width="30%" class="listhdr">Description</td>
+ <td width="10%" class="list">
+ <!--
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td width="17"></td>
+ <td valign="middle"><a href="freeswitch_recordings_edit.php"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" width="17" height="17" border="0"></a></td>
+ </tr>
+ </table>
+ -->
+ </td>
+ </tr>
+
+ <?php
+ $i = 0;
+ if (count($a_recordings) > 0) {
+ foreach ($a_recordings as $recordingent) {
+ ?>
+ <tr>
+ <td class="listlr" ondblclick="document.location='freeswitch_recordings_edit.php?id=<?=$i;?>'">
+ <a href="freeswitch_recordings.php?a=download&type=rec&t=bin&filename=<?=$recordingent['filename'];?>">
+ <?=$recordingent['filename']?>
+ </a>
+ </td>
+ <td class="listr" ondblclick="document.location='freeswitch_recordings_edit.php?id=<?=$i;?>';">
+ <a href="javascript:void(0);" onclick="window.open('freeswitch_recordings_play.php?a=download&type=rec&filename=<?=$recordingent['filename'];?>', 'play',' width=420,height=40,menubar=no,status=no,toolbar=no')">
+ <?=$recordingent['recordingname'];?>&nbsp;
+ </a>
+ </td>
+ <td class="listbg" ondblclick="document.location='freeswitch_recordings_edit.php?id=<?=$i;?>';">
+ <font color="#FFFFFF"><?=htmlspecialchars($recordingent['descr']);?>&nbsp;
+ </td>
+ <td valign="middle" nowrap class="list">
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td valign="middle"><a href="freeswitch_recordings_edit.php?id=<?=$i;?>"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_e.gif" width="17" height="17" border="0"></a></td>
+ <td><a href="freeswitch_recordings.php?type=rec&act=del&id=<?=$i;?>" onclick="return confirm('Do you really want to delete this?')"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_x.gif" width="17" height="17" border="0"></a></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <?php
+ $i++;
+ } //end for each
+ } //end count
+ ?>
+
+ <!--
+ <tr>
+ <td class="list" colspan="3"></td>
+ <td class="list">
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td width="17"></td>
+ <td valign="middle"><a href="freeswitch_recordings_edit.php"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" width="17" height="17" border="0"></a></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ -->
+
+ <tr>
+ <td class="list" colspan="3"></td>
+ <td class="list"></td>
+ </tr>
+ </table>
+
+
+
+ <br />
+ <br />
+ <br />
+
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td><p><span class="vexpl"><span class="red"><strong>Music on Hold:<br>
+ </strong></span>
+ Music on hold can be in WAV or MP3 format. To play MP3 you must have
+ mod_shout enabled on the 'Modules' tab. For best performance
+ upload 16bit 8khz/16khz Mono WAV files.
+ <!--Click on the 'Filename' to download it or the 'Recording Name' to
+ play the audio.-->
+ </span></p></td>
+ </tr>
+ </table>
+
+ <br />
+
+ <div id="niftyOutter">
+ <form action="" method="POST" enctype="multipart/form-data" name="frmUpload" onSubmit="">
+ <table border='0'>
+ <tr>
+ <td width='50%'><b>location:</b> <?php echo $dir_music_on_hold_8000; ?></td>
+ <td valign="top" class="label">
+ <input name="type" type="hidden" value="moh">
+ </td>
+ <td align="right">File to upload:</td>
+ <td valign="top" class="label">
+ <input name="ulfile" type="file" class="button" id="ulfile">
+ <input name="submit" type="submit" class="button" id="upload" value="Upload">
+ </td>
+ </tr>
+ </table>
+ </div>
+ </form>
+
+
+ <table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td width="28%" class="listhdrr">File Name (download)</td>
+ <td width="28%" class="listhdrr">Name (play)</td>
+ <td width="25%" class="listhdr">Last Modified</td>
+ <td width="10%" class="listhdr" nowrap>Size</td>
+ </tr>
+
+ <?php
+
+ if ($handle = opendir($dir_music_on_hold_8000)) {
+ while (false !== ($file = readdir($handle))) {
+ if ($file != "." && $file != ".." && is_file($dir_music_on_hold_8000.$file)) {
+
+ $tmp_filesize = filesize($dir_music_on_hold_8000.$file);
+ $tmp_filesize = byte_convert($tmp_filesize);
+
+ echo "<tr>\n";
+ echo " <td class=\"listlr\" ondblclick=\"\">\n";
+ echo " <a href=\"freeswitch_recordings.php?a=download&type=moh&t=bin&filename=".$file."\">\n";
+ echo " $file";
+ echo " </a>";
+ echo " </td>\n";
+ echo " <td class=\"listlr\" ondblclick=\"\">\n";
+ echo " <a href=\"javascript:void(0);\" onclick=\"window.open('freeswitch_recordings_play.php?a=download&type=moh&filename=".$file."', 'play',' width=420,height=40,menubar=no,status=no,toolbar=no')\">\n";
+ $tmp_file_array = split("\.",$file);
+ echo " ".$tmp_file_array[0];
+ echo " </a>";
+ echo " </td>\n";
+ echo " <td class=\"listlr\" ondblclick=\"\">\n";
+ echo date ("F d Y H:i:s", filemtime($dir_music_on_hold_8000.$file));
+ echo " </td>\n";
+ echo " <td class=\"listlr\" ondblclick=\"\">\n";
+ echo " ".$tmp_filesize;
+ echo " </td>\n";
+ echo " <td valign=\"middle\" nowrap class=\"list\">\n";
+ echo " <table border=\"0\" cellspacing=\"0\" cellpadding=\"1\">\n";
+ echo " <tr>\n";
+ //echo " <td valign=\"middle\"><a href=\"freeswitch_recordings.php?id=$i\"><img src=\"/themes/".$g['theme']."/images/icons/icon_e.gif\" width=\"17\" height=\"17\" border=\"0\"></a></td>\n";
+ echo " <td><a href=\"freeswitch_recordings.php?type=moh&act=del&filename=".$file."\" onclick=\"return confirm('Do you really want to delete this file?')\"><img src=\"/themes/". $g['theme']."/images/icons/icon_x.gif\" width=\"17\" height=\"17\" border=\"0\"></a></td>\n";
+ echo " </tr>\n";
+ echo " </table>\n";
+ echo " </td>\n";
+ echo "</tr>\n";
+
+ }
+ }
+ closedir($handle);
+ }
+ ?>
+
+ <tr>
+ <td class="list" colspan="3"></td>
+ <td class="list"></td>
+ </tr>
+ </table>
+
+<br>
+<br>
+<br>
+<br>
+<br>
+<br>
+
+</td>
+</tr>
+</table>
+
+</div>
+
+
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/freeswitch/freeswitch_recordings_edit.tmp b/config/freeswitch/freeswitch_recordings_edit.tmp
new file mode 100644
index 00000000..18612b93
--- /dev/null
+++ b/config/freeswitch/freeswitch_recordings_edit.tmp
@@ -0,0 +1,186 @@
+<?php
+/* $Id$ */
+/*
+
+ freeswitch_recordings_edit.php
+ Copyright (C) 2008 Mark J Crane
+ All rights reserved.
+
+ FreeSWITCH (TM)
+ http://www.freeswitch.org/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require("guiconfig.inc");
+require("/usr/local/pkg/freeswitch.inc");
+
+
+$a_recordings = &$config['installedpackages']['freeswitchrecordings']['config'];
+
+
+$id = $_GET['id'];
+if (isset($_POST['id'])) {
+ $id = $_POST['id'];
+}
+
+if (isset($id) && $a_recordings[$id]) {
+ $pconfig['filename'] = $a_recordings[$id]['filename'];
+ $pconfig['recordingname'] = $a_recordings[$id]['recordingname'];
+ $pconfig['recordingid'] = $a_recordings[$id]['recordingid'];
+ $pconfig['descr'] = $a_recordings[$id]['descr'];
+}
+
+if ($_POST) {
+
+ unset($input_errors);
+ $pconfig = $_POST;
+
+
+ if (!$input_errors) {
+
+
+ $recordingent = array();
+ $recordingent['recordingname'] = $_POST['recordingname'];
+ $recordingent['descr'] = $_POST['descr'];
+
+
+ if (isset($id) && $a_recordings[$id]) {
+ //update
+ if (strlen($_POST['recordingid']) > 0) {
+ $recordingent['recordingid'] = $_POST['recordingid'];
+ }
+ else {
+ $recordingent['recordingid'] = guid();
+ }
+
+ $recordingent['filename'] = $_POST['filename'];
+
+ //if file name is not the same then rename the file
+ if ($_POST['filename'] != $_POST['filename_orig']) {
+ rename('/usr/local/freeswitch/recordings/'.$_POST['filename_orig'], '/usr/local/freeswitch/recordings/'.$_POST['filename']);
+ }
+ $a_recordings[$id] = $recordingent;
+ }
+ else {
+ //add
+ $recordingent['filename'] = $_POST['filename'];
+ $a_recordings[] = $recordingent;
+ }
+
+ write_config();
+
+ header("Location: freeswitch_recordings.php");
+ exit;
+ }
+}
+
+include("head.inc");
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<?php include("fbegin.inc"); ?>
+<p class="pgtitle">FreeSWITCH: Recordings: Edit</p>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+
+
+<div id="mainlevel">
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+<tr><td class="tabnavtbl">
+<?php
+
+ $tab_array = array();
+ $tab_array[] = array(gettext("Settings"), false, "/pkg_edit.php?xml=freeswitch.xml&amp;id=0");
+ $tab_array[] = array(gettext("Dialplan"), false, "/freeswitch/freeswitch_dialplan_includes.php");
+ $tab_array[] = array(gettext("Extensions"), false, "/freeswitch/freeswitch_extensions.php");
+ $tab_array[] = array(gettext("External"), false, "/pkg_edit.php?xml=freeswitch_external.xml&amp;id=0");
+ $tab_array[] = array(gettext("Gateways"), false, "/freeswitch/freeswitch_gateways.php");
+ $tab_array[] = array(gettext("Internal"), false, "/pkg_edit.php?xml=freeswitch_internal.xml&amp;id=0");
+ $tab_array[] = array(gettext("IVR"), false, "/freeswitch/freeswitch_ivr.php");
+ $tab_array[] = array(gettext("Modules"), false, "/pkg_edit.php?xml=freeswitch_modules.xml&amp;id=0");
+ $tab_array[] = array(gettext("Public"), false, "/freeswitch/freeswitch_public_includes.php");
+ $tab_array[] = array(gettext("Rec"), true, "/freeswitch/freeswitch_recordings.php");
+ $tab_array[] = array(gettext("Status"), false, "/freeswitch/freeswitch_status.php");
+ $tab_array[] = array(gettext("Vars"), false, "/pkg_edit.php?xml=freeswitch_vars.xml&amp;id=0");
+ display_top_tabs($tab_array);
+
+?>
+</td></tr>
+</table>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabcont" >
+
+ <form action="freeswitch_recordings_edit.php" method="post" name="iform" id="iform">
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="22%" valign="top" class="vncellreq">Filename</td>
+ <td width="78%" class="vtable">
+ <input name="filename" type="text" class="formfld" id="filename" size="40" value="<?=htmlspecialchars($pconfig['filename']);?>">
+ <br> <span class="vexpl">Name of the file<br>
+ e.g. <em>example.wav</em></span></td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq">Recording Name</td>
+ <td width="78%" class="vtable">
+ <input name="recordingname" type="text" class="formfld" id="recordingname" size="40" value="<?=htmlspecialchars($pconfig['recordingname']);?>">
+ <br> <span class="vexpl">Recording Name<br>
+ e.g. <em>recordingx</em></span></td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Description</td>
+ <td width="78%" class="vtable">
+ <input name="descr" type="text" class="formfld" id="descr" size="40" value="<?=htmlspecialchars($pconfig['descr']);?>">
+ <br> <span class="vexpl">You may enter a description here
+ for your reference (not parsed).</span></td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <input name="Submit" type="submit" class="formbtn" value="Save"> <input class="formbtn" type="button" value="Cancel" onclick="history.back()">
+ <?php if (isset($id) && $a_recordings[$id]): ?>
+ <input name="filename_orig" type="hidden" value="<?=htmlspecialchars($pconfig['filename']);?>">
+ <input name="id" type="hidden" value="<?=$id;?>">
+ <input name="recordingid" type="hidden" value="<?=htmlspecialchars($pconfig['recordingid']);?>">
+ <?php endif; ?>
+ </td>
+ </tr>
+ </table>
+ </form>
+
+ <br>
+ <br>
+ <br>
+ <br>
+ <br>
+ <br>
+
+ </td>
+ </tr>
+</table>
+
+</div>
+
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/freeswitch/freeswitch_recordings_play.tmp b/config/freeswitch/freeswitch_recordings_play.tmp
new file mode 100644
index 00000000..8dfb90c2
--- /dev/null
+++ b/config/freeswitch/freeswitch_recordings_play.tmp
@@ -0,0 +1,71 @@
+<?php
+/* $Id$ */
+/*
+
+ freeswitch_recordings_play.php
+ Copyright (C) 2008 Mark J Crane
+ All rights reserved.
+
+ FreeSWITCH (TM)
+ http://www.freeswitch.org/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+$filename = $_GET['filename'];
+$type = $_GET['type']; //moh //rec
+
+?>
+<html>
+<head>
+</head>
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td align='center'>
+ <b>file: <?=$filename?></b>
+ </td>
+ </tr>
+ <tr>
+ <td align='center'>
+ <?php
+
+ $file_ext = substr($_GET['filename'], -3);
+ if ($file_ext == "wav") {
+ echo "<embed src=\"freeswitch_recordings.php?a=download&type=".$type."&filename=".$filename."\" autostart=true width=200 height=40 name=\"sound".$$filename."\" enablejavascript=\"true\">\n";
+ }
+ if ($file_ext == "mp3") {
+ echo "<object type=\"application/x-shockwave-flash\" width=\"400\" height=\"17\" data=\"slim.swf?autoplay=true&song_title=".urlencode($filename)."&song_url=".urlencode("/freeswitch/freeswitch_recordings.php?a=download&type=".$type."&filename=".$filename)."\">\n";
+ echo "<param name=\"movie\" value=\"slim.swf?autoplay=true&song_url=".urlencode("/freeswitch/freeswitch_recordings.php?a=download&type=".$type."&filename=".$filename)."\" />\n";
+ echo "<param name=\"quality\" value=\"high\"/>\n";
+ echo "<param name=\"bgcolor\" value=\"#E6E6E6\"/>\n";
+ echo "</object>\n";
+ }
+
+ ?>
+ </td>
+ </tr>
+</table>
+
+</body>
+</html>
diff --git a/config/freeswitch/freeswitch_status.tmp b/config/freeswitch/freeswitch_status.tmp
new file mode 100644
index 00000000..2d84a6ec
--- /dev/null
+++ b/config/freeswitch/freeswitch_status.tmp
@@ -0,0 +1,337 @@
+<?php
+/* $Id$ */
+/*
+ freeswitch_status.php
+ Copyright (C) 2008 Mark J Crane
+ All rights reserved.
+
+ FreeSWITCH (TM)
+ http://www.freeswitch.org/
+
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require("guiconfig.inc");
+require("/usr/local/pkg/freeswitch.inc");
+
+
+if ($_GET['a'] == "download") {
+ if ($_GET['t'] == "logs") {
+ $tmp = '/usr/local/freeswitch/log/';
+ $filename = 'freeswitch.log';
+ }
+ if ($_GET['t'] == "cdrcsv") {
+ $tmp = '/usr/local/freeswitch/log/cdr-csv/';
+ $filename = 'Master.csv';
+ }
+ if ($_GET['t'] == "backup") {
+ $tmp = '/tmp/';
+ $filename = 'freeswitch.bak.tgz';
+ system('cd /usr/local/;tar cvzf /tmp/freeswitch.bak.tgz freeswitch');
+ }
+ session_cache_limiter('public');
+ $fd = fopen($tmp.$filename, "rb");
+ header("Content-Type: binary/octet-stream");
+ header("Content-Length: " . filesize($tmp.$filename));
+ header('Content-Disposition: attachment; filename="'.$filename.'"');
+ fpassthru($fd);
+ exit;
+}
+
+if ($_GET['a'] == "other") {
+ if ($_GET['t'] == "restore") {
+ $tmp = '/tmp/';
+ $filename = 'freeswitch.bak.tgz';
+
+ //extract a specific directory to /usr/local/freeswitch
+ if (file_exists('/tmp/'.$filename)) {
+ //echo "The file $filename exists";
+
+ //Recommended
+ system('cd /usr/local; tar xvpfz /tmp/'.$filename.' freeswitch/db/');
+ system('cd /usr/local; tar xvpfz /tmp/'.$filename.' freeswitch/log/');
+ system('cd /usr/local; tar xvpfz /tmp/'.$filename.' freeswitch/recordings/');
+ system('cd /usr/local; tar xvpfz /tmp/'.$filename.' freeswitch/scripts/');
+ system('cd /usr/local; tar xvpfz /tmp/'.$filename.' freeswitch/storage/');
+
+ //Optional
+ //system('cd /usr/local; tar xvpfz /tmp/'.$filename.' freeswitch/conf/');
+ //system('cd /usr/local; tar xvpfz /tmp/'.$filename.' freeswitch/grammar/');
+ //system('cd /usr/local; tar xvpfz /tmp/'.$filename.' freeswitch/htdocs/');
+ //system('cd /usr/local; tar xvpfz /tmp/'.$filename.' freeswitch/sounds/');
+
+ header( 'Location: freeswitch_status.php?savemsg=Backup+has+been+restored.' ) ;
+ }
+ else {
+ header( 'Location: freeswitch_status.php?savemsg=Restore+failed.+Backup+file+not+found.' ) ;
+ }
+
+ exit;
+ }
+}
+
+include("head.inc");
+
+$password = $config['installedpackages']['freeswitchsettings']['config'][0]['event_socket_password'];
+$port = $config['installedpackages']['freeswitchsettings']['config'][0]['event_socket_port'];
+$host = $config['interfaces']['lan']['ipaddr'];
+
+$savemsg = $_GET["savemsg"];
+
+//if freeswitch is not running then start it
+if (!pkg_is_service_running('freeswitch')) {
+ $handle = popen("/usr/local/etc/rc.d/freeswitch.sh start", "r");
+ pclose($handle);
+}
+?>
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<?php include("fbegin.inc"); ?>
+
+<p class="pgtitle">FreeSWITCH: Status</font></p>
+
+<?php
+if ($savemsg) {
+ print_info_box($savemsg);
+}
+?>
+
+<div id="mainlevel">
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+<tr><td class="tabnavtbl">
+<?php
+
+ $tab_array = array();
+ $tab_array[] = array(gettext("Settings"), false, "/pkg_edit.php?xml=freeswitch.xml&amp;id=0");
+ $tab_array[] = array(gettext("Dialplan"), false, "/freeswitch/freeswitch_dialplan_includes.php");
+ $tab_array[] = array(gettext("Extensions"), false, "/freeswitch/freeswitch_extensions.php");
+ $tab_array[] = array(gettext("External"), false, "/pkg_edit.php?xml=freeswitch_external.xml&amp;id=0");
+ $tab_array[] = array(gettext("Gateways"), false, "/freeswitch/freeswitch_gateways.php");
+ $tab_array[] = array(gettext("Internal"), false, "/pkg_edit.php?xml=freeswitch_internal.xml&amp;id=0");
+ $tab_array[] = array(gettext("IVR"), false, "/freeswitch/freeswitch_ivr.php");
+ $tab_array[] = array(gettext("Modules"), false, "/pkg_edit.php?xml=freeswitch_modules.xml&amp;id=0");
+ $tab_array[] = array(gettext("Public"), false, "/freeswitch/freeswitch_public_includes.php");
+ $tab_array[] = array(gettext("Rec"), false, "/freeswitch/freeswitch_recordings.php");
+ $tab_array[] = array(gettext("Status"), true, "/freeswitch/freeswitch_status.php");
+ $tab_array[] = array(gettext("Vars"), false, "/pkg_edit.php?xml=freeswitch_vars.xml&amp;id=0");
+ display_top_tabs($tab_array);
+
+?>
+</td></tr>
+</table>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabcont" >
+
+<?php
+
+echo "<br /><br />\n\n";
+
+
+$fp = event_socket_create($host, $port, $password);
+$cmd = "api sofia status";
+$response = event_socket_request($fp, $cmd);
+echo "<table width='690' cellpadding='0' cellspacing='0' border='0'>\n";
+echo "<tr>\n";
+echo "<td width='50%'>\n";
+echo " <b>sofia status</b> \n";
+echo "</td>\n";
+echo "<td width='50%' align='right'>\n";
+echo " <input type='button' value='reloadxml' onclick=\"document.location.href='/freeswitch/freeswitch_cmd.php?cmd=api+reloadxml';\" />\n";
+echo "</td>\n";
+echo "</tr>\n";
+echo "</table>\n";
+echo "<pre style=\"font-size: 9pt;\">\n";
+echo $response;
+echo "</pre>\n";
+fclose($fp);
+echo "<br /><br />\n\n";
+
+
+$fp = event_socket_create($host, $port, $password);
+$cmd = "api sofia status profile internal";
+$response = event_socket_request($fp, $cmd);
+echo "<table width='690' cellpadding='0' cellspacing='0' border='0'>\n";
+echo "<tr>\n";
+echo "<td width='50%'>\n";
+echo " <b>sofia status profile internal</b> \n";
+echo "</td>\n";
+echo "<td width='50%' align='right'>\n";
+echo " <input type='button' value='start' onclick=\"document.location.href='/freeswitch/freeswitch_cmd.php?cmd=api+sofia+profile+internal+start';\" />\n";
+echo " <input type='button' value='stop' onclick=\"document.location.href='/freeswitch/freeswitch_cmd.php?cmd=api+sofia+profile+internal+stop';\" />\n";
+echo " <input type='button' value='flush_inbound_reg' onclick=\"document.location.href='/freeswitch/freeswitch_cmd.php?cmd=api+sofia+profile+internal+flush_inbound_reg';\" />\n";
+echo "</td>\n";
+echo "</tr>\n";
+echo "</table>\n";
+echo "<pre style=\"font-size: 9pt;\">\n";
+echo $response;
+echo "</pre>\n";
+fclose($fp);
+echo "<br /><br />\n\n";
+
+
+$fp = event_socket_create($host, $port, $password);
+$cmd = "api sofia status profile external";
+$response = event_socket_request($fp, $cmd);
+echo "<table width='690' cellpadding='0' cellspacing='0' border='0'>\n";
+echo "<tr>\n";
+echo "<td width='50%'>\n";
+echo " <b>sofia status profile external</b> \n";
+echo "</td>\n";
+echo "<td width='50%' align='right'>\n";
+echo " <input type='button' value='start' onclick=\"document.location.href='/freeswitch/freeswitch_cmd.php?cmd=api+sofia+profile+external+start+reloadxml';\" />\n";
+echo " <input type='button' value='stop' onclick=\"document.location.href='/freeswitch/freeswitch_cmd.php?cmd=api+sofia+profile+external+stop';\" />\n";
+echo " <input type='button' value='restart' onclick=\"document.location.href='/freeswitch/freeswitch_cmd.php?cmd=api+sofia+profile+external+restart+reloadxml';\" />\n";
+echo " <input type='button' value='rescan' onclick=\"document.location.href='/freeswitch/freeswitch_cmd.php?cmd=api+sofia+profile+external+rescan+reloadxml';\" />\n";
+echo "</td>\n";
+echo "</tr>\n";
+echo "</table>\n";
+echo "<pre style=\"font-size: 9pt;\">\n";
+echo $response;
+echo "</pre>\n";
+fclose($fp);
+echo "<br /><br />\n\n";
+
+
+$fp = event_socket_create($host, $port, $password);
+$cmd = "api status";
+$response = event_socket_request($fp, $cmd);
+echo "<b>status</b><br />\n";
+echo "<pre style=\"font-size: 9pt;\">\n";
+echo $response;
+echo "</pre>\n";
+fclose($fp);
+echo "<br /><br />\n\n";
+
+
+$fp = event_socket_create($host, $port, $password);
+$cmd = "api show channels";
+$response = event_socket_request($fp, $cmd);
+echo "<b>show channels</b>\n";
+if (strlen($response) > 40) {
+ echo "<textarea cols='85' rows='10' wrap='off'>\n";
+ echo $response;
+ echo "</textarea>\n";
+}
+else {
+ echo "<pre style=\"font-size: 9pt;\">\n";
+ echo $response;
+ echo "</pre>\n";
+}
+fclose($fp);
+echo "<br /><br />\n\n";
+echo "<br /><br />\n\n";
+
+
+$fp = event_socket_create($host, $port, $password);
+$cmd = "api show calls";
+$response = event_socket_request($fp, $cmd);
+echo "<b>show calls</b>\n";
+if (strlen($response) > 40) {
+ echo "<textarea cols='85' rows='10' wrap='off'>\n";
+ echo $response;
+ echo "</textarea>\n";
+}
+else {
+ echo "<pre style=\"font-size: 9pt;\">\n";
+ echo $response;
+ echo "</pre>\n";
+}
+fclose($fp);
+echo "<br /><br />\n\n";
+echo "<br /><br />\n\n";
+
+
+echo "<table width='690' cellpadding='0' cellspacing='0' border='0'>\n";
+echo "<tr>\n";
+echo "<td width='80%'>\n";
+echo "<b>Backup / Restore</b><br />\n";
+echo "The 'backup' button will tar gzip /usr/local/freeswitch/ to /tmp/freeswitch.bak.tgz it then presents a file to download. \n";
+echo "If the backup file does not exist in /tmp/freeswitch.bak.tgz then the 'restore' button will be hidden. \n";
+echo "Use Diagnostics->Command->File to upload: to browse to the file and then click on upload it now ready to be restored. \n";
+echo "<br /><br />\n";
+echo "</td>\n";
+echo "<td width='20%' valign='middle' align='right'>\n";
+echo " <input type='button' value='backup' onclick=\"document.location.href='/freeswitch/freeswitch_status.php?a=download&t=backup';\" />\n";
+if (file_exists('/tmp/freeswitch.bak.tgz')) {
+ echo " <input type='button' value='restore' onclick=\"document.location.href='/freeswitch/freeswitch_status.php?a=other&t=restore';\" />\n";
+}
+echo "</td>\n";
+echo "</tr>\n";
+echo "</table>\n";
+echo "<br /><br />\n\n";
+
+
+echo "<table width='690' cellpadding='0' cellspacing='0' border='0'>\n";
+echo "<tr>\n";
+echo "<td width='50%'>\n";
+echo "<b>Call Detail Records</b><br />\n";
+echo "/usr/local/freeswitch/log/cdr-csv/Master.csv<br /><br />\n";
+echo "</td>\n";
+echo "<td width='50%' align='right'>\n";
+echo " <input type='button' value='download cdr csv' onclick=\"document.location.href='/freeswitch/freeswitch_status.php?a=download&t=cdrcsv';\" />\n";echo "</td>\n";
+echo "</tr>\n";
+echo "</table>\n";
+echo "<br /><br />\n\n";
+
+
+echo "<table width='690' cellpadding='0' cellspacing='0' border='0'>\n";
+echo "<tr>\n";
+echo "<td width='50%'>\n";
+echo "<b>Logs</b><br />\n";
+echo "/usr/local/freeswitch/log/cdr-csv/freeswitch.log<br /><br />\n";
+echo "</td>\n";
+echo "<td width='50%' align='right'>\n";
+echo " <input type='button' value='download logs' onclick=\"document.location.href='/freeswitch/freeswitch_status.php?a=download&t=logs';\" />\n";
+echo "</tr>\n";
+echo "</table>\n";
+echo "<br /><br />\n\n";
+
+
+echo "<b>tail -n 100 /usr/local/freeswitch/log/freeswitch.log</b><br />\n";
+echo "<textarea cols='85' rows='30' wrap='off'>\n";
+echo system("tail -n 100 /usr/local/freeswitch/log/freeswitch.log");
+echo "</textarea>\n";
+echo "<br /><br />\n\n";
+
+
+//$fp = event_socket_create($host, $port, $password);
+//$cmd = "api sofia ";
+//$response = event_socket_request($fp, $cmd);
+//echo "<b>api sofia</b><br />\n";
+//echo "<pre style=\"font-size: 9pt;\">\n";
+//echo $response;
+//echo "</pre>\n";
+//fclose($fp);
+//echo "<br /><br />\n\n";
+
+?>
+
+ </td>
+ </tr>
+</table>
+
+</div>
+<?php include("fend.inc"); ?>
+
+</body>
+</html>
diff --git a/config/freeswitch/freeswitch_time_conditions.tmp b/config/freeswitch/freeswitch_time_conditions.tmp
new file mode 100644
index 00000000..617bb5cf
--- /dev/null
+++ b/config/freeswitch/freeswitch_time_conditions.tmp
@@ -0,0 +1,191 @@
+<?php
+/* $Id$ */
+/*
+ freeswitch_time_conditions.php
+ Copyright (C) 2008 Mark J Crane
+ All rights reserved.
+
+ FreeSWITCH (TM)
+ http://www.freeswitch.org/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require("guiconfig.inc");
+require("/usr/local/pkg/freeswitch.inc");
+
+
+$a_ivr_options = &$config['installedpackages']['freeswitchivroptions']['config'];
+
+
+if ($_GET['act'] == "del") {
+ if ($_GET['type'] == 'ivroptions') {
+ if ($a_ivr_options[$_GET['id']]) {
+ unset($a_ivr_options[$_GET['id']]);
+ write_config();
+ //touch($d_hostsdirty_path);
+ header("Location: freeswitch_ivr_edit.php?id=".$_GET['parentid']);
+ exit;
+ }
+ }
+}
+
+
+include("head.inc");
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<?php include("fbegin.inc"); ?>
+<p class="pgtitle">FreeSWITCH: IVR: Options</p>
+
+<div id="mainlevel">
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+<tr><td class="tabnavtbl">
+<?php
+
+ $tab_array = array();
+ $tab_array[] = array(gettext("Settings"), false, "/pkg_edit.php?xml=freeswitch.xml&amp;id=0");
+ $tab_array[] = array(gettext("Dialplan"), false, "/freeswitch/freeswitch_dialplan_includes.php");
+ $tab_array[] = array(gettext("Extensions"), false, "/freeswitch/freeswitch_extensions.php");
+ $tab_array[] = array(gettext("External"), false, "/pkg_edit.php?xml=freeswitch_external.xml&amp;id=0");
+ $tab_array[] = array(gettext("Gateways"), false, "/freeswitch/freeswitch_gateways.php");
+ $tab_array[] = array(gettext("Internal"), false, "/pkg_edit.php?xml=freeswitch_internal.xml&amp;id=0");
+ $tab_array[] = array(gettext("IVR"), true, "/freeswitch/freeswitch_ivr.php");
+ $tab_array[] = array(gettext("Modules"), false, "/pkg_edit.php?xml=freeswitch_modules.xml&amp;id=0");
+ $tab_array[] = array(gettext("Public"), false, "/freeswitch/freeswitch_public_includes.php");
+ $tab_array[] = array(gettext("Rec"), false, "/freeswitch/freeswitch_recordings.php");
+ $tab_array[] = array(gettext("Status"), false, "/freeswitch/freeswitch_status.php");
+ $tab_array[] = array(gettext("Vars"), false, "/pkg_edit.php?xml=freeswitch_vars.xml&amp;id=0");
+ display_top_tabs($tab_array);
+
+?>
+</td></tr>
+</table>
+
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabcont" >
+
+<form action="freeswitch_ivr_options.php" method="post" name="iform" id="iform">
+<?php
+
+
+//echo "<pre>";
+//print_r ($a_ivr);
+//echo "</pre>";
+
+//if ($savemsg) print_info_box($savemsg);
+//if (file_exists($d_hostsdirty_path)): echo"<p>";
+//print_info_box_np("The FreeSWITCH recordings have been changed.<br>You must apply the changes in order for them to take effect.");
+//echo"<br />";
+//endif;
+
+?>
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td><p><span class="vexpl"><span class="red"><strong>Note:<br>
+ </strong></span>
+ To make a recording dial extension 700 or you can make a
+ 16bit 8khz/16khz Mono WAV file then copy it to the
+ following directory then refresh the page to play it back.
+ </span></p></td>
+ </tr>
+ </table>
+ <br />
+
+ <table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td width="20%" class="listhdrr">Filename</td>
+ <td width="25%" class="listhdrr">Name</td>
+ <td width="25%" class="listhdr">Description</td>
+ <td width="10%" class="list">
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td width="17"></td>
+ <td valign="middle"><a href="freeswitch_ivr_edit.php"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" width="17" height="17" border="0"></a></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+
+ <?php $i = 0; foreach ($a_ivr as $ivrent): ?>
+ <tr>
+ <td class="listlr" ondblclick="document.location='freeswitch_ivr_edit.php?id=<?=$i;?>'">
+ <a href="javascript:void(0)" onclick="window.open('freeswitch_recordings_play.php?a=download&filename=<?=$recordingent['filename'];?>', 'play',' width=300,height=40,menubar=no,status=no,toolbar=no')">
+ <?=$ivrent['filename']?>
+ </a>
+ </td>
+ <td class="listr" ondblclick="document.location='freeswitch_ivr_edit.php?id=<?=$i;?>';">
+ <?=$ivrent['recordingname'];?>&nbsp;
+ </td>
+ <td class="listbg" ondblclick="document.location='freeswitch_ivr_edit.php?id=<?=$i;?>';">
+ <font color="#FFFFFF"><?=htmlspecialchars($recordingent['descr']);?>&nbsp;
+ </td>
+ <td valign="middle" nowrap class="list">
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td valign="middle"><a href="freeswitch_ivr_edit.php?id=<?=$i;?>"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_e.gif" width="17" height="17" border="0"></a></td>
+ <td><a href="freeswitch_ivr_options.php?type=ivroption&act=del&id=<?=$i;?>" onclick="return confirm('Do you really want to delete this?')"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_x.gif" width="17" height="17" border="0"></a></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <?php $i++; endforeach; ?>
+ <tr>
+ <td class="list" colspan="3"></td>
+ <td class="list">
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td width="17"></td>
+ <td valign="middle"><a href="freeswitch_ivr_options_edit.php"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" width="17" height="17" border="0"></a></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+
+
+ <tr>
+ <td class="list" colspan="3"></td>
+ <td class="list"></td>
+ </tr>
+ </table>
+
+</form>
+
+<br>
+<br>
+<br>
+<br>
+<br>
+<br>
+
+</td>
+</tr>
+</table>
+
+</div>
+
+
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/freeswitch/freeswitch_time_conditions_edit.tmp b/config/freeswitch/freeswitch_time_conditions_edit.tmp
new file mode 100644
index 00000000..c40b84f8
--- /dev/null
+++ b/config/freeswitch/freeswitch_time_conditions_edit.tmp
@@ -0,0 +1,215 @@
+<?php
+/* $Id$ */
+/*
+
+ freeswitch_time_conditions_edit.php
+ Copyright (C) 2008 Mark J Crane
+ All rights reserved.
+
+ FreeSWITCH (TM)
+ http://www.freeswitch.org/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require("guiconfig.inc");
+require("/usr/local/pkg/freeswitch.inc");
+
+
+$a_ivr_options = &$config['installedpackages']['freeswitchtimeconditions']['config'];
+
+$id = $_GET['id'];
+if (isset($_POST['id'])) {
+ $id = $_POST['id'];
+}
+
+//$parentid = $_GET['parentid'];
+//if (isset($_POST['parentid'])) {
+// $parentid = $_POST['parentid'];
+//}
+
+//$ivrid = $_GET['ivrid'];
+//if (isset($_POST['ivrid'])) {
+// $ivrid = $_POST['ivrid'];
+//}
+
+if (isset($id) && $a_ivr_options[$id]) {
+ $pconfig['conditionname'] = $a_ivr_options[$id]['conditionname'];
+ $pconfig['conditionstartday'] = $a_ivr_options[$id]['conditionstartday'];
+ $pconfig['conditionstarthrs'] = $a_ivr_options[$id]['conditionstarthrs'];
+ $pconfig['conditionstartmin'] = $a_ivr_options[$id]['conditionstartmin'];
+
+ $pconfig['conditionendday'] = $a_ivr_options[$id]['conditionendday'];
+ $pconfig['conditionendhrs'] = $a_ivr_options[$id]['conditionstarthrs'];
+ $pconfig['conditionendmin'] = $a_ivr_options[$id]['conditionendmin'];
+
+ $pconfig['conditionaction'] = $a_ivr_options[$id]['conditionaction'];
+ $pconfig['conditionantiaction'] = $a_ivr_options[$id]['conditionantiaction'];
+ $pconfig['conditionjavascript'] = $a_ivr_options[$id]['conditionjavascript'];
+ $pconfig['conditiondescr'] = $a_ivr_options[$id]['conditiondescr'];
+}
+
+
+
+if ($_POST) {
+
+ unset($input_errors);
+ $pconfig = $_POST;
+
+ if (!$input_errors) {
+
+ $ivroptionent = array();
+ $ivroptionent['ivrid'] = $_POST['ivrid'];
+ $ivroptionent['optionnumber'] = $_POST['optionnumber'];
+ $ivroptionent['optiontype'] = $_POST['optiontype'];
+ $ivroptionent['optiondest'] = $_POST['optiondest'];
+ $ivroptionent['optiondescr'] = $_POST['optiondescr'];
+
+ if (isset($id) && $a_ivr_options[$id]) {
+ //update
+ $a_ivr_options[$id] = $ivroptionent;
+ }
+ else {
+ //add
+ $a_ivr_options[] = $ivroptionent;
+ }
+
+ //touch($d_hostsdirty_path);
+ write_config();
+
+ header("Location: freeswitch_ivr_edit.php?id=".$parentid);
+ exit;
+ }
+}
+
+$pgtitle = "FreeSWITCH: IVR: Options: Edit";
+include("head.inc");
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<?php include("fbegin.inc"); ?>
+<p class="pgtitle"><?=$pgtitle?></p>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+
+<div id="mainlevel">
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+<tr><td class="tabnavtbl">
+<?php
+
+ $tab_array = array();
+ $tab_array[] = array(gettext("Settings"), false, "/pkg_edit.php?xml=freeswitch.xml&amp;id=0");
+ $tab_array[] = array(gettext("Dialplan"), false, "/freeswitch/freeswitch_dialplan_includes.php");
+ $tab_array[] = array(gettext("Extensions"), false, "/freeswitch/freeswitch_extensions.php");
+ $tab_array[] = array(gettext("External"), false, "/pkg_edit.php?xml=freeswitch_external.xml&amp;id=0");
+ $tab_array[] = array(gettext("Gateways"), false, "/freeswitch/freeswitch_gateways.php");
+ $tab_array[] = array(gettext("Internal"), false, "/pkg_edit.php?xml=freeswitch_internal.xml&amp;id=0");
+ $tab_array[] = array(gettext("IVR"), true, "/freeswitch/freeswitch_ivr.php");
+ $tab_array[] = array(gettext("Modules"), false, "/pkg_edit.php?xml=freeswitch_modules.xml&amp;id=0");
+ $tab_array[] = array(gettext("Public"), false, "/freeswitch/freeswitch_public_includes.php");
+ $tab_array[] = array(gettext("Rec"), false, "/freeswitch/freeswitch_recordings.php");
+ $tab_array[] = array(gettext("Status"), false, "/freeswitch/freeswitch_status.php");
+ $tab_array[] = array(gettext("Vars"), false, "/pkg_edit.php?xml=freeswitch_vars.xml&amp;id=0");
+ display_top_tabs($tab_array);
+
+?>
+</td></tr>
+</table>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabcont" >
+
+ <form action="freeswitch_ivr_options_edit.php" method="post" name="iform" id="iform">
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="22%" valign="top" class="vncellreq">Option Number</td>
+ <td width="78%" class="vtable">
+ <input name="optionnumber" type="text" class="formfld" id="optionnumber" size="40" value="<?=htmlspecialchars($pconfig['optionnumber']);?>">
+ <br> <span class="vexpl">Option Number<br>
+ e.g. <em>1</em></span></td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq">Type</td>
+ <td width="78%" class="vtable">
+ <?php
+ echo " <select name='optiontype' class='formfld'>\n";
+ echo " <option></option>\n";
+ if (htmlspecialchars($pconfig['optiontype']) == "extension") {
+ echo " <option selected='yes'>extension</option>\n";
+ }
+ else {
+ echo " <option>extension</option>\n";
+ }
+ if (htmlspecialchars($pconfig['optiontype']) == "voicemail") {
+ echo " <option selected='yes'>voicemail</option>\n";
+ }
+ else {
+ echo " <option>voicemail</option>\n";
+ }
+ echo " </select>\n";
+ ?>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq">Destination</td>
+ <td width="78%" class="vtable">
+ <input name="optiondest" type="text" class="formfld" id="optiondest" size="40" value="<?=htmlspecialchars($pconfig['optiondest']);?>">
+ <br> <span class="vexpl">Destination<br>
+ e.g. <em>1001</em></span></td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Description</td>
+ <td width="78%" class="vtable">
+ <input name="optiondescr" type="text" class="formfld" id="optiondescr" size="40" value="<?=htmlspecialchars($pconfig['optiondescr']);?>">
+ <br> <span class="vexpl">You may enter a description here
+ for your reference (not parsed).</span></td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <input name="ivrid" type="hidden" value="<?=$ivrid;?>">
+ <input name="parentid" type="hidden" value="<?=$parentid;?>">
+ <?php if (isset($id) && $a_ivr_options[$id]): ?>
+ <input name="id" type="hidden" value="<?=$id;?>">
+ <?php endif; ?>
+ <input name="Submit" type="submit" class="formbtn" value="Save"> <input class="formbtn" type="button" value="Cancel" onclick="history.back()">
+ </td>
+ </tr>
+ </table>
+ </form>
+
+ <br>
+ <br>
+ <br>
+ <br>
+ <br>
+ <br>
+
+ </td>
+ </tr>
+</table>
+
+</div>
+
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/freeswitch/freeswitch_vars.xml b/config/freeswitch/freeswitch_vars.xml
new file mode 100644
index 00000000..ac4246b9
--- /dev/null
+++ b/config/freeswitch/freeswitch_vars.xml
@@ -0,0 +1,136 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+
+ freeswitch_vars.xml
+ Copyright (C) 2008 Mark J Crane
+ All rights reserved.
+
+ FreeSWITCH (TM)
+ http://www.freeswitch.org/
+
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>FreeSWITCH is an open source telephony platform designed to facilitate the creation of voice and chat driven products scaling from a soft-phone up to a soft-switch. It can be used as a simple switching engine, a PBX, a media gateway or a media server to host IVR applications using simple scripts or XML to control the callflow.</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>freeswitchvars</name>
+ <version>0.1</version>
+ <title>FreeSWITCH: Vars</title>
+ <aftersaveredirect>pkg_edit.php?xml=freeswitch_vars.xml&amp;id=0</aftersaveredirect>
+ <include_file>/usr/local/pkg/freeswitch.inc</include_file>
+ <tabs>
+ <tab>
+ <text>Settings</text>
+ <url>/pkg_edit.php?xml=freeswitch.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Dialplan</text>
+ <url>/freeswitch/freeswitch_dialplan_includes.php</url>
+ </tab>
+ <tab>
+ <text>Extensions</text>
+ <url>/freeswitch/freeswitch_extensions.php</url>
+ </tab>
+ <tab>
+ <text>External</text>
+ <url>/pkg_edit.php?xml=freeswitch_external.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Gateways</text>
+ <url>/freeswitch/freeswitch_gateways.php</url>
+ </tab>
+ <tab>
+ <text>Internal</text>
+ <url>/pkg_edit.php?xml=freeswitch_internal.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>IVR</text>
+ <url>/freeswitch/freeswitch_ivr.php</url>
+ </tab>
+ <tab>
+ <text>Modules</text>
+ <url>/pkg_edit.php?xml=freeswitch_modules.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Public</text>
+ <url>/freeswitch/freeswitch_public_includes.php</url>
+ </tab>
+ <tab>
+ <text>Rec</text>
+ <url>/freeswitch/freeswitch_recordings.php</url>
+ </tab>
+ <tab>
+ <text>Status</text>
+ <url>/freeswitch/freeswitch_status.php</url>
+ </tab>
+ <tab>
+ <text>Vars</text>
+ <url>/pkg_edit.php?xml=freeswitch_vars.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ </tabs>
+ <configpath>installedpackages->package->$packagename->configuration->freeswitchvars</configpath>
+ <fields>
+ <field>
+ <fielddescr>&lt;b&gt;Vars&lt;/b&gt; &lt;br /&gt; &lt;br /&gt;Define preprocessor variables here. Can be accessed in the xml configation with $${var_name}.</fielddescr>
+ <fieldname>vars_xml</fieldname>
+ <description>&lt;br /&gt;Path: /usr/local/freeswitch/conf/vars.xml &lt;br /&gt;&lt;br /&gt;</description>
+ <type>textarea</type>
+ <encoding>base64</encoding>
+ <wrap>off</wrap>
+ <size>30</size>
+ <cols>70</cols>
+ <rows>33</rows>
+ </field>
+ </fields>
+ <custom_php_command_before_form>
+ </custom_php_command_before_form>
+ <custom_php_after_head_command>
+ sync_package_freeswitch_vars();
+ </custom_php_after_head_command>
+ <custom_php_after_form_command>
+ </custom_php_after_form_command>
+ <custom_php_validation_command>
+ </custom_php_validation_command>
+ <custom_php_resync_config_command>
+ sync_package_freeswitch_vars();
+ </custom_php_resync_config_command>
+</packagegui> \ No newline at end of file
diff --git a/config/freeswitch/libncurses.so.5.6 b/config/freeswitch/libncurses.so.5.6
new file mode 100644
index 00000000..3b40374c
--- /dev/null
+++ b/config/freeswitch/libncurses.so.5.6
Binary files differ
diff --git a/config/freeswitch/libogg.so.5.3 b/config/freeswitch/libogg.so.5.3
new file mode 100644
index 00000000..d230b68e
--- /dev/null
+++ b/config/freeswitch/libogg.so.5.3
Binary files differ
diff --git a/config/freeswitch/libspandsp.so.1 b/config/freeswitch/libspandsp.so.1
new file mode 100644
index 00000000..177b8c22
--- /dev/null
+++ b/config/freeswitch/libspandsp.so.1
Binary files differ
diff --git a/config/freeswitch/libtinfo.so.5.6 b/config/freeswitch/libtinfo.so.5.6
new file mode 100644
index 00000000..1263ec79
--- /dev/null
+++ b/config/freeswitch/libtinfo.so.5.6
Binary files differ
diff --git a/config/freeswitch/libvorbis.so.4 b/config/freeswitch/libvorbis.so.4
new file mode 100644
index 00000000..ec91ac85
--- /dev/null
+++ b/config/freeswitch/libvorbis.so.4
Binary files differ
diff --git a/config/freeswitch/mod_fax.so.1 b/config/freeswitch/mod_fax.so.1
new file mode 100644
index 00000000..68bd05d0
--- /dev/null
+++ b/config/freeswitch/mod_fax.so.1
Binary files differ
diff --git a/config/freeswitch/mod_shout.so.1 b/config/freeswitch/mod_shout.so.1
new file mode 100644
index 00000000..26d9b94b
--- /dev/null
+++ b/config/freeswitch/mod_shout.so.1
Binary files differ
diff --git a/config/freeswitch/please_enter_your_pin_number.wav b/config/freeswitch/please_enter_your_pin_number.wav
new file mode 100644
index 00000000..46263917
--- /dev/null
+++ b/config/freeswitch/please_enter_your_pin_number.wav
Binary files differ
diff --git a/config/freeswitch/your_pin_number_is_incorect_goodbye.wav b/config/freeswitch/your_pin_number_is_incorect_goodbye.wav
new file mode 100644
index 00000000..5683bb8e
--- /dev/null
+++ b/config/freeswitch/your_pin_number_is_incorect_goodbye.wav
Binary files differ
diff --git a/config/frickin.xml b/config/frickin.xml
new file mode 100644
index 00000000..8f59bb8c
--- /dev/null
+++ b/config/frickin.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>frickin</name>
+ <version>1.2</version>
+ <title>none</title>
+ <configpath>installedpackages->package->$packagename->configuration->settings</configpath>
+ <additional_files_needed>
+ <prefix>/usr/local/bin/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/All/frickin</item>
+ </additional_files_needed>
+ <custom_php_install_command>
+ $fout = fopen("/usr/local/etc/rc.d/frickin.sh", "w");
+ fwrite($fout, "#!/bin/sh\n# This package was automatically generated\n# by the pfSense package system.\n\n");
+ fwrite($fout, "# PACKAGE: Frickin Proxy\n");
+ fwrite($fout, "# EXECUTABLE: frickin\n");
+ fwrite($fout, "/usr/local/bin/frickin");
+ fwrite($fout, " -s 127.0.0.1");
+ fwrite($fout, " -c 20");
+ fwrite($fout, " &amp;\n");
+ fclose($fout);
+ mwexec("/usr/bin/killall frickin");
+ mwexec("chmod a+rx /usr/local/etc/rc.d/frickin.sh");
+ mwexec("/usr/local/etc/rc.d/frickin.sh");
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ unlink_if_exists("/usr/local/etc/rc.d/frickin.sh");
+ unlink_if_exists("/usr/local/bin/frickin");
+ </custom_php_deinstall_command>
+</packagegui>
diff --git a/config/frickin/bin/frickin b/config/frickin/bin/frickin
new file mode 100755
index 00000000..450dd733
--- /dev/null
+++ b/config/frickin/bin/frickin
Binary files differ
diff --git a/config/frickin/frickin.inc b/config/frickin/frickin.inc
new file mode 100644
index 00000000..ac7c7572
--- /dev/null
+++ b/config/frickin/frickin.inc
@@ -0,0 +1,137 @@
+<?php
+
+/* $Id$ */
+/*
+ frickin.inc
+ Copyright (C) 2006 Scott Ullrich
+ part of pfSense
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+function frickin_custom_php_install_command() {
+ global $config;
+ $fout = fopen("/usr/local/etc/rc.d/frickin.sh", "w");
+ fwrite($fout, "#!/bin/sh\n# This package was automatically generated\n# by the pfSense package system.\n\n");
+ fwrite($fout, "# PACKAGE: Frickin Proxy\n");
+ fwrite($fout, "# EXECUTABLE: frickin\n");
+ fwrite($fout, "/usr/local/bin/frickin");
+ fwrite($fout, " -c /usr/local/etc/frickin.conf");
+ fwrite($fout, " &\n");
+ fclose($fout);
+
+ $fout = fopen("/usr/local/etc/frickin.conf", "w");
+ $frickin_conf = <<<EOD
+
+proxy {
+ user = "nobody";
+ group = "nobody";
+ client {
+ queue = 5; # Maximum connection queue size
+ max = 100; # Maximum number of concurrent clients
+ multiple = FALSE; # Allow multiple connections from same ip
+ }
+ session {
+ connect = 15; # Connect timout (seconds)
+ idle = 60; # Idle timeout (seconds)
+ }
+}
+
+listeners {
+ default {
+ name = "Frickin PPTP Proxy";
+ vendor = "Placid Development";
+ ip = "127.0.0.1";
+ port = 1723;
+ }
+}
+
+EOD;
+
+ fwrite($fout, "{$frickin_conf}");
+ fclose($fout);
+
+ mwexec("/usr/bin/killall frickin");
+ mwexec("chmod a+rx /usr/local/etc/rc.d/frickin.sh");
+ mwexec("/usr/local/etc/rc.d/frickin.sh");
+
+// file_notice("System -> Advanced -> Scrub", "pfSenses scrub option has been disabled. See http://www.openbsd.org/faq/pf/scrub.html for more info.", "Scrub");
+// $config['system']['scrubnodf'] = "enabled";
+// write_config();
+
+ filter_configure();
+}
+
+function frickin_custom_php_deinstall_command() {
+ global $config;
+
+// unset($config['system']['scrubnodf']);
+// file_notice("System -> Advanced -> Scrub", "pfSenses scrub option has been enabled. See http://www.openbsd.org/faq/pf/scrub.html for more info.", "Scrub");
+// write_config();
+
+ unlink_if_exists("/usr/local/etc/rc.d/frickin.sh");
+ unlink_if_exists("/usr/local/bin/frickin");
+
+ mwexec("killall frickin");
+
+ filter_configure();
+}
+
+function frickin_generate_rules($type) {
+ global $config;
+
+ $rules = "";
+
+ $frickin_conf = $config['installedpackages']['frickin']['config'][0];
+ if (!is_process_running('frickin')) {
+ log_error("Frickin is installed but not started. Not installing redirect rules.");
+ return;
+ }
+
+ $ifaces = explode(',', $frickin_conf['active_interface']);
+ $ifaces = array_map('convert_friendly_interface_to_real_interface_name', $ifaces);
+
+ switch($type) {
+ case 'nat':
+ foreach ($ifaces as $iface) {
+ if(!$iface) {
+ //log_error("Not installing frickin pptp proxy rule. Please set it up");
+ //continue;
+ }
+ $rules .= "rdr on $iface proto tcp from any to any port = 1723 -> 127.0.0.1\n";
+ $rules .= "rdr on $iface inet proto gre all -> 127.0.0.1\n";
+ }
+ break;
+ case 'filter':
+ $ext_if = get_real_wan_interface();
+ $rules .= "pass out on $ext_if proto gre from any to any keep state\n";
+ $rules .= "pass in on $ext_if proto gre from any to any keep state\n";
+ break;
+ default:
+ break;
+ }
+
+ return $rules;
+}
+
+?> \ No newline at end of file
diff --git a/config/frickin/frickin.xml b/config/frickin/frickin.xml
new file mode 100644
index 00000000..6df9694e
--- /dev/null
+++ b/config/frickin/frickin.xml
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>frickin</name>
+ <version>2.0-BETA1</version>
+ <title>none</title>
+ <include_file>/usr/local/pkg/frickin.inc</include_file>
+ <menu>
+ <name>Frickin PPTP</name>
+ <tooltiptext>Setup Frickin PPTP Proxy specific settings</tooltiptext>
+ <section>Services</section>
+ <url>/pkg_edit.php?xml=frickin.xml&amp;id=0</url>
+ </menu>
+ <configpath>installedpackages->package->frickin->configuration->settings</configpath>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>077</chmod>
+ <item>http://www.pfsense.com/packages/config/frickin/frickin.inc</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/bin/</prefix>
+ <chmod>077</chmod>
+ <item>http://www.pfsense.com/packages/config/frickin/bin/frickin</item>
+ </additional_files_needed>
+ <fields>
+ <field>
+ <fielddescr>Proxy interface</fielddescr>
+ <fieldname>active_interface</fieldname>
+ <description>The interface(s) the proxy server will bind to.</description>
+ <type>interfaces_selection</type>
+ <required/>
+ <default_value>lan</default_value>
+ <multiple/>
+ </field>
+ </fields>
+ <custom_add_php_command>
+ frickin_custom_php_install_command();
+ </custom_add_php_command>
+ <custom_php_install_command>
+ frickin_custom_php_install_command();
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ frickin_custom_php_deinstall_command();
+ </custom_php_deinstall_command>
+</packagegui>
diff --git a/config/havp.inc b/config/havp.inc
new file mode 100644
index 00000000..3582986b
--- /dev/null
+++ b/config/havp.inc
@@ -0,0 +1,219 @@
+<?php
+require_once('globals.inc');
+require_once('config.inc');
+require_once('service-utils.inc');
+require_once('pkg-utils.inc');
+require_once('pfsense-utils.inc');
+require_once("notices.inc");
+
+/*
+ havp.inc
+ part of the HAVP package for pfSense
+ Copyright (C) 2006 Rajkumar S <raj@linuxense.com>
+ All rights reserved.
+ $Id$
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+*/
+function sync_package_havp() {
+ conf_mount_rw();
+ config_lock();
+ global $config, $g;
+ $fd = fopen("/etc/havp.config","w");
+ fwrite($fd, "USER havp\n");
+ fwrite($fd, "GROUP havp\n");
+ fwrite($fd, "ACCESSLOG /var/log/havp/access.log\n");
+ fwrite($fd, "ERRORLOG /var/log/havp/error.log\n");
+ fwrite($fd, "DISPLAYINITIALMESSAGES false\n");
+ fwrite($fd, "ENABLECLAMLIB true\n");
+ fwrite($fd, "CLAMDBDIR /var/db/clamav/\n");
+ fwrite($fd, "ENABLECLAMD false\n");
+ fwrite($fd, "ENABLEFPROT false\n");
+ fwrite($fd, "ENABLEAVG false\n");
+ fwrite($fd, "ENABLEAVESERVER false\n");
+ fwrite($fd, "ENABLESOPHIE false\n");
+ fwrite($fd, "ENABLETROPHIE false\n");
+ fwrite($fd, "ENABLENOD32 false\n");
+ fwrite($fd, "ENABLEAVAST false\n");
+ if($config['installedpackages']['havp']['config'] != "") {
+ foreach($config['installedpackages']['havp']['config'] as $tmp) {
+ if ($tmp['servernumber'] != "") fwrite($fd,"SERVERNUMBER " . $tmp['servernumber'] . "\n");
+ if ($tmp['maxservers'] != "") fwrite($fd,"MAXSERVERS " . $tmp['maxservers'] . "\n");
+ if ($tmp['port'] != "") fwrite($fd,"PORT " . $tmp['port'] . "\n");
+ if ($tmp['source_address'] != "") fwrite($fd,"SOURCE_ADDRESS " . $tmp['source_address'] . " \n");
+ if ($tmp['dbreload'] != "") fwrite($fd,"DBRELOAD " . $tmp['dbreload'] . " \n");
+ if ($tmp['parentproxy'] != "") fwrite($fd,"PARENTPROXY " . $tmp['parentproxy'] . " \n");
+ if ($tmp['parentport'] != "") fwrite($fd,"PARENTPORT " . $tmp['parentport'] . " \n");
+ if ($tmp['maxscansize'] != "") fwrite($fd,"MAXSCANSIZE " . $tmp['maxscansize'] . " \n");
+ if ($tmp['trickling'] != "") fwrite($fd,"TRICKLING " . $tmp['trickling'] . " \n");
+ if ($tmp['maxdownloadsize'] != "") fwrite($fd,"MAXDOWNLOADSIZE " . $tmp['maxdownloadsize'] . " \n");
+
+ /* If Transparent then, don't bother with bind address */
+ if ($tmp['transparent'] == "on"){
+ fwrite($fd,"TRANSPARENT true\n");
+ fwrite($fd,"BIND_ADDRESS 127.0.0.1\n");
+ setup_transparency();
+ }
+ else {
+ fwrite($fd,"TRANSPARENT false\n");
+ if ($tmp['bind_address'] != ""){
+ fwrite($fd,"BIND_ADDRESS " . $config['interfaces'][strtolower($tmp['bind_address'])]['ipaddr'] . " \n");
+ }else { /* just to be sure, default is lan */
+ fwrite($fd,"BIND_ADDRESS " . $config['interfaces']['lan']['ipaddr'] . " \n");
+ }
+ $havp_pf_result = mwexec ("pfctl -a rdr-package/havp -F nat");
+ $havp_pf_result = mwexec ("pfctl -t havp -T kill");
+ if($havp_pf_result <> 0) {
+ file_notice("HAVP", "There were error(s) clearing the transparency rules", "HAVP", "");
+ }
+ }
+
+ if ($tmp['range'] == "on"){
+ fwrite($fd,"RANGE true\n");
+ }
+ else {
+ fwrite($fd,"RANGE false\n");
+ }
+ if ($tmp['log_oks'] == "on"){
+ fwrite($fd,"LOG_OKS true\n");
+ }
+ else {
+ fwrite($fd,"LOG_OKS false\n");
+ }
+ }
+ } else {
+ fwrite($fd,"SERVERNUMBER 10\n");
+ fwrite($fd,"MAXSERVERS 100\n");
+ fwrite($fd,"PORT 8080\n");
+ fwrite($fd,"TRANSPARENT false\n");
+ fwrite($fd,"RANGE true\n");
+ fwrite($fd,"LOG_OKS true\n");
+ fwrite($fd,"BIND_ADDRESS " . $config['interfaces']['lan']['ipaddr'] . " \n");
+ }
+ fclose($fd);
+ conf_mount_ro();
+ config_unlock();
+ unlink_if_exists("/usr/local/etc/havp/havp.config");
+ mwexec("ln -sf /etc/havp.config /usr/local/etc/havp/havp.config");
+ mwexec("/usr/local/etc/rc.d/havp.sh stop");
+ mwexec("/usr/local/etc/rc.d/havp.sh start");
+}
+
+function havp_install_command() {
+ global $config, $g;
+ mwexec ("mkdir -p /var/log/havp/");
+ mwexec ("mkdir -p /var/tmp/havp/");
+ mwexec ("mkdir -p /var/run/havp/");
+ mwexec ("chown havp:havp /var/log/havp");
+ mwexec ("chown havp:havp /var/tmp/havp");
+ mwexec ("chown havp:havp /var/run/havp");
+ mwexec ("cp /usr/local/pkg/havp.sh /usr/local/etc/rc.d/");
+ mwexec ("chmod +x /usr/local/etc/rc.d/havp.sh");
+ sync_package_havp();
+}
+
+function havp_deinstall_command() {
+ global $config, $g;
+ mwexec("/usr/local/etc/rc.d/havp.sh stop");
+ conf_mount_rw();
+ unlink_if_exists("/usr/local/etc/rc.d/havp.sh");
+ unlink_if_exists("/usr/local/etc/havp/havp.config");
+ unlink_if_exists("/etc/havp.config");
+ conf_mount_ro();
+}
+function sync_package_havp_whitelist() {
+ global $config;
+ conf_mount_rw();
+ config_lock();
+ $fd = fopen("/usr/local/etc/havp/whitelist","w");
+ if($config['installedpackages']['havpwhitelist']['config'] != "")
+ foreach($config['installedpackages']['havpwhitelist']['config'] as $tmp) {
+ fwrite($fd, $tmp['url'] . "\n");
+ }
+ fclose($fd);
+ /* signal a reload of all files */
+ conf_mount_ro();
+ config_unlock();
+}
+
+function sync_package_havp_blacklist() {
+ global $config;
+ conf_mount_rw();
+ config_lock();
+ $fd = fopen("/usr/local/etc/havp/blacklist","w");
+ if($config['installedpackages']['havpblacklist']['config'] != "")
+ foreach($config['installedpackages']['havpblacklist']['config'] as $tmp) {
+ fwrite($fd, $tmp['url'] . "\n");
+ }
+ fclose($fd);
+ /* signal a reload of all files */
+ conf_mount_ro();
+ config_unlock();
+}
+
+function add_trans_table(){
+ global $config;
+ conf_mount_rw();
+ config_lock();
+
+ # Flush all entries first, and then add them.
+ $havp_pf_result = mwexec ('pfctl -a "rdr-package/havp" -t havp -T flush');
+ if($havp_pf_result <> 0) {
+ file_notice("HAVP", "There were error(s) flushing the exclude table", "HAVP", "");
+ }
+ if($config['installedpackages']['havptransexclude']['config'] != ""){
+ foreach($config['installedpackages']['havptransexclude']['config'] as $tmp) {
+ $havp_pf_result = mwexec ('pfctl -a "rdr-package/havp" -t havp -T add ' . $tmp['ip']);
+ if($havp_pf_result <> 0) {
+ file_notice("HAVP", "There were error(s) adding the ip " . $tmp['ip'], "HAVP", "");
+ }
+ }
+ }
+ /* signal a reload of all files */
+ conf_mount_ro();
+ config_unlock();
+}
+
+function setup_transparency(){
+ global $config;
+ $trans_file = fopen("/tmp/havp_pf.rules","w");
+ fwrite($trans_file, "table <havp> persist\n");
+ fwrite($trans_file, "rdr on " . $config['interfaces']['lan']['if'] . " inet proto tcp from !<havp> to ! " . $config['interfaces']['lan']['ipaddr'] . " port = http -> 127.0.0.1 port 8080 \n");
+ fclose($trans_file);
+ $havp_pf_result = mwexec ('pfctl -a "rdr-package/havp" -f /tmp/havp_pf.rules');
+ if($havp_pf_result <> 0) {
+ file_notice("HAVP", "There were error(s) loading the transparency rules", "HAVP", "");
+ }
+ add_trans_table();
+}
+
+function transparency_init(){
+ global $config;
+ if($config['installedpackages']['havp']['config'] != "") {
+ if($config['installedpackages']['havp']['config'][0]['transparent'] == "on") {
+ setup_transparency();
+ }
+ }
+}
+
+?>
diff --git a/config/havp.sh b/config/havp.sh
new file mode 100644
index 00000000..88a97250
--- /dev/null
+++ b/config/havp.sh
@@ -0,0 +1,85 @@
+#!/bin/sh
+# HAVP Init script
+# 6/23/06 - Gary Buckmaster
+# Modified by Rajkumar S.
+#
+pidfile=/var/run/havp/havp.pid
+piddir=/var/run/havp/
+logdir=/var/log/havp/
+required_dirs=/var/tmp/havp
+required_files=/usr/local/etc/havp/havp.config
+
+
+rc_start()
+{
+ if [ ! -d $piddir ]
+ then
+ mkdir -p $piddir
+ chown havp:havp $piddir
+ fi
+ if [ ! -d $logdir ]
+ then
+ mkdir -p $logdir
+ chown havp:havp $logdir
+ fi
+ if [ ! -f $required_files ]
+ then
+ echo "FATAL: Missing HAVP config file: $required_files"
+ return
+ fi
+ if [ ! -d $required_dirs ]
+ then
+ echo "FATAL: Missing HAVP working director: $required_dirs"
+ mkdir -p $required_dirs
+ chown havp:havp $required_dirs
+ fi
+ if [ -f $pidfile ]
+ then
+ pid=$(sed 's/ //g' $pidfile)
+ echo "FATAL: HAVP already running? pid: $pid"
+ return
+ else
+ echo "Starting HAVP Antivirus HTTP Proxy"
+ /usr/local/sbin/havp &
+ sleep 4
+ /usr/local/bin/php -q /usr/local/pkg/havp_startup.inc &
+ sleep 4
+ if [ -f $pidfile ]
+ then
+ pid=$(sed 's/ //g' $pidfile)
+ echo "Started pid: $pid"
+ else
+ echo "An error occurred starting HAVP"
+ return
+ fi
+ fi
+}
+
+rc_stop()
+{
+ pid=$(sed 's/ //g' $pidfile)
+ if [ ! -f $pidfile ]
+ then
+ echo "FATAL: HAVP already running pid: $pid"
+ return
+ else
+ echo "Stopping HAVP pid: $pid"
+ kill $pid
+ rm -f $required_dirs/*
+ fi
+}
+
+case $1 in
+ start)
+ rc_start
+ ;;
+ stop)
+ rc_stop
+ ;;
+ restart)
+ rc_stop
+ sleep 5
+ rc_start
+ ;;
+esac
+
diff --git a/config/havp.xml b/config/havp.xml
new file mode 100644
index 00000000..0dee82e3
--- /dev/null
+++ b/config/havp.xml
@@ -0,0 +1,220 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>havp</name>
+ <version>0.3</version>
+ <title>Havp: Settings</title>
+ <aftersaveredirect>/pkg_edit.php?xml=havp.xml&amp;id=0</aftersaveredirect>
+ <include_file>/usr/local/pkg/havp.inc</include_file>
+ <menu>
+ <name>HAVP</name>
+ <tooltiptext>Modify HAVP settings.</tooltiptext>
+ <section>Services</section>
+ <configfile>havp.xml</configfile>
+ <url>/pkg_edit.php?xml=havp.xml&amp;id=0</url>
+ </menu>
+
+ <service>
+ <name>havp</name>
+ <rcfile>/usr/local/etc/rc.d/havp.sh</rcfile>
+ <description>HTTP Anti Virus Proxy.</description>
+ </service>
+
+ <tabs>
+ <tab>
+ <text>Settings</text>
+ <url>/pkg_edit.php?xml=havp.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Whitelist</text>
+ <url>/pkg.php?xml=havp_whitelist.xml</url>
+ </tab>
+ <tab>
+ <text>Blacklist</text>
+ <url>/pkg.php?xml=havp_blacklist.xml</url>
+ </tab>
+ <tab>
+ <text>Exclude from Transparent Proxy</text>
+ <url>/pkg.php?xml=havp_trans_exclude.xml</url>
+ </tab>
+ </tabs>
+ <configpath>['installedpackages']['havp]['config']</configpath>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://agni.linuxense.com/packages/config/havp.inc</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://agni.linuxense.com/packages/config/havp_whitelist.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://agni.linuxense.com/packages/config/havp_blacklist.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://agni.linuxense.com/packages/config/havp_startup.inc</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://agni.linuxense.com/packages/config/havp_trans_exclude.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://agni.linuxense.com/packages/config/havp.sh</item>
+ </additional_files_needed>
+
+ <fields>
+ <field>
+ <fielddescr>Server Number</fielddescr>
+ <fieldname>servernumber</fieldname>
+ <description>Specify how many servers (child processes) are simultaneously listening on port PORT for a connection. Minimum value should be the peak requests-per-second expected + 5 for headroom.</description>
+ <type>input</type>
+ <default_value>10</default_value>
+ </field>
+ <field>
+ <fielddescr>Max Server Number</fielddescr>
+ <fieldname>maxservers</fieldname>
+ <description>This is the hard limit for concurrent requests processed.</description>
+ <type>input</type>
+ <default_value>100</default_value>
+ </field>
+ <field>
+ <fielddescr>Transparent?</fielddescr>
+ <fieldname>transparent</fieldname>
+ <description>Run HAVP as transparent Proxy? [Bind Address will be disregarded in this mode, HAVP will listen on localhost] </description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Port</fielddescr>
+ <fieldname>port</fieldname>
+ <description>Port HAVP is listening on.</description>
+ <type>input</type>
+ <default_value>8080</default_value>
+ </field>
+ <field>
+ <fielddescr>Bind Address</fielddescr>
+ <fieldname>bind_address</fieldname>
+ <description>IP address that HAVP listens on. Leave it empty to bind all addresses, defaults to LAN address</description>
+ <type>interfaces_selection</type>
+ <default_value>lan</default_value>
+ </field>
+ <field>
+ <fielddescr>Source Address</fielddescr>
+ <fieldname>source_address</fieldname>
+ <description>IP address used for sending outbound packets. Let it be undefined if you want OS to handle right address.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Range Requests</fielddescr>
+ <fieldname>range</fieldname>
+ <description> Allow HTTP Range Requests?</description>
+ <type>checkbox</type>
+ <default_value>on</default_value>
+ </field>
+ <field>
+ <fielddescr>Log All Requests?</fielddescr>
+ <fieldname>log_oks</fieldname>
+ <description>Log Details: true: Log all Requests, false: log only virus hits</description>
+ <type>checkbox</type>
+ <default_value>on</default_value>
+ </field>
+ <field>
+ <fielddescr>Virus Database Reload Time.</fielddescr>
+ <fieldname>dbreload</fieldname>
+ <description>Specify here the number of minutes to wait for reloading. Default 60 Minutes.</description>
+ <type>input</type>
+ <default_value>60</default_value>
+ </field>
+ <field>
+ <fielddescr>Parent Proxy Host</fielddescr>
+ <fieldname>parentproxy</fieldname>
+ <description>Specify the parent proxy hostname or ip</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Parent Proxy Port</fielddescr>
+ <fieldname>parentport</fieldname>
+ <description>Specify the parent proxy port</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Max size of temporary files on disk</fielddescr>
+ <fieldname>maxscansize</fieldname>
+ <description>Temporary file will grow only up to this size. This means scanner will scan data until this limit is reached. The value is in BYTES, not kb or mb. 0 is Unlimited.</description>
+ <type>input</type>
+ <default_value>0</default_value>
+ </field>
+ <field>
+ <fielddescr>Trickling Time</fielddescr>
+ <fieldname>trickling</fieldname>
+ <description>After Trickling Time (seconds), some bytes are sent to browser to keep the connection alive. Trickling is not needed if timeouts are not expected. Default is 5 seconds. </description>
+ <type>input</type>
+ <default_value>5</default_value>
+ </field>
+ <field>
+ <fielddescr>Absolute Maximum Download Size</fielddescr>
+ <fieldname>maxdownloadsize</fieldname>
+ <description>Downloads larger than this will be blocked, Unless whitelisted. 0 is unlimited.</description>
+ <type>input</type>
+ <default_value>0</default_value>
+ </field>
+ </fields>
+
+ <custom_php_resync_config_command> sync_package_havp(); </custom_php_resync_config_command>
+ <custom_php_install_command> havp_install_command(); </custom_php_install_command>
+ <custom_php_deinstall_command> havp_deinstall_command(); </custom_php_deinstall_command>
+
+</packagegui>
+
diff --git a/config/havp_blacklist.xml b/config/havp_blacklist.xml
new file mode 100644
index 00000000..aa82507a
--- /dev/null
+++ b/config/havp_blacklist.xml
@@ -0,0 +1,116 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>havp-blacklist</name>
+ <version>0.1.0</version>
+ <title>Havp: Blacklist</title>
+ <include_file>/usr/local/pkg/havp.inc</include_file>
+
+ <menu>
+ <name>HAVP Blacklist</name>
+ <tooltiptext></tooltiptext>
+ <section>Services</section>
+ <configfile>havp.xml</configfile>
+ </menu>
+ <tabs>
+ <tab>
+ <text>Settings</text>
+ <url>/pkg_edit.php?xml=havp.xml&amp;act=edit&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Whitelist</text>
+ <url>/pkg.php?xml=havp_whitelist.xml</url>
+ </tab>
+ <tab>
+ <text>Blacklist</text>
+ <url>/pkg.php?xml=havp_blacklist.xml</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Exclude from Transparent Proxy</text>
+ <url>/pkg.php?xml=havp_trans_exclude.xml</url>
+ </tab>
+ </tabs>
+
+ <configpath>['installedpackages']['havpblacklist']['config']</configpath>
+
+ <adddeleteeditpagefields>
+ <columnitem>
+ <fielddescr>Blocked URL</fielddescr>
+ <fieldname>url</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Description</fielddescr>
+ <fieldname>description</fieldname>
+ </columnitem>
+ </adddeleteeditpagefields>
+
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://agni.linuxense.com/packages/config/havp.inc</item>
+ </additional_files_needed>
+
+ <fields>
+ <field>
+ <fielddescr>Blocked URL</fielddescr>
+ <fieldname>url</fieldname>
+ <description>Enter the URL to blacklist</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Description</fielddescr>
+ <fieldname>description</fieldname>
+ <description>Enter the description for this url</description>
+ <type>input</type>
+ </field>
+ </fields>
+
+ <custom_php_command_before_form>sync_package_havp_blacklist();</custom_php_command_before_form>
+ <custom_delete_php_command>sync_package_havp_blacklist();</custom_delete_php_command>
+ <custom_php_resync_config_command>sync_package_havp_blacklist();</custom_php_resync_config_command>
+</packagegui>
diff --git a/config/havp_startup.inc b/config/havp_startup.inc
new file mode 100644
index 00000000..eb4cd31a
--- /dev/null
+++ b/config/havp_startup.inc
@@ -0,0 +1,12 @@
+#!/usr/local/bin/php
+<?php
+require_once('globals.inc');
+require_once('config.inc');
+require_once('service-utils.inc');
+require_once('pkg-utils.inc');
+require_once('pfsense-utils.inc');
+require_once('/usr/local/pkg/havp.inc');
+global $config;
+transparency_init();
+?>
+
diff --git a/config/havp_trans_exclude.xml b/config/havp_trans_exclude.xml
new file mode 100644
index 00000000..b04d168f
--- /dev/null
+++ b/config/havp_trans_exclude.xml
@@ -0,0 +1,116 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>havp_trans_exclude</name>
+ <version>0.1.0</version>
+ <title>HAVP: Exclude from Transparent Proxy</title>
+ <include_file>/usr/local/pkg/havp.inc</include_file>
+
+ <menu>
+ <name>Transparency Exclude</name>
+ <tooltiptext></tooltiptext>
+ <section>Services</section>
+ <configfile>havp.xml</configfile>
+ </menu>
+ <tabs>
+ <tab>
+ <text>Settings</text>
+ <url>/pkg_edit.php?xml=havp.xml&amp;act=edit&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Whitelist</text>
+ <url>/pkg.php?xml=havp_whitelist.xml</url>
+ </tab>
+ <tab>
+ <text>Blacklist</text>
+ <url>/pkg.php?xml=havp_blacklist.xml</url>
+ </tab>
+ <tab>
+ <text>Exclude from Transparent Proxy</text>
+ <url>/pkg.php?xml=havp_trans_exclude.xml</url>
+ <active/>
+ </tab>
+ </tabs>
+
+ <configpath>['installedpackages']['havptransexclude']['config']</configpath>
+
+ <adddeleteeditpagefields>
+ <columnitem>
+ <fielddescr>Exempted IP</fielddescr>
+ <fieldname>ip</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Description</fielddescr>
+ <fieldname>description</fieldname>
+ </columnitem>
+ </adddeleteeditpagefields>
+
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://agni.linuxense.com/packages/config/havp.inc</item>
+ </additional_files_needed>
+
+ <fields>
+ <field>
+ <fielddescr>Exempted IP</fielddescr>
+ <fieldname>ip</fieldname>
+ <description>Enter the IP to exempt from transparent proxy</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Description</fielddescr>
+ <fieldname>description</fieldname>
+ <description>Enter the description for this item</description>
+ <type>input</type>
+ </field>
+ </fields>
+
+ <custom_php_command_before_form>add_trans_table();</custom_php_command_before_form>
+ <custom_delete_php_command>add_trans_table();</custom_delete_php_command>
+ <custom_php_resync_config_command>add_trans_table();</custom_php_resync_config_command>
+</packagegui>
diff --git a/config/havp_whitelist.xml b/config/havp_whitelist.xml
new file mode 100644
index 00000000..ce64a838
--- /dev/null
+++ b/config/havp_whitelist.xml
@@ -0,0 +1,116 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>havp-whitelist</name>
+ <version>0.1.0</version>
+ <title>HAVP: Whitelist</title>
+ <include_file>/usr/local/pkg/havp.inc</include_file>
+
+ <menu>
+ <name>HAVP Whitelist</name>
+ <tooltiptext></tooltiptext>
+ <section>Services</section>
+ <configfile>havp.xml</configfile>
+ </menu>
+ <tabs>
+ <tab>
+ <text>Settings</text>
+ <url>/pkg_edit.php?xml=havp.xml&amp;act=edit&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Whitelist</text>
+ <url>/pkg.php?xml=havp_whitelist.xml</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Blacklist</text>
+ <url>/pkg.php?xml=havp_blacklist.xml</url>
+ </tab>
+ <tab>
+ <text>Exclude from Transparent Proxy</text>
+ <url>/pkg.php?xml=havp_trans_exclude.xml</url>
+ </tab>
+ </tabs>
+
+ <configpath>['installedpackages']['havpwhitelist']['config']</configpath>
+
+ <adddeleteeditpagefields>
+ <columnitem>
+ <fielddescr>Exempted URL</fielddescr>
+ <fieldname>url</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Description</fielddescr>
+ <fieldname>description</fieldname>
+ </columnitem>
+ </adddeleteeditpagefields>
+
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://agni.linuxense.com/packages/config/havp.inc</item>
+ </additional_files_needed>
+
+ <fields>
+ <field>
+ <fielddescr>Exempted URL</fielddescr>
+ <fieldname>url</fieldname>
+ <description>Enter the URL to exempt from blacklisting</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Description</fielddescr>
+ <fieldname>description</fieldname>
+ <description>Enter the description for this item</description>
+ <type>input</type>
+ </field>
+ </fields>
+
+ <custom_php_command_before_form>sync_package_havp_whitelist();</custom_php_command_before_form>
+ <custom_delete_php_command>sync_package_havp_whitelist();</custom_delete_php_command>
+ <custom_php_resync_config_command>sync_package_havp_whitelist();</custom_php_resync_config_command>
+</packagegui>
diff --git a/config/hula.xml b/config/hula.xml
new file mode 100644
index 00000000..0270e8c5
--- /dev/null
+++ b/config/hula.xml
@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>hula</name>
+ <version>3.0</version>
+ <title>Services: Hula</title>
+ <savetext>Change</savetext>
+ <preoutput>yes</preoutput>
+ <donotsave>true</donotsave>
+ <!-- Menu is where this packages menu will appear -->
+ <menu>
+ <name>Hula Setup</name>
+ <tooltiptext>This area will help setup Hula for the first time.</tooltiptext>
+ <section>Services</section>
+ <configfile>hula.xml</configfile>
+ </menu>
+ <menu>
+ <name>Hula Admin</name>
+ <tooltiptext>This area will help manage Hula from day to day.</tooltiptext>
+ <section>Services</section>
+ <url>http://$myurl:89</url>
+ </menu>
+ <menu>
+ <name>Hula Users</name>
+ <tooltiptext>This area is for user logins.</tooltiptext>
+ <section>Services</section>
+ <url>http://$myurl:8080</url>
+ </menu>
+
+ <additional_files_needed>
+ <item>http://www.pfsense.com/packages/All/hula.tgz</item>
+ </additional_files_needed>
+
+ <!-- Do not save invokes a simple input menu and will not update
+ the configuration database. -->
+ <fields>
+ <field>
+ <fielddescr>Hula Default Domain</fielddescr>
+ <fieldname>domain</fieldname>
+ <description>Enter the default domain that hula will use.</description>
+ <type>input</type>
+ </field>
+ </fields>
+ <custom_add_php_command>
+ conf_mount_rw();
+ config_lock();
+ system("/usr/local/hula/sbin/hulasetup --domain=" . $_POST['domain']);
+ system("/usr/local/etc/rc.d/hula.sh &amp;");
+ conf_mount_ro();
+ config_unlock();
+ </custom_add_php_command>
+ <custom_php_install_command>
+ $fout = fopen("/usr/local/etc/rc.d/hula.sh","w");
+ fwrite($fout, "#!/bin/sh\n\n");
+ fwrite($fout, "/sbin/mount -t linprocfs linprocfs /proc\n");
+ fwrite($fout, "/usr/local/hula/sbin/hulamanager &amp;\n");
+ fclose($fout);
+ chmod("/usr/local/etc/rc.d/hula.sh", 0755);
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ mwexec("/usr/bin/killall -9 hulamanager");
+ rmdir_recursive("/usr/local/hula");
+ unlink_if_exists("/usr/local/etc/rc.d/hula.sh");
+ </custom_php_deinstall_command>
+</packagegui>
diff --git a/config/ifdepd.xml b/config/ifdepd.xml
new file mode 100644
index 00000000..009a3b73
--- /dev/null
+++ b/config/ifdepd.xml
@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>ifdepd</name>
+ <version>20050303</version>
+ <title>ifdepd: Settings</title>
+ <aftersaveredirect>/pkg_edit.php?xml=ifdepd.xml&amp;id=0</aftersaveredirect>
+ <menu>
+ <name>ifdepd</name>
+ <tooltiptext>Modify ifdepd settings.</tooltiptext>
+ <section>Services</section>
+ <configfile>ifdepd.xml</configfile>
+ <url>pkg_edit.php?xml=ifdepd.xml&amp;id=0</url>
+ </menu>
+ <service>
+ <name>ifdepd</name>
+ <rcfile>ifdepd.sh</rcfile>
+ <executable>ifdepd</executable>
+ </service>
+ <configpath>installedpackages->package->$packagename->configuration->settings</configpath>
+ <fields>
+ <field>
+ <fielddescr>Use default values</fielddescr>
+ <fieldname>usedefaults</fieldname>
+ <description>If this is checked ifdepd will monitor the WAN and LAN interfaces for connectivity and will disable carp0 and carp1 upon their failure.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Source interfaces</fielddescr>
+ <fieldname>srcinterface</fieldname>
+ <description>Enter a colon seperated list of interfaces to monitor for connectivity. You must use the physical interface names.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Destination interfaces</fielddescr>
+ <fieldname>destinterface</fieldname>
+ <description>Enter a colon seperated list of interfaces to disable once one of the source interfaces loses connectivity. You must specify physical interface names.</description>
+ <type>input</type>
+ </field>
+ </fields>
+ <custom_php_global_functions>
+ function sync_package_ifdepd() {
+ conf_mount_rw();
+ config_lock();
+ global $config;
+ $ifdepd_config =&amp; $config['installedpackages']['ifdepd']['config'][0];
+ if($ifdepd_config != "") {
+ if(isset($ifdepd_config['usedefaults'])) {
+ $lan_int = $config['interfaces']['lan']['if'];
+ $wan_int = $config['interfaces']['wan']['if'];
+ $start = "/usr/local/bin/ifdepd -d -S " . $lan_int . ":" . $wan_int . " -D carp0:carp1\n";
+ } else {
+ $start = "/usr/local/bin/ifdepd -d -S " . $ifdepd_config['srcinterface'] . " -D " . $_POST['destinterface'] . "\n";
+ }
+ write_rcfile(array(
+ "file" => "ifdepd.sh",
+ "start" => $start,
+ "stop" => "/usr/bin/killall ifdepd"
+ )
+ );
+ restart_service("ifdepd");
+ }
+ conf_mount_ro();
+ config_unlock();
+ }
+ </custom_php_global_functions>
+ <custom_add_php_command>
+ sync_package_ifdepd();
+ </custom_add_php_command>
+ <custom_php_resync_config_command>
+ sync_package_ifdepd();
+ </custom_php_resync_config_command>
+</packagegui>
+
diff --git a/config/ifstated.xml b/config/ifstated.xml
new file mode 100644
index 00000000..5adcf9c4
--- /dev/null
+++ b/config/ifstated.xml
@@ -0,0 +1,140 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>ifstated</name>
+ <version>20041117</version>
+ <title>ifstated: Settings</title>
+ <aftersaveredirect>pkg_edit.php?xml=ifstated.xml&amp;id=0&amp;savemsg=Updated</aftersaveredirect>
+ <menu>
+ <name>ifstated</name>
+ <tooltiptext>Modify ifstated settings.</tooltiptext>
+ <section>Services</section>
+ <configfile>ifstated.xml</configfile>
+ <url>/pkg_edit.php?xml=ifstated.xml&amp;id=0</url>
+ </menu>
+ <modify_system>
+ <modifyitem>
+ <modifyfilename>/etc/sysctl.conf</modifyfilename>
+ <textneeded>net.inet.carp.preempt=1</textneeded>
+ </modifyitem>
+ </modify_system>
+ <configpath>installedpackages->package->$packagename->configuration->settings</configpath>
+ <fields>
+ <field>
+ <fielddescr>External Test IP</fielddescr>
+ <fieldname>exttestip</fieldname>
+ <description>Enter an IP to test external connectivity with. This should be a host with extremely high availability.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Internal Test IP</fielddescr>
+ <fieldname>inttestip</fieldname>
+ <description>Enter an IP to test internal connectivity with. This should be a host with extremely high availability.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Paired Firewall External IP</fielddescr>
+ <fieldname>pairextip</fieldname>
+ <description>Enter the real IP of the other firewall's (real) external interface.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Paired Firewall Internal IP</fielddescr>
+ <fieldname>pairintip</fieldname>
+ <description>Enter the real IP of the other firewall's (real) internal interface.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Initial State</fielddescr>
+ <fieldname>initstate</fieldname>
+ <description>Enter the desired initial state for this firewall.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>Primary</name>
+ <value>primary</value>
+ </option>
+ <option>
+ <name>Backup</name>
+ <value>backup</value>
+ </option>
+ </options>
+ </field>
+ </fields>
+ <custom_add_php_command>
+ conf_mount_rw();
+ config_lock();
+ global $config;
+ if ($_POST == "") $_POST = $config['installedpackages']['ifstated']['config'];
+ $fout = fopen("/usr/local/etc/ifstated.conf","w");
+ if($config['installedpackages']['ifstated']['config'] != "") {
+ fwrite($fout, "# This file was automatically generated by the pfSense\n# package management system.\n\n");
+ fwrite($fout, "init-state " . $_POST['initstate'] . "\n\n");
+ fwrite($fout, "carp_up = \"((carp0 link up) and (carp1 link up))\"\ncarp_down = \"((! carp0 link up) and (! carp1 link up))\"\ncarp_sync= \"((carp0 link up and carp1 link up) or ((!carp0 link up) and (!carp1 link up)))\"\n\n");
+ fwrite($fout, "net = '( \"ping -q -c 1 -t 1 " . $_POST['exttestip'] . " > /dev/null\" every 10 and \"ping -q -c 1 -t 1 " . $_POST['inttestip'] . " > /dev/null\" every 10)'\n\n");
+ fwrite($fout, "peer = '( \"ping -q -c 1 -t 1 " . $_POST['pairextip'] . " > /dev/null\" every 10 and \"ping -q -c 1 -t 1 " . $_POST['pairintip'] . " > /dev/null\" every 10)'\n\n");
+ fwrite($fout, "state auto {\nif \$carp_up {\nset-state primary\n}\nif \$carp_down {\nset-state backup\n}\n}\n\n");
+ fwrite($fout, "state primary {\ninit {\nrun \"ifconfig carp0 advskew 10\"\nrun \"ifconfig carp1 advskew 10\"\n}\nif ! \$net {\nset-state demoted\n}\n}\n\nstate demoted {\ninit {\nrun \"ifconfig carp0 advskew 254\"\nrun \"ifconfig carp1 advskew 254\"\n}\nif \$net {\nset-state primary\n}\n}\n\n");
+ fwrite($fout, "state promoted {\ninit {\nrun \"ifconfig carp0 advskew 0\"\nrun \"ifconfig carp1 advskew 0\"\n}\nif \$peer or ! \$net {\nset-state backup\n}\n}\n\n");
+ fwrite($fout, "state backup {\ninit {\nrun \"ifconfig carp0 advskew 100\"\nrun \"ifconfig carp1 advskew 100\"\n}\nif ! \$carp_sync and \$net and \"sleep 5\" every 10 {\nif (! \$carp_sync) and \$net {\nset-state promoted\n}\n}\n}\n");
+ }
+ fclose($fout);
+ conf_mount_ro();
+ config_unlock();
+ mwexec("/usr/bin/killall -HUP ifstated");
+ </custom_add_php_command>
+ <custom_php_install_command>
+ global $config;
+ $fout = fopen("/usr/local/etc/rc.d/ifstated.sh","w");
+ fwrite($fout,"#!/bin/sh\n\n/usr/local/sbin/ifstated\n");
+ fwrite($fout, "# PACKAGE: IFStated\n");
+ fwrite($fout, "# EXECUTABLE: ifstated\n");
+ fclose($fout);
+ chmod("/usr/local/etc/rc.d/ifstated.sh", 0755);
+ </custom_php_install_command>
+</packagegui>
+
diff --git a/config/imspector/imspector.inc b/config/imspector/imspector.inc
new file mode 100644
index 00000000..09974363
--- /dev/null
+++ b/config/imspector/imspector.inc
@@ -0,0 +1,268 @@
+<?php
+/*
+ imspector.inc
+ part of pfSense (http://www.pfsense.com/)
+
+ Copyright (C) 2007 Ryan Wagoner <rswagoner@gmail.com>.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+
+ require_once("config.inc");
+ require_once("functions.inc");
+
+ /* IMSpector */
+
+ define('IMSPECTOR_RCFILE', '/usr/local/etc/rc.d/imspector.sh');
+ define('IMSPECTOR_ETC', '/usr/local/etc/imspector');
+ define('IMSPECTOR_CONFIG', IMSPECTOR_ETC . '/imspector.conf');
+
+ function imspector_notice ($msg) { syslog(LOG_NOTICE, "imspector: {$msg}"); }
+ function imspector_warn ($msg) { syslog(LOG_WARNING, "imspector: {$msg}"); }
+
+ function imspector_action ($action) {
+ if (file_exists(IMSPECTOR_RCFILE))
+ mwexec(IMSPECTOR_RCFILE.' '.$action);
+ }
+
+ function imspector_running () {
+ if((int)exec('pgrep imspector | wc -l') > 0)
+ return true;
+ return false;
+ }
+
+ function write_imspector_config($file, $text) {
+ $conf = fopen($file, 'w');
+ if(!$conf) {
+ imspector_warn("Could not open {$file} for writing.");
+ exit;
+ }
+ fwrite($conf, $text);
+ fclose($conf);
+ }
+
+ function imspector_pf_rdr($iface, $port) {
+ return "rdr pass on {$iface} inet proto tcp from any to any port = {$port} -> 127.0.0.1 port 16667\n";
+ }
+
+ function imspector_pf_rule($iface, $port) {
+ return "pass in quick on {$iface} inet proto tcp from any to any port {$port} keep state\n";
+ }
+
+ function imspector_proto_to_port ($proto)
+ {
+ switch ($proto) {
+ case 'msn':
+ return 1863;
+ case 'icq':
+ return 5190;
+ case 'yahoo':
+ return 5050;
+ case 'irc':
+ return 6667;
+ default:
+ return null;
+ }
+ }
+
+ function validate_form_imspector($post, $input_errors) {
+ if($post['iface_array'])
+ foreach($post['iface_array'] as $iface)
+ if($iface == 'wan')
+ $input_errors[] = 'It is a security risk to specify WAN in the \'Interface\' field';
+ }
+
+ function deinstall_package_imspector() {
+ imspector_action('stop');
+
+ @unlink(IMSPECTOR_RCFILE);
+ @unlink(IMSPECTOR_CONFIG);
+ @unlink(IMSPECTOR_ETC . '/badwords_custom.txt');
+ @unlink(IMSPECTOR_ETC . '/acl_blacklist.txt');
+ @unlink(IMSPECTOR_ETC . '/acl_whitelist.txt');
+
+ //exec('pkg_delete imspector-0.4');
+ }
+
+ function sync_package_imspector() {
+ global $config;
+ global $input_errors;
+
+ config_lock();
+
+ $imspector_config = $config['installedpackages']['imspector']['config'][0];
+
+ /* remove existing rules */
+ exec('/sbin/pfctl -a imspector -Fr');
+ exec('/sbin/pfctl -a imspector -Fn');
+
+ $ifaces_active = '';
+
+ if($imspector_config['enable'] && $imspector_config['proto_array'])
+ $proto_array = explode(',', $imspector_config['proto_array']);
+
+ if($imspector_config['enable'] && $imspector_config['iface_array'])
+ $iface_array = explode(',', $imspector_config['iface_array']);
+
+ if($iface_array && $proto_array) {
+ foreach($iface_array as $iface) {
+ $if = convert_friendly_interface_to_real_interface_name($iface);
+ /* above function returns iface if fail */
+ if($if!=$iface) {
+ $addr = find_interface_ip($if);
+ /* non enabled interfaces are displayed in list on imspector settings page */
+ /* check that the interface has an ip address before adding parameters */
+ if($addr) {
+ foreach($proto_array as $proto) {
+ if(imspector_proto_to_port($proto)) {
+ /* we can use rdr pass to auto create the filter rule */
+ $pf_rules .= imspector_pf_rdr($if,imspector_proto_to_port($proto));
+ }
+ }
+ if(!$ifaces_active)
+ $ifaces_active = "{$iface}";
+ else
+ $ifaces_active .= ", {$iface}";
+ } else {
+ imspector_warn("Interface {$iface} has no ip address, ignoring");
+ }
+ } else {
+ imspector_warn("Could not resolve real interface for {$iface}");
+ }
+ }
+
+ if($pf_rules) {
+ exec("echo \"{$pf_rules}\" | /sbin/pfctl -a imspector -f -");
+
+ conf_mount_rw();
+
+ /* generate configuration files */
+
+ $conf['plugin_dir'] = '/usr/local/lib/imspector';
+
+ foreach($proto_array as $proto)
+ $conf[$proto . '_protocol'] = 'on';
+
+ if($imspector_config['log_file']) {
+ @mkdir('/var/imspector');
+ $conf['file_logging_dir'] = '/var/imspector';
+ }
+
+ if($imspector_config['log_mysql']) {
+ $conf['mysql_server'] = $imspector_config['mysql_server'];
+ $conf['mysql_database'] = $imspector_config['mysql_database'];
+ $conf['mysql_username'] = $imspector_config['mysql_username'];
+ $conf['mysql_password'] = $imspector_config['mysql_password'];
+ }
+
+ if($imspector_config['filter_badwords']) {
+ if(!empty($imspector_config["badwords_list"])) {
+ $conf['badwords_filename'] = IMSPECTOR_ETC . '/badwords_custom.txt';
+ write_imspector_config(IMSPECTOR_ETC . '/badwords_custom.txt',
+ str_replace("\r", '', base64_decode($imspector_config["badwords_list"])));
+ } else
+ $conf['badwords_filename'] = IMSPECTOR_ETC . '/badwords.txt';
+ }
+
+ if($imspector_config['block_files'])
+ $conf['block_files'] = 'on';
+
+ if($imspector_config['block_unlisted'])
+ $conf['block_unlisted'] = 'on';
+
+ if(!empty($imspector_config['acl_whitelist'])) {
+ $conf['whitelist_filename'] = IMSPECTOR_ETC . '/acl_whitelist.txt';
+ write_imspector_config(IMSPECTOR_ETC . '/acl_whitelist.txt',
+ str_replace("\r", '', base64_decode($imspector_config["acl_whitelist"])));
+ }
+
+ if(!empty($imspector_config['acl_blacklist'])) {
+ $conf['blacklist_filename'] = IMSPECTOR_ETC . '/acl_blacklist.txt';
+ write_imspector_config(IMSPECTOR_ETC . '/acl_blacklist.txt',
+ str_replace("\r", '', base64_decode($imspector_config["acl_blacklist"])));
+ }
+
+ $conftext = '';
+ foreach($conf as $var => $key)
+ $conftext .= "{$var}={$key}\n";
+ write_imspector_config(IMSPECTOR_CONFIG, $conftext);
+
+ /* generate rc file start and stop */
+ $stop = <<<EOD
+if [ `pgrep imspector | wc -l` != 0 ]; then
+ /usr/bin/killall imspector
+ while [ `pgrep imspector | wc -l` != 0 ]; do
+ sleep 1
+ done
+ fi
+EOD;
+ $start = $stop."\n\tldconfig -m /usr/local/lib/mysql\n";
+ $start .= "\t/usr/local/sbin/imspector -c \"".IMSPECTOR_CONFIG."\"";
+
+ write_rcfile(array(
+ 'file' => 'imspector.sh',
+ 'start' => $start,
+ 'stop' => $stop
+ )
+ );
+
+ conf_mount_ro();
+
+ /* if imspector not running start it */
+ if(!imspector_running()) {
+ imspector_notice("Starting service on interface: {$ifaces_active}");
+ imspector_action('start');
+ }
+ /* or restart imspector if settings were changed */
+ elseif($_POST['iface_array']) {
+ imspector_notice("Restarting service on interface: {$ifaces_active}");
+ imspector_action('restart');
+ }
+ }
+ }
+
+ if(!$iface_array || !$proto_array || !$pf_rules) {
+ /* no parameters user does not want imspector running */
+ /* lets stop the service and remove the rc file */
+
+ if(file_exists(IMSPECTOR_RCFILE)) {
+ if(!$imspector_config['enable'])
+ imspector_notice('Stopping service: imspector disabled');
+ else
+ imspector_notice('Stopping service: no interfaces and/or protocols selected');
+
+ imspector_action('stop');
+
+ conf_mount_rw();
+ unlink(IMSPECTOR_RCFILE);
+ unlink(IMSPECTOR_CONFIG);
+ @unlink(IMSPECTOR_ETC . '/badwords_custom.txt');
+ @unlink(IMSPECTOR_ETC . '/acl_blacklist.txt');
+ @unlink(IMSPECTOR_ETC . '/acl_whitelist.txt');
+ conf_mount_ro();
+ }
+ }
+
+ config_unlock();
+ }
+?>
diff --git a/config/imspector/imspector.xml b/config/imspector/imspector.xml
new file mode 100644
index 00000000..076dca13
--- /dev/null
+++ b/config/imspector/imspector.xml
@@ -0,0 +1,225 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>imspector</name>
+ <version>0.4</version>
+ <title>Services: IMSpector</title>
+ <savetext>Change</savetext>
+ <aftersaveredirect>/services_imspector_logs.php</aftersaveredirect>
+ <include_file>/usr/local/pkg/imspector.inc</include_file>
+ <menu>
+ <name>IMSpector</name>
+ <tooltiptext>Set IMSpector settings such as protocols to listen on.</tooltiptext>
+ <section>Services</section>
+ <url>/services_imspector_logs.php</url>
+ </menu>
+ <service>
+ <name>imspector</name>
+ <rcfile>imspector.sh</rcfile>
+ <executable>imspector</executable>
+ </service>
+ <tabs>
+ <tab>
+ <text>IMSpector Log Viewer</text>
+ <url>/services_imspector_logs.php</url>
+ </tab>
+ <tab>
+ <text>IMSpector Settings</text>
+ <url>/pkg_edit.php?xml=imspector.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ </tabs>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.org/packages/config/imspector/imspector.inc</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.org/packages/config/imspector/services_imspector_logs.php</item>
+ </additional_files_needed>
+ <fields>
+ <field>
+ <fielddescr>Enable IMSpector</fielddescr>
+ <fieldname>enable</fieldname>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Interfaces (generally LAN)</fielddescr>
+ <fieldname>iface_array</fieldname>
+ <description>You can use the CTRL or COMMAND key to select multiple interfaces.</description>
+ <type>interfaces_selection</type>
+ <size>3</size>
+ <required/>
+ <value>lan</value>
+ <multiple>true</multiple>
+ </field>
+ <field>
+ <fielddescr>Listen on protocols</fielddescr>
+ <fieldname>proto_array</fieldname>
+ <description>You can use the CTRL or COMMAND key to select multiple protocols.</description>
+ <type>select</type>
+ <size>4</size>
+ <required/>
+ <multiple>true</multiple>
+ <options>
+ <option>
+ <name>MSN</name>
+ <value>msn</value>
+ </option>
+ <option>
+ <name>ICQ/AIM</name>
+ <value>icq</value>
+ </option>
+ <option>
+ <name>Yahoo</name>
+ <value>yahoo</value>
+ </option>
+ <option>
+ <name>IRC</name>
+ <value>irc</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Enable file logging</fielddescr>
+ <fieldname>log_file</fieldname>
+ <description>Log files stored in /var/imspector.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Enable mySQL logging</fielddescr>
+ <fieldname>log_mysql</fieldname>
+ <description>Make sure to specify your MySQL credentials below.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>mySQL server</fielddescr>
+ <fieldname>mysql_server</fieldname>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>mySQL database</fielddescr>
+ <fieldname>mysql_database</fieldname>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>mySQL username</fielddescr>
+ <fieldname>mysql_username</fieldname>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>mySQL password</fielddescr>
+ <fieldname>mysql_password</fieldname>
+ <type>password</type>
+ </field>
+ <field>
+ <fielddescr>Enable bad word filtering</fielddescr>
+ <fieldname>filter_badwords</fieldname>
+ <description>Replace characters of matched bad word with *.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Bad words list</fielddescr>
+ <fieldname>badwords_list</fieldname>
+ <description>
+ Place one word or phrase to match per line.&lt;br /&gt;
+ If left blank the default list in /usr/local/etc/imspector/badwords.txt will be used.
+ </description>
+ <type>textarea</type>
+ <encoding>base64</encoding>
+ <rows>5</rows>
+ <cols>40</cols>
+ </field>
+ <field>
+ <fielddescr>Block file transfers</fielddescr>
+ <fieldname>block_files</fieldname>
+ <description>Block file transfers on supported protocols.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Block non ACL defined</fielddescr>
+ <fieldname>block_unlisted</fieldname>
+ <description>Overide the default of allowing user's not defined the whitelist or blacklist ACLs.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>ACL whitelist</fielddescr>
+ <fieldname>acl_whitelist</fieldname>
+ <description>
+ Example (allow specifc access): localuser: remoteuser1 remoteuser2&lt;br /&gt;
+ Example (allow full access): localuser:
+ </description>
+ <type>textarea</type>
+ <encoding>base64</encoding>
+ <rows>5</rows>
+ <cols>40</cols>
+ </field>
+ <field>
+ <fielddescr>ACL blacklist</fielddescr>
+ <fieldname>acl_blacklist</fieldname>
+ <description>
+ Example (block specifc access): localuser: remoteuser1 remoteuser2&lt;br /&gt;
+ Example (block all access): localuser:
+ </description>
+ <type>textarea</type>
+ <encoding>base64</encoding>
+ <rows>5</rows>
+ <cols>40</cols>
+ </field>
+ </fields>
+ <custom_php_validation_command>
+ validate_form_imspector($_POST, &amp;$input_errors);
+ </custom_php_validation_command>
+ <custom_php_resync_config_command>
+ sync_package_imspector();
+ </custom_php_resync_config_command>
+ <custom_php_deinstall_command>
+ deinstall_package_imspector();
+ </custom_php_deinstall_command>
+</packagegui>
diff --git a/config/imspector/services_imspector_logs.php b/config/imspector/services_imspector_logs.php
new file mode 100644
index 00000000..616d3dfc
--- /dev/null
+++ b/config/imspector/services_imspector_logs.php
@@ -0,0 +1,288 @@
+<?php
+/*
+ services_imspector_logs.php
+ part of pfSense (http://www.pfsense.com/)
+
+ JavaScript Code is GPL Licensed from SmoothWall Express.
+
+ Copyright (C) 2007 Ryan Wagoner <rswagoner@gmail.com>.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require("guiconfig.inc");
+
+/* variables */
+$log_dir = '/var/imspector';
+$imspector_config = $config['installedpackages']['imspector']['config'][0];
+
+$border_color = '#c0c0c0';
+$default_bgcolor = '#eeeeee';
+
+$list_protocol_color = '#000000';
+$list_local_color = '#000000';
+$list_remote_color = '#000000';
+$list_convo_color = '#000000';
+
+$list_protocol_bgcolor = '#cccccc';
+$list_local_bgcolor = '#dddddd';
+$list_remote_bgcolor = '#eeeeee';
+$list_end_bgcolor = '#bbbbbb';
+
+$convo_title_color = 'black';
+$convo_local_color = 'blue';
+$convo_remote_color = 'red';
+
+$convo_title_bgcolor = '#cccccc';
+$convo_local_bgcolor = '#dddddd';
+$convo_remote_bgcolor = '#eeeeee';
+
+/* functions */
+
+function convert_dir_list ($topdir) {
+ if (!is_dir($topdir)) return;
+ if ($dh = opendir($topdir)) {
+ while (($file = readdir($dh)) !== false) {
+ if(!preg_match('/^\./', $file) == 0) continue;
+ if (is_dir("$topdir/$file")) {
+ $list .= convert_dir_list("$topdir/$file");
+ } else {
+ $list .= "$topdir/$file\n";
+ }
+ }
+ closedir($dh);
+ }
+ return $list;
+}
+
+/* ajax response */
+if ($_POST['mode'] == "render") {
+
+ /* user list */
+ print(str_replace(array($log_dir,'/'),array('','|'),convert_dir_list($log_dir)));
+ print("--END--\n");
+
+ /* log files */
+ if ($_POST['section'] != "none") {
+ $section = explode('|',$_POST['section']);
+ $protocol = $section[0];
+ $localuser = $section[1];
+ $remoteuser = $section[2];
+ $conversation = $section[3];
+
+ /* conversation title */
+ print(implode(', ', $section)."\n");
+ print("--END--\n");
+
+ /* conversation content */
+ $filename = $log_dir.'/'.implode('/', $section);
+ if($fd = fopen($filename, 'r')) {
+ print("<table width='100%' border='0' cellpadding='2' cellspacing='0'>\n");
+ while (!feof($fd)) {
+ $line = fgets($fd);
+ if(feof($fd)) continue;
+
+ preg_match('/([^,]*),([^,]*),([^,]*),([^,]*),([^,]*),(.*)/', $line, $matches);
+ $address = $matches[1];
+ $timestamp = $matches[2];
+ $direction = $matches[3];
+ $type = $matches[4];
+ $filtered = $matches[5];
+ $data = $matches[6];
+
+ if($direction == '0') {
+ $bgcolor = $convo_remote_bgcolor;
+ $user = "&lt;<span style='color: $convo_remote_color;'>$remoteuser</span>&gt;";
+ }
+ if($direction == '1') {
+ $bgcolor = $convo_local_bgcolor;
+ $user = "&lt;<span style='color: $convo_local_color;'>$localuser</span>&gt;";
+ }
+
+ $time = strftime("%H:%M:%S", $timestamp);
+
+ print("<tr bgcolor='$bgcolor'><td style='width: 30px; vertical-align: top;'>[$time]</td>\n
+ <td style=' width: 60px; vertical-align: top;'>$user</td>\n
+ <td style='vertical-align: top;'>$data</td></tr>\n");
+ }
+ print("</table>\n");
+ fclose($fd);
+ }
+ }
+ exit;
+}
+/* defaults to this page but if no settings are present, redirect to setup page */
+if(!$imspector_config["enable"] || !$imspector_config["iface_array"] || !$imspector_config["proto_array"])
+ Header("Location: /pkg_edit.php?xml=imspector.xml&id=0");
+
+$pgtitle = "Services: IMSpector Log Viewer";
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+//$pfSenseHead->addMeta("<meta http-equiv=\"refresh\" content=\"120;url={$_SERVER['SCRIPT_NAME']}\" />");
+//echo $pfSenseHead->getHTML();
+?>
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<?php include("fbegin.inc"); ?>
+<p class="pgtitle"><?=$pgtitle?></font></p>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+<div id="mainlevel">
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+<?php
+ $tab_array = array();
+ $tab_array[] = array(gettext("IMSpector Log Viewer "), true, "/services_imspector_logs.php");
+ $tab_array[] = array(gettext("IMSpector Settings "), false, "/pkg_edit.php?xml=imspector.xml&id=0");
+ display_top_tabs($tab_array);
+?>
+</table>
+
+<?php
+$zz = <<<EOD
+<script type="text/javascript">
+var section = 'none';
+var moveit = 1;
+var the_timeout;
+
+function xmlhttpPost()
+{
+ var xmlHttpReq = false;
+ var self = this;
+
+ if (window.XMLHttpRequest)
+ self.xmlHttpReq = new XMLHttpRequest();
+ else if (window.ActiveXObject)
+ self.xmlHttpReq = new ActiveXObject("Microsoft.XMLHTTP");
+
+ self.xmlHttpReq.open('POST', 'services_imspector_logs.php', true);
+ self.xmlHttpReq.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
+
+ self.xmlHttpReq.onreadystatechange = function() {
+ if (self.xmlHttpReq && self.xmlHttpReq.readyState == 4)
+ updatepage(self.xmlHttpReq.responseText);
+ }
+
+ document.getElementById('im_status').style.display = "inline";
+ self.xmlHttpReq.send("mode=render&section=" + section);
+}
+
+function updatepage(str)
+{
+ /* update the list of conversations ( if we need to ) */
+ var parts = str.split("--END--\\n");
+ var lines = parts[0].split("\\n");
+
+ for (var line = 0 ; line < lines.length ; line ++) {
+ var a = lines[line].split("|");
+
+ if (!a[1] || !a[2] || !a[3]) continue;
+
+ /* create titling information if needed */
+ if (!document.getElementById(a[1])) {
+ document.getElementById('im_convos').innerHTML +=
+ "<div id='" + a[1] + "_t' style='width: 100%; background-color: $list_protocol_bgcolor; color: $list_protocol_color;'>" + a[1] + "</div>" +
+ "<div id='" + a[1] + "' style='width: 100%; background-color: $list_local_bgcolor;'></div>";
+ }
+ if (!document.getElementById(a[1] + "_" + a[2])) {
+ var imageref = "";
+ if (a[0]) imageref = "<img src='" + a[0] + "' alt='" + a[1] + "'/>";
+ document.getElementById(a[1]).innerHTML +=
+ "<div id='" + a[1] + "_" + a[2] + "_t' style='width: 100%; color: $list_local_color; padding-left: 5px;'>" + imageref + a[2] + "</div>" +
+ "<div id='" + a[1] + "_" + a[2] + "' style='width: 100%; background-color: $list_remote_bgcolor; border-bottom: solid 1px $list_end_bgcolor;'></div>";
+ }
+ if (!document.getElementById(a[1] + "_" + a[2] + "_" + a[3])) {
+ document.getElementById(a[1] + "_" + a[2]).innerHTML +=
+ "<div id='" + a[1] + "_" + a[2] + "_" + a[3] + "_t' style='width: 100%; color: $list_remote_color; padding-left: 10px;'>" + a[3] + "</div>" +
+ "<div id='" + a[1] + "_" + a[2] + "_" + a[3] + "' style='width: 100%;'></div>";
+ }
+ if (!document.getElementById(a[1] + "_" + a[2] + "_" + a[3] + "_" + a[4])) {
+ document.getElementById(a[1] + "_" + a[2] + "_" + a[3]).innerHTML +=
+ "<div id='" + a[1] + "_" + a[2] + "_" + a[3] + "_" + a[4] +
+ "' style='width: 100%; color: $list_convo_color; cursor: pointer; padding-left: 15px;' onClick=" +
+ '"' + "setsection('" + a[1] + "|" + a[2] + "|" + a[3] + "|" + a[4] + "');" + '"' + "' + >&raquo;" + a[4] + "</div>";
+ }
+ }
+
+ /* determine the title of this conversation */
+ var details = parts[1].split(",");
+ var title = details[0] + " conversation between <span style='color: $convo_local_color;'>" + details[ 1 ] +
+ "</span> and <span style='color: $convo_remote_color;'>" + details[2] + "</span>";
+ if (!details[1]) title = "&nbsp;";
+ if (!parts[2]) parts[2] = "&nbsp;";
+
+ document.getElementById('im_status').style.display = "none";
+ var bottom = parseInt(document.getElementById('im_content').scrollTop);
+ var bottom2 = parseInt(document.getElementById('im_content').style.height);
+ var absheight = parseInt( bottom + bottom2 );
+ if (absheight == document.getElementById('im_content').scrollHeight) {
+ moveit = 1;
+ } else {
+ moveit = 0;
+ }
+ document.getElementById('im_content').innerHTML = parts[2];
+ if (moveit == 1) {
+ document.getElementById('im_content').scrollTop = 0;
+ document.getElementById('im_content').scrollTop = document.getElementById('im_content').scrollHeight;
+ }
+ document.getElementById('im_content_title').innerHTML = title;
+ the_timeout = setTimeout( "xmlhttpPost();", 5000 );
+}
+
+function setsection(value)
+{
+ section = value;
+ clearTimeout(the_timeout);
+ xmlhttpPost();
+ document.getElementById('im_content').scrollTop = 0;
+ document.getElementById('im_content').scrollTop = document.getElementById('im_content').scrollHeight;
+}
+</script>
+EOD;
+print($zz);
+?>
+
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabcont">
+ <div style='width: 100%; text-align: right;'><span id='im_status' style='display: none;'>Updating</span>&nbsp;</div>
+ <table width="100%">
+ <tr>
+ <td width="15%" bgcolor="<?=$default_bgcolor?>" style="overflow: auto; border: solid 1px <?=$border_color?>;">
+ <div id="im_convos" style="height: 400px; overflow: auto; overflow-x: hidden;"></div>
+ </td>
+ <td width="75%" bgcolor="<?=$default_bgcolor?>" style="border: solid 1px <?=$border_color?>;">
+ <div id="im_content_title" style="height: 20px; overflow: auto; vertical-align: top;
+ color: <?=$convo_title_color?>; background-color: <?=$convo_title_bgcolor?>;"></div>
+ <div id="im_content" style="height: 380px; overflow: auto; vertical-align: bottom; overflow-x: hidden;"></div>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+</table>
+
+<script type="text/javascript">xmlhttpPost();</script>
+
+</div>
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/iperf.xml b/config/iperf.xml
new file mode 100644
index 00000000..29469d33
--- /dev/null
+++ b/config/iperf.xml
@@ -0,0 +1,161 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>iperf</name>
+ <version>1.7.0</version>
+ <title>iperf: Client</title>
+ <preoutput>yes</preoutput>
+ <donotsave>true</donotsave>
+ <menu>
+ <name>iperf</name>
+ <tooltiptext>Run iperf in client or server mode.</tooltiptext>
+ <section>Diagnostics</section>
+ <configfile>iperf.xml</configfile>
+ </menu>
+ <service>
+ <name>iperf</name>
+ <executable>iperf</executable>
+ </service>
+ <tabs>
+ <tab>
+ <text>Client</text>
+ <url>/pkg_edit.php?xml=iperf.xml</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Server</text>
+ <url>/pkg_edit.php?xml=iperfserver.xml</url>
+ </tab>
+ </tabs>
+ <additional_files_needed>
+ <item>http://www.pfsense.com/packages/config/iperfserver.xml</item>
+ </additional_files_needed>
+ <fields>
+ <field>
+ <fielddescr>Server</fielddescr>
+ <fieldname>hostname</fieldname>
+ <description>Enter the IP address or hostname that iperf will connect to.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Port</fielddescr>
+ <fieldname>port</fieldname>
+ <description>Enter the port that iperf will connect to. (default 5001)</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Protocol</fielddescr>
+ <fieldname>protocol</fieldname>
+ <description>Choose whether to use TCP or UDP here. (default is TCP)</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>TCP</name>
+ <value>tcp</value>
+ </option>
+ <option>
+ <name>UDP</name>
+ <value>udp</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Output format</fielddescr>
+ <fieldname>format</fieldname>
+ <description>Choose to display output in bits/sec or bytes/sec. (default is bits)</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>bits/sec</name>
+ <value>bits</value>
+ </option>
+ <option>
+ <name>bytes/sec</name>
+ <value>bytes</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Interval</fielddescr>
+ <fieldname>interval</fieldname>
+ <description>Enter the desired interval between bandwidth, jitter and loss reports here. (default is 0 for no periodic reports)</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Buffer length</fielddescr>
+ <fieldname>length</fieldname>
+ <description>Enter the length of buffers to read or write here. (default 8KB for TCP, 1470B for UDP)</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Socket buffer bize</fielddescr>
+ <fieldname>window</fieldname>
+ <description>Enter the desired socket buffer size, if needed.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>UDP Bandwidth</fielddescr>
+ <fieldname>udpbandwidth</fieldname>
+ <description>Enter the UDP bandwidth to send at in bits/sec. (default is 1Mbit/sec)</description>
+ <type>input</type>
+ </field>
+ </fields>
+ <custom_add_php_command>
+ mwexec("killall iperf");
+ $iperf_options = "";
+ if($_POST['protocol'] == "udp") $iperf_options .= " -u";
+ if($_POST['format'] == "bytes") $iperf_options .= " -f A";
+ if($_POST['interval'] != "") $iperf_options .= " -i {$_POST['interval']}";
+ if($_POST['length'] != "") $iperf_options .= " -l {$_POST['length']}";
+ if($_POST['window'] != "") $iperf_options .= " -w {$_POST['window']}";
+ if($_POST['udpbandwidth'] != "") $iperf_options .= " -b {$_POST['udpbandwidth']}";
+ if($_POST['port'] != "") $iperf_options .= " -p {$_POST['port']}";
+ $iperf_options .= " -c {$_POST['hostname']}";
+ system("/usr/local/bin/iperf" . $iperf_options);
+ </custom_add_php_command>
+</packagegui>
+
diff --git a/config/iperfserver.xml b/config/iperfserver.xml
new file mode 100644
index 00000000..40d1964b
--- /dev/null
+++ b/config/iperfserver.xml
@@ -0,0 +1,141 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>iperf</name>
+ <version>1.7.0</version>
+ <title>iperf: Server</title>
+ <preoutput>yes</preoutput>
+ <donotsave>true</donotsave>
+ <menu>
+ <name>iperf</name>
+ <tooltiptext>Run iperf in client or server mode.</tooltiptext>
+ <section>Diagnostics</section>
+ <configfile>iperf.xml</configfile>
+ </menu>
+ <tabs>
+ <tab>
+ <text>Client</text>
+ <url>/pkg_edit.php?xml=iperf.xml</url>
+ </tab>
+ <tab>
+ <text>Server</text>
+ <url>/pkg_edit.php?xml=iperfserver.xml</url>
+ <active/>
+ </tab>
+ </tabs>
+ <fields>
+ <field>
+ <fielddescr>Port</fielddescr>
+ <fieldname>port</fieldname>
+ <description>Enter the port that iperf will listen for connections on. (default 5001)</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Protocol</fielddescr>
+ <fieldname>protocol</fieldname>
+ <description>Choose whether to use TCP or UDP here. (default is TCP)</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>TCP</name>
+ <value>tcp</value>
+ </option>
+ <option>
+ <name>UDP</name>
+ <value>udp</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Output format</fielddescr>
+ <fieldname>format</fieldname>
+ <description>Choose to display output in bits/sec or bytes/sec. (default is bits)</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>bits/sec</name>
+ <value>bits</value>
+ </option>
+ <option>
+ <name>bytes/sec</name>
+ <value>bytes</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Interval</fielddescr>
+ <fieldname>interval</fieldname>
+ <description>Enter the desired interval between bandwidth, jitter and loss reports here. (default is 0 for no periodic reports)</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Buffer length</fielddescr>
+ <fieldname>length</fieldname>
+ <description>Enter the length of buffers to read or write here. (default 8KB for TCP, 1470B for UDP)</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Socket buffer bize</fielddescr>
+ <fieldname>window</fieldname>
+ <description>Enter the desired socket buffer size, if needed.</description>
+ <type>input</type>
+ </field>
+ </fields>
+ <custom_add_php_command>
+ mwexec("killall iperf");
+ $iperf_options = "";
+ if($_POST['protocol'] == "udp") $iperf_options .= " -u";
+ if($_POST['format'] == "bytes") $iperf_options .= " -f A";
+ if($_POST['interval'] != "") $iperf_options .= " -i {$_POST['interval']}";
+ if($_POST['length'] != "") $iperf_options .= " -l {$_POST['length']}";
+ if($_POST['window'] != "") $iperf_options .= " -w {$_POST['window']}";
+ if($_POST['port'] != "") $iperf_options .= " -p {$_POST['port']}";
+ $iperf_options .= " -s";
+ system("/usr/local/bin/iperf" . $iperf_options);
+ </custom_add_php_command>
+</packagegui>
+
diff --git a/config/lcdproc/lcdproc.inc b/config/lcdproc/lcdproc.inc
new file mode 100644
index 00000000..b296b841
--- /dev/null
+++ b/config/lcdproc/lcdproc.inc
@@ -0,0 +1,363 @@
+<?php
+/* $Id$ */
+/*
+ lcdproc.inc
+ Copyright (C) 2007 Seth Mos <seth.mos@xs4all.nl>
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+ require_once("config.inc");
+ require_once("functions.inc");
+
+ /* LCDproc */
+ define('LCDPROC_RCFILE', '/usr/local/etc/rc.d/lcdproc.sh');
+ define('LCDPROC_CLIENT', '/tmp/lcdclient.sh');
+ define('LCDPROC_CONFIG','/usr/local/etc/LCDd.conf');
+ define('LCDPROC_HOST','localhost');
+ define('LCDPROC_PORT','13666');
+
+ function lcdproc_notice ($msg) { syslog(LOG_NOTICE, "lcdproc: {$msg}"); }
+ function lcdproc_warn ($msg) { syslog(LOG_WARNING, "lcdproc: {$msg}"); }
+
+ function lcdproc_action ($action) {
+ if (file_exists(LCDPROC_RCFILE))
+ mwexec(LCDPROC_RCFILE.' '.$action);
+ }
+
+ function lcdproc_running () {
+ if((int)exec('pgrep LCDd | wc -l') > 0)
+ return true;
+ return false;
+ }
+
+ function lcdproc_write_config($file, $text) {
+ $handle = fopen($file, 'w');
+ if(!$handle) {
+ lcdproc_warn("Could not open {$file} for writing.");
+ exit;
+ }
+ fwrite($handle, $text);
+ fclose($handle);
+ }
+
+ function lcdproc_write_script($file, $text) {
+ $handle = fopen($file, 'wx');
+ if(!$handle) {
+ lcdproc_warn("Could not open {$file} for writing.");
+ exit;
+ }
+ fwrite($handle, $text);
+ fclose($handle);
+ chmod($file, 0755);
+ }
+
+ function before_form_lcdproc($pkg) {
+ global $config;
+
+ config_lock();
+
+ config_unlock();
+ }
+
+ function before_form_lcdproc_screens($pkg) {
+ global $config;
+
+ config_lock();
+
+ config_unlock();
+ }
+
+ function validate_form_lcdproc($post, $input_errors) {
+ if($post['comport']) {
+ switch($post['comport']) {
+ case "none":
+ continue;
+ break;
+ case "com2":
+ continue;
+ break;
+ case "ucom1":
+ continue;
+ break;
+ case "ucom2":
+ continue;
+ break;
+ case "lpt1":
+ continue;
+ break;
+ default:
+ $input_errors[] = "The chosen com port is not valid";
+ break;
+ }
+ }
+ if($post['size']) {
+ switch($post['size']) {
+ case "12x1":
+ continue;
+ break;
+ case "12x2":
+ continue;
+ break;
+ case "12x4":
+ continue;
+ break;
+ case "16x1":
+ continue;
+ break;
+ case "16x2":
+ continue;
+ break;
+ case "16x4":
+ continue;
+ break;
+ case "20x1":
+ continue;
+ break;
+ case "20x2":
+ continue;
+ break;
+ case "20x4":
+ continue;
+ break;
+ default:
+ $input_errors[] = "The chosen display size is not valid";
+ break;
+ }
+ }
+ }
+ function validate_form_lcdproc_screens($post, $input_errors) {
+ // No validation required ?!
+ }
+
+ function sync_package_lcdproc_screens() {
+ sync_package_lcdproc();
+ }
+ function sync_package_lcdproc() {
+ global $g;
+ global $config;
+ global $input_errors;
+
+ config_lock();
+
+ $lcdproc_config = $config['installedpackages']['lcdproc']['config'][0];
+ $lcdproc_screens_config = $config['installedpackages']['lcdprocscreens']['config'][0];
+
+ /* since config is written before this file invoked we don't need to read post data */
+ if($lcdproc_config['enable'] && ($lcdproc_config['comport'] != "none")) {
+ switch($lcdproc_config['comport']) {
+ case "com2":
+ $realport = "/dev/cua1";
+ break;
+ case "ucom1":
+ $realport = "/dev/cuaU0";
+ break;
+ case "ucom2":
+ $realport = "/dev/cuaU1";
+ break;
+ case "lpt1":
+ $realport = "/dev/lpt0";
+ break;
+ default:
+ lcdproc_warn("The selected com port is not valid!");
+ return;
+ }
+
+ $config_text = "[server]\n";
+ $config_text .= "Driver={$lcdproc_config[driver]}\n";
+ $config_text .= "Bind=127.0.0.1\n";
+ $config_text .= "Port=13666\n";
+ $config_text .= "ReportLevel=3\n";
+ $config_text .= "ReportToSyslog=yes\n";
+ $config_text .= "WaitTime=5\n";
+ $config_text .= "User=nobody\n";
+ $config_text .= "ServerScreen=no\n";
+ $config_text .= "Foreground=no\n";
+ $config_text .= "DriverPath=/usr/local/lib/lcdproc/\n";
+ $config_text .= "GoodBye=\"Thanks for using\"\n";
+ $config_text .= "GoodBye=\" {$g['product_name']} \"\n";
+ /* FIXME: Specific to the pyramid project */
+ $config_text .= "ToggleRotateKey=Enter\n";
+ $config_text .= "PrevScreenKey=Left\n";
+ $config_text .= "NextScreenKey=Right\n";
+ $config_text .= "ScrollUpKey=Up\n";
+ $config_text .= "ScrollDownKey=Down\n";
+ /* FIXME: pyramid test menu */
+ $config_text .= "[menu]\n";
+ $config_text .= "MenuKey=Escape\n";
+ $config_text .= "EnterKey=Enter\n";
+ $config_text .= "UpKey=Up\n";
+ $config_text .= "DownKey=Down\n";
+
+ /* lcdproc default driver definitions */
+ switch($lcdproc_config[driver]) {
+ case "bayrad":
+ $config_text .= "[{$lcdproc_config['driver']}]\n";
+ $config_text .= "Device={$realport}\n";
+ $config_text .= "Speed=9600\n";
+ break;
+ case "CFontz":
+ $config_text .= "[{$lcdproc_config['driver']}]\n";
+ $config_text .= "Device={$realport}\n";
+ $config_text .= "Size={$lcdproc_config['size']}\n";
+ $config_text .= "Contrast=350\n";
+ $config_text .= "Brightness=1000\n";
+ $config_text .= "OffBrightness=50\n";
+ $config_text .= "Speed=9600\n";
+ $config_text .= "NewFirmware=no\n";
+ $config_text .= "Reboot=no\n";
+ break;
+ case "CFontz633":
+ $config_text .= "[{$lcdproc_config['driver']}]\n";
+ $config_text .= "Device={$realport}\n";
+ $config_text .= "Size={$lcdproc_config['size']}\n";
+ $config_text .= "Contrast=350\n";
+ $config_text .= "Brightness=1000\n";
+ $config_text .= "OffBrightness=50\n";
+ $config_text .= "Speed=19200\n";
+ $config_text .= "NewFirmware=yes\n";
+ $config_text .= "Reboot=yes\n";
+ break;
+ case "CFontzPacket":
+ $config_text .= "[{$lcdproc_config['driver']}]\n";
+ $config_text .= "Device={$realport}\n";
+ $config_text .= "Model=635\n";
+ $config_text .= "Size={$lcdproc_config['size']}\n";
+ $config_text .= "Contrast=350\n";
+ $config_text .= "Brightness=1000\n";
+ $config_text .= "OffBrightness=50\n";
+ $config_text .= "Speed=115200\n";
+ $config_text .= "NewFirmware=yes\n";
+ $config_text .= "Reboot=yes\n";
+ break;
+ case "curses":
+ $config_text .= "[{$lcdproc_config['driver']}]\n";
+ $config_text .= "Foreground=blue\n";
+ $config_text .= "Background=cyan\n";
+ $config_text .= "Backlight=red\n";
+ $config_text .= "Size={$lcdproc_config['size']}\n";
+ $config_text .= "TopLeftX=7\n";
+ $config_text .= "TopLeftY=7\n";
+ $config_text .= "UseACS=no\n";
+ break;
+ case "CwLynx":
+ $config_text .= "[{$lcdproc_config['driver']}]\n";
+ $config_text .= "Model=12232\n";
+ $config_text .= "Device={$realport}\n";
+ $config_text .= "Size={$lcdproc_config['size']}\n";
+ $config_text .= "Speed=19200\n";
+ $config_text .= "Reboot=no\n";
+ break;
+ case "pyramid":
+ $config_text .= "[{$lcdproc_config['driver']}]\n";
+ $config_text .= "Device={$realport}\n";
+ $config_text .= "Size={$lcdproc_config['size']}\n";
+ break;
+ case "ea65":
+ $config_text .= "[{$lcdproc_config['driver']}]\n";
+ $config_text .= "Device={$realport}\n";
+ $config_text .= "OffBrightness=0\n";
+ $config_text .= "Brightness=500\n";
+ break;
+ default:
+ lcdproc_warn("The chosen lcdproc driver is not a valid choice");
+ unset($lcdproc_config[driver]);
+ }
+
+ /* generate rc file start and stop */
+ $client_script = <<<EOD
+#!/bin/sh
+
+# script starts a lcd client and always keeps it active.
+counter=1
+while [ "\$counter" -ne 0 ]
+do
+ # loop the client to drive the display
+ /usr/local/bin/php -f /usr/local/pkg/lcdproc_client.php
+ sleep 1
+done
+
+EOD;
+
+ /* generate rc file start and stop */
+ $stop = <<<EOD
+
+if [ `ps auxw |awk '/LCD[d]/ {print $2}'| wc -l` != 0 ]; then
+ ps auxw |awk '/LCD[d]/ {print $2}'|xargs kill
+ sleep 1
+fi
+if [ `ps auxw |awk '/lcdclient.s[h]/ {print $2}'| wc -l` != 0 ]; then
+ ps auxw |awk '/lcdclient.s[h]/ {print $2}'|xargs kill
+ sleep 1
+fi
+
+EOD;
+ $start = $stop ."\n";
+ $start .= "\t/usr/local/sbin/LCDd -c ". LCDPROC_CONFIG ."\n";
+ $start .= "\t". LCDPROC_CLIENT ." &\n";
+
+ /* write out the configuration */
+ conf_mount_rw();
+ lcdproc_write_script(LCDPROC_CLIENT, $client_script);
+ lcdproc_write_config(LCDPROC_CONFIG, $config_text);
+ write_rcfile(array(
+ 'file' => 'lcdproc.sh',
+ 'start' => $start,
+ 'stop' => $stop
+ ));
+ conf_mount_ro();
+
+ /* if lcdproc not running start it */
+ if(!lcdproc_running()) {
+ lcdproc_notice("Starting service lcdproc");
+ lcdproc_action('start');
+ }
+ /* or restart lcdproc if settings were changed */
+ elseif($_POST['comport']) {
+ lcdproc_notice("Restarting service lcdproc");
+ lcdproc_action('restart');
+ }
+ }
+
+ if((! $lcdproc_config['driver']) || ($lcdproc_config['comport'] == "none")) {
+ /* no parameters user does not want lcdproc running */
+ /* lets stop the service and remove the rc file */
+
+ if(file_exists(LCDPROC_RCFILE)) {
+ if(!$lcdproc_config['enable']) {
+ lcdproc_notice('Stopping service: lcdproc disabled');
+ } else {
+ lcdproc_notice('Stopping service: no com port selected');
+ }
+ lcdproc_action('stop');
+ conf_mount_rw();
+ unlink(LCDPROC_RCFILE);
+ unlink(LCDPROC_CLIENT);
+ unlink(LCDPROC_CONFIG);
+ conf_mount_ro();
+ }
+ }
+ config_unlock();
+ }
+
+?>
diff --git a/config/lcdproc/lcdproc.xml b/config/lcdproc/lcdproc.xml
new file mode 100644
index 00000000..fb097248
--- /dev/null
+++ b/config/lcdproc/lcdproc.xml
@@ -0,0 +1,304 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<packagegui>
+ <title>Services: LCDproc</title>
+ <name>lcdproc</name>
+ <version>0.5.2_1-p11</version>
+ <savetext>Save</savetext>
+ <include_file>/usr/local/pkg/lcdproc.inc</include_file>
+ <tabs>
+ <tab>
+ <text>Server</text>
+ <url>/pkg_edit.php?xml=lcdproc.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Screens</text>
+ <url>/pkg_edit.php?xml=lcdproc_screens.xml&amp;id=0</url>
+ </tab>
+ </tabs>
+ <menu>
+ <name>LCDproc</name>
+ <tooltiptext>Set LCDproc settings such as display driver and com port</tooltiptext>
+ <section>Services</section>
+ <url>/pkg_edit.php?xml=lcdproc.xml&amp;id=0</url>
+ </menu>
+ <additional_files_needed>
+ <item>http://www.pfsense.org/packages/config/lcdproc/lcdproc.inc</item>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ </additional_files_needed>
+ <additional_files_needed>
+ <item>http://www.pfsense.org/packages/config/lcdproc/lcdproc_screens.xml</item>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ </additional_files_needed>
+ <additional_files_needed>
+ <item>http://www.pfsense.org/packages/config/lcdproc/lcdproc_client.php</item>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ </additional_files_needed>
+ <service>
+ <name>lcdproc</name>
+ <rcfile>lcdproc.sh</rcfile>
+ <executable>lcdproc</executable>
+ </service>
+ <fields>
+ <field>
+ <fielddescr>Enable LCDproc</fielddescr>
+ <fieldname>enable</fieldname>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fieldname>comport</fieldname>
+ <fielddescr>Com Port</fielddescr>
+ <description>Set the com port LCDproc should use.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <value>none</value>
+ <name>none</name>
+ </option>
+ <option>
+ <value>com2</value>
+ <name>Serial Com port 2 (/dev/cua1)</name>
+ </option>
+ <option>
+ <value>ucom1</value>
+ <name>USB Com port 1 (/dev/cuaU0)</name>
+ </option>
+ <option>
+ <value>ucom2</value>
+ <name>USB Com port 2 (/dev/cuaU1)</name>
+ </option>
+ <option>
+ <value>lpt1</value>
+ <name>Parallel port 1 (/dev/lpt0)</name>
+ </option>
+ </options>
+ <default_value>ucom1</default_value>
+ </field>
+ <field>
+ <fieldname>size</fieldname>
+ <fielddescr>Display Size</fielddescr>
+ <description>Set the display size lcdproc should use.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <value>12x1</value>
+ <name>1 rows 12 colums</name>
+ </option>
+ <option>
+ <value>12x2</value>
+ <name>2 rows 12 colums</name>
+ </option>
+ <option>
+ <value>12x4</value>
+ <name>4 rows 12 colums</name>
+ </option>
+ <option>
+ <value>16x1</value>
+ <name>1 row 16 colums</name>
+ </option>
+ <option>
+ <value>16x2</value>
+ <name>2 rows 16 colums</name>
+ </option>
+ <option>
+ <value>16x4</value>
+ <name>4 rows 16 colums</name>
+ </option>
+ <option>
+ <value>20x1</value>
+ <name>1 row 20 colums</name>
+ </option>
+ <option>
+ <value>20x2</value>
+ <name>2 rows 20 colums</name>
+ </option>
+ <option>
+ <value>20x4</value>
+ <name>4 rows 20 colums</name>
+ </option>
+ </options>
+ <default_value>16x2</default_value>
+ </field>
+ <field>
+ <fieldname>driver</fieldname>
+ <fielddescr>Driver</fielddescr>
+ <description>Set the LCD driver LCDproc should use.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <value>bayrad</value>
+ <name>bayrad</name>
+ </option>
+ <option>
+ <value>CFontz</value>
+ <name>CrystalFontz</name>
+ </option>
+ <option>
+ <value>CFontz633</value>
+ <name>CrystalFontz 633</name>
+ </option>
+ <option>
+ <value>CFontzPacket</value>
+ <name>CrystalFontz Packet</name>
+ </option>
+ <option>
+ <value>curses</value>
+ <name>curses</name>
+ </option>
+ <option>
+ <value>CwLnx</value>
+ <name>CwLnx</name>
+ </option>
+ <option>
+ <value>ea65</value>
+ <name>ea65</name>
+ </option>
+ <option>
+ <value>EyeBoxOne</value>
+ <name>EyeBoxOne</name>
+ </option>
+ <option>
+ <value>gl5</value>
+ <name>gl5</name>
+ </option>
+ <option>
+ <value>glcdlib</value>
+ <name>glcdlib</name>
+ </option>
+ <option>
+ <value>glk</value>
+ <name>glk</name>
+ </option>
+ <option>
+ <value>hd44780</value>
+ <name>hd44780</name>
+ </option>
+ <option>
+ <value>icp_a106</value>
+ <name>icp_a106</name>
+ </option>
+ <option>
+ <value>imon</value>
+ <name>imon</name>
+ </option>
+ <option>
+ <value>IOWarrior</value>
+ <name>IOWarrior</name>
+ </option>
+ <option>
+ <value>irman</value>
+ <name>irman</name>
+ </option>
+ <option>
+ <value>joy</value>
+ <name>joy</name>
+ </option>
+ <option>
+ <value>lb216</value>
+ <name>lb216</name>
+ </option>
+ <option>
+ <value>lcdm001</value>
+ <name>lcdm001</name>
+ </option>
+ <option>
+ <value>lcterm</value>
+ <name>lcterm</name>
+ </option>
+ <option>
+ <value>lirc</value>
+ <name>lirc</name>
+ </option>
+ <option>
+ <value>MD8800</value>
+ <name>MD8800</name>
+ </option>
+ <option>
+ <value>ms6931</value>
+ <name>ms6931</name>
+ </option>
+ <option>
+ <value>mtc_s16209x</value>
+ <name>mtc_s16209x</name>
+ </option>
+ <option>
+ <value>MtxOrb</value>
+ <name>MtxOrb</name>
+ </option>
+ <option>
+ <value>NoritakeVFD</value>
+ <name>NoritakeVFD</name>
+ </option>
+ <option>
+ <value>picolcd</value>
+ <name>picolcd</name>
+ </option>
+ <option>
+ <value>pyramid</value>
+ <name>pyramid</name>
+ </option>
+ <option>
+ <value>Sed1330</value>
+ <name>Sed1330</name>
+ </option>
+ <option>
+ <value>sed1520</value>
+ <name>sed1520</name>
+ </option>
+ <option>
+ <value>serialpos</value>
+ <name>serialpos</name>
+ </option>
+ <option>
+ <value>serialVFD</value>
+ <name>serialVFD</name>
+ </option>
+ <option>
+ <value>sli</value>
+ <name>sli</name>
+ </option>
+ <option>
+ <value>stv5730</value>
+ <name>stv5730</name>
+ </option>
+ <option>
+ <value>svga</value>
+ <name>svga</name>
+ </option>
+ <option>
+ <value>t6963</value>
+ <name>t6963</name>
+ </option>
+ <option>
+ <value>text</value>
+ <name>text</name>
+ </option>
+ <option>
+ <value>tyan</value>
+ <name>tyan</name>
+ </option>
+ <option>
+ <value>ula200</value>
+ <name>ula200</name>
+ </option>
+ <option>
+ <value>xosd</value>
+ <name>xosd</name>
+ </option>
+ </options>
+ <default_value>pyramid</default_value>
+ </field>
+ </fields>
+ <custom_php_command_before_form>
+ before_form_lcdproc(&amp;$pkg);
+ </custom_php_command_before_form>
+ <custom_php_validation_command>
+ validate_form_lcdproc($_POST, &amp;$input_errors);
+ </custom_php_validation_command>
+ <custom_php_resync_config_command>
+ sync_package_lcdproc();
+ </custom_php_resync_config_command>
+</packagegui>
diff --git a/config/lcdproc/lcdproc_client.php b/config/lcdproc/lcdproc_client.php
new file mode 100644
index 00000000..b26767c3
--- /dev/null
+++ b/config/lcdproc/lcdproc_client.php
@@ -0,0 +1,525 @@
+<?php
+/* $Id$ */
+/*
+ lcdproc_client.php
+ Copyright (C) 2007 Seth Mos <seth.mos@xs4all.nl>
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+ // require_once("config.inc");
+ // require_once("functions.inc");
+ require_once("/usr/local/pkg/lcdproc.inc");
+ require_once("/usr/local/www/includes/functions.inc.php");
+
+ function get_uptime_stats() {
+ exec("/usr/bin/uptime", $output, $ret);
+ if(stristr($output[0], "day")) {
+ $temp = explode(" ", $output[0]);
+ $status = "$temp[2] $temp[3] $temp[4] $temp[5] $temp[6] $temp[7] ". substr($temp[8], 0, -1);
+ } else {
+ $temp = explode(" ", $output[0]);
+ $status = "$temp[2] $temp[3] $temp[4] $temp[5] $temp[6] ". substr($temp[7], 0, -1);
+ }
+ return($status);
+ }
+
+ function get_loadavg_stats() {
+ exec("/usr/bin/uptime", $output, $ret);
+ if(stristr($output[0], "day")) {
+ $temp = explode(" ", $output[0]);
+ $status = "$temp[11] $temp[12] $temp[13]";
+ } else {
+ $temp = explode(" ", $output[0]);
+ $status = "$temp[10] $temp[11] $temp[12]";
+ }
+ return($status);
+ }
+
+ function get_interfaces_stats() {
+ global $g;
+ global $config;
+ $ifstatus = array();
+ $i = 0;
+ $ifdescrs = array('wan' => 'WAN', 'lan' => 'LAN');
+ for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++) {
+ $ifdescrs['opt' . $j] = $config['interfaces']['opt' . $j]['descr'];
+ }
+ foreach ($ifdescrs as $ifdescr => $ifname){
+ $ifinfo = get_interface_info($ifdescr);
+ if($ifinfo['status'] == "up") {
+ $online = "Up";
+ } else {
+ $online = "Down";
+ }
+ if(!empty($ifinfo['ipaddr'])) {
+ $ip = htmlspecialchars($ifinfo['ipaddr']);
+ } else {
+ $ip = "-";
+ }
+ $ifstatus[] = htmlspecialchars($ifname) ." [$online]";
+ }
+ $status = " ". implode(", ", $ifstatus);
+ return($status);
+ }
+
+ function get_slbd_stats() {
+ global $g;
+ global $config;
+
+ if (!is_array($config['load_balancer']['lbpool'])) {
+ $config['load_balancer']['lbpool'] = array();
+ }
+ $a_pool = &$config['load_balancer']['lbpool'];
+
+ $slbd_logfile = "{$g['varlog_path']}/slbd.log";
+
+ $nentries = $config['syslog']['nentries'];
+ if (!$nentries)
+ $nentries = 50;
+
+ $now = time();
+ $year = date("Y");
+ $pstatus = "";
+ $i = 0;
+ foreach ($a_pool as $vipent) {
+ $pstatus[] = "{$vipent['name']}";
+ if ($vipent['type'] == "gateway") {
+ $poolfile = "{$g['tmp_path']}/{$vipent['name']}.pool";
+ if(file_exists("$poolfile")) {
+ $poolstatus = file_get_contents("$poolfile");
+ } else {
+ continue;
+ }
+ foreach ((array) $vipent['servers'] as $server) {
+ $lastchange = "";
+ $svr = split("\|", $server);
+ $monitorip = $svr[1];
+ if(stristr($poolstatus, $monitorip)) {
+ $online = "Up";
+ } else {
+ $online = "Down";
+ }
+ $pstatus[] = strtoupper($svr[0]) ." [{$online}]";
+ }
+ } else {
+ $pstatus[] = "{$vipent['monitor']}";
+ }
+ }
+ if(count($a_pool) == 0) {
+ $pstatus[] = "Disabled";
+ }
+ $status = implode(", ", $pstatus);
+ return($status);
+ }
+
+ function get_carp_stats () {
+ global $g;
+ global $config;
+
+ if(is_array($config['virtualip']['vip'])) {
+ $carpint = 0;
+ $initcount = 0;
+ $mastercount = 0;
+ $backupcount = 0;
+ foreach($config['virtualip']['vip'] as $carp) {
+ if ($carp['mode'] != "carp") {
+ continue;
+ }
+ $ipaddress = $carp['subnet'];
+ $password = $carp['password'];
+ $netmask = $carp['subnet_bits'];
+ $vhid = $carp['vhid'];
+ $advskew = $carp['advskew'];
+ $carp_int = find_carp_interface($ipaddress);
+ $status = get_carp_interface_status($carp_int);
+ switch($status) {
+ case "MASTER":
+ $mastercount++;
+ break;
+ case "BACKUP":
+ $backupcount++;
+ break;
+ case "INIT":
+ $initcount++;
+ break;
+ }
+ }
+ $status = "M/B/I {$mastercount}/{$backupcount}/{$initcount}";
+ } else {
+ $status = "CARP Disabled";
+ }
+ return($status);
+ }
+
+ function get_ipsec_tunnel_sad() {
+ /* query SAD */
+ $fd = @popen("/sbin/setkey -D", "r");
+ $sad = array();
+ if ($fd) {
+ while (!feof($fd)) {
+ $line = chop(fgets($fd));
+ if (!$line)
+ continue;
+ if ($line == "No SAD entries.")
+ break;
+ if ($line[0] != "\t") {
+ if (is_array($cursa))
+ $sad[] = $cursa;
+ $cursa = array();
+ list($cursa['src'],$cursa['dst']) = explode(" ", $line);
+ $i = 0;
+ } else {
+ $linea = explode(" ", trim($line));
+ if ($i == 1) {
+ $cursa['proto'] = $linea[0];
+ $cursa['spi'] = substr($linea[2], strpos($linea[2], "x")+1, -1);
+ } else if ($i == 2) {
+ $cursa['ealgo'] = $linea[1];
+ } else if ($i == 3) {
+ $cursa['aalgo'] = $linea[1];
+ }
+ }
+ $i++;
+ }
+ if (is_array($cursa) && count($cursa))
+ $sad[] = $cursa;
+ pclose($fd);
+ }
+ return($sad);
+ }
+
+ function get_ipsec_tunnel_src($tunnel) {
+ global $g, $config, $sad;
+ $if = "WAN";
+ if ($tunnel['interface']) {
+ $if = $tunnel['interface'];
+ $realinterface = convert_friendly_interface_to_real_interface_name($if);
+ $interfaceip = find_interface_ip($realinterface);
+ }
+ return $interfaceip;
+ }
+
+ function output_ipsec_tunnel_status($tunnel) {
+ global $g, $config, $sad;
+ $if = "WAN";
+ $interfaceip = get_ipsec_tunnel_src($tunnel);
+ $foundsrc = false;
+ $founddst = false;
+
+ if(!is_array($sad)) {
+ /* we have no sad array, bail */
+ return(false);
+ }
+ foreach($sad as $sa) {
+ if($sa['src'] == $interfaceip)
+ $foundsrc = true;
+ if($sa['dst'] == $tunnel['remote-gateway'])
+ $founddst = true;
+ }
+ if($foundsrc && $founddst) {
+ /* tunnel is up */
+ $iconfn = "pass";
+ return(true);
+ } else {
+ /* tunnel is down */
+ $iconfn = "reject";
+ return(false);
+ }
+ }
+
+ function get_ipsec_stats() {
+ global $g, $config, $sad;
+ $sad = array();
+ $sad = get_ipsec_tunnel_sad();
+
+ $activecounter = 0;
+ $inactivecounter = 0;
+
+ foreach ($config['ipsec']['tunnel'] as $tunnel){
+ $ipsecstatus = false;
+
+ $tun_disabled = "false";
+ $foundsrc = false;
+ $founddst = false;
+
+ if (isset($tunnel['disabled'])) {
+ $tun_disabled = "true";
+ continue;
+ }
+
+ if(output_ipsec_tunnel_status($tunnel)) {
+ /* tunnel is up */
+ $iconfn = "true";
+ $activecounter++;
+ } else {
+ /* tunnel is down */
+ $iconfn = "false";
+ $inactivecounter++;
+ }
+
+ }
+
+ if (is_array($config['ipsec']['tunnel'])) {
+ $status = "Up/Down $activecounter/$inactivecounter";
+ } else {
+ $status = "IPSEC Disabled";
+ }
+ return($status);
+ }
+
+
+ /* Define functions */
+ function send_lcd_commands($lcd, $lcd_cmds) {
+ if(!is_array($lcd_cmds) || (empty($lcd_cmds))) {
+ lcdproc_warn("Failed to interpret lcd commands");
+ return;
+ }
+ foreach($lcd_cmds as $lcd_cmd) {
+ $cmd_output = "";
+ if(! fwrite($lcd, "$lcd_cmd\n")) {
+ lcdproc_warn("Connection to LCDd process lost $errstr ($errno)");
+ die();
+ }
+ $cmd_output = fgets($lcd, 256);
+ // FIXME: add support for interpreting menu commands here.
+ if(preg_match("/^huh?/", $cmd_output)) {
+ lcdproc_notice("LCDd output: \"$cmd_output\". Executed \"$lcd_cmd\"");
+ }
+ }
+ }
+
+ function build_interface($lcd) {
+ global $g;
+ global $config;
+ $lcdproc_screens_config = $config['installedpackages']['lcdprocscreens']['config'][0];
+
+ $lcd_cmds = array();
+ $lcd_cmds[] = "hello";
+ $lcd_cmds[] = "client_set name pfSense";
+ $lcd_cmds[] = "screen_add welcome_scr";
+ $lcd_cmds[] = "screen_set welcome_scr heartbeat off";
+ $lcd_cmds[] = "screen_set welcome_scr name welcome";
+ $lcd_cmds[] = "screen_set $name duration 80";
+ $lcd_cmds[] = "widget_add welcome_scr title_wdgt title";
+ $lcd_cmds[] = "widget_add welcome_scr text_wdgt scroller";
+
+ /* process screens to display */
+ if(is_array($lcdproc_screens_config)) {
+ foreach($lcdproc_screens_config as $name => $screen) {
+ if($screen == "on") {
+ switch($name) {
+ case "scr_time":
+ $lcd_cmds[] = "screen_add $name";
+ $lcd_cmds[] = "screen_set $name heartbeat off";
+ $lcd_cmds[] = "screen_set $name name $name";
+ $lcd_cmds[] = "screen_set $name duration 40";
+ $lcd_cmds[] = "widget_add $name title_wdgt string";
+ $lcd_cmds[] = "widget_add $name text_wdgt scroller";
+ break;
+ case "scr_uptime":
+ $lcd_cmds[] = "screen_add $name";
+ $lcd_cmds[] = "screen_set $name heartbeat off";
+ $lcd_cmds[] = "screen_set $name name $name";
+ $lcd_cmds[] = "screen_set $name duration 80";
+ $lcd_cmds[] = "widget_add $name title_wdgt string";
+ $lcd_cmds[] = "widget_add $name text_wdgt scroller";
+ break;
+ case "scr_hostname":
+ $lcd_cmds[] = "screen_add $name";
+ $lcd_cmds[] = "screen_set $name heartbeat off";
+ $lcd_cmds[] = "screen_set $name name $name";
+ $lcd_cmds[] = "screen_set $name duration 80";
+ $lcd_cmds[] = "widget_add $name title_wdgt string";
+ $lcd_cmds[] = "widget_add $name text_wdgt scroller";
+ break;
+ case "scr_system":
+ $lcd_cmds[] = "screen_add $name";
+ $lcd_cmds[] = "screen_set $name heartbeat off";
+ $lcd_cmds[] = "screen_set $name name $name";
+ $lcd_cmds[] = "screen_set $name duration 80";
+ $lcd_cmds[] = "widget_add $name title_wdgt string";
+ $lcd_cmds[] = "widget_add $name text_wdgt scroller";
+ break;
+ case "scr_disk":
+ $lcd_cmds[] = "screen_add $name";
+ $lcd_cmds[] = "screen_set $name heartbeat off";
+ $lcd_cmds[] = "screen_set $name name $name";
+ $lcd_cmds[] = "screen_set $name duration 80";
+ $lcd_cmds[] = "widget_add $name title_wdgt string";
+ $lcd_cmds[] = "widget_add $name text_wdgt scroller";
+ break;
+ case "scr_load":
+ $lcd_cmds[] = "screen_add $name";
+ $lcd_cmds[] = "screen_set $name heartbeat off";
+ $lcd_cmds[] = "screen_set $name name $name";
+ $lcd_cmds[] = "screen_set $name duration 80";
+ $lcd_cmds[] = "widget_add $name title_wdgt string";
+ $lcd_cmds[] = "widget_add $name text_wdgt scroller";
+ break;
+ case "scr_states":
+ $lcd_cmds[] = "screen_add $name";
+ $lcd_cmds[] = "screen_set $name heartbeat off";
+ $lcd_cmds[] = "screen_set $name name $name";
+ $lcd_cmds[] = "screen_set $name duration 80";
+ $lcd_cmds[] = "widget_add $name title_wdgt string";
+ $lcd_cmds[] = "widget_add $name text_wdgt scroller";
+ break;
+ case "scr_carp":
+ $lcd_cmds[] = "screen_add $name";
+ $lcd_cmds[] = "screen_set $name heartbeat off";
+ $lcd_cmds[] = "screen_set $name name $name";
+ $lcd_cmds[] = "screen_set $name duration 80";
+ $lcd_cmds[] = "widget_add $name title_wdgt string";
+ $lcd_cmds[] = "widget_add $name text_wdgt scroller";
+ break;
+ case "scr_ipsec":
+ $lcd_cmds[] = "screen_add $name";
+ $lcd_cmds[] = "screen_set $name heartbeat off";
+ $lcd_cmds[] = "screen_set $name name $name";
+ $lcd_cmds[] = "screen_set $name duration 80";
+ $lcd_cmds[] = "widget_add $name title_wdgt string";
+ $lcd_cmds[] = "widget_add $name text_wdgt scroller";
+ break;
+ case "scr_slbd":
+ $lcd_cmds[] = "screen_add $name";
+ $lcd_cmds[] = "screen_set $name heartbeat off";
+ $lcd_cmds[] = "screen_set $name name $name";
+ $lcd_cmds[] = "screen_set $name duration 80";
+ $lcd_cmds[] = "widget_add $name title_wdgt string";
+ $lcd_cmds[] = "widget_add $name text_wdgt scroller";
+ break;
+ case "scr_interfaces":
+ $lcd_cmds[] = "screen_add $name";
+ $lcd_cmds[] = "screen_set $name heartbeat off";
+ $lcd_cmds[] = "screen_set $name name $name";
+ $lcd_cmds[] = "screen_set $name duration 80";
+ $lcd_cmds[] = "widget_add $name title_wdgt string";
+ $lcd_cmds[] = "widget_add $name text_wdgt scroller";
+ break;
+ }
+ }
+ }
+ }
+ send_lcd_commands($lcd, $lcd_cmds);
+ }
+
+ function loop_status($lcd) {
+ global $g;
+ global $config;
+ $lcdproc_screens_config = $config['installedpackages']['lcdprocscreens']['config'][0];
+ if(empty($g['product_name'])) {
+ $g['product_name'] = "pfSense";
+ }
+ $version = @file_get_contents("/etc/version");
+ $version = trim($version);
+ /* keep a counter to see how many times we can loop */
+ $i = 1;
+ while($i) {
+ $lcd_cmds = array();
+ $lcd_cmds[] = "widget_set welcome_scr title_wdgt \"Welcome to\"";
+ $lcd_cmds[] = "widget_set welcome_scr text_wdgt 1 2 16 2 h 2 \"{$g['product_name']} {$version}\"";
+
+ /* process screens to display */
+ foreach((array) $lcdproc_screens_config as $name => $screen) {
+ if($screen != "on") {
+ continue;
+ }
+ switch($name) {
+ case "scr_time":
+ $time = date ("n/j/Y H:i");
+ $lcd_cmds[] = "widget_set $name title_wdgt 1 1 \"+ System Time\"";
+ $lcd_cmds[] = "widget_set $name text_wdgt 1 2 16 2 h 2 \"{$time}\"";
+ break;
+ case "scr_uptime":
+ $uptime = get_uptime_stats();
+ $lcd_cmds[] = "widget_set $name title_wdgt 1 1 \"+ System Uptime\"";
+ $lcd_cmds[] = "widget_set $name text_wdgt 1 2 16 2 h 2 \"{$uptime}\"";
+ break;
+ case "scr_hostname":
+ exec("/bin/hostname", $output, $ret);
+ $hostname = $output[0];
+ $lcd_cmds[] = "widget_set $name title_wdgt 1 1 \"+ System Name\"";
+ $lcd_cmds[] = "widget_set $name text_wdgt 1 2 16 2 h 2 \"{$hostname}\"";
+ break;
+ case "scr_system":
+ $processor = cpu_usage();
+ $memory = mem_usage();
+ $lcd_cmds[] = "widget_set $name title_wdgt 1 1 \"+ System Stats\"";
+ $lcd_cmds[] = "widget_set $name text_wdgt 1 2 16 2 h 2 \"CPU {$processor}%, Mem {$memory}%\"";
+ break;
+ case "scr_disk":
+ $disk = disk_usage();
+ $lcd_cmds[] = "widget_set $name title_wdgt 1 1 \"+ Disk Use\"";
+ $lcd_cmds[] = "widget_set $name text_wdgt 1 2 16 2 h 2 \"Disk {$disk}%\"";
+ break;
+ case "scr_load":
+ $loadavg = get_loadavg_stats();
+ $lcd_cmds[] = "widget_set $name title_wdgt 1 1 \"+ Load Averages\"";
+ $lcd_cmds[] = "widget_set $name text_wdgt 1 2 16 2 h 2 \"{$loadavg}\"";
+ break;
+ case "scr_states":
+ $states = get_pfstate();
+ $lcd_cmds[] = "widget_set $name title_wdgt 1 1 \"+ Traffic States\"";
+ $lcd_cmds[] = "widget_set $name text_wdgt 1 2 16 2 h 2 \"Curr/Max {$states}\"";
+ break;
+ case "scr_carp":
+ $carp = get_carp_stats();
+ $lcd_cmds[] = "widget_set $name title_wdgt 1 1 \"+ CARP State\"";
+ $lcd_cmds[] = "widget_set $name text_wdgt 1 2 16 2 h 2 \"{$carp}\"";
+ break;
+ case "scr_ipsec":
+ $ipsec = get_ipsec_stats();
+ $lcd_cmds[] = "widget_set $name title_wdgt 1 1 \"+ IPsec Tunnels\"";
+ $lcd_cmds[] = "widget_set $name text_wdgt 1 2 16 2 h 2 \"{$ipsec}\"";
+ break;
+ case "scr_slbd":
+ $slbd = get_slbd_stats();
+ $lcd_cmds[] = "widget_set $name title_wdgt 1 1 \"+ Load Balancer\"";
+ $lcd_cmds[] = "widget_set $name text_wdgt 1 2 16 2 h 2 \"{$slbd}\"";
+ break;
+ case "scr_interfaces":
+ $interfaces = get_interfaces_stats();
+ $lcd_cmds[] = "widget_set $name title_wdgt 1 1 \"+ Interfaces\"";
+ $lcd_cmds[] = "widget_set $name text_wdgt 1 2 16 2 h 2 \"{$interfaces}\"";
+ break;
+ }
+ }
+
+ send_lcd_commands($lcd, $lcd_cmds);
+ sleep(5);
+ $i++;
+ }
+ }
+
+ /* Connect to the LCDd port and interface with the LCD */
+ $lcd = fsockopen(LCDPROC_HOST, LCDPROC_PORT, $errno, $errstr, 10);
+ if (!$lcd) {
+ lcdproc_warn("Failed to connect to LCDd process $errstr ($errno)");
+ } else {
+ build_interface($lcd);
+ loop_status($lcd);
+ /* loop exited? Close fd and wait for the script to kick in again */
+ fclose($lcd);
+ }
+?>
diff --git a/config/lcdproc/lcdproc_screens.xml b/config/lcdproc/lcdproc_screens.xml
new file mode 100644
index 00000000..5c43ab61
--- /dev/null
+++ b/config/lcdproc/lcdproc_screens.xml
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<packagegui>
+ <title>Services: LCDproc: Screens</title>
+ <name>lcdproc_screens</name>
+ <version>0.5.2_1-p9</version>
+ <savetext>Save</savetext>
+ <include_file>/usr/local/pkg/lcdproc.inc</include_file>
+ <tabs>
+ <tab>
+ <text>Server</text>
+ <url>/pkg_edit.php?xml=lcdproc.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Screens</text>
+ <url>/pkg_edit.php?xml=lcdproc_screens.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ </tabs>
+ <menu>
+ <name>LCDproc</name>
+ <tooltiptext>Set LCDproc settings such as display driver and com port</tooltiptext>
+ <section>Services</section>
+ <url>/pkg_edit.php?xml=lcdproc.xml&amp;id=0</url>
+ </menu>
+ <fields>
+ <field>
+ <fielddescr>Enable Time</fielddescr>
+ <fieldname>scr_time</fieldname>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Enable Uptime</fielddescr>
+ <fieldname>scr_uptime</fieldname>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Enable Hostname</fielddescr>
+ <fieldname>scr_hostname</fieldname>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Enable System</fielddescr>
+ <fieldname>scr_system</fieldname>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Enable Disk</fielddescr>
+ <fieldname>scr_disk</fieldname>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Enable Load</fielddescr>
+ <fieldname>scr_load</fieldname>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Enable States</fielddescr>
+ <fieldname>scr_states</fieldname>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Enable Carp</fielddescr>
+ <fieldname>scr_carp</fieldname>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Enable IPsec</fielddescr>
+ <fieldname>scr_ipsec</fieldname>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Enable Load Balancer</fielddescr>
+ <fieldname>scr_slbd</fieldname>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Enable Interfaces</fielddescr>
+ <fieldname>scr_interfaces</fieldname>
+ <type>checkbox</type>
+ </field>
+ </fields>
+ <custom_php_command_before_form>
+ before_form_lcdproc_screens(&amp;$pkg);
+ </custom_php_command_before_form>
+ <custom_php_validation_command>
+ validate_form_lcdproc_screens($_POST, &amp;$input_errors);
+ </custom_php_validation_command>
+ <custom_php_resync_config_command>
+ sync_package_lcdproc_screens();
+ </custom_php_resync_config_command>
+</packagegui>
diff --git a/config/lightsquid/.project b/config/lightsquid/.project
new file mode 100644
index 00000000..7e6f47b6
--- /dev/null
+++ b/config/lightsquid/.project
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>lightsquid</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ </buildSpec>
+ <natures>
+ </natures>
+</projectDescription>
diff --git a/config/lightsquid/.settings/org.eclipse.ltk.core.refactoring.prefs b/config/lightsquid/.settings/org.eclipse.ltk.core.refactoring.prefs
new file mode 100644
index 00000000..123de66a
--- /dev/null
+++ b/config/lightsquid/.settings/org.eclipse.ltk.core.refactoring.prefs
@@ -0,0 +1,3 @@
+#Fri Jun 22 21:59:25 MSD 2007
+eclipse.preferences.version=1
+org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false
diff --git a/config/lightsquid/lightsquid.inc b/config/lightsquid/lightsquid.inc
new file mode 100644
index 00000000..de06bbf0
--- /dev/null
+++ b/config/lightsquid/lightsquid.inc
@@ -0,0 +1,432 @@
+<?php
+/*
+ lightsquid.inc
+ Copyright (C) 2006 Serg Dvorianceev
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require_once('globals.inc');
+require_once('config.inc');
+require_once('util.inc');
+require_once('pfsense-utils.inc');
+require_once('pkg-utils.inc');
+require_once('filter.inc');
+require_once('service-utils.inc');
+require_once('squid.inc');
+
+define ('CMD_PKGDELETE', 'pkg_delete lightsquid-1.7.1');
+
+// enable GUI debug
+define('LS_GUI_DEBUG', 'on');
+define('LS_LOG_FILE', '/tmp/lightsquid_gui.log');
+
+// configuration settings !-- CHECK THIS --!
+define('LS_CONFIGPATH', '/usr/local/etc/lightsquid');
+define('LS_CONFIGFILE', 'lightsquid.cfg');
+define('LS_CONFIGFILE_DIST', 'lightsquid.cfg.dist');
+define('LS_WWWPATH', '/usr/local/www/lightsquid');
+define('LS_TEMPLATEPATH', '/usr/local/www/lightsquid/tpl');
+define('LS_LANGPATH', '/usr/local/share/lightsquid/lang');
+define('LS_REPORTPATH', '/var/lightsquid/report');
+define('LS_SQUIDLOGPATH', '/var/squid/log');
+define('LS_SQUIDLOG', 'access.log');
+define('LS_IP2NAMEPATH', '/usr/local/libexec/lightsquid');
+
+define('CRONTAB_FILE', '/var/cron/tabs/root');
+define('CRONTAB_LS_TEMPLATE', '/usr/bin/perl /usr/local/www/lightsquid/lightparser.pl');
+define('CRONTAB_LS_JOBKEY', '/lightparser.pl');
+define('CRONTAB_SQUID_TEMPLATE', '/usr/local/sbin/squid -k rotate > /dev/null');
+define('CRONTAB_SQUID_JOBKEY', '/squid -k rotate');
+
+// default values
+define('LS_DEF_IP2NAME', 'dns');
+define('LS_DEF_SQUIDLOGTYPE', '0');
+define('LS_DEF_SKIPURL', 'zzz\.zzz');
+define('LS_DEF_LANG', 'eng');
+define('LS_DEF_TEMPLATE', 'base');
+define('LS_DEF_BARCOLOR', 'orange');
+
+// variable names
+define('LS_VAR_CFGPATH', 'cfgpath');
+define('LS_VAR_LOGPATH', 'logpath');
+define('LS_VAR_TPLPATH', 'tplpath');
+define('LS_VAR_LANGPATH', 'langpath');
+define('LS_VAR_LANG', 'lang');
+define('LS_VAR_REPORTPATH', 'reportpath');
+define('LS_VAR_SQUIDLOGTYPE', 'squidlogtype');
+define('LS_VAR_SKIPURL', 'skipurl');
+define('LS_VAR_IP2NAMEPATH', 'ip2namepath');
+define('LS_VAR_IP2NAME', 'ip2name');
+define('LS_VAR_TEMPLATE', 'templatename');
+define('LS_VAR_BARCOLOR', 'barcolor');
+
+// xml variables
+define('LS_XML_LANG', 'lightsquid_lang');
+define('LS_XML_SKIPURL', 'lightsquid_skipurl');
+define('LS_XML_IP2NAME', 'lightsquid_ip2name');
+define('LS_XML_TEMPLATE', 'lightsquid_template');
+define('LS_XML_BARCOLOR', 'lightsquid_barcolor');
+define('LS_XML_SHEDULERTIME', 'lightsquid_refreshsheduler_time');
+define('LS_XML_SQUID_SHEDULERTIME', 'lightsquid_squidrotatelog_sheduler_time');
+
+function lightsquid_install() {
+ update_log("lightsquid_install: started");
+ // create lightsquid report catalog
+ if (!file_exists(LS_REPORTPATH)) {
+ update_log("lightsquid_install: Create report dir " . LS_REPORTPATH);
+ mwexec("mkdir -p " . LS_REPORTPATH);
+ }
+
+ // install templates
+ $lstpl_file = "/var/tmp/lightsquid_tpl.tbz";
+ if (file_exists($lstpl_file)) {
+ mwexec("tar zxvf $lstpl_file -C " . LS_TEMPLATEPATH);
+ update_log("lightsquid_install: Install templates from $lstpl_file");
+ }
+
+ # check perl
+ if (!file_exists("/usr/bin/perl"))
+ mwexec("ln -s /usr/local/bin/perl /usr/bin/perl");
+
+ update_log("lightsquid_install: stopped");
+}
+
+function lightsquid_deinstall() {
+ update_log("lightsquid_deinstall: started");
+
+ // delete cron task's
+ ls_setup_cron("lightsquid_squid_rotate", "", "", false);
+ ls_setup_cron("lightsquid_parser", "", "", false);
+ // control shoot to head :)
+# mwexec(CMD_PKGDELETE);
+ // remove '/usr/local/www/lightsquid' dir - any time can't be removed by templates
+# if (file_exists(LS_WWWPATH))
+# mwexec("rm -rf " . LS_WWWPATH);
+
+ update_log("lightsquid_deinstall: stopped");
+}
+
+function lightsquid_resync() {
+ global $config;
+ $tm = '';
+ $tm_squid = '';
+
+ # check perl
+ if (!file_exists("/usr/bin/perl"))
+ mwexec("ln -s /usr/local/bin/perl /usr/bin/perl");
+
+ // debug
+ $light_test = array();
+ if (($_POST['Submit'] === 'Save') or !isset($_POST['Submit'])) {
+ $lsconf_var = array();
+
+ // variables for update
+ $lsconf_var[LS_VAR_CFGPATH] = "\"" . LS_CONFIGPATH . "\"";
+ $lsconf_var[LS_VAR_LOGPATH] = "\"" . LS_SQUIDLOGPATH . "\"";
+ $lsconf_var[LS_VAR_TPLPATH] = "\"" . LS_TEMPLATEPATH . "\"";
+ $lsconf_var[LS_VAR_LANGPATH] = "\"" . LS_LANGPATH . "\"";
+ $lsconf_var[LS_VAR_REPORTPATH] = "\"" . LS_REPORTPATH . "\"";
+ $lsconf_var[LS_VAR_IP2NAMEPATH] = "\"" . LS_IP2NAMEPATH . "\"";
+
+ $lsconf_var[LS_VAR_LANG] = "\"" . LS_DEF_LANG . "\"";
+ $lsconf_var[LS_VAR_TEMPLATE] = "\"" . LS_DEF_TEMPLATE . "\"";
+ $lsconf_var[LS_VAR_IP2NAME] = "\"" . LS_DEF_IP2NAME . "\"";
+ $lsconf_var[LS_VAR_SKIPURL] = "\"" . LS_DEF_SKIPURL . "\"";
+ $lsconf_var[LS_VAR_SQUIDLOGTYPE] = LS_DEF_SQUIDLOGTYPE;
+
+ // update variables from package GUI config
+ if(isset($config['installedpackages']['lightsquid']['config'][0])) {
+ $cfg = $config['installedpackages']['lightsquid']['config'][0];
+
+ $tm = $cfg[LS_XML_SHEDULERTIME];
+ $tm_squid = $cfg[LS_XML_SQUID_SHEDULERTIME];
+
+ if (isset($cfg[LS_XML_LANG]) and !empty($cfg[LS_XML_LANG]))
+ $lsconf_var[LS_VAR_LANG] = "\"" . $cfg[LS_XML_LANG] . "\";";
+
+ if (isset($cfg[LS_XML_SKIPURL]) and !empty($cfg[LS_XML_SKIPURL]))
+ $lsconf_var[LS_VAR_SKIPURL] = "\"" . $cfg[LS_XML_SKIPURL] . "\";";
+
+ if (isset($cfg[LS_XML_IP2NAME]) and !empty($cfg[LS_XML_IP2NAME] ))
+ $lsconf_var[LS_VAR_IP2NAME] = "\"" . $cfg[LS_XML_IP2NAME] . "\";";
+
+ if (isset($cfg[LS_XML_TEMPLATE]) and !empty($cfg[LS_XML_TEMPLATE])) {
+ $tpl_val = $cfg[LS_XML_TEMPLATE];
+ // check template path
+ if (!file_exists(LS_TEMPLATEPATH."/$tpl_val")) $tpl_val = 'base';
+ $lsconf_var[LS_VAR_TEMPLATE] = "\"" . $tpl_val . "\";";
+ }
+
+ if (isset($cfg[LS_XML_BARCOLOR]) and !empty($cfg[LS_XML_BARCOLOR]))
+ $lsconf_var[LS_VAR_BARCOLOR] = "\"" . $cfg[LS_XML_BARCOLOR] . "\";";
+ }
+
+ $lsconf = "";
+ $lsconf_file = LS_CONFIGPATH . "/" . LS_CONFIGFILE;
+ // open lightsquid config
+ if (file_exists($lsconf_file)) {
+ $lsconf = file_get_contents($lsconf_file);
+ update_log("Load config file $lsconf_file");
+ } else {
+ update_log("Error loading config file $lsconf_file");
+ // or open from 'lightsquid.cfg.dist'
+ $lsconf_dist_file = LS_CONFIGPATH . "/" . LS_CONFIGFILE_DIST;
+ if (file_exists($lsconf_dist_file)) {
+ $lsconf = file_get_contents($lsconf_dist_file);
+ update_log("Load config dist. file $lsconf_dist_file");
+ } else update_log("Error loading config dist. file $lsconf_dist_file");
+ }
+
+ // update lightsquid config
+ if (!empty($lsconf)) {
+ $lsconf = explode("\n", $lsconf);
+ foreach ($lsconf_var as $key => $val) {
+ for($i = 0; $i < count($lsconf); $i++) {
+ $s = trim($lsconf[$i]);
+ $e_key = "^[$]" . $key . "[ ]*[=]+";
+# update_log("Regular: eregi(\"$e_key," . "'$s')"); // debug regular template
+ if (eregi($e_key, $s)) {
+# update_log("Regular PASSED: eregi(\"$e_key," . "'$s')"); // debug regular template
+ $lsconf[$i] = '$' . "$key = $val;";
+ update_log("Update config: $key=$val");
+ }
+ }
+ }
+
+ $lsconf = implode("\n", $lsconf);
+ $fl = file_put_contents($lsconf_file, $lsconf);
+ update_log("Save config file $lsconf_file ($fl)");
+ }
+
+ // set shedule - refresh data job
+ if ($tm) {
+ $on = false;
+ $opt = array("*", "*", "*", "*", "*", "root", CRONTAB_LS_TEMPLATE . " today");
+ switch($tm) {
+ case 'lhp_none': $on = false; break;
+ case 'lhp_10m': $on = true; $opt[0]= "*/10"; break;
+ case 'lhp_20m': $on = true; $opt[0]= "*/20"; break;
+ case 'lhp_30m': $on = true; $opt[0]= "*/30"; break;
+ case 'lhp_40m': $on = true; $opt[0]= "*/40"; break;
+ case 'lhp_50m': $on = true; $opt[0]= "*/50"; break;
+ case 'lhp_60m': $on = true; $opt[0]= "*/60"; break;
+ case 'lhp_2h': $on = true; $opt[0]= "0"; $opt[1]= "*/2"; break;
+ case 'lhp_3h': $on = true; $opt[0]= "0"; $opt[1]= "*/3"; break;
+ case 'lhp_4h': $on = true; $opt[0]= "0"; $opt[1]= "*/4"; break;
+ case 'lhp_6h': $on = true; $opt[0]= "0"; $opt[1]= "*/6"; break;
+ case 'lhp_8h': $on = true; $opt[0]= "0"; $opt[1]= "*/8"; break;
+ case 'lhp_12h': $on = true; $opt[0]= "0"; $opt[1]= "*/12"; break;
+ case 'lhp_24h': $on = true; $opt[0]= "0"; $opt[1]= "0"; $opt[2]= "*/24"; break;
+ }
+ ls_setup_cron("lightsquid_parser", $opt, CRONTAB_LS_JOBKEY, $on);
+ } else
+ ls_setup_cron("lightsquid_parser", "", "", false);
+
+ // set shedule - squid rotate
+ if ($tm_squid) {
+ $on = false;
+ $opt = array("0", "0", "*", "*", "*", "root", CRONTAB_SQUID_TEMPLATE);
+ switch($tm_squid) {
+ // day of month
+ case 'lsr_none':$on = false; break;
+ case 'lsr_d1': $on = true; $opt[2]= "*/1"; break;
+ case 'lsr_d2': $on = true; $opt[2]= "*/2"; break;
+ case 'lsr_d3': $on = true; $opt[2]= "*/3"; break;
+ case 'lsr_d4': $on = true; $opt[2]= "*/4"; break;
+ case 'lsr_d5': $on = true; $opt[2]= "*/5"; break;
+ case 'lsr_d6': $on = true; $opt[2]= "*/6"; break;
+ case 'lsr_d10': $on = true; $opt[2]= "*/10"; break;
+ case 'lsr_d15': $on = true; $opt[2]= "*/15"; break;
+ case 'lsr_d20': $on = true; $opt[2]= "*/20"; break;
+ case 'lsr_d25': $on = true; $opt[2]= "*/25"; break;
+ case 'lsr_d30': $on = true; $opt[2]= "*/30"; break;
+ // day of week
+ case 'lsr_w1': $on = true; $opt[4]= "*/1"; break;
+ case 'lsr_w2': $on = true; $opt[4]= "*/1"; break;
+ case 'lsr_w3': $on = true; $opt[4]= "*/1"; break;
+ case 'lsr_w4': $on = true; $opt[4]= "*/1"; break;
+ case 'lsr_w5': $on = true; $opt[4]= "*/1"; break;
+ case 'lsr_w6': $on = true; $opt[4]= "*/1"; break;
+ case 'lsr_w7': $on = true; $opt[4]= "*/1"; break;
+ }
+ ls_setup_cron("lightsquid_squid_rotate", $opt, CRONTAB_SQUID_JOBKEY, $on);
+ } else
+ ls_setup_cron("lightsquid_squid_rotate", "", "", false);
+
+ // update squid conf
+ if (isset($config['installedpackages']['squid']['config'][0])) {
+ $config['installedpackages']['squid']['config'][0]['log_enabled'] = 'on';
+ $config['installedpackages']['squid']['config'][0]['log_dir'] = LS_SQUIDLOGPATH;
+ write_config();
+ squid_resync();
+ }
+ }
+
+ if ($_POST['Submit'] === 'Refresh now') refresh_now();
+ if ($_POST['Submit'] === 'Refresh full') refresh_full();
+}
+
+// setup cron tasks
+// original source from '/etc/inc/pfsense-utils.inc' function 'tdr_install_cron'
+// this function safe for other tasks
+// *****************************************************************************
+// - $task_name: cron task name (for config identification) /for searching my cron tasks/
+// - $options: array=[0:minute][1:hour][2:mday][3:month][4:wday][5:who][6:cmd]
+// - $task_key: cron command key for searching
+// - $on_off: true-'on task', false-'off' task
+// required: $task_nameand $on_off
+// *****************************************************************************
+define('FIELD_TASKNAME', 'task_name');
+
+function ls_setup_cron($task_name, $options, $task_key, $on_off) {
+ global $config;
+ update_log("ls_setup_cron: start task_name=$task_name, task_key=$task_key, on_off=$on_off");
+
+ // check input params
+ if(!$task_name) {
+ update_log("ls_setup_cron: exit - uncomplete input params.");
+ return;
+ }
+ // search cron config settings
+ if(!$config['cron']['item']) {
+ update_log("ls_setup_cron: exit - 'config.xml'->[cron]->[items] not found.");
+ return;
+ }
+
+ // searching task
+ $x_name='';
+ $x=0;
+ foreach($config['cron']['item'] as $item) {
+ if($item[FIELD_TASKNAME] and $task_name and ($item[FIELD_TASKNAME]==$task_name)) {
+ update_log("ls_setup_cron: found cron task with name=$task_name on [$x_name].");
+ $x_name = $x;
+ }
+ $x++;
+ }
+ unset($x);
+
+ // install cron:
+ // - if not found with such name and not found 'task_key', when install task
+ // - if found task with such name, when renew this item (delete and add new with all check's)
+ // deinstall cron:
+ // - deinstall only, if found such name
+ switch($on_off) {
+ case true:
+ if($task_key) {
+ // searching task
+ $x=0;
+ $x_task='';
+ foreach($config['cron']['item'] as $item) {
+ if(strstr($item['command'], $task_key)) {
+ $x_task = $x;
+ update_log("ls_setup_cron: found cron task with key=$task_key on [$x].");
+ }
+ $x++;
+ }
+ unset($x);
+
+ if($x_task and (!$x_name or ($x_task != $x_name))) { // other task with $task_key alredy installed
+ update_log("ls_setup_cron: can't add cron task, while such task exists $task_key");
+ break;
+ } else {
+ if(is_array($options)) {
+
+ // delete this item (by name)
+ if($x_name > 0)
+ unset($config['cron']['item'][$x_name]);
+ // and add new
+ $cron_item = array();
+ $cron_item[FIELD_TASKNAME] = $task_name;
+ $cron_item['minute'] = $options[0];
+ $cron_item['hour'] = $options[1];
+ $cron_item['mday'] = $options[2];
+ $cron_item['month'] = $options[3];
+ $cron_item['wday'] = $options[4];
+ $cron_item['who'] = $options[5];
+ $cron_item['command'] = $options[6];
+ // check options
+ if(!$cron_item['who']) $cron_item['who'] = "nobody";
+ $config['cron']['item'][] = $cron_item;
+ write_config("Installed cron task '$task_name' for 'lightsquid' package");
+ configure_cron();
+ // log
+ update_log("ls_setup_cron: add cron task '$task_name'='" . $cron_item['command'] . "'");
+ }
+ }
+ } else
+ // log
+ update_log("ls_setup_cron: input prm 'task_key' not defined");
+ break;
+ case false:
+ // delete cron task with only name $task_name
+ if($x_name > 0) {
+ unset($config['cron']['item'][$x_name]);
+ write_config();
+ // log
+ update_log("ls_setup_cron: delete cron task '$task_name'");
+ }
+ break;
+ }
+ configure_cron();
+ update_log("ls_setup_cron: end");
+}
+
+function update_log($log) {
+ if (LS_GUI_DEBUG === 'on') {
+ $t_ls_log = '';
+ if (file_exists(LS_LOG_FILE))
+ $t_ls_log = file_get_contents(LS_LOG_FILE);
+ $t_ls_log .= "\n$log";
+ file_put_contents(LS_LOG_FILE, $t_ls_log);
+ }
+}
+
+function refresh_now() {
+ $cmd = CRONTAB_LS_TEMPLATE . " today";
+ update_log("refresh_now: execute command '$cmd'");
+ mwexec_bg($cmd);
+}
+
+function refresh_full() {
+ $cmd = CRONTAB_LS_TEMPLATE;
+ $log_name = LS_SQUIDLOG;
+ update_log("refresh_full: start");
+
+ // parse access.log
+ update_log("refresh_full: execute command '$cmd'");
+ mwexec_bg("$cmd $lg");
+ // parse access.log.x
+ for ($i=0; $i<100; $i++) {
+ $lg = LS_SQUIDLOG . ".$i";
+ if (file_exists(LS_SQUIDLOGPATH . "/$lg")) {
+ update_log("refresh_full: execute command '$cmd $lg'");
+ mwexec_bg("$cmd $lg");
+ } else
+ // really go <= 10 cycles
+ break;
+ }
+ update_log("refresh_full: stop");
+}
+
+?> \ No newline at end of file
diff --git a/config/lightsquid/lightsquid.xml b/config/lightsquid/lightsquid.xml
new file mode 100644
index 00000000..5f4293bf
--- /dev/null
+++ b/config/lightsquid/lightsquid.xml
@@ -0,0 +1,254 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>lightsquid</name>
+ <version>1.7.1</version>
+ <title>Services: Proxy server Report(LightSquid) -> Settings</title>
+ <category>Status</category>
+ <include_file>/usr/local/pkg/lightsquid.inc</include_file>
+
+ <!-- Installation -->
+ <menu>
+ <name>Proxy report</name>
+ <tooltiptext>Proxy server statistic report</tooltiptext>
+ <section>Status</section>
+ <url>/pkg_edit.php?xml=lightsquid.xml&amp;id=0</url>
+ </menu>
+ <tabs>
+ <tab>
+ <text>Settings</text>
+ <url>/pkg_edit.php?xml=lightsquid.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Lightsquid Report</text>
+ <url>/lightsquid/index.cgi</url>
+ </tab>
+ </tabs>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.org/packages/config/lightsquid/lightsquid.inc</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/var/tmp/</prefix>
+ <chmod>0755</chmod>
+ <item>http://files.pfsense.org/packages/All/lightsquid_tpl.tbz</item>
+ </additional_files_needed>
+ <fields>
+ <field>
+ <fielddescr>Language</fielddescr>
+ <fieldname>lightsquid_lang</fieldname>
+ <description>Select report language</description>
+ <type>select</type>
+ <value>eng</value>
+ <options>
+ <option><name>Bulgarian</name><value>bg</value></option>
+ <option><name>Czech</name><value>cz</value></option>
+ <option><name>English</name><value>eng</value></option>
+ <option><name>French</name><value>fr</value></option>
+ <option><name>Hungarian</name><value>hu</value></option>
+ <option><name>Italian</name><value>it</value></option>
+ <option><name>Portuguese - Brazil</name><value>pt_br</value></option>
+ <option><name>Russian</name><value>ru</value></option>
+ <option><name>Russian KOI-8</name><value>ru-koi8</value></option>
+ <option><name>Spanish</name><value>sp</value></option>
+ <option><name>Ukrainian</name><value>ua</value></option>
+ </options>
+ </field>
+
+ <field>
+ <fielddescr>Bar color</fielddescr>
+ <fieldname>lightsquid_barcolor</fieldname>
+ <description>Select bar color</description>
+ <type>select</type>
+ <value>orange</value>
+ <options>
+ <option><name>Orange</name><value>orange</value></option>
+ <option><name>Blue</name><value>blue</value></option>
+ <option><name>Green</name><value>green</value></option>
+ <option><name>Yellow</name><value>yellow</value></option>
+ <option><name>Brown</name><value>brown</value></option>
+ <option><name>Red</name><value>red</value></option>
+ </options>
+ </field>
+
+ <field>
+ <fielddescr>Report scheme</fielddescr>
+ <fieldname>lightsquid_template</fieldname>
+ <description>Select report scheme</description>
+ <type>select</type>
+ <value>base</value>
+ <options>
+ <option><name>Base</name><value>base</value></option>
+ <option><name>Text</name><value>text</value></option>
+ <option><name>NovoSea</name><value>novosea</value></option>
+ <option><name>NovoPf</name><value>novopf</value></option>
+ </options>
+ </field>
+
+ <field>
+ <fielddescr>IP resolve method (future)</fielddescr>
+ <fieldname>lightsquid_ip2name</fieldname>
+ <description>
+ &lt;table cellpadding=1 cellspacing=0 style=&quot;text-align: left;&quot;&gt; &lt;tbody&gt;
+ &lt;tr&gt;&lt;th colspan=2&gt; Select IP to Name resolve method (take effect only on new data): &lt;/th&gt;&lt;tr&gt;
+ &lt;tr&gt;&lt;th&gt; IP &lt;/th&gt;&lt;td&gt; - return IP &lt;/td&gt;&lt;tr&gt;
+ &lt;tr&gt;&lt;th&gt; Demo &lt;/th&gt;&lt;td&gt; - return AUTHNAME, else DNSNAME, else IP &lt;/td&gt;&lt;tr&gt;
+ &lt;tr&gt;&lt;th&gt; DNS &lt;/th&gt;&lt;td&gt; - return DNSNAME &lt;/td&gt;&lt;tr&gt;
+ &lt;tr&gt;&lt;th&gt; Simple &lt;/th&gt;&lt;td&gt; - return AUTHNAME else IP &lt;/td&gt;&lt;tr&gt;
+ &lt;tr&gt;&lt;th&gt; SMB &lt;/th&gt;&lt;td&gt; - return SMB name of pc &lt;/td&gt;&lt;tr&gt;
+ &lt;tr&gt;&lt;th&gt; Squidauth &lt;/th&gt;&lt;td&gt; - return AUTHNAME else IP, allow cyrilyc name &lt;/td&gt;&lt;tr&gt;
+ &lt;/tbody&gt; &lt;/table&gt;
+ </description>
+ <type>select</type>
+ <value>dns</value>
+ <options>
+ <option><name>IP</name><value>ip</value></option>
+ <option><name>Demo</name><value>demo</value></option>
+ <option><name>DNS</name><value>dns</value></option>
+ <option><name>Simple</name><value>simple</value></option>
+ <option><name>SMB</name><value>smb</value></option>
+ <option><name>Squidauth</name><value>squidauth</value></option>
+ </options>
+ </field>
+
+ <field>
+ <fielddescr>Refresh sheduler</fielddescr>
+ <fieldname>lightsquid_refreshsheduler_time</fieldname>
+ <description>
+ Select data refresh period. System will execute task every XX time as from 00:00 hours. &lt;br&gt;
+ For example: if selected 2h - system wil start task at 0-2-4-..-24h. &lt;br&gt;
+ Note: (!),(*) - use only for powerful system; (+) - recomended. &lt;br&gt;&lt;br&gt;
+ &lt;input type=&quot;submit&quot; name=&quot;Submit&quot; value=&quot;Refresh now&quot;&gt;&lt;br&gt;
+ &lt;input type=&quot;submit&quot; name=&quot;Submit&quot; value=&quot;Refresh full&quot;&gt;
+ &lt;br&gt; Press button for start background refresh (this take some time).
+ &lt;br&gt; &lt;span style=&quot;color: rgb(153, 51, 0);&quot;&gt; Note after installation:
+ &lt;br&gt; On the first - enable log in squid package with &quot;/var/squid/log&quot; path.
+ &lt;br&gt; On the second - press Refresh button for create lightsquid reports, else you will have error diagnostic page.&lt;/span&gt;
+ </description>
+ <type>select</type>
+ <value>lhp_none</value>
+ <options>
+ <option><name>none</name><value>lhp_none</value></option>
+ <option><name>10min(!)</name><value>lhp_10m</value></option>
+ <option><name>20min(!)</name><value>lhp_20m</value></option>
+ <option><name>30min(*)</name><value>lhp_30m</value></option>
+ <option><name>40min(*)</name><value>lhp_40m</value></option>
+ <option><name>50min(+)</name><value>lhp_50m</value></option>
+ <option><name>60min(+)</name><value>lhp_60m</value></option>
+ <option><name>2h</name><value>lhp_2h</value></option>
+ <option><name>3h</name><value>lhp_3h</value></option>
+ <option><name>4h</name><value>lhp_4h</value></option>
+ <option><name>6h</name><value>lhp_6h</value></option>
+ <option><name>8h</name><value>lhp_8h</value></option>
+ <option><name>12h</name><value>lhp_12h</value></option>
+ <option><name>24(00)h</name><value>lhp_24h</value></option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Squid rotate log sheduler</fielddescr>
+ <fieldname>lightsquid_squidrotatelog_sheduler_time</fieldname>
+ <description>
+ Select squid log rotate period. System will execute task every XX time as from 00:00 hours. &lt;br&gt;
+ This option will allow the updating of the faster &lt;br&gt;
+ For example: if selected '2 day' - system wil start task every 2 day of month. &lt;br&gt;
+ This option will allow the updating of the faster &lt;br&gt;
+ Note: You must choose from that the rate of filling dialogue access.log squid; &lt;br&gt;
+ The more customers, the more often it should be the job.
+ </description>
+ <type>select</type>
+ <value>lsr_none</value>
+ <options>
+ <option><name>none</name><value>lsr_none</value></option>
+ <option><name>every 1 day</name><value>lsr_d1</value></option>
+ <option><name>every 2 day</name><value>lsr_d2</value></option>
+ <option><name>every 3 day</name><value>lsr_d3</value></option>
+ <option><name>every 4 day</name><value>lsr_d4</value></option>
+ <option><name>every 5 day</name><value>lsr_d5</value></option>
+ <option><name>every 6 day</name><value>lsr_d6</value></option>
+ <option><name>weekly at Monday</name><value>lsr_w1</value></option>
+ <option><name>weekly at Tuesday</name><value>lsr_w2</value></option>
+ <option><name>weekly at Wednesday</name><value>lsr_w3</value></option>
+ <option><name>weekly at Thursday</name><value>lsr_w4</value></option>
+ <option><name>weekly at Friday</name><value>lsr_w5</value></option>
+ <option><name>weekly at Saturday</name><value>lsr_w6</value></option>
+ <option><name>weekly at Sunday</name><value>lsr_w7</value></option>
+ <option><name>every 10 day</name><value>lsr_d10</value></option>
+ <option><name>every 15 day</name><value>lsr_d15</value></option>
+ <option><name>every 20 day</name><value>lsr_d20</value></option>
+ <option><name>every 25 day</name><value>lsr_d25</value></option>
+ <option><name>every 30 day</name><value>lsr_d30</value></option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Skip url</fielddescr>
+ <fieldname>lightsquid_skipurl</fieldname>
+ <description>
+ If you want skip some sites from stat, example our local www server
+ Example, if you want skip LOCAL site, put it here
+ zdd.com|192.168.1.|cnn.com
+ </description>
+ <type>textarea</type>
+ <cols>60</cols>
+ <rows>5</rows>
+ </field>
+ </fields>
+ <custom_add_php_command>
+ </custom_add_php_command>
+ <custom_php_resync_config_command>
+ lightsquid_resync();
+ </custom_php_resync_config_command>
+ <custom_php_install_command>
+ lightsquid_install();
+ lightsquid_resync();
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+# mwexec("pkg_delete lightsquid-1.7.1");
+ lightsquid_deinstall();
+ </custom_php_deinstall_command>
+</packagegui> \ No newline at end of file
diff --git a/config/miniupnpd/miniupnpd.inc b/config/miniupnpd/miniupnpd.inc
new file mode 100644
index 00000000..98e44951
--- /dev/null
+++ b/config/miniupnpd/miniupnpd.inc
@@ -0,0 +1,290 @@
+<?php
+
+/* package is now in base, check to see
+ * if we are already being included
+ */
+if(!function_exists("upnp_action")) {
+
+ require_once("config.inc");
+ require_once("functions.inc");
+
+ /* MiniUPnPd */
+
+ define('UPNP_RCFILE', '/usr/local/etc/rc.d/miniupnpd.sh');
+ define('UPNP_CONFIG','/usr/local/etc/miniupnpd.conf');
+
+ function upnp_notice ($msg) { syslog(LOG_NOTICE, "miniupnpd: {$msg}"); }
+ function upnp_warn ($msg) { syslog(LOG_WARNING, "miniupnpd: {$msg}"); }
+
+ function upnp_action ($action) {
+ if (file_exists(UPNP_RCFILE))
+ mwexec(UPNP_RCFILE.' '.$action);
+ }
+
+ function upnp_running () {
+ if((int)exec('pgrep miniupnpd | wc -l') > 0)
+ return true;
+ return false;
+ }
+
+ function upnp_write_config($file, $text) {
+ $handle = fopen($file, 'w');
+ if(!$handle) {
+ upnp_warn("Could not open {$file} for writing.");
+ exit;
+ }
+ fwrite($handle, $text);
+ fclose($handle);
+ }
+
+ function upnp_uuid() {
+ /* md5 hash of wan mac */
+ $uuid = md5(exec('arp -an -i '.get_real_wan_interface().' | /usr/bin/cut -d " " -f4'));
+ /* put uuid in correct format 8-4-4-4-12 */
+ return substr($uuid,0,8).'-'.substr($uuid,9,4).'-'.substr($uuid,13,4).'-'.substr($uuid,17,4).'-'.substr($uuid,21,12);
+ }
+
+ function upnp_validate_ip($ip,$check_cdir) {
+ /* validate cdir */
+ if($check_cdir) {
+ $ip_array = explode('/',$ip);
+ if(count($ip_array) == 2) {
+ if($ip_array[1] < 1 || $ip_array[1] > 32)
+ return false;
+ } else
+ if(count($ip_array) != 1)
+ return false;
+ } else
+ $ip_array[] = $ip;
+
+ /* validate ip */
+ if(!eregi('^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$', $ip_array[0]))
+ return false;
+ foreach(explode('.', $ip_array[0]) as $sub)
+ if($sub < 0 || $sub > 256)
+ return false;
+ return true;
+ }
+
+ function upnp_validate_port($port) {
+ foreach(explode('-', $port) as $sub)
+ if($sub < 0 || $sub > 65535)
+ return false;
+ return true;
+ }
+
+ function before_form_miniupnpd($pkg) {
+ global $config;
+
+ config_lock();
+
+ /* if shaper connection speed defined hide fields */
+ if($config['ezshaper']['step2']['download'] && $config['ezshaper']['step2']['upload']) {
+ $i=0;
+ foreach ($pkg['fields']['field'] as $field) {
+ if ($field['fieldname'] == 'download' || $field['fieldname'] == 'upload')
+ unset($pkg['fields']['field'][$i]);
+ $i++;
+ }
+ }
+
+ config_unlock();
+ }
+
+ function validate_form_miniupnpd($post, $input_errors) {
+ if($post['iface_array'])
+ foreach($post['iface_array'] as $iface)
+ if($iface == 'wan')
+ $input_errors[] = 'It is a security risk to specify WAN in the \'Interface\' field';
+ if($post['overridewanip'] && !upnp_validate_ip($post['overridewanip'],false))
+ $input_errors[] = 'You must specify a valid ip address in the \'Override WAN address\' field';
+ if(($post['download'] && !$post['upload']) || ($post['upload'] && !$post['download']))
+ $input_errors[] = 'You must fill in both \'Maximum Download Speed\' and \'Maximum Upload Speed\' fields';
+ if($post['download'] && $post['download'] <= 0)
+ $input_errors[] = 'You must specify a value greater than 0 in the \'Maximum Download Speed\' field';
+ if($post['upload'] && $post['upload'] <= 0)
+ $input_errors[] = 'You must specify a value greater than 0 in the \'Maximum Upload Speed\' field';
+
+ /* user permissions validation */
+ for($i=1; $i<=4; $i++) {
+ if($post["permuser{$i}"]) {
+ $perm = explode(' ',$post["permuser{$i}"]);
+ /* should explode to 4 args */
+ if(count($perm) != 4) {
+ $input_errors[] = "You must follow the specified format in the 'User specified permissions {$i}' field";
+ } else {
+ /* must with allow or deny */
+ if(!($perm[0] == 'allow' || $perm[0] == 'deny'))
+ $input_errors[] = "You must begin with allow or deny in the 'User specified permissions {$i}' field";
+ /* verify port or port range */
+ if(!upnp_validate_port($perm[1]) || !upnp_validate_port($perm[3]))
+ $input_errors[] = "You must specify a port or port range between 0 and 65535 in the 'User specified
+ permissions {$i}' field";
+ /* verify ip address */
+ if(!upnp_validate_ip($perm[2],true))
+ $input_errors[] = "You must specify a valid ip address in the 'User specified permissions {$i}' field";
+ }
+ }
+ }
+ }
+
+ function sync_package_miniupnpd() {
+ global $config;
+ global $input_errors;
+
+ config_lock();
+
+ $upnp_config = $config['installedpackages']['miniupnpd']['config'][0];
+
+ $config_text = "ext_ifname=".get_real_wan_interface()."\n";
+ $config_text .= "port=2189\n";
+
+ $ifaces_active = '';
+
+ /* since config is written before this file invoked we don't need to read post data */
+ if($upnp_config['enable'] && $upnp_config['iface_array'])
+ $iface_array = explode(',', $upnp_config['iface_array']);
+
+ if($iface_array) {
+ foreach($iface_array as $iface) {
+ $if = convert_friendly_interface_to_real_interface_name($iface);
+ /* above function returns iface if fail */
+ if($if!=$iface) {
+ $addr = find_interface_ip($if);
+ /* non enabled interfaces are displayed in list on miniupnpd settings page */
+ /* check that the interface has an ip address before adding parameters */
+ if($addr) {
+ $config_text .= "listening_ip={$addr}\n";
+ if(!$ifaces_active) {
+ $webgui_ip = $addr;
+ $ifaces_active = $iface;
+ } else {
+ $ifaces_active .= ", {$iface}";
+ }
+ } else {
+ upnp_warn("Interface {$iface} has no ip address, ignoring");
+ }
+ } else {
+ upnp_warn("Could not resolve real interface for {$iface}");
+ }
+ }
+
+ if($ifaces_active) {
+ /* override wan ip address, common for carp, etc */
+ if($upnp_config['overridewanip'])
+ $config_text .= "ext_ip={$upnp_config['overridewanip']}\n";
+
+ /* if shaper connection speed defined use those values */
+ if($config['ezshaper']['step2']['download'] && $config['ezshaper']['step2']['upload']) {
+ $download = $config['ezshaper']['step2']['download']*1000;
+ $upload = $config['ezshaper']['step2']['upload']*1000;
+ } else {
+ $download = $upnp_config['download']*1000;
+ $upload = $upnp_config['upload']*1000;
+ }
+
+ /* set upload and download bitrates */
+ if($download && $upload) {
+ $config_text .= "bitrate_down={$download}\n";
+ $config_text .= "bitrate_up={$upload}\n";
+ }
+
+ /* enable logging of packets handled by miniupnpd rules */
+ if($upnp_config['logpackets'])
+ $config_text .= "packet_log=yes\n";
+
+ /* enable system uptime instead of miniupnpd uptime */
+ if($upnp_config['sysuptime'])
+ $config_text .= "system_uptime=yes\n";
+
+ /* set webgui url */
+ if($config['system']['webgui']['protocol']) {
+ $config_text .= "presentation_url={$config['system']['webgui']['protocol']}://{$webgui_ip}";
+ if($config['system']['webgui']['port'])
+ $config_text .= ":{$config['system']['webgui']['port']}";
+ $config_text .= "/\n";
+ }
+
+ /* set uuid and serial */
+ $config_text .= "uuid=".upnp_uuid()."\n";
+ $config_text .= "serial=".strtoupper(substr(upnp_uuid(),0,8))."\n";
+
+ /* set model number */
+ $config_text .= "model_number=".exec("/bin/cat /etc/version")."\n";
+
+ /* upnp access restrictions */
+ for($i=1; $i<=4; $i++) {
+ if($upnp_config["permuser{$i}"])
+ $config_text .= "{$upnp_config["permuser{$i}"]}\n";
+ }
+
+ if($upnp_config['permdefault'])
+ $config_text .= "deny 0-65535 0.0.0.0/0 0-65535\n";
+
+ /* generate rc file start and stop */
+ $stop = <<<EOD
+if [ `pgrep miniupnpd | wc -l` != 0 ]; then
+ /usr/bin/killall miniupnpd
+ while [ `pgrep miniupnpd | wc -l` != 0 ]; do
+ sleep 1
+ done
+ fi
+ # Clear existing rules and rdr entries
+ if [ `pfctl -aminiupnpd -sr | wc -l` != 0 ]; then
+ /sbin/pfctl -aminiupnpd -Fr 2>&1 >/dev/null
+ fi
+ if [ `pfctl -aminiupnpd -sn | wc -l` != 0 ]; then
+ /sbin/pfctl -aminiupnpd -Fn 2>&1 >/dev/null
+ fi
+EOD;
+ $start = $stop."\n\t/usr/local/sbin/miniupnpd -f ".UPNP_CONFIG;
+
+ /* write out the configuration */
+ conf_mount_rw();
+ upnp_write_config(UPNP_CONFIG, $config_text);
+ write_rcfile(array(
+ 'file' => 'miniupnpd.sh',
+ 'start' => $start,
+ 'stop' => $stop
+ )
+ );
+ conf_mount_ro();
+
+ /* if miniupnpd not running start it */
+ if(!upnp_running()) {
+ upnp_notice("Starting service on interface: {$ifaces_active}");
+ upnp_action('start');
+ }
+ /* or restart miniupnpd if settings were changed */
+ elseif($_POST['iface_array']) {
+ upnp_notice("Restarting service on interface: {$ifaces_active}");
+ upnp_action('restart');
+ }
+ }
+ }
+
+ if(!$iface_array || !$ifaces_active) {
+ /* no parameters user does not want miniupnpd running */
+ /* lets stop the service and remove the rc file */
+
+ if(file_exists(UPNP_RCFILE)) {
+ if(!$upnp_config['enable'])
+ upnp_notice('Stopping service: miniupnpd disabled');
+ else
+ upnp_notice('Stopping service: no interfaces selected');
+
+ upnp_action('stop');
+
+ conf_mount_rw();
+ unlink(UPNP_RCFILE);
+ unlink(UPNP_CONFIG);
+ conf_mount_ro();
+ }
+ }
+
+ config_unlock();
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/miniupnpd/miniupnpd.xml b/config/miniupnpd/miniupnpd.xml
new file mode 100644
index 00000000..53d70851
--- /dev/null
+++ b/config/miniupnpd/miniupnpd.xml
@@ -0,0 +1,182 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>miniupnpd</name>
+ <version>20070927</version>
+ <title>Services: MiniUPnPd</title>
+ <savetext>Change</savetext>
+ <aftersaveredirect>/status_upnp.php</aftersaveredirect>
+ <include_file>/usr/local/pkg/miniupnpd.inc</include_file>
+ <menu>
+ <name>MiniUPnPd</name>
+ <tooltiptext>Set miniupnpd settings such as interfaces to listen on.</tooltiptext>
+ <section>Services</section>
+ <url>/status_upnp.php</url>
+ </menu>
+ <service>
+ <name>miniupnpd</name>
+ <rcfile>miniupnpd.sh</rcfile>
+ <executable>miniupnpd</executable>
+ </service>
+ <tabs>
+ <tab>
+ <text>UPnP Status</text>
+ <url>/status_upnp.php</url>
+ </tab>
+ <tab>
+ <text>MiniUPnPd Settings</text>
+ <url>/pkg_edit.php?xml=miniupnpd.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ </tabs>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.org/packages/config/miniupnpd/miniupnpd.inc</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.org/packages/config/miniupnpd/status_upnp.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/sbin/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/miniupnpd/sbin/miniupnpd</item>
+ </additional_files_needed>
+ <fields>
+ <field>
+ <fielddescr>Enable MiniUPnPd</fielddescr>
+ <fieldname>enable</fieldname>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Interfaces (generally LAN)</fielddescr>
+ <fieldname>iface_array</fieldname>
+ <description>You can use the CTRL or COMMAND key to select multiple interfaces.</description>
+ <type>interfaces_selection</type>
+ <size>3</size>
+ <required/>
+ <value>lan</value>
+ <multiple>true</multiple>
+ </field>
+ <field>
+ <fielddescr>Maximum Download Speed (Kbits/second)</fielddescr>
+ <fieldname>download</fieldname>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Maximum Upload Speed (Kbits/second)</fielddescr>
+ <fieldname>upload</fieldname>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Override WAN address</fielddescr>
+ <fieldname>overridewanip</fieldname>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Log packets handled by miniupnpd rules?</fielddescr>
+ <fieldname>logpackets</fieldname>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Use system uptime instead of miniupnpd uptime?</fielddescr>
+ <fieldname>sysuptime</fieldname>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>By default deny access to miniupnpd?</fielddescr>
+ <fieldname>permdefault</fieldname>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>User specified permissions 1</fielddescr>
+ <fieldname>permuser1</fieldname>
+ <description>Format: [allow or deny] [ext port or range] [int ipaddr or ipaddr/cdir] [int port or range]
+ &lt;br /&gt;Example: allow 1024-65535 192.168.0.0/24 1024-65535</description>
+ <type>input</type>
+ <size>60</size>
+ </field>
+ <field>
+ <fielddescr>User specified permissions 2</fielddescr>
+ <fieldname>permuser2</fieldname>
+ <description>Format: [allow or deny] [ext port or range] [int ipaddr or ipaddr/cdir] [int port or range]</description>
+ <type>input</type>
+ <size>60</size>
+ </field>
+ <field>
+ <fielddescr>User specified permissions 3</fielddescr>
+ <fieldname>permuser3</fieldname>
+ <description>Format: [allow or deny] [ext port or range] [int ipaddr or ipaddr/cdir] [int port or range]</description>
+ <type>input</type>
+ <size>60</size>
+ </field>
+ <field>
+ <fielddescr>User specified permissions 4</fielddescr>
+ <fieldname>permuser4</fieldname>
+ <description>Format: [allow or deny] [ext port or range] [int ipaddr or ipaddr/cdir] [int port or range]</description>
+ <type>input</type>
+ <size>60</size>
+ </field>
+ </fields>
+ <custom_php_command_before_form>
+ before_form_miniupnpd(&amp;$pkg);
+ </custom_php_command_before_form>
+ <custom_php_validation_command>
+ validate_form_miniupnpd($_POST, &amp;$input_errors);
+ </custom_php_validation_command>
+ <custom_php_resync_config_command>
+ sync_package_miniupnpd();
+ </custom_php_resync_config_command>
+ <custom_php_install_command>
+ sync_package_miniupnpd();
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ exec("rm -f /usr/local/etc/rc.d/miniupnpd*");
+ </custom_php_deinstall_command>
+</packagegui>
diff --git a/config/miniupnpd/sbin/miniupnpd b/config/miniupnpd/sbin/miniupnpd
new file mode 100755
index 00000000..cb2f107d
--- /dev/null
+++ b/config/miniupnpd/sbin/miniupnpd
Binary files differ
diff --git a/config/miniupnpd/status_upnp.php b/config/miniupnpd/status_upnp.php
new file mode 100644
index 00000000..87e2294d
--- /dev/null
+++ b/config/miniupnpd/status_upnp.php
@@ -0,0 +1,120 @@
+<?php
+/* $Id$ */
+/*
+ status_upnp.php
+ part of pfSense (http://www.pfsense.com/)
+
+ Copyright (C) 2006 Seth Mos <seth.mos@xs4all.nl>.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require("guiconfig.inc");
+
+/* Defaults to this page but if no settings are present, redirect to setup page */
+if(!$config['installedpackages']['miniupnpd']['config'][0]['iface_array'] ||
+ !$config['installedpackages']['miniupnpd']['config'][0]['enable'])
+ Header("Location: /pkg_edit.php?xml=miniupnpd.xml&id=0");
+
+if ($_POST) {
+ if ($_POST['clear'] == "Clear") {
+ mwexec("/bin/sh /usr/local/etc/rc.d/miniupnpd.sh restart");
+ $savemsg = "Rules have been cleared and the daemon restarted";
+ }
+}
+
+$rdr_entries = array();
+exec("/sbin/pfctl -aminiupnpd -sn", $rdr_entries, $pf_ret);
+
+$now = time();
+$year = date("Y");
+
+$pgtitle = "Status: UPnP Status";
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+//$pfSenseHead->addMeta("<meta http-equiv=\"refresh\" content=\"120;url={$_SERVER['SCRIPT_NAME']}\" />");
+//echo $pfSenseHead->getHTML();
+
+?>
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<?php include("fbegin.inc"); ?>
+<p class="pgtitle"><?=$pgtitle?></font></p>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+
+<div id="mainlevel">
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+<?php
+ $tab_array = array();
+ $tab_array[] = array(gettext("UPnP Status "), true, "/status_upnp.php");
+ $tab_array[] = array(gettext("MiniUPnPd Settings "), false, "/pkg_edit.php?xml=miniupnpd.xml&id=0");
+ display_top_tabs($tab_array);
+?>
+</table>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabcont" >
+ <form action="status_upnp.php" method="post">
+ <b><input type="submit" name="clear" id="clear" value="Clear" /></b>
+ </form>
+ </td>
+ </tr>
+ <tr>
+ <td class="tabcont" >
+ <table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td width="10%" class="listhdrr"><?=gettext("Port")?></td>
+ <td width="10%" class="listhdrr"><?=gettext("Protocol")?></td>
+ <td width="20%" class="listhdrr"><?=gettext("Internal IP")?></td>
+ <td width="60%" class="listhdr"><?=gettext("Description")?></td>
+ </tr>
+ <?php $i = 0; foreach ($rdr_entries as $rdr_entry) {
+ if (preg_match("/on (.*) inet proto (.*) from any to any port = (.*) label \"(.*)\" -> (.*) port (.*)/", $rdr_entry, $matches))
+ $rdr_proto = $matches[2];
+ $rdr_port = $matches[3];
+ $rdr_ip = $matches[5];
+ $rdr_label =$matches[4];
+ ?>
+ <tr>
+ <td class="listlr">
+ <?php print $rdr_port;?>
+ </td>
+ <td class="listlr">
+ <?php print $rdr_proto;?>
+ </td>
+ <td class="listlr">
+ <?php print $rdr_ip;?>
+ </td>
+ <td class="listlr">
+ <?php print $rdr_label;?>
+ </td>
+ </tr>
+ <?php $i++; }?>
+ </table>
+ </td>
+ </tr>
+</table>
+</div>
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/mtr-nox11.xml b/config/mtr-nox11.xml
new file mode 100644
index 00000000..e0125333
--- /dev/null
+++ b/config/mtr-nox11.xml
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>mtr</name>
+ <version>0.65_2</version>
+ <title>Diagnostics: mtr</title>
+ <savetext>mtr</savetext>
+ <preoutput>yes</preoutput>
+ <donotsave>true</donotsave>
+ <!-- Menu is where this packages menu will appear -->
+ <menu>
+ <name>mtr</name>
+ <tooltiptext>mtr combines the functionality of the "traceroute" and "ping" programs into a single network diagnostic tool</tooltiptext>
+ <section>Diagnostics</section>
+ <configfile>mtr-nox11.xml</configfile>
+ </menu>
+ <!-- Do not save invokes a simple input menu and will not update
+ the configuration database. -->
+ <fields>
+ <field>
+ <fielddescr>IP or Hostname</fielddescr>
+ <fieldname>hostname</fieldname>
+ <description>Enter the IP address or hostname that you would like to traceroute to.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Count</fielddescr>
+ <fieldname>count</fieldname>
+ <description>This is the number of pings to send, each one takes 1 second</description>
+ <type>input</type>
+ <typehint>Defaults to 10</typehint>
+ </field>
+ <field>
+ <fielddescr>No DNS Lookup</fielddescr>
+ <fieldname>nodns</fieldname>
+ <description>Use this option to force mtr to display numeric IP numbers and not try to resolve the host names</description>
+ <type>checkbox</type>
+ </field>
+ </fields>
+ <custom_add_php_command>
+ $mtr_options = " -r";
+ if($_POST['count']) $mtr_options .= " -c " . $_POST['count'];
+ if($_POST['nodns']) $mtr_options .= " -n";
+ $mtr_options .= " " . $_POST['hostname'];
+ system("/usr/local/sbin/mtr" . $mtr_options);
+ </custom_add_php_command>
+ <custom_php_deinstall_command>
+ </custom_php_deinstall_command>
+</packagegui>
diff --git a/config/netio-newpkg.xml b/config/netio-newpkg.xml
new file mode 100644
index 00000000..00ba1971
--- /dev/null
+++ b/config/netio-newpkg.xml
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<package>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <nosync/>
+ <info>
+ <name>netio-newpkg</name>
+ <descr>This is a network benchmark for DOS, OS/2 2.x, Windows NT/2000 and Unix. It measures the net throughput of a network via NetBIOS and/or TCP/IP protocols (Unix and DOS only support TCP/IP) using various different packet sizes.</descr>
+ <category>Network Management</category>
+ <version>1.14</version>
+ <status>ALPHA</status>
+ </info>
+ <files>
+ <file>
+ <type>package</type>
+ <location>http://ftp2.freebsd.org/pub/FreeBSD/ports/i386/packages-6-current/All/netio-1.14.tbz</location>
+ </file>
+ <file>
+ <type>configfile</type>
+ <location>http://www.pfsense.com/packages/config/netioserver-newpkg.xml</location>
+ </file>
+ </files>
+ <services>
+ <service>
+ <name>netio-newpkg</name>
+ <executable>netio</executable>
+ </service>
+ </services>
+ <gui>
+ <title>netio: Client</title>
+ <donotsave>true</donotsave>
+ <preoutput>yes</preoutput>
+ <menus>
+ <menu>
+ <name>netio</name>
+ <tooltiptext>Run netio in client or server mode.</tooltiptext>
+ <section>Diagnostics</section>
+ <configfile>netio-newpkg.xml</configfile>
+ </menu>
+ </menus>
+ <tabs>
+ <tab>
+ <text>Client</text>
+ <url>/pkg_edit.php?xml=netio-newpkg.xml</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Server</text>
+ <url>/pkg_edit.php?xml=netioserver-newpkg.xml</url>
+ </tab>
+ </tabs>
+ <fields>
+ <field>
+ <fielddescr>Server</fielddescr>
+ <fieldname>hostname</fieldname>
+ <description>Enter the IP address or hostname that netio will connect to.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Port</fielddescr>
+ <fieldname>port</fieldname>
+ <description>Enter the port that netio will connect to. (default 18767)</description>
+ <type>input</type>
+ </field>
+ </fields>
+ </gui>
+ <commands>
+ <add_commands>
+ stop_service("netio-newpkg");
+ $netio_options = "";
+ if($_POST['port'] != "") $netio_options .= " -p {$_POST['port']}";
+ $netio_options .= $_POST['hostname'];
+ system("/usr/local/bin/netio " . $netio_options);
+ </add_commands>
+ </commands>
+</package>
+
diff --git a/config/netio.xml b/config/netio.xml
new file mode 100644
index 00000000..bce2e077
--- /dev/null
+++ b/config/netio.xml
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>netio</name>
+ <version>1.14</version>
+ <title>netio: Client</title>
+ <preoutput>yes</preoutput>
+ <donotsave>true</donotsave>
+ <menu>
+ <name>netio</name>
+ <tooltiptext>Run netio in client or server mode.</tooltiptext>
+ <section>Diagnostics</section>
+ <configfile>netio.xml</configfile>
+ </menu>
+ <tabs>
+ <tab>
+ <text>Client</text>
+ <url>/pkg_edit.php?xml=netio.xml</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Server</text>
+ <url>/pkg_edit.php?xml=netioserver.xml</url>
+ </tab>
+ </tabs>
+ <additional_files_needed>
+ <item>http://www.pfsense.com/packages/config/netioserver.xml</item>
+ </additional_files_needed>
+ <fields>
+ <field>
+ <fielddescr>Server</fielddescr>
+ <fieldname>hostname</fieldname>
+ <description>Enter the IP address or hostname that netio will connect to.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Port</fielddescr>
+ <fieldname>port</fieldname>
+ <description>Enter the port that netio will connect to. (default 18767)</description>
+ <type>input</type>
+ </field>
+ </fields>
+ <custom_add_php_command>
+ mwexec("killall netio");
+ $netio_options = "";
+ if($_POST['port'] != "") $netio_options .= " -p {$_POST['port']}";
+ $netio_options .= $_POST['hostname'];
+ system("/usr/local/bin/netio " . $netio_options);
+ </custom_add_php_command>
+</packagegui>
diff --git a/config/netioserver-newpkg.xml b/config/netioserver-newpkg.xml
new file mode 100644
index 00000000..1a0c709c
--- /dev/null
+++ b/config/netioserver-newpkg.xml
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<package>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <nosync/>
+ <info>
+ <name>netioserver-newpkg</name>
+ </info>
+ <gui>
+ <title>netio: Server</title>
+ <donotsave>true</donotsave>
+ <preoutput>yes</preoutput>
+ <tabs>
+ <tab>
+ <text>Client</text>
+ <url>/pkg_edit.php?xml=netio-newpkg.xml</url>
+ </tab>
+ <tab>
+ <text>Server</text>
+ <url>/pkg_edit.php?xml=netioserver-newpkg.xml</url>
+ <active/>
+ </tab>
+ </tabs>
+ <fields>
+ <field>
+ <fielddescr>Port</fielddescr>
+ <fieldname>port</fieldname>
+ <description>Enter the port that netio will bind to. (default 18767)</description>
+ <type>input</type>
+ </field>
+ </fields>
+ </gui>
+ <commands>
+ <add_commands>
+ stop_service("netio-newpkg");
+ if($_POST['port'] != "") $netioserver_options = " -p {$_POST['port']}";
+ system("/usr/local/bin/netio -s" . $netioserver_options);
+ </add_commands>
+ </commands>
+</package>
+
diff --git a/config/netioserver.xml b/config/netioserver.xml
new file mode 100644
index 00000000..4c32ee19
--- /dev/null
+++ b/config/netioserver.xml
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>netioserver</name>
+ <version>1.14</version>
+ <title>netio: Server</title>
+ <preoutput>yes</preoutput>
+ <donotsave>true</donotsave>
+ <menu>
+ <name>netio</name>
+ <tooltiptext>Run netio in client or server mode.</tooltiptext>
+ <section>Diagnostics</section>
+ <configfile>netio.xml</configfile>
+ </menu>
+ <tabs>
+ <tab>
+ <text>Client</text>
+ <url>/pkg_edit.php?xml=netio.xml</url>
+ </tab>
+ <tab>
+ <text>Server</text>
+ <url>/pkg_edit.php?xml=netioserver.xml</url>
+ <active/>
+ </tab>
+ </tabs>
+ <fields>
+ <field>
+ <fielddescr>Port</fielddescr>
+ <fieldname>port</fieldname>
+ <description>Enter the port that netio will bind to. (default 18767)</description>
+ <type>input</type>
+ </field>
+ </fields>
+ <custom_add_php_command>
+ mwexec("killall netio");
+ if($_POST['port'] != "") $netioserver_options = " -p {$_POST['port']}";
+ system("/usr/local/bin/netio -s" . $netioserver_options);
+ </custom_add_php_command>
+</packagegui>
diff --git a/config/nmap/nmap.inc b/config/nmap/nmap.inc
new file mode 100644
index 00000000..e9093077
--- /dev/null
+++ b/config/nmap/nmap.inc
@@ -0,0 +1,55 @@
+<?
+/* $Id$ */
+/*
+ part of pfSense (http://www.pfsense.org/)
+
+ Copyright (C) 2006 Bill Marquette - bill.marquette@gmail.com.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+function nmap_custom_add_php_command() {
+ $nmap_options = "";
+ switch($_POST['scanmethod']) {
+ case 'syn':
+ $nmap_options .= " -sS";
+ break;
+ case 'connect':
+ $nmap_options .= " -sT";
+ break;
+ case 'icmp':
+ $nmap_options .= " -sP";
+ break;
+ case 'udp':
+ $nmap_options .= " -sU";
+ break;
+ }
+
+ if($_POST['noping']) $nmap_options .= " -P0";
+ if($_POST['servicever']) $nmap_options .= " -sV";
+ if($_POST['osdetect']) $nmap_options .= " -O";
+ $nmap_options .= " " . $_POST['hostname'];
+ system("/usr/local/bin/nmap" . $nmap_options);
+}
+
+?>
diff --git a/config/nmap/nmap.xml b/config/nmap/nmap.xml
new file mode 100644
index 00000000..d616ea86
--- /dev/null
+++ b/config/nmap/nmap.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>nmap</name>
+ <version>4.76</version>
+ <title>Diagnostics: NMap</title>
+ <savetext>Scan</savetext>
+ <preoutput>yes</preoutput>
+ <donotsave>true</donotsave>
+ <include_file>/usr/local/pkg/nmap.inc</include_file>
+ <!-- Menu is where this packages menu will appear -->
+ <menu>
+ <name>NMap</name>
+ <tooltiptext>NMap is a utility for network exploration or security auditing. It supports ping scanning (determine which hosts are up), many port scanning techniques (determine what services the hosts are offering), version detection (determine what application/service is runing on a port), and TCP/IP fingerprinting (remote host OS or device identification). It also offers flexible target and port specification, decoy/stealth scanning, SunRPC scanning, and more. Most Unix and Windows platforms are supported in both GUI and command line modes. Several popular handheld devices are also supported, including the Sharp Zaurus and the iPAQ.</tooltiptext>
+ <section>Diagnostics</section>
+ <configfile>nmap.xml</configfile>
+ </menu>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>077</chmod>
+ <item>http://www.pfsense.org/packages/config/nmap/nmap.inc</item>
+ </additional_files_needed>
+ <fields>
+ <field>
+ <fielddescr>IP or Hostname</fielddescr>
+ <fieldname>hostname</fieldname>
+ <description>Enter the IP address or hostname that you would like to scan.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Scan Method</fielddescr>
+ <fieldname>scanmethod</fieldname>
+ <type>select</type>
+ <default_value>syn</default_value>
+ <options>
+ <option><name>SYN</name><value>syn</value></option>
+ <option><name>TCP connect()</name><value>connect</value></option>
+ <option><name>Ping</name><value>icmp</value></option>
+ <option><name>UDP</name><value>udp</value></option>
+ </options>
+ <typehint>Scan method</typehint>
+ </field>
+ <field>
+ <fielddescr>-P0</fielddescr>
+ <fieldname>noping</fieldname>
+ <description>This allows the scanning of networks that don't allow ICMP echo requests (or responses) through their firewall. microsoft.com is an example of such a network, and thus you should always use -P0 or -PT80 when port scanning microsoft.com. Note the "ping" in this contecx may involve more than the traditional ICMP echo request packet. Nmap supports many such probes, including arbitrary combinations of TCP, UDP, and ICMP probes. By default, Nmap sends an ICMP echo request and a TCP ACK packet to port 80.</description>
+ <type>checkbox</type>
+ <typehint>Do not try to ping hosts at all before scanning them.</typehint>
+ </field>
+ <field>
+ <fielddescr>-sV</fielddescr>
+ <fieldname>servicever</fieldname>
+ <description>After TCP and/or UDP ports are discovered using one of the other scan methods, version detection communicates with those ports to try and determine more about what is actually running. A file called nmap-service-probes is used to determine the best probes for detecting various services and the match strings to expect. Nmap tries to determine the service protocol (e.g. ftp, ssh, telnet, http), the application name (e.g. ISC Bind, Apache httpd, Solaris telnetd), the version number, and sometimes miscellaneous details like whether an X server is open to connections or the SSH protocol version)</description>
+ <type>checkbox</type>
+ <typehint>Try to identify service versions</typehint>
+ </field>
+ <field>
+ <fielddescr>-O</fielddescr>
+ <fieldname>osdetect</fieldname>
+ <description>This option activates remote host identification via TCP/IP fingerprinting. In other words, it uses a bunch of techniques to detect subtleties in the underlying operating system network stack of the computers you are scanning. It uses this information to create a "fingerprint" which it compares with its database of known OS fingerprints (the nmap-os-fingerprints file) to decide what type of system you are scanning</description>
+ <type>checkbox</type>
+ <typehint>Turn on OS detection</typehint>
+ </field>
+ </fields>
+ <custom_add_php_command>
+ nmap_custom_add_php_command();
+ </custom_add_php_command>
+ <custom_php_deinstall_command>
+ </custom_php_deinstall_command>
+</packagegui>
diff --git a/config/notes/notes.inc b/config/notes/notes.inc
new file mode 100644
index 00000000..64d8bfd5
--- /dev/null
+++ b/config/notes/notes.inc
@@ -0,0 +1,99 @@
+<?php
+/* $Id$ */
+/*
+/* ========================================================================== */
+/*
+ notes.inc
+ Copyright (C) 2008 Mark J Crane
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+function php_sync_package()
+{
+
+ //global $config;
+
+}
+
+
+function php_install_command()
+{
+
+ global $config;
+ conf_mount_rw();
+ config_lock();
+
+ if (!is_dir('/usr/local/www/packages/')) {
+ exec("mkdir /usr/local/www/packages/");
+ }
+
+ //if (!is_dir('/usr/local/www/packages/notes/')) {
+ // exec("mkdir /usr/local/www/packages/notes/");
+ //}
+
+
+ //rename PHP files from .tmp to .php
+ //exec("cp /tmp/notes.tmp /usr/local/www/packages/phpservice/notes.php");
+ //unlink_if_exists("/tmp/notes.tmp");
+
+
+ //write_config();
+
+
+ //write_rcfile(array(
+ // "file" => "notes.sh",
+ // "start" => "/usr/local/bin/php /usr/local/pkg/notes.php",
+ // "stop" => "rm /tmp/phpmonitor.pid"
+ // )
+ //);
+
+
+ php_sync_package();
+
+
+ //if (pkg_is_service_running('notes')) {
+ //documentation purposes
+ //}
+
+ conf_mount_ro();
+ config_unlock();
+
+}
+
+
+function deinstall_command()
+{
+
+ conf_mount_rw();
+ config_lock();
+ unlink_if_exists("/usr/local/pkg/notes.xml");
+ unlink_if_exists("/usr/local/pkg/notes.inc");
+ conf_mount_ro();
+ config_unlock();
+
+}
+
+?> \ No newline at end of file
diff --git a/config/notes/notes.xml b/config/notes/notes.xml
new file mode 100644
index 00000000..5d2bdf91
--- /dev/null
+++ b/config/notes/notes.xml
@@ -0,0 +1,115 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ notes.xml
+ Copyright (C) 2008 Mark J Crane
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Notes</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>Notes</name>
+ <version>0.2.3</version>
+ <title>Settings</title>
+ <include_file>/usr/local/pkg/notes.inc</include_file>
+ <menu>
+ <name>Notes</name>
+ <tooltiptext>Notes.</tooltiptext>
+ <section>Status</section>
+ <configfile>notes.xml</configfile>
+ <url>/pkg.php?xml=notes.xml</url>
+ </menu>
+ <tabs>
+ <tab>
+ <text>Settings</text>
+ <url>/pkg_edit.php?xml=notes.xml</url>
+ <active/>
+ </tab>
+ </tabs>
+ <configpath>installedpackages->package->$packagename->configuration->notes</configpath>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/notes/notes.inc</item>
+ </additional_files_needed>
+ <adddeleteeditpagefields>
+ <columnitem>
+ <fielddescr>Title</fielddescr>
+ <fieldname>title</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Category</fielddescr>
+ <fieldname>category</fieldname>
+ </columnitem>
+ </adddeleteeditpagefields>
+ <fields>
+ <field>
+ <fielddescr>Title</fielddescr>
+ <fieldname>title</fieldname>
+ <description>Enter the title.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Category</fielddescr>
+ <fieldname>category</fieldname>
+ <description>Enter a category.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>&lt;b&gt;Notes&lt;/b&gt; &lt;br /&gt; &lt;br /&gt;</fielddescr>
+ <fieldname>notes</fieldname>
+ <description></description>
+ <type>textarea</type>
+ <encoding>base64</encoding>
+ <size>30</size>
+ <cols>70</cols>
+ <rows>20</rows>
+ </field>
+ </fields>
+ <custom_add_php_command>
+ </custom_add_php_command>
+ <custom_php_resync_config_command>
+ php_sync_package();
+ </custom_php_resync_config_command>
+ <custom_delete_php_command>
+ php_sync_package();
+ </custom_delete_php_command>
+ <custom_php_install_command>
+ php_install_command();
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ deinstall_command();
+ </custom_php_deinstall_command>
+</packagegui> \ No newline at end of file
diff --git a/config/ntop/bin/librrd_th.so.2 b/config/ntop/bin/librrd_th.so.2
new file mode 100755
index 00000000..eae27341
--- /dev/null
+++ b/config/ntop/bin/librrd_th.so.2
Binary files differ
diff --git a/config/ntop/ntop.xml b/config/ntop/ntop.xml
new file mode 100644
index 00000000..bc01e46f
--- /dev/null
+++ b/config/ntop/ntop.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2008 Scott Ullrich
+ All rights reserved. */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <name>ntop</name>
+ <version>3.0</version>
+ <title>Diagnostics: ntop Settings</title>
+ <savetext>Change</savetext>
+ <aftersaveredirect>pkg_edit.php?xml=ntop.xml&amp;id=0</aftersaveredirect>
+ <additional_files_needed>
+ <prefix>/usr/local/lib/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/ntop/bin/librrd_th.so.2</item>
+ </additional_files_needed>
+ <menu>
+ <name>ntop Settings</name>
+ <tooltiptext>Set ntop settings such as password and port.</tooltiptext>
+ <section>Diagnostics</section>
+ <url>/pkg_edit.php?xml=ntop.xml&amp;id=0</url>
+ </menu>
+ <menu>
+ <name>ntop</name>
+ <tooltiptext>Access ntop</tooltiptext>
+ <section>Diagnostics</section>
+ <url>http://$myurl:3000</url>
+ <depends_on_service>ntop</depends_on_service>
+ </menu>
+ <service>
+ <name>ntop</name>
+ <rcfile>ntop.sh</rcfile>
+ <executable>ntop</executable>
+ </service>
+ <tabs>
+ <tab>
+ <text>ntop Settings</text>
+ <url>/pkg_edit.php?xml=ntop.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Access ntop</text>
+ <url>http://$myurl:3000</url>
+ </tab>
+ </tabs>
+ <fields>
+ <field>
+ <fielddescr>ntop Admin Password</fielddescr>
+ <fieldname>password</fieldname>
+ <description>Enter the password for the NTOP Web GUI. Minimum 5 characters.</description>
+ <type>password</type>
+ </field>
+ <field>
+ <fielddescr>ntop Admin Password AGAIN</fielddescr>
+ <fieldname>passwordagain</fieldname>
+ <type>password</type>
+ </field>
+ <field>
+ <fielddescr>Interface</fielddescr>
+ <fieldname>interface_array</fieldname>
+ <type>interfaces_selection</type>
+ <size>3</size>
+ <value>lan</value>
+ <multiple>true</multiple>
+ </field>
+ </fields>
+ <custom_php_global_functions>
+ function sync_package_ntop() {
+ conf_mount_rw();
+ config_lock();
+ global $config;
+ global $input_errors;
+ $ntop_config =&amp; $_POST;
+ $if_final = "";
+ $ifaces_final = "";
+ system("/bin/mkdir -p /var/db/ntop");
+ system("/bin/mkdir -p /var/db/ntop/rrd");
+ system("/bin/mkdir -p /var/db/ntop/rrd/graphics");
+ system("chown nobody:nobody /var/db/ntop");
+ system("chown nobody:nobody /var/db/ntop/rrd/graphics");
+ if($ntop_config['password'] and $ntop_config['passwordagain']) {
+ if($ntop_config['password'] == $ntop_config['passwordagain']) {
+ $first = 0;
+ foreach($_POST['interface_array'] as $iface) {
+ $if = convert_friendly_interface_to_real_interface_name($iface);
+ if($if) {
+ if($first == 1)
+ $ifaces_final .= ",";
+ $ifaces_final .= $if;
+ $first = 1;
+ }
+ }
+ exec("/usr/local/bin/ntop --set-admin-password=" . $_POST['password'] . " &amp;", $ntopout);
+ $start = "/usr/local/bin/ntop -i " . $ifaces_final . " -u root -d --ipv4 -M -x 8102 -X 8192 &amp;";
+ write_rcfile(array(
+ "file" => "ntop.sh",
+ "start" => $start,
+ "stop" => "/usr/bin/killall ntop"
+ )
+ );
+ restart_service("ntop");
+ } else {
+ $input_errors[] = "The provided passwords did not match.";
+ }
+ } else {
+ $input_errors[] = "You must provide (and confirm) ntop's password.";
+ }
+ conf_mount_ro();
+ config_unlock();
+ }
+ </custom_php_global_functions>
+ <custom_add_php_command>
+ sync_package_ntop();
+ </custom_add_php_command>
+ <custom_php_resync_config_command>
+ sync_package_ntop();
+ </custom_php_resync_config_command>
+ <custom_php_install_command>
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ exec("rm /usr/local/etc/rc.d/ntop*");
+ </custom_php_deinstall_command>
+</packagegui> \ No newline at end of file
diff --git a/config/nut/nut.inc b/config/nut/nut.inc
new file mode 100644
index 00000000..a8465dce
--- /dev/null
+++ b/config/nut/nut.inc
@@ -0,0 +1,394 @@
+<?php
+/*
+ nut.inc
+ part of pfSense (http://www.pfsense.com/)
+
+ Copyright (C) 2007 Ryan Wagoner <rswagoner@gmail.com>.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+ require_once("config.inc");
+ require_once("functions.inc");
+
+ /* Nut */
+
+ define('NUT_RCFILE', '/usr/local/etc/rc.d/nut.sh');
+ define('NUT_DIR','/usr/local/etc/nut');
+
+ function nut_notice ($msg) { syslog(LOG_NOTICE, "nut: {$msg}"); return; }
+ function nut_warn ($msg) { syslog(LOG_WARNING, "nut: {$msg}"); return; }
+
+ function nut_action ($action) {
+ if (file_exists(NUT_RCFILE))
+ mwexec(NUT_RCFILE.' '.$action);
+ }
+
+ function nut_config ($name) {
+ global $config;
+ if($config['installedpackages']['nut']['config'][0]["{$name}"])
+ return $config['installedpackages']['nut']['config'][0]["{$name}"];
+ return null;
+ }
+
+ function nut_config_sub ($name,$len) {
+ global $config;
+ if(nut_config($name))
+ return substr(nut_config($name),0,strlen(nut_config($name))-$len);
+ return null;
+ }
+
+ function nut_write_config($file, $text, $mask = null, $uid = null) {
+ $conf = fopen($file, "w");
+ if(!$conf) {
+ nut_warn("Could not open {$file} for writing.");
+ exit;
+ }
+ fwrite($conf, $text);
+ fclose($conf);
+ if($mask) chmod($file, $mask);
+ if($uid) chown($file, $uid);
+ }
+
+ function nut_validate_ip($ip,$check_cdir) {
+ /* validate cdir */
+ if($check_cdir) {
+ $ip_array = explode("/",$ip);
+ if(count($ip_array) == 2) {
+ if($ip_array[1] < 1 || $ip_array[1] > 32)
+ return false;
+ } else
+ if(count($ip_array) != 1)
+ return false;
+ } else
+ $ip_array[] = $ip;
+
+ /* validate ip */
+ if(!eregi("^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$", $ip_array[0]))
+ return false;
+ foreach(explode(".", $ip_array[0]) as $sub)
+ if($sub < 0 || $sub > 256)
+ return false;
+ return true;
+ }
+
+ function before_form_nut($pkg) {
+ /* return available serial ports */
+ $handle = popen('dmesg | grep \'^sio[0-9]: type\'','r');
+ $read = fread($handle, 2096);
+ pclose($handle);
+
+ /* explode at the newlines */
+ $read = explode("\n",$read);
+
+ /* parse resulting text */
+ foreach($read as $line) {
+ if($line!= '') {
+ $names[] = 'ttyd'.$line{3}.' (COM'.($line{3}+1).')';
+ $values[] = '/dev/ttyd'.$line{3};
+ }
+ }
+
+ /* find correct field */
+ $i = 0;
+ foreach ($pkg['fields']['field'] as $field) {
+ if ($field['fieldname'] == 'port')
+ break;
+ $i++;
+ }
+ $field = &$pkg['fields']['field'][$i];
+
+ /* add available serial ports */
+ for ($i = 0; $i < count($values) ; $i++)
+ $field['options']['option'][] = array('name' => $names[$i], 'value' => $values[$i]);
+ }
+
+ function validate_form_nut($post, $input_errors) {
+ global $config;
+
+ /* monitor remote validation */
+ if($post['monitor'] == 'remote') {
+ if(!$post['remotename'])
+ $input_errors[] = 'You must specify a name in the \'Remote UPS Name\' field';
+ if($post['remotename'] && !eregi('^[a-z0-9_.-]+$', $post['remotename']))
+ $input_errors[] = 'Only [Aa-Zz], [0-9], and [-_] accepted in the \'Remote UPS Name\' field';
+ if(!$post['remoteaddr'] || !nut_validate_ip($post['remoteaddr'],false))
+ $input_errors[] = 'You must specify a valid address \'Remote UPS Address\' field';
+ if(!$post['remoteuser'])
+ $input_errors[] = 'You must specify a name in the \'Remote UPS User\' field';
+ if(!$post['remotepass'])
+ $input_errors[] = 'You must specify a name in the \'Remote UPS Password\' field';
+ }
+
+ /* monitor local validation */
+ elseif($post['monitor'] == 'local') {
+ if(!$post['name'])
+ $input_errors[] = 'You must specify a name in the \'Local UPS Name\' field';
+ if($post['name'] && !eregi('^[a-z0-9_.-]+$', $post['name']))
+ $input_errors[] = 'Only [Aa-Zz], [0-9], and [-_] accepted in the \'Local UPS Name\' field';
+ if(!$post['driver'])
+ $input_errors[] = 'You must select a driver in the \'Local UPS Driver\' field';
+ if(!$post['port'])
+ $input_errors[] = 'You must select a port in the \'Local UPS Port\' field';
+ if($post['allowaddr'] && !nut_validate_ip($post['allowaddr'],true))
+ $input_errors[] = 'You must specify a valid address \'Local Remote Access Address\' field';
+ }
+ }
+
+ function deinstall_package_nut() {
+ nut_action('stop');
+
+ @unlink(NUT_RCFILE);
+ @unlink(NUT_DIR.'/upsmon.conf');
+ @unlink(NUT_DIR.'/ups.conf');
+ @unlink(NUT_DIR.'/upsd.conf');
+ @unlink(NUT_DIR.'/upsd.users');
+
+ exec('rm -rf /var/db/nut');
+ }
+
+ function sync_package_nut_remote() {
+ $remotename = nut_config('remotename');
+ $remoteaddr = nut_config('remoteaddr');
+ $remoteuser = nut_config('remoteuser');
+ $remotepass = nut_config('remotepass');
+
+ if(!($remotename && $remoteaddr && $remoteuser && $remotepass))
+ return false;
+
+ /* upsmon.conf */
+ $upsmon_conf = <<<EOD
+MONITOR {$remotename}@{$remoteaddr} 1 {$remoteuser} {$remotepass} slave
+MINSUPPLIES 1
+SHUTDOWNCMD "/sbin/shutdown -h +0"
+POWERDOWNFLAG /etc/killpower
+EOD;
+
+ $stop = <<<EOD
+if [ `pgrep upsmon | wc -l` != 0 ]; then
+ /usr/bin/killall upsmon
+ while [ `pgrep upsmon | wc -l` != 0 ]; do
+ sleep 1
+ done
+ fi
+EOD;
+
+ $start = $stop."\n\t/usr/local/sbin/upsmon {$remotename}@{$remoteaddr}\n";
+
+ /* write out configuration */
+ conf_mount_rw();
+ nut_write_config(NUT_DIR.'/upsmon.conf', $upsmon_conf, 0640, 'uucp');
+ write_rcfile(array(
+ 'file' => 'nut.sh',
+ 'start' => $start,
+ 'stop' => $stop
+ )
+ );
+ conf_mount_ro();
+
+ return true;
+ }
+
+ function sync_package_nut_local() {
+ $name = nut_config('name');
+ $driver = nut_config_sub('driver', 2);
+ $port = nut_config('port');
+ $upstype = nut_config_sub('upstype', 3);
+ $cable = nut_config_sub('cable', 3);
+ $allowaddr = nut_config('allowaddr');
+ $allowuser = nut_config('allowuser');
+ $allowpass = nut_config('allowpass');
+
+ if(!($name && $driver && $port))
+ return false;
+
+ /* some installs are missing the lock dir */
+ if(!is_dir('/var/spool/lock')) {
+ @mkdir('/var/spool');
+ mkdir('/var/spool/lock');
+ chown('/var/spool/lock', 'uucp');
+ chgrp('/var/spool/lock', 'dialer');
+ }
+
+ /* determine permissions for port */
+ if($port != 'auto') {
+ $port_rel = "chown root {$port}";
+ $port_set = "chown uucp {$port}";
+ }
+
+ /* ups.conf */
+ /* for usb ups run as root */
+ if($port == 'auto') {
+ $ups_conf = "user=root\n";
+ $ovr_user = '-u root';
+ }
+ $ups_conf .= "[{$name}]\n";
+ $ups_conf .= "driver={$driver}\n";
+ $ups_conf .= "port={$port}\n";
+ if($cable)
+ $ups_conf .= "cable={$cable}\n";
+ if($upstype)
+ $ups_conf .= "upstype={$upstype}\n";
+
+ /* upsd.conf */
+ $upsd_conf = "ACL all 0.0.0.0/0\n";
+ $upsd_conf .= "ACL localhost 127.0.0.1/32\n";
+ if($allowaddr && $allowuser) {
+ $upsd_conf .= "ACL remote {$allowaddr}\n";
+ $upsd_conf .= "ACCEPT remote\n";
+ }
+ $upsd_conf .= "ACCEPT localhost\n";
+ $upsd_conf .= "REJECT all\n";
+
+ /* upsd.users */
+ $upsd_users = "[monuser]\n";
+ $upsd_users .= "password = mypass\n";
+ $upsd_users .= "allowfrom = localhost\n";
+ $upsd_users .= "upsmon master\n";
+ if($allowaddr && $allowuser) {
+ $upsd_users .= "\n[$allowuser]\n";
+ $upsd_users .= "password = $allowpass\n";
+ $upsd_users .= "allowfrom = remote\n";
+ $upsd_users .= "upsmon master\n";
+ }
+
+ /* upsmon.conf */
+ $upsmon_conf = <<<EOD
+MONITOR {$name}@localhost 1 monuser mypass master
+MINSUPPLIES 1
+SHUTDOWNCMD "/sbin/shutdown -h +0"
+POWERDOWNFLAG /etc/killpower
+EOD;
+
+ $stop = <<<EOD
+ if [ `pgrep upsmon | wc -l` != 0 ]; then
+ echo stopping upsmon
+ /usr/bin/killall upsmon
+ while [ `pgrep upsmon | wc -l` != 0 ]; do
+ sleep 1
+ done
+ fi
+ if [ `pgrep upsd | wc -l` != 0 ]; then
+ echo stopping upsd
+ /usr/bin/killall upsd
+ fi
+ if [ `pgrep {$driver} | wc -l` != 0 ]; then
+ echo stopping {$driver}
+ /usr/local/libexec/nut/upsdrvctl stop
+ fi
+ sleep 1
+ if [ `pgrep {$driver} | wc -l` != 0 ]; then
+ echo forcing {$driver} termination
+ /usr/bin/killall {$driver}
+ while [ `pgrep {$driver} | wc -l` != 0 ]; do
+ sleep 1
+ done
+ fi
+ {$port_rel}
+EOD;
+
+ $start = <<<EOD
+if [ `pgrep {$driver} | wc -l` != 0 ]; then
+ {$stop}
+ fi
+ {$port_set}
+ echo starting {$driver}
+ if /usr/local/libexec/nut/upsdrvctl start; then
+ echo starting upsd
+ /usr/local/sbin/upsd {$ovr_user}
+ echo starting upsmon
+ /usr/local/sbin/upsmon {$name}@localhost
+ else
+ echo {$driver} failed to start
+ fi
+EOD;
+
+ /* write out configuration */
+ conf_mount_rw();
+ nut_write_config(NUT_DIR.'/ups.conf', $ups_conf);
+ nut_write_config(NUT_DIR.'/upsd.conf', $upsd_conf, 0640, 'uucp');
+ nut_write_config(NUT_DIR.'/upsd.users', $upsd_users, 0640, 'uucp');
+ nut_write_config(NUT_DIR.'/upsmon.conf', $upsmon_conf, 0640, 'uucp');
+ write_rcfile(array(
+ 'file' => 'nut.sh',
+ 'start' => $start,
+ 'stop' => $stop
+ )
+ );
+ conf_mount_ro();
+
+ return true;
+ }
+
+ function sync_package_nut() {
+ global $config;
+ global $input_errors;
+
+ config_lock();
+
+ nut_action('stop');
+
+ /* create state path */
+ if(!is_dir('/var/db/nut')) {
+ mkdir('/var/db/nut');
+ chmod('/var/db/nut', 0700);
+ chown('/var/db/nut', 'uucp');
+ }
+
+ if(nut_config('monitor') == 'remote')
+ $return = sync_package_nut_remote();
+ elseif(nut_config('monitor') == 'local')
+ $return = sync_package_nut_local();
+
+ if($return && $_POST['monitor']) {
+ /* only start if changing settings as we have a startup script for system boot */
+ /* this prevents service from starting / stopping / starting on boot */
+
+ nut_notice('Starting service');
+ nut_action('start');
+ if((int)exec('pgrep upsmon | wc -l') == 0)
+ nut_notice('Service failed to start: check configuration');
+
+ } elseif(!$return && file_exists(NUT_RCFILE)) {
+ /* no parameters user does not want nut running */
+ /* lets stop the service and remove the rc file */
+
+ if(!nut_config('monitor'))
+ nut_notice('Service stopped: nut disabled');
+ else
+ nut_notice('Service stopped: check configuration');
+
+ conf_mount_rw();
+ unlink(NUT_RCFILE);
+ unlink(NUT_DIR.'/upsmon.conf');
+ /* might not always exist */
+ @unlink(NUT_DIR.'/ups.conf');
+ @unlink(NUT_DIR.'/upsd.conf');
+ @unlink(NUT_DIR.'/upsd.users');
+ exec('rm -rf /var/db/nut');
+ conf_mount_ro();
+ }
+
+ config_unlock();
+ }
+?>
diff --git a/config/nut/nut.xml b/config/nut/nut.xml
new file mode 100644
index 00000000..fdaa6295
--- /dev/null
+++ b/config/nut/nut.xml
@@ -0,0 +1,518 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>nut</name>
+ <version>2.0.4</version>
+ <title>Services: NUT</title>
+ <savetext>Change</savetext>
+ <aftersaveredirect>/status_nut.php</aftersaveredirect>
+ <include_file>/usr/local/pkg/nut.inc</include_file>
+ <menu>
+ <name>NUT</name>
+ <tooltiptext>Set Network UPS Tools settings.</tooltiptext>
+ <section>Services</section>
+ <url>/status_nut.php</url>
+ </menu>
+ <service>
+ <name>nut</name>
+ <rcfile>nut.sh</rcfile>
+ <executable>upsmon</executable>
+ </service>
+ <tabs>
+ <tab>
+ <text>NUT Status</text>
+ <url>/status_nut.php</url>
+ </tab>
+ <tab>
+ <text>NUT Settings</text>
+ <url>/pkg_edit.php?xml=nut.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ </tabs>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/nut/nut.inc</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/nut/status_nut.php</item>
+ </additional_files_needed>
+ <fields>
+ <field>
+ <fielddescr>UPS Monitoring</fielddescr>
+ <fieldname>monitor</fieldname>
+ <type>select</type>
+ <required/>
+ <options>
+ <option>
+ <name>Disabled</name>
+ <value></value>
+ </option>
+ <option>
+ <name>Local UPS</name>
+ <value>local</value>
+ </option>
+ <option>
+ <name>Remote UPS</name>
+ <value>remote</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>&lt;strong&gt;Local UPS Name&lt;/strong&gt;</fielddescr>
+ <fieldname>name</fieldname>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>&lt;strong&gt;Local UPS Model&lt;/strong&gt;</fielddescr>
+ <fieldname>driver</fieldname>
+ <description>If generic or cable specified in parenthesis you need
+ to select the appropriate option below.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>APC Back-UPS (Generic)</name>
+ <value>genericups00</value>
+ </option>
+ <option>
+ <name>APC Back-UPS RS (Generic)</name>
+ <value>genericups01</value>
+ </option>
+ <option>
+ <name>APC Back-UPS Pro (Cable)</name>
+ <value>apcsmart00</value>
+ </option>
+ <option>
+ <name>APC Smart-UPS (Cable)</name>
+ <value>apcsmart01</value>
+ </option>
+ <option>
+ <name>APC Matrix-UPS</name>
+ <value>apcsmart02</value>
+ </option>
+ <option>
+ <name>APC Masterswitch (Generic)</name>
+ <value>genericups02</value>
+ </option>
+ <option>
+ <name>APC Back-UPS USB</name>
+ <value>newhidups00</value>
+ </option>
+ <option>
+ <name>APC Back-UPS LS USB</name>
+ <value>newhidups01</value>
+ </option>
+ <option>
+ <name>APC Back-UPS ES USB</name>
+ <value>newhidups02</value>
+ </option>
+ <option>
+ <name>APC Back-UPS RS USB</name>
+ <value>newhidups03</value>
+ </option>
+ <option>
+ <name>APC Back-UPS Pro USB</name>
+ <value>newhidups04</value>
+ </option>
+ <option>
+ <name>APC Smart-UPS USB</name>
+ <value>newhidups05</value>
+ </option>
+ <option>
+ <name>Belkin Regulator Pro</name>
+ <value>belkin00</value>
+ </option>
+ <option>
+ <name>Belkin Universal UPS</name>
+ <value>belkinunv00</value>
+ </option>
+ <option>
+ <name>Belkin Universal UPS USB</name>
+ <value>newhidups06</value>
+ </option>
+ <option>
+ <name>Best Power Fortress</name>
+ <value>bestups00</value>
+ </option>
+ <option>
+ <name>Best Power Fortress Telecom</name>
+ <value>bestups01</value>
+ </option>
+ <option>
+ <name>Best Power Axxium Rackmount</name>
+ <value>bestups02</value>
+ </option>
+ <option>
+ <name>Best Power Patriot Pro</name>
+ <value>bestups03</value>
+ </option>
+ <option>
+ <name>Best Power Patriot (Generic/Cable)</name>
+ <value>genericups03</value>
+ </option>
+ <option>
+ <name>Best Power Micro-Ferrups</name>
+ <value>bestuferrups00</value>
+ </option>
+ <option>
+ <name>Best Power Fortress/Ferrups</name>
+ <value>bestfcom00</value>
+ </option>
+ <option>
+ <name>Cyber Power Systems 320AVR</name>
+ <value>cyberpower00</value>
+ </option>
+ <option>
+ <name>Cyber Power Systems 500AVR</name>
+ <value>cyberpower01</value>
+ </option>
+ <option>
+ <name>Cyber Power Systems 650AVR</name>
+ <value>cyberpower02</value>
+ </option>
+ <option>
+ <name>Cyber Power Systems 700AVR</name>
+ <value>cyberpower03</value>
+ </option>
+ <option>
+ <name>Cyber Power Systems 800AVR</name>
+ <value>cyberpower04</value>
+ </option>
+ <option>
+ <name>Cyber Power Systems 850AVR</name>
+ <value>cyberpower05</value>
+ </option>
+ <option>
+ <name>Cyber Power Systems 900AVR</name>
+ <value>cyberpower06</value>
+ </option>
+ <option>
+ <name>Cyber Power Systems 1250AVR</name>
+ <value>cyberpower07</value>
+ </option>
+ <option>
+ <name>Cyber Power Systems 1500AVR</name>
+ <value>cyberpower08</value>
+ </option>
+ <option>
+ <name>Inform GUARD Line Interactive</name>
+ <value>powercom00</value>
+ </option>
+ <option>
+ <name>Meta System HF Line</name>
+ <value>metasys00</value>
+ </option>
+ <option>
+ <name>Meta System HF Millennium</name>
+ <value>metasys01</value>
+ </option>
+ <option>
+ <name>Meta System HF TOP Line</name>
+ <value>metasys02</value>
+ </option>
+ <option>
+ <name>Meta System ECO Network</name>
+ <value>metasys03</value>
+ </option>
+ <option>
+ <name>Meta System ECO</name>
+ <value>metasys04</value>
+ </option>
+ <option>
+ <name>Meta System ally HF</name>
+ <value>metasys05</value>
+ </option>
+ <option>
+ <name>Meta System Megaline</name>
+ <value>metasys06</value>
+ </option>
+ <option>
+ <name>MGE UPS SYSTEMS NOVA AVR</name>
+ <value>mge-shut00</value>
+ </option>
+ <option>
+ <name>MGE UPS SYSTEMS Pulsar Ellipse</name>
+ <value>mge-shut01</value>
+ </option>
+ <option>
+ <name>MGE UPS SYSTEMS Ellipse Office</name>
+ <value>mge-shut02</value>
+ </option>
+ <option>
+ <name>MGE UPS SYSTEMS Pulsar EXtreme</name>
+ <value>mge-shut03</value>
+ </option>
+ <option>
+ <name>MGE UPS SYSTEMS Comet</name>
+ <value>mge-shut04</value>
+ </option>
+ <option>
+ <name>MGE UPS SYSTEMS Pulsar Esprit</name>
+ <value>mge-shut05</value>
+ </option>
+ <option>
+ <name>MGE UPS SYSTEMS Evolution</name>
+ <value>mge-shut06</value>
+ </option>
+ <option>
+ <name>MGE UPS SYSTEMS Comet USB</name>
+ <value>newhidups07</value>
+ </option>
+ <option>
+ <name>MGE UPS SYSTEMS Protection Center USB</name>
+ <value>newhidups08</value>
+ </option>
+ <option>
+ <name>MGE UPS SYSTEMS NOVA AVR USB</name>
+ <value>newhidups09</value>
+ </option>
+ <option>
+ <name>MGE UPS SYSTEMS Pulsar Ellipse USB</name>
+ <value>newhidups10</value>
+ </option>
+ <option>
+ <name>MGE UPS SYSTEMS Ellipse Office USB</name>
+ <value>newhidups11</value>
+ </option>
+ <option>
+ <name>MGE UPS SYSTEMS Pulsar Evolution USB</name>
+ <value>newhidups12</value>
+ </option>
+ <option>
+ <name>MGE UPS SYSTEMS Evolution USB</name>
+ <value>newhidups13</value>
+ </option>
+ <option>
+ <name>MGE UPS SYSTEMS Pulsar USB</name>
+ <value>newhidups14</value>
+ </option>
+ <option>
+ <name>MicroDowell B.Box BP</name>
+ <value>cpsups00</value>
+ </option>
+ <option>
+ <name>Microsol Solis</name>
+ <value>solis00</value>
+ </option>
+ <option>
+ <name>Microsol Rhino</name>
+ <value>rhino00</value>
+ </option>
+ <option>
+ <name>Mustek Various</name>
+ <value>megatec00</value>
+ </option>
+ <option>
+ <name>Mustek Powermust</name>
+ <value>megatec01</value>
+ </option>
+ <option>
+ <name>Mustek Powermust USB</name>
+ <value>megatec02</value>
+ </option>
+ <option>
+ <name>Powercom SMK</name>
+ <value>megatec03</value>
+ </option>
+ <option>
+ <name>Powercom ULT</name>
+ <value>megatec04</value>
+ </option>
+ <option>
+ <name>Powercom Trust</name>
+ <value>powercom01</value>
+ </option>
+ <option>
+ <name>Powercom Various</name>
+ <value>powercom02</value>
+ </option>
+ <option>
+ <name>Tripp-Lite SmartUPS</name>
+ <value>tripplite00</value>
+ </option>
+ <option>
+ <name>Tripp-Lite SmartOnline</name>
+ <value>tripplitesu00</value>
+ </option>
+ <option>
+ <name>Tripp-Lite AVR USB</name>
+ <value>newhidups15</value>
+ </option>
+ <option>
+ <name>Tripp-Lite OMNI USB</name>
+ <value>newhidups16</value>
+ </option>
+ <option>
+ <name>Tripp-Lite OMNIVUS USB</name>
+ <value>tripplite_usb00</value>
+ </option>
+ <option>
+ <name>Tripp-Lite SMART USB</name>
+ <value>tripplite_usb01</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>&lt;strong&gt;Local UPS Port&lt;/strong&gt;</fielddescr>
+ <fieldname>port</fieldname>
+ <type>select</type>
+ <options>
+ <option>
+ <name>auto (USB only)</name>
+ <value>auto</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Local UPS Generic Type</fielddescr>
+ <fieldname>upstype</fieldname>
+ <type>select</type>
+ <options>
+ <option>
+ <name></name>
+ <value></value>
+ </option>
+ <option>
+ <name>1 (APC Back-UPS using 940-0095A/C cables)</name>
+ <value>1 00</value>
+ </option>
+ <option>
+ <name>2 (APC Back-UPS using 940-0020B/C cables)</name>
+ <value>2 00</value>
+ </option>
+ <option>
+ <name>9 (APC Back-UPS using 940-0023A cable)</name>
+ <value>9 00</value>
+ </option>
+ <option>
+ <name>12 (APC Back-UPS Office using 940-0119A cable)</name>
+ <value>12 00</value>
+ </option>
+ <option>
+ <name>12 (APC Masterswitch using 940-0020 cable)</name>
+ <value>12 01</value>
+ </option>
+ <option>
+ <name>20 (APC Back-UPS RS)</name>
+ <value>20 00</value>
+ </option>
+ <option>
+ <name>6 (Best Power Patriot using INT51 cable)</name>
+ <value>6 00</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Local UPS Cable Type</fielddescr>
+ <fieldname>cable</fieldname>
+ <type>select</type>
+ <options>
+ <option>
+ <name></name>
+ <value></value>
+ </option>
+ <option>
+ <name>940-0095B (Gray Cable)</name>
+ <value>940-0095B 00</value>
+ </option>
+ <option>
+ <name>940-0024C (Black Cable)</name>
+ <value>940-0024C 00</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Local Remote Access Address &lt;br&gt;(ex: 192.168.1.0/24)</fielddescr>
+ <fieldname>allowaddr</fieldname>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Local Remote Access User</fielddescr>
+ <fieldname>allowuser</fieldname>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Local Remote Acces Password</fielddescr>
+ <fieldname>allowpass</fieldname>
+ <type>password</type>
+ </field>
+ <field>
+ <fielddescr>&lt;strong&gt;Remote UPS Name&lt;/strong&gt;</fielddescr>
+ <fieldname>remotename</fieldname>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>&lt;strong&gt;Remote UPS Address&lt;/strong&gt; &lt;br&gt;(ex: 192.168.1.10)</fielddescr>
+ <fieldname>remoteaddr</fieldname>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>&lt;strong&gt;Remote UPS User&lt;/strong&gt;</fielddescr>
+ <fieldname>remoteuser</fieldname>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>&lt;strong&gt;Remote UPS Password&lt;/strong&gt;</fielddescr>
+ <fieldname>remotepass</fieldname>
+ <type>password</type>
+ </field>
+ </fields>
+ <custom_php_command_before_form>
+ before_form_nut(&amp;$pkg);
+ </custom_php_command_before_form>
+ <custom_php_validation_command>
+ validate_form_nut($_POST, &amp;$input_errors);
+ </custom_php_validation_command>
+ <custom_php_resync_config_command>
+ sync_package_nut();
+ </custom_php_resync_config_command>
+ <custom_php_deinstall_command>
+ deinstall_package_nut();
+ </custom_php_deinstall_command>
+</packagegui>
diff --git a/config/nut/status_nut.php b/config/nut/status_nut.php
new file mode 100644
index 00000000..a181734f
--- /dev/null
+++ b/config/nut/status_nut.php
@@ -0,0 +1,242 @@
+<?php
+/*
+ status_nut.php
+ part of pfSense (http://www.pfsense.com/)
+
+ Copyright (C) 2007 Ryan Wagoner <rswagoner@gmail.com>.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require("guiconfig.inc");
+
+$nut_config = $config['installedpackages']['nut']['config'][0];
+
+/* functions */
+
+function tblopen () {
+ print('<table width="100%" class="tabcont" cellspacing="0" cellpadding="6">'."\n");
+}
+
+function tblclose () {
+ print("</table>\n");
+}
+
+function tblrow ($name, $value, $symbol = null) {
+ if(!$value) return;
+
+ if($symbol == '&deg;')
+ $value = sprintf("%.1f", $value);
+
+ if($symbol == 'Hz')
+ $value = sprintf("%d", $value);
+
+ print(<<<EOD
+<tr>
+ <td class="vncellreq" width="100px">{$name}</td>
+ <td class="vtable">{$value}{$symbol}</td>
+<tr>
+EOD
+ ."\n");
+}
+
+function tblrowbar ($name, $value, $symbol, $red, $yellow, $green) {
+ if(!$value) return;
+
+ $value = sprintf("%.1f", $value);
+
+ $red = explode('-', $red);
+ $yellow = explode('-', $yellow);
+ $green = explode('-', $green);
+
+ sort($red);
+ sort($yellow);
+ sort($green);
+
+ if($value >= $red[0] && $value <= ($red[0]+9)) {
+ $color = 'black';
+ $bgcolor = 'red';
+ }
+ if($value >= ($red[0]+10) && $value <= $red[1]) {
+ $color = 'white';
+ $bgcolor = 'red';
+ }
+ if($value >= $yellow[0] && $value <= $yellow[1]) {
+ $color = 'black';
+ $bgcolor = 'yellow';
+ }
+ if($value >= $green[0] && $value <= ($green[0]+9)) {
+ $color = 'black';
+ $bgcolor = 'green';
+ }
+ if($value >= ($green[0]+10) && $value <= $green[1]) {
+ $color = 'white';
+ $bgcolor = 'green';
+ }
+
+ print(<<<EOD
+<tr>
+ <td class="vncellreq" width="100px">{$name}</td>
+ <td class="vtable">
+ <div style="width: 125px; height: 12px; border-top: thin solid gray; border-bottom: thin solid gray;">
+ <div style="width: {$value}{$symbol}; height: 12px; background-color: {$bgcolor};">
+ <div style="text-align: center; color: {$color}">{$value}{$symbol}</div>
+ </div>
+ </div>
+ </td>
+<tr>
+EOD
+ ."\n");
+}
+
+/* defaults to this page but if no settings are present, redirect to setup page */
+if(!$nut_config['monitor'])
+ Header("Location: /pkg_edit.php?xml=nut.xml&id=0");
+
+$pgtitle = "Status: NUT Status";
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+//$pfSenseHead->addMeta("<meta http-equiv=\"refresh\" content=\"120;url={$_SERVER['SCRIPT_NAME']}\" />");
+//echo $pfSenseHead->getHTML();
+
+?>
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<?php include("fbegin.inc"); ?>
+<p class="pgtitle"><?=$pgtitle?></font></p>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+
+<div id="mainlevel">
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+<?php
+ $tab_array = array();
+ $tab_array[] = array(gettext("NUT Status "), true, "/status_nut.php");
+ $tab_array[] = array(gettext("NUT Settings "), false, "/pkg_edit.php?xml=nut.xml&id=0");
+ display_top_tabs($tab_array);
+?>
+</table>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td>
+<?php
+ tblopen();
+
+ $running = ((int)exec('pgrep upsmon | wc -l') > 0) ? true : false;
+
+ if($nut_config['monitor'] == 'local') {
+ tblrow('Monitoring:','Local UPS');
+ $cmd = "upsc {$nut_config['name']}@localhost";
+ } else {
+ tblrow('Monitoring:','Remote UPS');
+ $cmd = "upsc {$nut_config['remotename']}@{$nut_config['remoteaddr']}";
+ }
+
+ if($running)
+ $handle = popen($cmd, 'r');
+ else
+ tblrow('ERROR:','NUT is enabled, however the service is not running!');
+
+ if($handle) {
+ $read = fread($handle, 4096);
+ pclose($handle);
+
+ $lines = explode("\n", $read);
+ $ups = array();
+ foreach($lines as $line) {
+ $line = explode(':', $line);
+ $ups[$line[0]] = trim($line[1]);
+ }
+
+ if(count($lines) == 1)
+ tblrow('ERROR:', 'Data stale!');
+
+ tblrow('Model:', $ups['ups.model']);
+
+ $status = explode(' ', $ups['ups.status']);
+ foreach($status as $condition) {
+ if($disp_status) $disp_status .= ', ';
+ switch ($condition) {
+ case 'WAIT':
+ $disp_status .= 'Waiting';
+ break;
+ case 'OFF':
+ $disp_status .= 'Off Line';
+ break;
+ case 'OL':
+ $disp_status .= 'On Line';
+ break;
+ case 'OB':
+ $disp_status .= 'On Battery';
+ break;
+ case 'TRIM':
+ $disp_status .= 'SmartTrim';
+ break;
+ case 'BOOST':
+ $disp_status .= 'SmartBoost';
+ break;
+ case 'OVER':
+ $disp_status .= 'Overload';
+ break;
+ case 'LB':
+ $disp_status .= 'Battery Low';
+ break;
+ case 'RB':
+ $disp_status .= 'Replace Battery';
+ break;
+ case 'CAL':
+ $disp_status .= 'Calibration';
+ break;
+ default:
+ $disp_status .= $condition;
+ break;
+ }
+ }
+ tblrow('Status:', $disp_status);
+
+ tblrowbar('Load:', $ups['ups.load'], '%', '100-80', '79-60', '59-0');
+ tblrowbar('Battery Charge:', $ups['battery.charge'], '%', '0-29' ,'30-79', '80-100');
+
+ tblclose();
+ tblopen();
+
+ tblrow('Runtime Remaining:', $ups['battery.runtime'], ' seconds');
+ tblrow('Battery Voltage:', $ups['battery.voltage'], 'V');
+ tblrow('Input Voltage:', $ups['input.voltage'], 'V');
+ tblrow('Input Frequency:', $ups['input.frequency'], 'Hz');
+ tblrow('Output Voltage:', $ups['output.voltage'], 'V');
+ tblrow('Temperature:', $ups['ups.temperature'], '&deg;');
+ }
+
+ tblclose();
+?>
+ </td>
+ </tr>
+</table>
+<?php
+ /* display upsc array */
+ /*print('<pre>'); print_r($ups); print('</pre>');*/
+?>
+</div>
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/open-vm-tools/open-vm-tools.xml b/config/open-vm-tools/open-vm-tools.xml
new file mode 100644
index 00000000..5d157f09
--- /dev/null
+++ b/config/open-vm-tools/open-vm-tools.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ open-vm-tools.xml
+ part of pfSense (http://www.pfSense.org)
+ Copyright (C) 2008 BSD Perimeter LLC
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2008 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>open-vm-tools</name>
+ <version>102166_7</version>
+ <title>Open VM Tools</title>
+ <custom_add_php_command>
+ </custom_add_php_command>
+ <custom_php_install_command>
+ conf_mount_rw();
+ config_lock();
+ exec("pkg_add -r ");
+ conf_mount_ro();
+ config_unlock();
+ /usr/local/etc/rc.d/vmware-guestd.sh start
+ /usr/local/etc/rc.d/vmware-kmod.sh start
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ </custom_php_deinstall_command>
+</packagegui>
diff --git a/config/openbgpd/openbgpd.inc b/config/openbgpd/openbgpd.inc
new file mode 100644
index 00000000..8e64c683
--- /dev/null
+++ b/config/openbgpd/openbgpd.inc
@@ -0,0 +1,219 @@
+<?php
+
+/* $Id$ */
+/*
+ openbgpd.inc
+ Copyright (C) 2007 Scott Ullrich (sullrich@gmail.com)
+ part of pfSense
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+function openbgpd_install_conf() {
+ global $config, $g;
+
+ conf_mount_rw();
+
+ if($config['installedpackages']['openbgpd']['config'])
+ $openbgpd_conf = &$config['installedpackages']['openbgpd']['config'][0];
+ if($config['installedpackages']['openbgpd']['config'][0]['row'])
+ $openbgpd_rows = &$config['installedpackages']['openbgpd']['config'][0]['row'];
+ if($config['installedpackages']['openbgpdgroups']['config'])
+ $openbgpd_groups = &$config['installedpackages']['openbgpdgroups']['config'];
+ if($config['installedpackages']['openbgpdneighbors']['config'])
+ $openbgpd_neighbors = &$config['installedpackages']['openbgpdneighbors']['config'];
+
+ $fd = fopen("/usr/local/etc/bgpd.conf", "w");
+
+ $conffile = "";
+
+ // Setup AS #
+ if($openbgpd_conf['asnum'])
+ $conffile .= "AS {$openbgpd_conf['asnum']}\n";
+
+ // Setup holdtime if defined. Default is 90.
+ if($openbgpd_conf['holdtime'])
+ $conffile .= "holdtime {$openbgpd_conf['holdtime']}\n";
+
+ // Specify listen ip
+ if($openbgpd_conf['listenip'])
+ $conffile .= "listen on {$openbgpd_conf['listenip']}\n";
+
+ // Specify router id
+ if($openbgpd_conf['routerid'])
+ $conffile .= "router-id {$openbgpd_conf['routerid']}\n";
+
+ // Handle advertised networks
+ if($config['installedpackages']['openbgpd']['config'][0]['row'])
+ if(is_array($openbgpd_rows))
+ foreach($openbgpd_rows as $row)
+ $conffile .= "network {$row['networks']}\n";
+
+ // Attach neighbors to their respective group owner
+ if(is_array($openbgpd_groups)) {
+ foreach($openbgpd_groups as $group) {
+ $conffile .= "group \"{$group['name']}\" {\n";
+ $conffile .= " remote-as {$group['remoteas']}\n";
+ if(is_array($openbgpd_neighbors)) {
+ foreach($openbgpd_neighbors as $neighbor) {
+ if($neighbor['groupname'] == $group['name']) {
+ $conffile .= " neighbor {$neighbor['neighbor']} {\n";
+ $conffile .= " descr \"{$neighbor['descr']}\"\n";
+ foreach($neighbor['row'] as $row) {
+ $conffile .= " {$row['paramaters']} {$row['parmvalue']} \n";
+ }
+ $conffile .= " }\n";
+ }
+ }
+ }
+ $conffile .= "}\n";
+ }
+ }
+
+ // Handle neighbors that do not have a group assigned to them
+ if(is_array($openbgpd_neighbors)) {
+ foreach($openbgpd_neighbors as $neighbor) {
+ $used_this_item = false;
+ if($neighbor['groupname'] == "") {
+ $conffile .= " neighbor {$neighbor['neighbor']} {\n";
+ $conffile .= " descr \"{$neighbor['descr']}\"\n";
+ $used_this_item = true;
+ foreach($neighbor['row'] as $row) {
+ $conffile .= " {$row['paramaters']} {$row['parmvalue']} \n";
+ }
+ if($used_this_item)
+ $conffile .= " }\n";
+ }
+ }
+ if($used_this_item)
+ $conffile .= "}\n";
+ }
+
+ // OpenBGPD filters
+ $conffile .= "deny from any\n";
+ $conffile .= "deny to any\n";
+ if(is_array($openbgpd_neighbors)) {
+ foreach($openbgpd_neighbors as $neighbor) {
+ $conffile .= "allow from {$neighbor['neighbor']}\n";
+ $conffile .= "allow to {$neighbor['neighbor']}\n";
+ }
+ }
+
+ // Write out the configuration file
+ fwrite($fd, "# This file was created by the pfSense package manager. Do not edit!\n\n");
+ fwrite($fd, $conffile);
+
+ // Close file handle
+ fclose($fd);
+
+ // Create rc.d file
+ $fd = fopen("/usr/local/etc/rc.d/bgpd.sh","w");
+ fwrite($fd, "#!/bin/sh\n\n");
+ fwrite($fd, "# This file was created by the pfSense package manager. Do not edit!\n\n");
+ fwrite($fd, "bgpd\n");
+ fclose($fd);
+ exec("chmod a+rx /usr/local/etc/rc.d/bgpd.sh");
+ exec("chmod a-rw /usr/local/etc/bgpd.conf");
+ exec("chmod u+rw /usr/local/etc/bgpd.conf");
+
+ // bgpd process running? if so reload, elsewise start.
+ if(is_openbgpd_running() == true) {
+ exec("bgpctl reload");
+ } else {
+ exec("bgpd");
+ }
+
+ conf_mount_ro();
+}
+
+function deinstall_openbgpd() {
+ exec("rm /usr/local/etc/rc.d/bgpd.sh");
+ exec("rm /usr/local/www/openbgpd_status.php");
+ exec("killall bgpd");
+}
+
+function check_group_usage($groupname) {
+ global $config, $g;
+
+ if($config['installedpackages']['openbgpd']['config'])
+ $openbgpd_conf = &$config['installedpackages']['openbgpd']['config'][0];
+ if($config['installedpackages']['openbgpd']['config'][0]['row'])
+ $openbgpd_rows = &$config['installedpackages']['openbgpd']['config'][0]['row'];
+ if($config['installedpackages']['openbgpdgroups']['config'])
+ $openbgpd_groups = &$config['installedpackages']['openbgpdgroups']['config'];
+ if($config['installedpackages']['openbgpdneighbors']['config'])
+ $openbgpd_neighbors = &$config['installedpackages']['openbgpdneighbors']['config'];
+
+ if(is_array($openbgpd_groups)) {
+ foreach($openbgpd_groups as $group) {
+ foreach($openbgpd_neighbors as $neighbor) {
+ if($neighbor['groupname'] == $group['name'])
+ return $neighbor['groupname'];
+ }
+ }
+ }
+ return "";
+}
+
+function grey_out_value_boxes() {
+ echo <<<EOF
+ <script language="javascript">
+ function grey_out_value_boxes() {
+ var x = 0;
+ for(x=0; x<99; x++) {
+ if( \$('paramaters' + x) ) {
+ var fieldvalue = $('paramaters' + x).options[$('paramaters' + x).selectedIndex].text;
+ var length = fieldvalue.length;
+ length = length -2;
+ var last_two = fieldvalue.substring(length);
+ var without_last_two = fieldvalue.substring(0,length);
+ if( \$('parmvalue' + x) ) {
+ if(last_two != ' X') {
+ \$('parmvalue' + x).value = '';
+ \$('parmvalue' + x).disabled = true;
+ } else {
+ \$('parmvalue' + x).disabled = false;
+ }
+ }
+ }
+ }
+ var timerID = setTimeout("grey_out_value_boxes()", 1200);
+
+ }
+ grey_out_value_boxes();
+ </script>
+
+
+EOF;
+
+}
+
+function is_openbgpd_running() {
+ $status = `ps awux | grep bgpd | grep "parent" | wc -l | awk '{ print \$1 }'`;
+ if(intval($status) > 0)
+ return true;
+ else
+ return false;
+}
+
+?> \ No newline at end of file
diff --git a/config/openbgpd/openbgpd.xml b/config/openbgpd/openbgpd.xml
new file mode 100644
index 00000000..4b85dbd0
--- /dev/null
+++ b/config/openbgpd/openbgpd.xml
@@ -0,0 +1,155 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ openbgpd.xml
+ Copyright (C) 2007 Scott Ullrich (sullrich@gmail.com)
+ part of pfSense (http://www.pfSense.com)
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>OpenBGPD</name>
+ <version>1</version>
+ <title>Services: OpenBGPD</title>
+ <include_file>/usr/local/pkg/openbgpd.inc</include_file>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>077</chmod>
+ <item>http://www.pfsense.com/packages/config/openbgpd/openbgpd_status.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>077</chmod>
+ <item>http://www.pfsense.com/packages/config/openbgpd/openbgpd.inc</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>077</chmod>
+ <item>http://www.pfsense.com/packages/config/openbgpd/openbgpd_groups.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>077</chmod>
+ <item>http://www.pfsense.com/packages/config/openbgpd/openbgpd_neighbors.xml</item>
+ </additional_files_needed>
+ <menu>
+ <name>OpenBGPD</name>
+ <tooltiptext></tooltiptext>
+ <section>Services</section>
+ <url>/pkg_edit.php?xml=openbgpd.xml&amp;id=0</url>
+ </menu>
+ <tabs>
+ <tab>
+ <text>Settings</text>
+ <url>/pkg_edit.php?xml=openbgpd.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Neighbors</text>
+ <url>/pkg.php?xml=openbgpd_neighbors.xml</url>
+ </tab>
+ <tab>
+ <text>Groups</text>
+ <url>/pkg.php?xml=openbgpd_groups.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Status</text>
+ <url>/openbgpd_status.php</url>
+ </tab>
+ </tabs>
+ <fields>
+ <field>
+ <fielddescr>Autonomous Systems (AS) Number</fielddescr>
+ <fieldname>asnum</fieldname>
+ <description>Set the local autonomous system number to as-number.</description>
+ <type>input</type>
+ </field>
+
+ <field>
+ <fielddescr>Holdtime</fielddescr>
+ <fieldname>holdtime</fieldname>
+ <description>Set the holdtime in seconds. The holdtime is reset to its initial value every time either a KEEPALIVE or an UPDATE message is received from the neighbor. If the holdtime expires the session is dropped. The default is 90 seconds. Neighboring systems negotiate the holdtime used when the connection is established in the OPEN messages. Each neighbor announces its configured hold- time; the smaller one is then agreed upon.</description>
+ <type>input</type>
+ </field>
+
+ <field>
+ <fielddescr>fib-update</fielddescr>
+ <fieldname>fibupdate</fieldname>
+ <description>If set to no, do not update the Forwarding Information Base a.k.a. the kernel routing table. The default is yes.</description>
+ <type>select</type>
+ <options>
+ <option><name>yes</name><value>yes</value></option>
+ <option><name>no</name><value>no</value></option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Listen on IP</fielddescr>
+ <fieldname>listenip</fieldname>
+ <description>Specify the local IP address bgpd(8) should listen on.</description>
+ <type>input</type>
+ </field>
+
+ <field>
+ <fielddescr>Router IP</fielddescr>
+ <fieldname>routerid</fieldname>
+ <description>Set the router ID to the given IP address, which must be local to the machine.</description>
+ <type>input</type>
+ </field>
+
+
+ <field>
+ <fielddescr>Networks</fielddescr>
+ <fieldname>network</fieldname>
+ <type>rowhelper</type>
+ <description></description>
+ <rowhelper>
+ <rowhelperfield>
+ <fielddescr>Announce the specified network as belonging to our AS. If set to connected, routes to directly attached networks will be announced. If set to static, all static routes will be announced.</fielddescr>
+ <fieldname>networks</fieldname>
+ <description>Network that you would like to advertise</description>
+ <type>input</type>
+ <size>45</size>
+ </rowhelperfield>
+ </rowhelper>
+ </field>
+ </fields>
+ <custom_php_deinstall_command>
+ deinstall_openbgpd();
+ </custom_php_deinstall_command>
+ <custom_php_resync_config_command>
+ openbgpd_install_conf();
+ </custom_php_resync_config_command>
+</packagegui>
diff --git a/config/openbgpd/openbgpd_groups.xml b/config/openbgpd/openbgpd_groups.xml
new file mode 100644
index 00000000..248a97df
--- /dev/null
+++ b/config/openbgpd/openbgpd_groups.xml
@@ -0,0 +1,115 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ openbgpd_groups.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 Scott Ullrich (sullrich@gmail.com)
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>OpenBGPDGroups</name>
+ <version>1</version>
+ <title>Services: OpenBGPD Groups</title>
+ <include_file>/usr/local/pkg/openbgpd.inc</include_file>
+ <tabs>
+ <tab>
+ <text>Settings</text>
+ <url>/pkg_edit.php?xml=openbgpd.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Neighbors</text>
+ <url>/pkg.php?xml=openbgpd_neighbors.xml</url>
+ </tab>
+ <tab>
+ <text>Groups</text>
+ <url>/pkg.php?xml=openbgpd_groups.xml</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Status</text>
+ <url>/openbgpd_status.php</url>
+ </tab>
+ </tabs>
+ <adddeleteeditpagefields>
+ <columnitem>
+ <fielddescr>Name</fielddescr>
+ <fieldname>name</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Description</fielddescr>
+ <fieldname>descr</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Remote AS</fielddescr>
+ <fieldname>remoteas</fieldname>
+ </columnitem>
+ </adddeleteeditpagefields>
+ <fields>
+ <field>
+ <fielddescr>Name</fielddescr>
+ <fieldname>name</fieldname>
+ <description></description>
+ <type>input</type>
+ <size>35</size>
+ </field>
+ <field>
+ <fielddescr>Remote AS</fielddescr>
+ <fieldname>remoteas</fieldname>
+ <description></description>
+ <type>input</type>
+ <size>8</size>
+ </field>
+ <field>
+ <fielddescr>Description</fielddescr>
+ <fieldname>descr</fieldname>
+ <description></description>
+ <type>input</type>
+ <size>80</size>
+ </field>
+ </fields>
+ <custom_php_deinstall_command>
+ deinstall_openbgpd();
+ </custom_php_deinstall_command>
+ <custom_php_resync_config_command>
+ openbgpd_install_conf();
+ </custom_php_resync_config_command>
+ <custom_php_validation_command>
+ $status = check_group_usage($_POST['groupname']);
+ if($status != "")
+ $input_errors[] = "Sorry this group is in use by {$status} and cannot be deleted.";
+ </custom_php_validation_command>
+</packagegui>
diff --git a/config/openbgpd/openbgpd_neighbors.xml b/config/openbgpd/openbgpd_neighbors.xml
new file mode 100644
index 00000000..cc170c0b
--- /dev/null
+++ b/config/openbgpd/openbgpd_neighbors.xml
@@ -0,0 +1,179 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ openbgpd_neighbors.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 Scott Ullrich (sullrich@gmail.com)
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>OpenBGPDNeighbors</name>
+ <version>1</version>
+ <title>Services: OpenBGPD Neighbors</title>
+ <include_file>/usr/local/pkg/openbgpd.inc</include_file>
+ <tabs>
+ <tab>
+ <text>Settings</text>
+ <url>/pkg_edit.php?xml=openbgpd.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Neighbors</text>
+ <url>/pkg.php?xml=openbgpd_neighbors.xml</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Groups</text>
+ <url>/pkg.php?xml=openbgpd_groups.xml</url>
+ </tab>
+ <tab>
+ <text>Status</text>
+ <url>/openbgpd_status.php</url>
+ </tab>
+ </tabs>
+ <adddeleteeditpagefields>
+ <columnitem>
+ <fielddescr>Description</fielddescr>
+ <fieldname>descr</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Group</fielddescr>
+ <fieldname>groupname</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Neighbor</fielddescr>
+ <fieldname>neighbor</fieldname>
+ </columnitem>
+ </adddeleteeditpagefields>
+ <fields>
+ <field>
+ <fielddescr>Description</fielddescr>
+ <fieldname>descr</fieldname>
+ <description></description>
+ <type>input</type>
+ <size>80</size>
+ </field>
+ <field>
+ <fielddescr>Neighbor</fielddescr>
+ <fieldname>neighbor</fieldname>
+ <description>Neighbor IP address</description>
+ <type>input</type>
+ <size>25</size>
+ </field>
+ <field>
+ <fielddescr>Group</fielddescr>
+ <fieldname>groupname</fieldname>
+ <description>Add neighbor to BGP group.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>NAME</name>
+ <value>VALUE</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>none</fielddescr>
+ <fieldname>none</fieldname>
+ <type>rowhelper</type>
+ <rowhelper>
+ <rowhelperfield>
+ <fielddescr>Paramaters</fielddescr>
+ <fieldname>paramaters</fieldname>
+ <description>Neighbor settings.</description>
+ <type>select</type>
+ <options>
+ <option><name>Announce all</name><value>announce all</value></option>
+ <option><name>Announce none</name><value>announce none</value></option>
+ <option><name>Announce self</name><value>announce self</value></option>
+ <option><name>Announce default-route</name><value>announce default-route</value></option>
+ <option><name>Holdtime X</name><value>holdtime</value></option>
+ <option><name>Metric X</name><value>set metric</value></option>
+ <option><name>Multihop X</name><value>multihop</value></option>
+ <option><name>Localpref X</name><value>set localpref</value></option>
+ <option><name>Remote AS X</name><value>remote-as</value></option>
+ <option><name>Route-reflector X</name><value>route-reflector</value></option>
+ <option><name>Softreconfig in yes</name><value>softreconfig in yes</value></option>
+ <option><name>Softreconfig in no</name><value>softreconfig in no</value></option>
+ <option><name>Softreconfig out yes</name><value>softreconfig out yes</value></option>
+ <option><name>Softreconfig out no</name><value>softreconfig out no</value></option>
+ <option><name>Tcp md5sig password X</name><value>tcp md5sig password</value></option>
+ <option><name>Local address X</name><value>local-address</value></option>
+ </options>
+ </rowhelperfield>
+ <rowhelperfield>
+ <fielddescr>Value</fielddescr>
+ <fieldname>parmvalue</fieldname>
+ <type>input</type>
+ <size>25</size>
+ </rowhelperfield>
+ </rowhelper>
+ </field>
+ </fields>
+ <custom_php_command_before_form>
+ $newoptions = array();
+ $new_groups = array();
+ if($config['installedpackages']['openbgpdgroups']['config']) {
+ foreach($config['installedpackages']['openbgpdgroups']['config'] as $item)
+ $new_groups[] = $item['name'];
+ $counter = 0;
+ foreach($new_groups as $group) {
+ $newoptions['option'][$counter]['name'] = $group;
+ $newoptions['option'][$counter]['value'] = $group;
+ $counter++;
+ }
+ $newoptions['option'][$counter]['name'] = "";
+ $newoptions['option'][$counter]['value'] = "";
+ $pkg['fields']['field'][2]['options'] = $newoptions;
+ $counter = 0;
+ foreach($pkg['fields']['field'] as $field) {
+ if($field['name'] == "group") {
+ $foundgroupid = $counter;
+ echo "found it: $counter";
+ }
+ $counter++;
+ }
+ }
+ </custom_php_command_before_form>
+ <custom_php_deinstall_command>
+ </custom_php_deinstall_command>
+ <custom_php_resync_config_command>
+ openbgpd_install_conf();
+ </custom_php_resync_config_command>
+ <custom_php_after_form_command>
+ grey_out_value_boxes();
+ </custom_php_after_form_command>
+</packagegui> \ No newline at end of file
diff --git a/config/openbgpd/openbgpd_status.php b/config/openbgpd/openbgpd_status.php
new file mode 100644
index 00000000..912539ce
--- /dev/null
+++ b/config/openbgpd/openbgpd_status.php
@@ -0,0 +1,166 @@
+<?php
+/* $Id$ */
+/*
+ openbgpd_status.php
+ part of pfSense (http://www.pfsense.com/)
+ Copyright (C) 2007 Scott Ullrich (sullrich@gmail.com)
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require("guiconfig.inc");
+
+$pgtitle = "OpenBGPD: Status";
+include("head.inc");
+
+function doCmdT($title, $command) {
+ echo "<p>\n";
+ echo "<a name=\"" . $title . "\">\n";
+ echo "<table width=\"100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\">\n";
+ echo "<tr><td class=\"listtopic\">" . $title . "</td></tr>\n";
+ echo "<tr><td class=\"listlr\"><pre>"; /* no newline after pre */
+
+ if ($command == "dumpconfigxml") {
+ $fd = @fopen("/conf/config.xml", "r");
+ if ($fd) {
+ while (!feof($fd)) {
+ $line = fgets($fd);
+ /* remove sensitive contents */
+ $line = preg_replace("/<password>.*?<\\/password>/", "<password>xxxxx</password>", $line);
+ $line = preg_replace("/<pre-shared-key>.*?<\\/pre-shared-key>/", "<pre-shared-key>xxxxx</pre-shared-key>", $line);
+ $line = preg_replace("/<rocommunity>.*?<\\/rocommunity>/", "<rocommunity>xxxxx</rocommunity>", $line);
+ $line = str_replace("\t", " ", $line);
+ echo htmlspecialchars($line,ENT_NOQUOTES);
+ }
+ }
+ fclose($fd);
+ } else {
+ $execOutput = "";
+ $execStatus = "";
+ exec ($command . " 2>&1", $execOutput, $execStatus);
+ for ($i = 0; isset($execOutput[$i]); $i++) {
+ if ($i > 0) {
+ echo "\n";
+ }
+ echo htmlspecialchars($execOutput[$i],ENT_NOQUOTES);
+ }
+ }
+ echo "</pre></tr>\n";
+ echo "</table>\n";
+}
+
+/* Execute a command, giving it a title which is the same as the command. */
+function doCmd($command) {
+ doCmdT($command,$command);
+}
+
+/* Define a command, with a title, to be executed later. */
+function defCmdT($title, $command) {
+ global $commands;
+ $title = htmlspecialchars($title,ENT_NOQUOTES);
+ $commands[] = array($title, $command);
+}
+
+/* Define a command, with a title which is the same as the command,
+ * to be executed later.
+ */
+function defCmd($command) {
+ defCmdT($command,$command);
+}
+
+/* List all of the commands as an index. */
+function listCmds() {
+ global $commands;
+ echo "<p>This status page includes the following information:\n";
+ echo "<ul width=\"700\">\n";
+ for ($i = 0; isset($commands[$i]); $i++ ) {
+ echo "<li><strong><a href=\"#" . $commands[$i][0] . "\">" . $commands[$i][0] . "</a></strong>\n";
+ }
+ echo "</ul>\n";
+}
+
+/* Execute all of the commands which were defined by a call to defCmd. */
+function execCmds() {
+ global $commands;
+ for ($i = 0; isset($commands[$i]); $i++ ) {
+ doCmdT($commands[$i][0], $commands[$i][1]);
+ }
+}
+
+?>
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<?php include("fbegin.inc"); ?>
+<p class="pgtitle"><?=$pgtitle?></font></p>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+
+<div id="mainlevel">
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+<?php
+ $tab_array = array();
+ $tab_array[] = array(gettext("Settings"), false, "/pkg_edit.php?xml=openbgpd.xml&id=0");
+ $tab_array[] = array(gettext("Neighbors"), false, "/pkg.php?xml=openbgpd_neighbors.xml");
+ $tab_array[] = array(gettext("Groups"), false, "/pkg.php?xml=openbgpd_groups.xml");
+ $tab_array[] = array(gettext("Status"), true, "/openbgpd_status.php");
+ display_top_tabs($tab_array);
+?>
+</table>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabcont" >
+ <form action="tinydns_status.php" method="post">
+ </form>
+ </td>
+ </tr>
+ <tr>
+ <td class="tabcont" >
+
+<?php
+
+defCmdT("OpenBGPD Summary","bgpctl show summary");
+defCmdT("OpenBGPD Interfaces","bgpctl show interfaces");
+defCmdT("OpenBGPD Routing","bgpctl show rib");
+defCmdT("OpenBGPD Routing","bgpctl show fib");
+defCmdT("OpenBGPD Network","bgpctl show network");
+defCmdT("OpenBGPD Nexthops","bgpctl show nexthop");
+defCmdT("OpenBGPD IP","bgpctl show ip");
+defCmdT("OpenBGPD Neighbors","bgpctl show neighbor");
+
+?>
+ <div id="cmdspace" style="width:100%">
+ <?php listCmds(); ?>
+
+ <?php execCmds(); ?>
+ </div>
+
+ </table>
+ </td>
+ </tr>
+</table>
+</div>
+
+<?php include("fend.inc"); ?>
+
+<meta http-equiv="refresh" content="60;url=<?php print $_SERVER['SCRIPT_NAME']; ?>">
+
+</body>
+</html>
diff --git a/config/openvpn-client-export/client-export/template/7zS.sfx b/config/openvpn-client-export/client-export/template/7zS.sfx
new file mode 100755
index 00000000..f72ac75e
--- /dev/null
+++ b/config/openvpn-client-export/client-export/template/7zS.sfx
Binary files differ
diff --git a/config/openvpn-client-export/client-export/template/config-import b/config/openvpn-client-export/client-export/template/config-import
new file mode 100755
index 00000000..6b4465c2
--- /dev/null
+++ b/config/openvpn-client-export/client-export/template/config-import
@@ -0,0 +1,3 @@
+;!@Install@!UTF-8!
+RunProgram="procchain.exe procchain-import"
+;!@InstallEnd@!
diff --git a/config/openvpn-client-export/client-export/template/config-standard b/config/openvpn-client-export/client-export/template/config-standard
new file mode 100755
index 00000000..19e410e9
--- /dev/null
+++ b/config/openvpn-client-export/client-export/template/config-standard
@@ -0,0 +1,3 @@
+;!@Install@!UTF-8!
+RunProgram="procchain.exe procchain-standard"
+;!@InstallEnd@!
diff --git a/config/openvpn-client-export/client-export/template/openvpn-postinstall.exe b/config/openvpn-client-export/client-export/template/openvpn-postinstall.exe
new file mode 100755
index 00000000..903885d8
--- /dev/null
+++ b/config/openvpn-client-export/client-export/template/openvpn-postinstall.exe
Binary files differ
diff --git a/config/openvpn-client-export/client-export/template/procchain-import b/config/openvpn-client-export/client-export/template/procchain-import
new file mode 100755
index 00000000..3b7c74fb
--- /dev/null
+++ b/config/openvpn-client-export/client-export/template/procchain-import
@@ -0,0 +1,2 @@
+"openvpn-install.exe"
+"openvpn-postinstall.exe" /Import
diff --git a/config/openvpn-client-export/client-export/template/procchain-standard b/config/openvpn-client-export/client-export/template/procchain-standard
new file mode 100755
index 00000000..b9d1a1e5
--- /dev/null
+++ b/config/openvpn-client-export/client-export/template/procchain-standard
@@ -0,0 +1,2 @@
+"openvpn-install.exe"
+"openvpn-postinstall.exe"
diff --git a/config/openvpn-client-export/client-export/template/procchain.exe b/config/openvpn-client-export/client-export/template/procchain.exe
new file mode 100755
index 00000000..924e7a47
--- /dev/null
+++ b/config/openvpn-client-export/client-export/template/procchain.exe
Binary files differ
diff --git a/config/openvpn-client-export/client-export/vpn_openvpn_export.php b/config/openvpn-client-export/client-export/vpn_openvpn_export.php
new file mode 100755
index 00000000..e5d474cb
--- /dev/null
+++ b/config/openvpn-client-export/client-export/vpn_openvpn_export.php
@@ -0,0 +1,362 @@
+<?php
+/*
+ vpn_openvpn_export.php
+
+ Copyright (C) 2008 Shrew Soft Inc.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ DISABLE_PHP_LINT_CHECKING
+*/
+
+require("guiconfig.inc");
+require("openvpn-client-export.inc");
+
+$pgtitle = array("OpenVPN", "Client Export Utility");
+
+if (!is_array($config['openvpn']['openvpn-server']))
+ $config['openvpn']['openvpn-server'] = array();
+
+$a_server = $config['openvpn']['openvpn-server'];
+
+if (!is_array($config['system']['user']))
+ $config['system']['user'] = array();
+
+$a_user = $config['system']['user'];
+
+$ras_server = array();
+foreach($a_server as $sindex => & $server) {
+ $ras_user = array();
+ if (stripos($server['mode'], "server") === false)
+ continue;
+ foreach($a_user as $uindex => & $user) {
+ if (!is_array($user['cert']))
+ continue;
+ foreach($user['cert'] as $cindex => & $cert) {
+ if ($cert['caref'] != $server['caref'])
+ continue;
+ $ras_userent = array();
+ $ras_userent['uindex'] = $uindex;
+ $ras_userent['cindex'] = $cindex;
+ $ras_userent['name'] = $user['name'];
+ $ras_userent['certname'] = $cert['name'];
+ $ras_user[] = $ras_userent;
+ }
+ }
+ if (!count($ras_user))
+ continue;
+ $ras_serverent = array();
+ $prot = $server['protocol'];
+ $port = $server['local_port'];
+ if ($server['description'])
+ $name = "{$server['description']} {$prot}:{$port}";
+ else
+ $name = "Server {$prot}:{$port}";
+ $ras_serverent['index'] = $sindex;
+ $ras_serverent['name'] = $name;
+ $ras_serverent['users'] = $ras_user;
+ $ras_server[] = $ras_serverent;
+}
+
+$id = $_GET['id'];
+if (isset($_POST['id']))
+ $id = $_POST['id'];
+
+$act = $_GET['act'];
+if (isset($_POST['act']))
+ $act = $_POST['act'];
+
+if($act == "conf") {
+ $srvid = $_GET['srvid'];
+ $usrid = $_GET['usrid'];
+ $crtid = $_GET['crtid'];
+ if (($srvid === false) || ($usrid === false) || ($crtid === false)) {
+ pfSenseHeader("vpn_openvpn_export.php");
+ exit;
+ }
+ $useaddr = $_GET['useaddr'];
+ $usetoken = $_GET['usetoken'];
+
+ $exp_name = openvpn_client_export_prefix($srvid);
+ $exp_name = urlencode($exp_name."-config.ovpn");
+ $exp_data = openvpn_client_export_config($srvid, $usrid, $crtid, $useaddr, $usetoken);
+ $exp_size = strlen($exp_data);
+
+ header("Content-Type: application/octet-stream");
+ header("Content-Disposition: attachment; filename={$exp_name}");
+ header("Content-Length: $exp_size");
+ echo $exp_data;
+ exit;
+}
+
+if($act == "inst") {
+ $srvid = $_GET['srvid'];
+ $usrid = $_GET['usrid'];
+ $crtid = $_GET['crtid'];
+ if (($srvid === false) || ($usrid === false) || ($crtid === false)) {
+ pfSenseHeader("vpn_openvpn_export.php");
+ exit;
+ }
+ $useaddr = $_GET['useaddr'];
+ $usetoken = $_GET['usetoken'];
+ $password = "";
+ if ($_GET['password'])
+ $password = $_GET['password']; ;
+
+ $exp_name = openvpn_client_export_prefix($srvid);
+ $exp_name = urlencode($exp_name."-install.exe");
+ $exp_path = openvpn_client_export_installer($srvid, $usrid, $crtid, $useaddr, $usetoken, $password);
+ $exp_size = filesize($exp_path);
+
+ header("Content-Type: application/octet-stream");
+ header("Content-Disposition: attachment; filename={$exp_name}");
+ header("Content-Length: $exp_size");
+ readfile($exp_path);
+ unlink($exp_path);
+ exit;
+}
+
+include("head.inc");
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<?php include("fbegin.inc"); ?>
+<script language="JavaScript">
+<!--
+
+var servers = new Array();
+<?php foreach ($ras_server as $sindex => & $server): ?>
+servers[<?=$sindex;?>] = new Array();
+servers[<?=$sindex;?>][0] = '<?=$server['index'];?>';
+servers[<?=$sindex;?>][1] = new Array();
+<?php foreach ($server['users'] as $uindex => & $user): ?>
+servers[<?=$sindex;?>][1][<?=$uindex;?>] = new Array();
+servers[<?=$sindex;?>][1][<?=$uindex;?>][0] = '<?=$user['uindex'];?>';
+servers[<?=$sindex;?>][1][<?=$uindex;?>][1] = '<?=$user['cindex'];?>';
+servers[<?=$sindex;?>][1][<?=$uindex;?>][2] = '<?=$user['name'];?>';
+servers[<?=$sindex;?>][1][<?=$uindex;?>][3] = '<?=$user['certname'];?>';
+<? endforeach; ?>
+<? endforeach; ?>
+
+function download_begin(act, i) {
+
+ var index = document.getElementById("server").selectedIndex;
+ var users = servers[index][1];
+
+ var useaddr = 0;
+ if (document.getElementById("useaddr").checked)
+ useaddr = 1;
+ var usetoken = 0;
+ if (document.getElementById("usetoken").checked)
+ usetoken = 1;
+ var usepass = 0;
+ if (document.getElementById("usepass").checked)
+ usepass = 1;
+
+ var pass = document.getElementById("pass").value;
+ var conf = document.getElementById("conf").value;
+ if (usepass && (act == "inst")) {
+ if (!pass || !conf) {
+ alert("The password or confirm field is empty");
+ return;
+ }
+ if (pass != conf) {
+ alert("The password and confirm fields must match");
+ return;
+ }
+ }
+
+ var dlurl;
+ dlurl = "/vpn_openvpn_export.php?act=" + act;
+ dlurl += "&srvid=" + servers[index][0];
+ dlurl += "&usrid=" + users[i][0];
+ dlurl += "&crtid=" + users[i][1];
+ dlurl += "&useaddr=" + useaddr;
+ dlurl += "&usetoken=" + usetoken;
+ if (usepass)
+ dlurl += "&password=" + pass;
+
+ window.open(dlurl,"_self");
+}
+
+function server_changed() {
+
+ var table = document.getElementById("users");
+ while (table.rows.length > 1 )
+ table.deleteRow(1);
+
+ var index = document.getElementById("server").selectedIndex;
+ var users = servers[index][1];
+ for (i=0; i < users.length; i++) {
+ var row = table.insertRow(table.rows.length);
+ var cell0 = row.insertCell(0);
+ var cell1 = row.insertCell(1);
+ var cell2 = row.insertCell(2);
+ cell0.className = "listlr";
+ cell0.innerHTML = users[i][2];
+ cell1.className = "listr";
+ cell1.innerHTML = users[i][3];
+ cell2.className = "listr";
+ cell2.innerHTML = "<a href='javascript:download_begin(\"conf\"," + i + ")'>Configuration</a>";
+ cell2.innerHTML += "&nbsp;/&nbsp;";
+ cell2.innerHTML += "<a href='javascript:download_begin(\"inst\"," + i + ")'>Windows Installer</a>";
+ }
+}
+
+function usepass_changed() {
+
+ if (document.getElementById("usepass").checked)
+ document.getElementById("usepass_opts").style.display = "";
+ else
+ document.getElementById("usepass_opts").style.display = "none";
+}
+
+//-->
+</script>
+<?php
+ if ($input_errors)
+ print_input_errors($input_errors);
+ if ($savemsg)
+ print_info_box($savemsg);
+?>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td>
+ <?php
+ $tab_array = array();
+ $tab_array[] = array(gettext("Server"), false, "vpn_openvpn_server.php");
+ $tab_array[] = array(gettext("Client"), false, "vpn_openvpn_client.php");
+ $tab_array[] = array(gettext("Client Specific Overrides"), false, "vpn_openvpn_csc.php");
+ $tab_array[] = array(gettext("Client Export"), true, "vpn_openvpn_export.php");
+ display_top_tabs($tab_array);
+ ?>
+ </td>
+ </tr>
+ <tr>
+ <td id="mainarea">
+ <div class="tabcont">
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="22%" valign="top" class="vncellreq">Remote Access Server</td>
+ <td width="78%" class="vtable">
+ <select name="server" id="server" class="formselect" onChange="server_changed()">
+ <?php foreach($ras_server as & $server): ?>
+ <option value="<?=$server['sindex'];?>"><?=$server['name'];?></option>
+ <?php endforeach; ?>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Host Name Resolution</td>
+ <td width="78%" class="vtable">
+ <table border="0" cellpadding="2" cellspacing="0">
+ <tr>
+ <td>
+ <input name="useaddr" id="useaddr" type="checkbox" value="yes">
+ </td>
+ <td>
+ <span class="vexpl">
+ Use the server IP address instead of the hostname.
+ </span>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Certificate Export Options</td>
+ <td width="78%" class="vtable">
+ <table border="0" cellpadding="2" cellspacing="0">
+ <tr>
+ <td>
+ <input name="usetoken" id="usetoken" type="checkbox" value="yes">
+ </td>
+ <td>
+ <span class="vexpl">
+ Use Microsoft Certificate Storage instead of local files.
+ </span>
+ </td>
+ </tr>
+ </table>
+ <table border="0" cellpadding="2" cellspacing="0">
+ <tr>
+ <td>
+ <input name="usepass" id="usepass" type="checkbox" value="yes" onClick="usepass_changed()" checked>
+ </td>
+ <td>
+ <span class="vexpl">
+ Use a password to protect the pkcs12 file contents.
+ </span>
+ </td>
+ </tr>
+ </table>
+ <table border="0" cellpadding="2" cellspacing="0" id="usepass_opts">
+ <tr>
+ <td align="right">
+ <span class="vexpl">
+ &nbsp;Password :&nbsp;
+ </span>
+ </td>
+ <td>
+ <input name="pass" id="pass" type="password" class="formfld pwd" size="20" value="" />
+ </td>
+ </tr>
+ <tr>
+ <td align="right">
+ <span class="vexpl">
+ &nbsp;Confirm :&nbsp;
+ </span>
+ </td>
+ <td>
+ <input name="conf" id="conf" type="password" class="formfld pwd" size="20" value="" />
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2" class="list" height="12">&nbsp;</td>
+ </tr>
+ <tr>
+ <td colspan="2" valign="top" class="listtopic">Client Install Packages</td>
+ </tr>
+ </table>
+ <table width="100%" id="users" width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td width="25%" class="listhdrr"><?=gettext("User");?></td>
+ <td width="50%" class="listhdrr"><?=gettext("Certificate Name");?></td>
+ <td width="25%" class="listhdrr"><?=gettext("Export");?></td>
+ </tr>
+ </table>
+ </div>
+ </td>
+ </tr>
+</table>
+<script language="JavaScript">
+<!--
+server_changed();
+//-->
+</script>
+</body>
+<?php include("fend.inc"); ?>
diff --git a/config/openvpn-client-export/openvpn-client-export.inc b/config/openvpn-client-export/openvpn-client-export.inc
new file mode 100755
index 00000000..222fe71b
--- /dev/null
+++ b/config/openvpn-client-export/openvpn-client-export.inc
@@ -0,0 +1,256 @@
+<?php
+/*
+ openvpn-client-export.inc
+ Copyright (C) 2008 Shrew Soft Inc
+ All rights reserved.
+
+ Parts of this code was originally based on vpn_ipsec_sad.php
+ Copyright (C) 2003-2004 Manuel Kasper
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require_once("globals.inc");
+
+function openvpn_client_export_install() {
+ $tarpath = "/tmp/openvpn-client-export.tgz";
+ $phpfile = "vpn_openvpn_export.php";
+ $ovpndir = "/usr/local/share/openvpn";
+ $workdir = "{$ovpndir}/client-export";
+
+ if(!is_dir("/usr/local/share/openvpn"))
+ mkdir("/usr/local/share/openvpn");
+
+ exec("/usr/bin/tar zxf {$tarpath} -C {$ovpndir}");
+ unlink($tarpath);
+ rename("{$workdir}/{$phpfile}", "/usr/local/www/{$phpfile}");
+}
+
+function openvpn_client_export_deinstall() {
+ $phpfile = "vpn_openvpn_export.php";
+ $ovpndir = "/usr/local/share/openvpn";
+ $workdir = "{$ovpndir}/client-export";
+
+ unlink_if_exists("/usr/local/www/{$phpfile}");
+ exec("/bin/rm -r {$workdir}");
+}
+
+function openvpn_client_export_prefix($srvid) {
+ global $config;
+
+ // lookup server settings
+ $settings = $config['openvpn']['openvpn-server'][$srvid];
+ if (empty($settings))
+ return false;
+ if ($settings['disable'])
+ return false;
+
+ $host = $config['system']['hostname'];
+ $prot = ($settings['protocol'] == 'UDP' ? 'udp' : "tcp-{$mode}");
+ $port = $settings['local_port'];
+
+ return "{$host}-{$prot}-{$port}";
+}
+
+function openvpn_client_pem_to_pk12($outpath, $outpass, $crtpath, $keypath, $capath = false) {
+
+ if ($capath)
+ exec("/usr/bin/openssl pkcs12 -export -in {$crtpath} -inkey {$keypath} -certfile {$capath} -out {$outpath} -passout pass:{$outpass}");
+ else
+ exec("/usr/bin/openssl pkcs12 -export -in {$crtpath} -inkey {$keypath} -out {$outpath} -passout pass:{$outpass}");
+
+ unlink($crtpath);
+ unlink($keypath);
+ if ($capath)
+ unlink($capath);
+}
+
+function openvpn_client_export_config($srvid, $usrid, $crtid, $useaddr, $usetoken) {
+ global $config;
+
+ // lookup server settings
+ $settings = $config['openvpn']['openvpn-server'][$srvid];
+ if (empty($settings))
+ return false;
+ if ($settings['disable'])
+ return false;
+
+ // lookup server certificate info
+ $server_cert =& lookup_cert($settings['certref']);
+ $server_ca =& lookup_ca($server_cert['caref']);
+ if (!$server_cert || !$server_ca)
+ return false;
+
+ // lookup user info
+ $user =& $config['system']['user'][$usrid];
+ if (!$user)
+ return false;
+
+ // determine basic variables
+ if ($useaddr) {
+ $interface = $settings['interface'];
+ if (!$interface)
+ $interface = 'WAN';
+ $iface = convert_friendly_interface_to_real_interface_name($interface);
+ $lines = explode(' ', trim(shell_exec("ifconfig {$iface} | grep inet | grep -v inet6")));
+ $server_host = $lines[1];
+ } else
+ $server_host = "{$config['system']['hostname']}.{$config['system']['domain']}";
+ $server_port = $settings['local_port'];
+ $proto = ($settings['protocol'] == 'UDP' ? 'udp' : "tcp-client");
+ $cipher = $settings['crypto'];
+
+ // add basic settings
+ $conf = "dev tun\n";
+ $conf .= "persist-tun\n";
+ $conf .= "persist-key\n";
+ $conf .= "proto {$proto}\n";
+ $conf .= "cipher {$cipher}\n";
+ $conf .= "tls-client\n";
+ $conf .= "client\n";
+ $conf .= "resolv-retry infinite\n";
+ $conf .= "remote {$server_host} {$server_port}\n";
+
+ // add user auth settings
+ switch($settings['mode']) {
+ case 'server_user':
+ case 'server_tls_user':
+ $conf .= "auth-user-pass\n";
+ break;
+ }
+
+ // add key settings
+ $prefix = openvpn_client_export_prefix($srvid);
+ if ($usetoken) {
+ $conf .= "ca {$prefix}-ca.crt\n";
+ $conf .= "cryptoapicert \"SUBJ:{$user['name']}\"\n";
+ } else {
+ $conf .= "pkcs12 {$prefix}.p12\n";
+ }
+
+ if ($settings['tls'])
+ $conf .= "tls-auth {$prefix}-tls.key\n";
+
+ // add optional settings
+ if ($settings['compression'])
+ $conf .= "comp-lzo\n";
+ if ($settings['passtos'])
+ $conf .= "passtos\n";
+
+ return $conf;
+}
+
+function openvpn_client_export_installer($srvid, $usrid, $crtid, $useaddr, $usetoken, $outpass) {
+ global $config, $g;
+
+ $ovpndir = "/usr/local/share/openvpn";
+ $workdir = "{$ovpndir}/client-export";
+
+ // lookup server settings
+ $settings = $config['openvpn']['openvpn-server'][$srvid];
+ if (empty($settings))
+ return false;
+ if ($settings['disable'])
+ return false;
+
+ // lookup server certificate info
+ $server_cert =& lookup_cert($settings['certref']);
+ $server_ca =& lookup_ca($server_cert['caref']);
+ if (!$server_cert || !$server_ca)
+ return false;
+
+ // lookup user info
+ $user =& $config['system']['user'][$usrid];
+ if (!$user)
+ return false;
+
+ // lookup user certificate info
+ $cert =& $user['cert'][$crtid];
+ if (!$cert)
+ return false;
+
+ // create template directory
+ $tempdir = $g['tmp_path']."/openvpn-export-".uniqid();
+ mkdir($tempdir, 0700, true);
+
+ // create config directory
+ $confdir = "{$tempdir}/config";
+ if (!is_dir($conf_dir))
+ mkdir($confdir, 0700, true);
+
+ // copy the template directory
+ exec("cp -r {$workdir}/template/* {$tempdir}");
+
+ // write cofiguration file
+ $prefix = openvpn_client_export_prefix($srvid);
+ $cfgfile = "{$confdir}/{$prefix}-config.ovpn";
+ $conf = openvpn_client_export_config($srvid, $usrid, $crtid, $useaddr, $usetoken);
+ if (!$conf)
+ return false;
+ file_put_contents($cfgfile, $conf);
+
+ // write key files
+ $cafile = "{$tempdir}/config/{$prefix}-ca.crt";
+ file_put_contents($cafile, base64_decode($server_ca['crt']));
+ $crtfile = "{$tempdir}/config/{$prefix}-{$user['name']}.crt";
+ file_put_contents($crtfile, base64_decode($cert['crt']));
+ $keyfile = "{$tempdir}/config/{$prefix}-{$user['name']}.key";
+ file_put_contents($keyfile, base64_decode($cert['prv']));
+ if ($settings['tls']) {
+ $tlsfile = "{$tempdir}/config/{$prefix}-tls.key";
+ file_put_contents($tlsfile, base64_decode($settings['tls']));
+ }
+
+ // convert to pkcs12 format
+ $p12file = "{$tempdir}/config/{$prefix}.p12";
+ if ($usetoken)
+ openvpn_client_pem_to_pk12($p12file, $outpass, $crtfile, $keyfile);
+ else
+ openvpn_client_pem_to_pk12($p12file, $outpass, $crtfile, $keyfile, $cafile);
+
+ // 7zip the configuration data
+ chdir($tempdir);
+ $files = "config ";
+ $files .= "procchain.exe ";
+ $files .= "openvpn-install.exe ";
+ $files .= "openvpn-postinstall.exe ";
+ if ($usetoken)
+ $files .= "procchain-import";
+ else
+ $files .= "procchain-standard";
+ exec("/usr/local/libexec/p7zip/7z -y a archive.7z {$files}");
+
+ // create the final installer
+ $outfile = "{$tempdir}-install.exe";
+ chdir($g['tmp_path']);
+ if ($usetoken)
+ exec("/bin/cat {$tempdir}/7zS.sfx {$tempdir}/config-import {$tempdir}/archive.7z > {$outfile}");
+ else
+ exec("/bin/cat {$tempdir}/7zS.sfx {$tempdir}/config-standard {$tempdir}/archive.7z > {$outfile}");
+
+ // cleanup
+ exec("/bin/rm -r {$tempdir}");
+
+ return $outfile;
+}
+
+?>
diff --git a/config/openvpn-client-export/openvpn-client-export.xml b/config/openvpn-client-export/openvpn-client-export.xml
new file mode 100755
index 00000000..611d6a83
--- /dev/null
+++ b/config/openvpn-client-export/openvpn-client-export.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<packagegui>
+ <name>OpenVPN Client Export</name>
+ <version>0.0.1</version>
+ <title>OpenVPN Client Export</title>
+ <include_file>/usr/local/pkg/openvpn-client-export.inc</include_file>
+ <backup_file></backup_file>
+ <aftersaveredirect></aftersaveredirect>
+ <configpath></configpath>
+ <tabs>
+ <tab>
+ <name>Client Export</name>
+ <tabgroup>OpenVPN</tabgroup>
+ <url>/vpn_openvpn_export.php</url>
+ </tab>
+ </tabs>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>077</chmod>
+ <item>http://www.pfsense.com/packages/config/openvpn-client-export/openvpn-client-export.inc</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/tmp/</prefix>
+ <chmod>077</chmod>
+ <item>http://www.pfsense.com/packages/config/openvpn-client-export/openvpn-client-export.tgz</item>
+ </additional_files_needed>
+ <adddeleteeditpagefields>
+ <columnitem>
+ <fielddescr></fielddescr>
+ <fieldname></fieldname>
+ </columnitem>
+ </adddeleteeditpagefields>
+ <fields>
+ <field>
+ <fielddescr></fielddescr>
+ <fieldname></fieldname>
+ <description></description>
+ <size></size>
+ <type></type>
+ </field>
+ </fields>
+ <custom_php_install_command>
+ openvpn_client_export_install();
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ openvpn_client_export_deinstall();
+ </custom_php_deinstall_command>
+</packagegui>
diff --git a/config/openvpn-client-export/readme.txt b/config/openvpn-client-export/readme.txt
new file mode 100755
index 00000000..c1c0e3b7
--- /dev/null
+++ b/config/openvpn-client-export/readme.txt
@@ -0,0 +1,44 @@
+pfSense OpenVPN Client Export Package
+-------------------------------------
+
+This package includes a webConfigurator interface that allows for easy
+expory of user based OpenVPN configurations and pre-configured windows
+installer packages.
+
+Contents
+--------
+client-export - tgz archive root path
+client-export/vpn_openvpn_export.php - pfSense php interface code
+client-export/template - installer template path
+client-export/template/7zS.sfx - 7zip windows self extractor
+client-export/template/config-import - 7zip sfx configuration
+client-export/template/config-standard - 7zip sfx configuration
+client-export/template/procchain.exe - process chain utility
+client-export/template/openvpn-install.exe - openvpn installer
+client-export/template/openvpn-postinstall.exe - post installer
+client-export/template/procchain-import - procchain configuration
+client-export/template/procchain-standard - procchain configuration
+client-export/template/config - OpenVPN configuration import path
+source/openvpn-postinstall.nsi - post install NSIS script
+source/openvpn-postinstall.ico - post install icon
+source/procchain.cpp - C++ source for process chain utility
+openvpn-client-export.inc - pfSense php pagkage include file
+openvpn-client-export.xml - pfSense xml package description
+
+Configuration
+-------------
+Before the package can be used, place the OpenVPN installer of your
+choice in the template directory and name it 'openvpn-install.exe'.
+Then use tar to archive the entire client-export directory from the
+root package directory using the following command ...
+
+tar zcvf openvpn-client-export.tgz client-export
+
+With the archive created, you will have three relevent files in the
+root package directory ...
+
+openvpn-client-export.inc
+openvpn-client-export.tgz
+openvpn-client-export.xml
+
+These files are the only files required for distribution.
diff --git a/config/openvpn-client-export/source/openvpn-postinstall.ico b/config/openvpn-client-export/source/openvpn-postinstall.ico
new file mode 100755
index 00000000..03ea0b1d
--- /dev/null
+++ b/config/openvpn-client-export/source/openvpn-postinstall.ico
Binary files differ
diff --git a/config/openvpn-client-export/source/openvpn-postinstall.nsi b/config/openvpn-client-export/source/openvpn-postinstall.nsi
new file mode 100755
index 00000000..d23ecdb4
--- /dev/null
+++ b/config/openvpn-client-export/source/openvpn-postinstall.nsi
@@ -0,0 +1,112 @@
+;--------------------------------
+; OpenVPN NSIS Post-Installer
+;--------------------------------
+
+;--------------------------------
+;Include Modern UI
+
+ !include "MUI.nsh"
+ !include "FileFunc.nsh"
+ !include "LogicLib.nsh"
+
+;--------------------------------
+; General
+;--------------------------------
+
+ Name "OpenVPN Configuration"
+ OutFile "openvpn-postinstall.exe"
+ SetCompressor /SOLID lzma
+
+ ShowInstDetails show
+
+;--------------------------------
+;Include Settings
+;--------------------------------
+
+ !define MUI_ICON "openvpn-postinstall.ico"
+ !define MUI_ABORTWARNING
+
+;--------------------------------
+;Pages
+;--------------------------------
+
+ !insertmacro MUI_PAGE_INSTFILES
+ !insertmacro Locate
+ !insertmacro GetParameters
+ !insertmacro GetOptions
+
+;--------------------------------
+;Languages
+;--------------------------------
+
+ !insertmacro MUI_LANGUAGE "English"
+
+;--------------------------------
+;Functions
+;--------------------------------
+
+Function .onInit
+
+ Var /GLOBAL CONFPATH
+ ReadRegStr $CONFPATH HKLM "Software\OpenVPN" "config_dir"
+
+FunctionEnd
+
+Function CopyConfFile
+
+ CopyFiles $R9 $CONFPATH\$R7
+ Push $0
+
+FunctionEnd
+
+Function ImportConfFile
+
+ ExecWait "rundll32.exe cryptext.dll,CryptExtAddPFX $R9"
+ Push $0
+
+FunctionEnd
+
+;--------------------------------
+;Installer Sections
+;--------------------------------
+
+Section "Imort Configuration" SectionImport
+
+ DetailPrint "Installing configuration files ..."
+ ${Locate} ".\config" "/L=F /M=*.ovpn" "CopyConfFile"
+
+ DetailPrint "Installing certificate and key files ..."
+ ${Locate} ".\config" "/L=F /M=*.crt" "CopyConfFile"
+ ${Locate} ".\config" "/L=F /M=*.key" "CopyConfFile"
+
+ ${GetParameters} $R0
+ ${GetOptions} $R0 "/Import" $R1
+ IfErrors p12_copy p12_import
+
+ p12_copy:
+ ${Locate} ".\config" "/L=F /M=*.p12" "CopyConfFile"
+ Goto p12_done
+
+ p12_import:
+ ${Locate} ".\config" "/L=F /M=*.p12" "ImportConfFile"
+ Goto p12_done
+
+ p12_done:
+
+SectionEnd
+
+;--------------------------------
+;Descriptions
+;--------------------------------
+
+ ;Language strings
+ LangString DESC_SectionImport ${LANG_ENGLISH} "Import OpenVPN Configurations and Key Files."
+
+ ;Assign language strings to sections
+ !insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
+ !insertmacro MUI_DESCRIPTION_TEXT ${SectionImport} $(DESC_SectionImport)
+ !insertmacro MUI_FUNCTION_DESCRIPTION_END
+
+;--------------------------------
+; END
+;--------------------------------
diff --git a/config/openvpn-client-export/source/procchain.cpp b/config/openvpn-client-export/source/procchain.cpp
new file mode 100755
index 00000000..b95536cc
--- /dev/null
+++ b/config/openvpn-client-export/source/procchain.cpp
@@ -0,0 +1,80 @@
+
+/*
+ * Copyright (c) 2008
+ * Shrew Soft Inc. All rights reserved.
+ *
+ * AUTHOR : Matthew Grooms
+ * mgrooms@shrew.net
+ *
+ */
+
+#include <windows.h>
+#include <stdio.h>
+
+bool runproc( char * path )
+{
+ STARTUPINFO si;
+ memset( &si, 0, sizeof( si ) );
+ si.cb = sizeof( si );
+
+ PROCESS_INFORMATION pi;
+ memset( &pi, 0, sizeof( pi ) );
+
+ // Start the child process.
+ if( !CreateProcess(
+ NULL, // No module name (use command line).
+ path, // Command line.
+ NULL, // Process handle not inheritable.
+ NULL, // Thread handle not inheritable.
+ FALSE, // Set handle inheritance to FALSE.
+ 0, // No creation flags.
+ NULL, // Use parent's environment block.
+ NULL, // Use parent's starting directory.
+ &si, // Pointer to STARTUPINFO structure.
+ &pi ) ) // Pointer to PROCESS_INFORMATION structure.
+ {
+ return false;
+ }
+
+ // Wait until child process exits.
+ WaitForSingleObject( pi.hProcess, INFINITE );
+
+ // Get the exit code
+ DWORD ExitCode;
+ GetExitCodeProcess( pi.hProcess, &ExitCode );
+
+ // Close process and thread handles.
+ CloseHandle( pi.hProcess );
+ CloseHandle( pi.hThread );
+
+ return ( ExitCode == 0 );
+}
+
+int APIENTRY WinMain(
+ HINSTANCE hinstance,
+ HINSTANCE hPrevInstance,
+ LPSTR lpCmdLine,
+ int nCmdShow )
+{
+ FILE * fp;
+ if( fopen_s( &fp, lpCmdLine, "r" ) )
+ return -1;
+
+ while( true )
+ {
+ char cmd[ MAX_PATH ];
+ memset( cmd, 0, MAX_PATH );
+ if( fgets( cmd, MAX_PATH, fp ) == NULL )
+ break;
+
+ char * term = strchr( cmd, '\n' );
+ if( term != NULL )
+ *term = 0;
+
+ if( !runproc( cmd ) )
+ return -2;
+ }
+
+ return 0;
+}
+
diff --git a/config/p3scan-pf/p3scan-pf-emer.xml b/config/p3scan-pf/p3scan-pf-emer.xml
new file mode 100644
index 00000000..da39aef8
--- /dev/null
+++ b/config/p3scan-pf/p3scan-pf-emer.xml
@@ -0,0 +1,131 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <!-- change this if configpath works -->
+ <name>p3scanpfemer</name>
+ <version>1.0</version>
+ <title>Services: POP3 Proxy: Emergency Contact</title>
+ <include_file>p3scan-pf.inc</include_file>
+ <tabs>
+ <tab>
+ <text>Daemon Settings</text>
+ <url>/pkg_edit.php?xml=p3scan-pf.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Transparent Proxy Exclusion</text>
+ <url>/pkg.php?xml=p3scan-pf-transex.xml</url>
+ </tab>
+ <tab>
+ <text>Message Processing</text>
+ <url>/pkg_edit.php?xml=p3scan-pf-msg.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Emergency Contact</text>
+ <url>/pkg.php?xml=p3scan-pf-emer.xml</url>
+ <active />
+ </tab>
+ <tab>
+ <text>Virus Scanner Settings</text>
+ <url>/pkg_edit.php?xml=p3scan-pf-vir.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>SPAM Settings</text>
+ <url>/pkg_edit.php?xml=p3scan-pf-spam.xml&amp;id=0</url>
+ </tab>
+ </tabs>
+ <!--
+ configpath gets expanded out automatically and config items
+ will be stored in that location
+ -->
+ <configpath>['installedpackages']['p3scanpf']['config']['contacts']</configpath>
+ <!--
+ adddeleteeditpagefields items will appear on the first page where you can
+ add / delete or edit items. An example of this would be the nat page where
+ you add new nat redirects
+ -->
+ <adddeleteeditpagefields>
+ <columnitem>
+ <fielddescr>Email Address</fielddescr>
+ <fieldname>emailaddress</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Description</fielddescr>
+ <fieldname>description</fieldname>
+ </columnitem>
+ </adddeleteeditpagefields>
+ <!--
+ fields gets invoked when the user adds or edits a item. The following items
+ will be parsed and rendered for the user as a gui with input, and selectboxes.
+ -->
+ <fields>
+ <field>
+ <fielddescr>Email Address</fielddescr>
+ <fieldname>emailaddress</fieldname>
+ <description>
+ In the event p3scan encounters a catastrophic problem and has to terminate,
+ it will send an email to these email addresses just before setting up to
+ close down on the next iteration of a child process.
+ </description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Description</fielddescr>
+ <fieldname>description</fieldname>
+ <description>Description.</description>
+ <type>input</type>
+ </field>
+ </fields>
+ <!--
+ Arbitrary PHP Code, that gets executed if a certain event gets triggered.
+ -->
+ <custom_delete_php_command>
+ sync_package_p3scan();
+ </custom_delete_php_command>
+ <custom_php_resync_config_command>
+ sync_package_p3scan();
+ </custom_php_resync_config_command>
+</packagegui>
diff --git a/config/p3scan-pf/p3scan-pf-msg.xml b/config/p3scan-pf/p3scan-pf-msg.xml
new file mode 100644
index 00000000..d3f81aa2
--- /dev/null
+++ b/config/p3scan-pf/p3scan-pf-msg.xml
@@ -0,0 +1,202 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <!-- change this if configpath works -->
+ <name>p3scanpfmsg</name>
+ <version>1.0</version>
+ <title>Services: POP3 Proxy: Message Processing</title>
+ <note>
+ This &lt;acronym title=&quot;Hypertext Markup Language&quot;&gt;HTML&lt;/acronym&gt; page uses default values, hence even if each field is
+ set, you are still required to save this page if you are editing this page
+ for the very first time!
+ </note>
+ <aftersaveredirect>pkg_edit.php?xml=p3scan-pf-msg.xml&amp;id=0</aftersaveredirect>
+ <include_file>p3scan-pf.inc</include_file>
+ <tabs>
+ <tab>
+ <text>Daemon Settings</text>
+ <url>/pkg_edit.php?xml=p3scan-pf.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Transparent Proxy Exclusion</text>
+ <url>/pkg.php?xml=p3scan-pf-transex.xml</url>
+ </tab>
+ <tab>
+ <text>Message Processing</text>
+ <url>/pkg_edit.php?xml=p3scan-pf-msg.xml&amp;id=0</url>
+ <active />
+ </tab>
+ <tab>
+ <text>Emergency Contact</text>
+ <url>/pkg.php?xml=p3scan-pf-emer.xml</url>
+ </tab>
+ <tab>
+ <text>Virus Scanner Settings</text>
+ <url>/pkg_edit.php?xml=p3scan-pf-vir.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>SPAM Settings</text>
+ <url>/pkg_edit.php?xml=p3scan-pf-spam.xml&amp;id=0</url>
+ </tab>
+ </tabs>
+ <!--
+ configpath gets expanded out automatically and config items
+ will be stored in that location
+ -->
+ <configpath>['installedpackages']['p3scanpf']['config']['messaging']</configpath>
+ <!--
+ fields gets invoked when the user adds or edits a item. The following items
+ will be parsed and rendered for the user as a gui with input, and selectboxes.
+ -->
+ <fields>
+ <field>
+ <fielddescr>Just Delete</fielddescr>
+ <fieldname>justdelete</fieldname>
+ <description>
+ Instead of keeping an infected message in the Virus Directory, delete it
+ after reporting it to the user.
+ </description>
+ <type>checkbox</type>
+ <donotdisable>true</donotdisable>
+ </field>
+ <field>
+ <fielddescr>Bytes Free</fielddescr>
+ <fieldname>bytesfree</fieldname>
+ <description>The number of KB's there must be free before processing any mail.</description>
+ <type>input</type>
+ <required />
+ <default_value>10000</default_value>
+ </field>
+ <field>
+ <fielddescr>Broken Email Clients</fielddescr>
+ <fieldname>brokenec</fieldname>
+ <description>
+ Some email clients may require special processing.
+ </description>
+ <type>checkbox</type>
+ <donotdisable>true</donotdisable>
+ </field>
+ <field>
+ <fielddescr>ISP Spam</fielddescr>
+ <fieldname>ispspam</fieldname>
+ <description>
+ This option allows you to set the string your &lt;acronym title=&quot;Internet Service Provider&quot;&gt;ISP&lt;/acronym&gt; uses if it processes
+ your email for SPAM. Leave this field blank if you are not going to use
+ this option.
+ </description>
+ <type>input</type>
+ <default_value>-- Spam --</default_value>
+ </field>
+ <field>
+ <fielddescr>Subject</fielddescr>
+ <fieldname>subject</fieldname>
+ <description>
+ This option can be used to change the default subject line when
+ reporting a virus infected message.
+ </description>
+ <type>input</type>
+ <size>60</size>
+ <required />
+ <default_value>Subject: "[Virus] found in a mail to you:" &lt;virus name&gt;</default_value>
+ </field>
+ <field>
+ <fielddescr>Notify</fielddescr>
+ <fieldname>notify</fieldname>
+ <description>
+ This option can be used to change the default file deleted notification
+ that is displayed in the virus notification message when the
+ &quot;justdelete&quot; option is used.
+ </description>
+ <type>input</type>
+ <size>60</size>
+ <required />
+ <default_value>Per instruction, the message has been deleted.</default_value>
+ </field>
+ <field>
+ <fielddescr>SMTP Reject</fielddescr>
+ <fieldname>smtpreject</fieldname>
+ <description>
+ This option can be used to change the default &lt;acronym title=&quot;Simple Mail Transfer Protocol&quot;&gt;SMTP&lt;/acronym&gt; Reject message that
+ is sent to the client in the event a message is rejected due to a virus.
+ The error message will have a prefix of &quot;554&quot;.
+ </description>
+ <type>input</type>
+ <size>60</size>
+ <required />
+ <default_value>Virus detected! P3scan rejected message!</default_value>
+ </field>
+ <field>
+ <fielddescr>Check SMTP size</fielddescr>
+ <fieldname>checksize</fieldname>
+ <description>
+ This option can be used to set the maximum message size (in KBytes)
+ that p3scan will use to determine if it should scan an smtp submission.
+ Leave this field blank if you are not going to use this option.
+ </description>
+ <type>input</type>
+ <default_value>1024</default_value>
+ </field>
+ <field>
+ <fielddescr>Footer</fielddescr>
+ <fieldname>footer</fieldname>
+ <description>
+ This option is used to add the virus definition info from your scanner
+ to an SMTP message. Leave this field blank if you are not going to use
+ this option.
+ </description>
+ <type>input</type>
+ <size>40</size>
+ <default_value>/usr/local/bin/clamdscan -V</default_value>
+ </field>
+ </fields>
+ <!--
+ Arbitrary PHP Code, that gets executed if a certain event gets triggered.
+ -->
+ <custom_php_resync_config_command>
+ sync_package_p3scan();
+ </custom_php_resync_config_command>
+</packagegui>
diff --git a/config/p3scan-pf/p3scan-pf-spam.xml b/config/p3scan-pf/p3scan-pf-spam.xml
new file mode 100644
index 00000000..86301a50
--- /dev/null
+++ b/config/p3scan-pf/p3scan-pf-spam.xml
@@ -0,0 +1,122 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <!-- change this if configpath works -->
+ <name>p3scanpfspam</name>
+ <version>1.0</version>
+ <title>Services: POP3 Proxy: SPAM Settings</title>
+ <note>
+ This &lt;acronym title=&quot;Hypertext Markup Language&quot;&gt;HTML&lt;/acronym&gt; page uses default values, hence even if each field is
+ set, you are still required to save this page if you are editing this page
+ for the very first time!
+ </note>
+ <aftersaveredirect>pkg_edit.php?xml=p3scan-pf-spam.xml&amp;id=0</aftersaveredirect>
+ <include_file>p3scan-pf.inc</include_file>
+ <tabs>
+ <tab>
+ <text>Daemon Settings</text>
+ <url>/pkg_edit.php?xml=p3scan-pf.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Transparent Proxy Exclusion</text>
+ <url>/pkg.php?xml=p3scan-pf-transex.xml</url>
+ </tab>
+ <tab>
+ <text>Message Processing</text>
+ <url>pkg_edit.php?xml=p3scan-pf-msg.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Emergency Contact</text>
+ <url>/pkg.php?xml=p3scan-pf-emer.xml</url>
+ </tab>
+ <tab>
+ <text>Virus Scanner Settings</text>
+ <url>/pkg_edit.php?xml=p3scan-pf-vir.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>SPAM Settings</text>
+ <url>/pkg_edit.php?xml=p3scan-pf-spam.xml&amp;id=0</url>
+ <active />
+ </tab>
+ </tabs>
+ <!--
+ configpath gets expanded out automatically and config items
+ will be stored in that location
+ -->
+ <configpath>['installedpackages']['p3scanpf']['config']['spam']</configpath>
+ <!--
+ fields gets invoked when the user adds or edits a item. The following items
+ will be parsed and rendered for the user as a gui with input, and selectboxes.
+ -->
+ <fields>
+ <field>
+ <fielddescr>Enable Spam Checking</fielddescr>
+ <fieldname>checkspam</fieldname>
+ <description>
+ If set, will scan for Spam before scanning for a virus.
+ </description>
+ <type>checkbox</type>
+ <donotdisable>true</donotdisable>
+ <enablefields>spamcheck</enablefields>
+ </field>
+ <field>
+ <fielddescr>SPAM Executable Command</fielddescr>
+ <fieldname>spamcheck</fieldname>
+ <description>The command (plus arguments) that should be invoked to check for SPAM messages.</description>
+ <type>input</type>
+ <size>70</size>
+ <!-- the below tag plus its inline text must be on one single line. -->
+ <default_value>/usr/local/bin/dspam --user dspamuser --mode=teft --stdout --deliver=innocent,spam --feature=ch,no,wh</default_value>
+ </field>
+ </fields>
+ <!--
+ Arbitrary PHP Code, that gets executed if a certain event gets triggered.
+ -->
+ <custom_php_resync_config_command>
+ sync_package_p3scan();
+ </custom_php_resync_config_command>
+</packagegui>
diff --git a/config/p3scan-pf/p3scan-pf-transex.xml b/config/p3scan-pf/p3scan-pf-transex.xml
new file mode 100644
index 00000000..e1b2070a
--- /dev/null
+++ b/config/p3scan-pf/p3scan-pf-transex.xml
@@ -0,0 +1,124 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <!-- change this if configpath works -->
+ <name>p3scanpftransex</name>
+ <version>1.0</version>
+ <title>Services: POP3 Proxy: Exclude from Transparent Proxy</title>
+ <note>
+ Below you will have the opportunity to define specific IP addresses
+ which should be exempt from beeing served via transparent proxying.
+ </note>
+ <include_file>p3scan-pf.inc</include_file>
+ <tabs>
+ <tab>
+ <text>Daemon Settings</text>
+ <url>/pkg_edit.php?xml=p3scan-pf.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Transparent Proxy Exclusion</text>
+ <url>/pkg.php?xml=p3scan-pf-transex.xml</url>
+ <active />
+ </tab>
+ <tab>
+ <text>Message Processing</text>
+ <url>/pkg_edit.php?xml=p3scan-pf-msg.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Emergency Contact</text>
+ <url>/pkg.php?xml=p3scan-pf-emer.xml</url>
+ </tab>
+ <tab>
+ <text>Virus Scanner Settings</text>
+ <url>/pkg_edit.php?xml=p3scan-pf-vir.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>SPAM Settings</text>
+ <url>/pkg_edit.php?xml=p3scan-pf-spam.xml&amp;id=0</url>
+ </tab>
+ </tabs>
+ <!--
+ configpath gets expanded out automatically and config items
+ will be stored in that location
+ -->
+ <configpath>['installedpackages']['p3scanpf']['config']['virus']</configpath>
+
+ <adddeleteeditpagefields>
+ <columnitem>
+ <fielddescr>Exempted IP</fielddescr>
+ <fieldname>ip</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Description</fielddescr>
+ <fieldname>description</fieldname>
+ </columnitem>
+ </adddeleteeditpagefields>
+ <!--
+ fields gets invoked when the user adds or edits a item. The following items
+ will be parsed and rendered for the user as a gui with input, and selectboxes.
+ -->
+ <fields>
+ <field>
+ <fielddescr>Exempted IP</fielddescr>
+ <fieldname>ip</fieldname>
+ <description>Enter the IP to exempt from transparent proxy</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Description</fielddescr>
+ <fieldname>description</fieldname>
+ <description>Enter the description for this item</description>
+ <type>input</type>
+ </field>
+ </fields>
+ <!--
+ Arbitrary PHP Code, that gets executed if a certain event gets triggered.
+ -->
+ <custom_php_resync_config_command>
+ sync_package_p3scan();
+ </custom_php_resync_config_command>
+</packagegui>
diff --git a/config/p3scan-pf/p3scan-pf-vir.xml b/config/p3scan-pf/p3scan-pf-vir.xml
new file mode 100644
index 00000000..d96e8a87
--- /dev/null
+++ b/config/p3scan-pf/p3scan-pf-vir.xml
@@ -0,0 +1,166 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <!-- change this if configpath works -->
+ <name>p3scanpfvir</name>
+ <version>1.0</version>
+ <title>Services: POP3 Proxy: Virus Scanner Settings</title>
+ <note>
+ This &lt;acronym title=&quot;Hypertext Markup Language&quot;&gt;HTML&lt;/acronym&gt; page uses default values, hence even if each field is
+ set, you are still required to save this page if you are editing this page
+ for the very first time!
+ </note>
+ <aftersaveredirect>pkg_edit.php?xml=p3scan-pf-vir.xml&amp;id=0</aftersaveredirect>
+ <include_file>p3scan-pf.inc</include_file>
+ <tabs>
+ <tab>
+ <text>Daemon Settings</text>
+ <url>/pkg_edit.php?xml=p3scan-pf.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Transparent Proxy Exclusion</text>
+ <url>/pkg.php?xml=p3scan-pf-transex.xml</url>
+ </tab>
+ <tab>
+ <text>Message Processing</text>
+ <url>/pkg_edit.php?xml=p3scan-pf-msg.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Emergency Contact</text>
+ <url>/pkg.php?xml=p3scan-pf-emer.xml</url>
+ </tab>
+ <tab>
+ <text>Virus Scanner Settings</text>
+ <url>/pkg_edit.php?xml=p3scan-pf-vir.xml&amp;id=0</url>
+ <active />
+ </tab>
+ <tab>
+ <text>SPAM Settings</text>
+ <url>/pkg_edit.php?xml=p3scan-pf-spam.xml&amp;id=0</url>
+ </tab>
+ </tabs>
+ <!--
+ configpath gets expanded out automatically and config items
+ will be stored in that location
+ -->
+ <configpath>['installedpackages']['p3scanpf']['config']['virus']</configpath>
+ <!--
+ fields gets invoked when the user adds or edits a item. The following items
+ will be parsed and rendered for the user as a gui with input, and selectboxes.
+ -->
+ <fields>
+ <field>
+ <fielddescr>Scanner Type</fielddescr>
+ <fieldname>scannertype</fieldname>
+ <description>Select here which type of scanner you want to use.</description>
+ <type>select</type>
+ <size>1</size>
+ <default_value>clamd</default_value>
+ <options>
+ <option><name>Kaspersky Anti-Virus for Linux</name><value>avpd</value></option>
+ <option><name>Kaspersky Anti-Virus for Linux (New)</name><value>avpd_new</value></option>
+ <option><name>Shell Script</name><value>bash</value></option>
+ <option><name>Default Scanner Type</name><value>basic</value></option>
+ <option><name>Clam Anti-Virus</name><value>clamd</value></option>
+ <option><name>Trophie Daemon</name><value>trophie</value></option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Virusscanner</fielddescr>
+ <fieldname>scanner</fieldname>
+ <description>Depends on scannertype.</description>
+ <type>input</type>
+ <required />
+ <default_value>127.0.0.1:3310</default_value>
+ </field>
+ <field>
+ <fielddescr>Scanner Returncode</fielddescr>
+ <fieldname>viruscode</fieldname>
+ <description>
+ Specify the returncode(s) which the scanner returns when
+ the mail is infected.
+ </description>
+ <type>input</type>
+ <default_value>1</default_value>
+ </field>
+ <field>
+ <fielddescr>Good Scanner return codes</fielddescr>
+ <fieldname>goodcode</fieldname>
+ <description>
+ Some scanners can report more than good or infected. Place valid return
+ codes here that will enable the message to be delivered without a warning.
+ </description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Regular Expression for Virusname</fielddescr>
+ <fieldname>virusregexp</fieldname>
+ <description>
+ Specify here a regular expression which describes where the name of
+ the virus can be found.
+ </description>
+ <type>input</type>
+ <default_value>.*: (.*) FOUND</default_value>
+ </field>
+ <field>
+ <fielddescr>deMIME Setting</fielddescr>
+ <fieldname>demime</fieldname>
+ <description>
+ Tick this if we should parse all &lt;acronym title=&quot;Multipurpose Internet Mail Extensions&quot;&gt;MIME&lt;/acronym&gt;-sections instead of passing the
+ message as-is to the scanner.
+ </description>
+ <type>checkbox</type>
+ <donotdisable>true</donotdisable>
+ </field>
+ </fields>
+ <!--
+ Arbitrary PHP Code, that gets executed if a certain event gets triggered.
+ -->
+ <custom_php_resync_config_command>
+ sync_package_p3scan();
+ </custom_php_resync_config_command>
+</packagegui>
diff --git a/config/p3scan-pf/p3scan-pf.inc b/config/p3scan-pf/p3scan-pf.inc
new file mode 100644
index 00000000..b6f497b2
--- /dev/null
+++ b/config/p3scan-pf/p3scan-pf.inc
@@ -0,0 +1,395 @@
+<?php
+/* $Id$ */
+/*
+ $RCSfile$
+ Copyright (C) 2006 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Copyright (C) 2006 Fernando Lemos
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notices,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notices, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/* ====================== USAGE NOTE: ====================== */
+/* Depending on your use case scenario, this software may */
+/* depend on the following software packages: */
+/* */
+/* - renatach (part of the FreeBSD ports collection) */
+/* - a virus scanner (e.g. ClamAV) */
+/* - a spam filter (e.g. DSPAM or SpamAssassin) */
+/* ========================================================= */
+
+
+/* include all configuration functions */
+require_once("functions.inc");
+require_once("notices.inc");
+
+function sync_package_p3scan() {
+ global $config, $g;
+ conf_mount_rw();
+ config_lock();
+ $fd = fopen("/etc/p3scan.conf","w");
+
+ /* shorten the config path */
+ $cfg = $config['installedpackages']['p3scanpf']['config'][0];
+ $cfgmsg = $config['installedpackages']['p3scanpfmsg']['config'][0];
+ $cfgemer = $config['installedpackages']['p3scanpfemer']['config'];
+ $cfgvir = $config['installedpackages']['p3scanpfvir']['config'][0];
+ $cfgspam = $config['installedpackages']['p3scanpfspam']['config'][0];
+
+ fwrite($fd, "## p3scan-pf config file - generated by pfSense.\n##\n");
+ fwrite($fd, "## at: " . date("l dS of F Y h:i:s A") . "\n##\n");
+ /* ================================================================ */
+ /* == Tab: Daemon Settings == */
+ /* ================================================================ */
+ fwrite($fd, "## Daemon Settings.\n");
+ fwrite($fd, "pidfile = /var/run/p3scan/p3scan.pid\n");
+ if (isset($cfg['maxchilds']) && $cfg['maxchilds'] <> "")
+ fwrite($fd, "maxchilds = {$cfg['maxchilds']}\n");
+ else
+ fwrite($fd, "maxchilds = 10\n");
+ if (isset($cfg['ipaddr']) && $cfg['ipaddr'] <> "")
+ fwrite($fd, "ip = {$cfg['ipaddr']}\n");
+ else
+ fwrite($fd, "ip = 127.0.0.1\n");
+ if (isset($cfg['port']) && $cfg['port'] <> "")
+ fwrite($fd, "port = {$cfg['port']}\n");
+ else
+ fwrite($fd, "port = 8110\n");
+ if (isset($cfg['sslport']) && $cfg['sslport'] <> "")
+ fwrite($fd, "sslport = {$cfg['sslport']}\n");
+ else
+ fwrite($fd, "sslport = 995\n");
+ if (isset($cfg['targetip']) && $cfg['targetip'] <> "") {
+ if ($cfg['targetip'] == "0.0.0.0")
+ setup_transparency();
+ else
+ remove_transparency();
+ fwrite($fd, "targetip = {$cfg['targetip']}\n");
+ } else {
+ setup_transparency();
+ fwrite($fd, "targetip = 0.0.0.0\n");
+ }
+ if (isset($cfg['targetport']) && $cfg['targetport'] <> "")
+ fwrite($fd, "targetport = {$cfg['targetport']}\n");
+ else
+ fwrite($fd, "targetport = 8110\n");
+ if (isset($cfg['emailport']) && $cfg['emailport'] <> "")
+ fwrite($fd, "emailport = {$cfg['emailport']}\n");
+ else
+ fwrite($fd, "emailport = 25\n");
+ if (isset($cfg['daemonuser']) && $cfg['daemonuser'] <> "")
+ fwrite($fd, "user = {$cfg['daemonuser']}\n");
+ else
+ fwrite($fd, "user = root\n");
+ fwrite($fd, "notifydir = /var/spool/p3scan/notify\n");
+ fwrite($fd, "virusdir = /var/spool/p3scan\n");
+ fwrite($fd, "template = /usr/local/etc/p3scan/p3scan.mail\n");
+
+ /* ================================================================ */
+ /* == Tab: Message Processing == */
+ /* ================================================================ */
+ fwrite($fd, "## Message Processing Settings.\n");
+ if (isset($cfgmsg['justdelete']) && $cfgmsg['justdelete'] <> "")
+ fwrite($fd, "justdelete\n");
+ if (isset($cfgmsg['bytesfree']) && $cfgmsg['bytesfree'] <> "")
+ fwrite($fd, "bytesfree = {$cfgmsg['bytesfree']}\n");
+ else
+ fwrite($fd, "bytesfree = 10000\n");
+ if (isset($cfgmsg['broken']) && $cfgmsg['broken'] <> "")
+ fwrite($fd, "broken\n");
+ if (isset($cfgmsg['timeout']) && $cfgmsg['timeout'] <> "")
+ fwrite($fd, "timeout = {$cfgmsg['timeout']}\n");
+ else
+ fwrite($fd, "timeout = 30\n");
+ if (isset($cfgmsg['ispspam']) && $cfgmsg['ispspam'] <> "")
+ fwrite($fd, "ispspam = {$cfgmsg['ispspam']}\n");
+ if (file_exists("/usr/local/bin/renattach"))
+ fwrite($fd, "renattach = /usr/local/bin/renattach\n");
+ if (isset($cfgmsg['subject']) && $cfgmsg['subject'] <> "")
+ fwrite($fd, "subject = {$cfgmsg['subject']}\n");
+ else
+ fwrite($fd, "subject = Subject: \"[Virus] found in a mail to you:\" <virus name>\n");
+ if (isset($cfgmsg['notify']) && $cfgmsg['notify'] <> "")
+ fwrite($fd, "notify = {$cfgmsg['notify']}\n");
+ else
+ fwrite($fd, "notify = Per instruction, the message has been deleted.\n");
+ if (isset($cfgmsg['smtpreject']) && $cfgmsg['smtpreject'] <> "")
+ fwrite($fd, "smtprset = {$cfgmsg['smtpreject']}\n");
+ else
+ fwrite($fd, "smtprset = Virus detected! P3scan rejected message!\n");
+ if (isset($cfgmsg['checksize']) && $cfgmsg['checksize'] <> "")
+ fwrite($fd, "checksize = {$cfgmsg['checksize']}\n");
+ if (isset($cfgmsg['footer']) && $cfgmsg['footer'] <> "")
+ fwrite($fd, "footer = {$cfgmsg['footer']}\n");
+
+ /* ================================================================ */
+ /* == Tab: Emergency Contact == */
+ /* ================================================================ */
+ fwrite($fd, "## Emergency Contacts.\n");
+ if (is_array($cfgemer)) {
+ foreach ($cfgemer as $addr) {
+ $contact .= "{$addr['emailaddress']} ";
+ }
+ if (isset($contact) && $contact <> "")
+ fwrite($fd, "emergcon = {$contact}\n");
+ }
+
+ /* ================================================================ */
+ /* == Tab: Virus Scanner Settings == */
+ /* ================================================================ */
+ fwrite($fd, "## Virus Scanner Settings.\n");
+ if (isset($cfgvir['scannertype']) && $cfgvir['scannertype'] <> "")
+ fwrite($fd, "scannertype = {$cfgvir['scannertype']}\n");
+ else
+ fwrite($fd, "scannertype = clamd\n");
+ if (isset($cfgvir['scanner']) && $cfgvir['scanner'] <> "")
+ fwrite($fd, "scanner = {$cfgvir['scanner']}\n");
+ else
+ fwrite($fd, "scanner = 127.0.0.1:3310\n");
+ if (isset($cfgvir['viruscode']) && $cfgvir['viruscode'] <> "")
+ fwrite($fd, "viruscode = {$cfgvir['viruscode']}\n");
+ else
+ fwrite($fd, "viruscode = 1\n");
+ if (isset($cfgvir['goodcode']) && $cfgvir['goodcode'] <> "")
+ fwrite($fd, "goodcode = {$cfgvir['goodcode']}\n");
+ if (isset($cfgvir['virusregexp']) && $cfgvir['virusregexp'] <> "")
+ fwrite($fd, "virusregexp = {$cfgvir['virusregexp']}\n");
+ if (isset($cfgvir['demime']) && $cfgvir['demime'] <> "")
+ fwrite($fd, "demime\n");
+
+ /* ================================================================ */
+ /* == Tab: SPAM Settings == */
+ /* ================================================================ */
+ if ((isset($cfgspam['checkspam']) && $cfgspam['checkspam'] <> "") ||
+ $config['installedpackages']['sassassin']['config'][0]['enable'] == 'on') {
+ fwrite($fd, "## SPAM Settings.\n");
+ fwrite($fd, "checkspam\n");
+ if (isset($cfgspam['spamcheck']) && $cfgspam['spamcheck'] <> "") {
+ /* most times the command line for the spam binary becomes
+ * quite lengthy, which my be the reason that users are
+ * the XML tag and the command line itself into several
+ * lines. Thus strip whitespaces.
+ */
+ $cfgspam['spamcheck'] = trim($cfgspam['spamcheck']);
+ fwrite($fd, "spamcheck = {$cfgspam['spamcheck']}\n");
+ } else {
+ if ($config['installedpackages']['sassassin']['config'][0]['enable'] == 'on') {
+ fwrite($fd, "spamcheck = /usr/bin/spamc\n");
+ } else {
+ fwrite($fd, "spamcheck = /usr/local/bin/dspam --user dspamuser --mode=teft --stdout --deliver=innocent,spam --feature=ch,no,wh\n");
+ }
+ }
+ }
+
+ fclose($fd);
+
+ /* NOTE: The following code requires the p3scan-pf.inc file to
+ * be saved with UNIX Linefeeds. LF that is and NOT CR LF.
+ */
+ $start = <<<EOD
+test_p3scan_user=`cat /etc/passwd | grep p3scan`
+test_p3scan_group=`cat /etc/passwd | grep p3scan`
+
+if [ -z "\${test_p3scan_group}" ]; then
+ pw groupadd p3scan -g 108
+fi
+
+if [ -z "\${test_p3scan_user}" ]; then
+ pw useradd p3scan -u 108 -g p3scan -d /var/spool/p3scan -s /sbin/nologin -c 'P3Scan Daemon'
+fi
+
+if [ ! -d "/var/spool/p3scan" ]; then
+ mkdir /var/spool/p3scan && chown p3scan:p3scan /var/spool/p3scan
+fi
+
+if [ ! -d "/var/spool/p3scan/children" ]; then
+ mkdir /var/spool/p3scan/children && chown p3scan:p3scan /var/spool/p3scan/children
+fi
+
+if [ ! -d "/var/spool/p3scannotify" ]; then
+ mkdir /var/spool/p3scannotify && chown p3scan:p3scan /var/spool/p3scannotify
+fi
+
+if [ ! -d "/var/run/p3scan" ]; then
+ mkdir /var/run/p3scan && chown p3scan:p3scan /var/run/p3scan
+fi
+
+/sbin/mount_fdescfs fdescfs /dev/fd
+/usr/local/sbin/p3scan --configfile=/usr/local/etc/p3scan/p3scan.conf &
+
+EOD;
+
+ $stop = "/usr/bin/killall p3scan\n" .
+ "sleep 2";
+
+ if (! file_exists("/usr/local/etc/rc.d/030.p3scan.sh")) {
+ write_rcfile(array(
+ "file" => "030.p3scan.sh",
+ "start" => $start,
+ "stop" => $stop
+ )
+ );
+ }
+
+ /* finally get rid of files that were instaled by the package */
+ removePackageLeftovers();
+
+ conf_mount_ro();
+ config_unlock();
+
+ if (! file_exists("/usr/local/etc/p3scan")) {
+ mkdir("/usr/local/etc/p3scan");
+ }
+ if (! file_exists("/usr/local/etc/p3scan/p3scan.conf")) {
+ mwexec("ln -s /etc/p3scan.conf /usr/local/etc/p3scan/p3scan.conf");
+ }
+ if (! file_exists("/usr/local/etc/p3scan/p3scan.mail")) {
+ $fd = fopen("/usr/local/etc/p3scan/p3scan.mail","w");
+
+ $p3scanmail = <<<EOD
+MIME-Version: 1.0
+Content-Transfer-Encoding: 8bit
+Content-Type: text/plain;
+ charset="iso-8859-1"
+
+Hello %USERNAME%.
+This message body was generated automatically from P3Scan, which runs on
+%HOSTNAME%.%DOMAINNAME% for scanning all incoming email.
+
+It replaces the body of a message sent to you that contained a VIRUS!
+
+Instead of the infected email this message has been sent to you.
+
+You may look at the message header of this message for the complete
+email header information of the infected message.
+
+Virus name:
+ %VIRUSNAME%
+(Supposed) Sender of the email:
+ %MAILFROM%
+Sent To:
+ %MAILTO%
+On Date:
+ %MAILDATE%
+Subject:
+ %SUBJECT%
+Connection data:
+ %PROTOCOL% from %CLIENTIP%:%CLIENTPORT% to %SERVERIP%:%SERVERPORT%
+Message File:
+ %P3SCANID%
+Virus Definition Info:
+ %VDINFO%
+--
+%PROGNAME% %VERSION%
+by Jack S. Lai <laitcg@cox.net>
+
+EOD;
+
+ fwrite($fd, $p3scanmail);
+ fclose($fd);
+ }
+
+ mwexec("/usr/local/etc/rc.d/030.p3scan.sh stop");
+ /* test whether a pid file still exists and remove it if necessary */
+ if (! is_service_running("p3scan-pf"))
+ unlink_if_exists("/var/run/p3scan/p3scan.pid");
+ mwexec("/usr/local/etc/rc.d/030.p3scan.sh start");
+
+ return 0;
+}
+
+function custom_php_install_command() {
+ global $config, $g;
+ sync_package_p3scan();
+}
+
+function custom_php_deinstall_command() {
+ global $config, $g;
+ conf_mount_rw();
+
+ if (is_service_running("p3scan-pf"))
+ stop_service("p3scan-pf");
+
+ unlink_if_exists("/usr/local/etc/p3scan/p3scan.conf");
+ unlink_if_exists("/usr/local/etc/p3scan/p3scan.mail");
+ unlink_if_exists("/usr/local/etc/rc.d/030.p3scan.sh");
+ rmdir("/usr/local/etc/p3scan");
+ mwexec("rm -rf /var/spool/p3scan");
+ mwexec("rm -rf /var/run/p3scan");
+ mwexec("rm -rf /var/run/p3scan");
+
+ conf_mount_ro();
+}
+
+function removePackageLeftovers() {
+ unlink_if_exists("/usr/local/etc/rc.d/p3scan.sh");
+ unlink_if_exists("/usr/local/etc/p3scan.conf.sample");
+ unlink_if_exists("/usr/local/etc/p3scan.mail.sample");
+
+}
+
+function add_trans_table(){
+ global $config;
+
+ /* Flush all entries first, and then add them. */
+ $p3scan_pf_result = mwexec ('pfctl -a "rdr-package/p3scan" -t p3scan -T flush');
+ if($p3scan_pf_result <> 0) {
+ file_notice("P3SCAN", "There were error(s) flushing the exclude table", "P3SCAN", "");
+ }
+ if($config['installedpackages']['p3scanpftransex']['config'] != ""){
+ foreach($config['installedpackages']['p3scanpftransex']['config'] as $tmp) {
+ $p3scan_pf_result = mwexec ('pfctl -a "rdr-package/p3scan" -t p3scan -T add ' . $tmp['ip']);
+ if($p3scan_pf_result <> 0) {
+ file_notice("P3SCAN", "There were error(s) adding the ip " . $tmp['ip'], "P3SCAN", "");
+ }
+ }
+ }
+}
+
+function remove_transparency() {
+ $p3scan_pf_result = mwexec ('pfctl -a "rdr-package/p3scan" -t p3scan -T flush');
+ if($p3scan_pf_result <> 0) {
+ file_notice("P3SCAN", "There were error(s) flushing the exclude table", "P3SCAN", "");
+ }
+}
+
+function setup_transparency() {
+ global $config;
+ $cfg = $config['installedpackages']['p3scanpf']['config'][0];
+ $ip = $cfg['ipaddr'];
+ $port = $cfg['port'];
+
+ if ($ip == "" || $port == "") { return; }
+
+ $trans_file = fopen("/tmp/p3scan_pf.rules","w");
+ fwrite($trans_file, "table <p3scan> persist\n");
+ fwrite($trans_file, "rdr on " . $config['interfaces']['lan']['if'] . " inet proto tcp from !<p3scan> to ! " . $config['interfaces']['lan']['ipaddr'] . " port = pop3 -> {$ip} port {$port} \n");
+ fclose($trans_file);
+ $p3scan_pf_result = mwexec ('pfctl -a "rdr-package/p3scan" -f /tmp/p3scan_pf.rules');
+ if($p3scan_pf_result <> 0) {
+ file_notice("P3SCAN", "There were error(s) loading the transparency rules", "P3SCAN", "");
+ }
+ add_trans_table();
+}
+?> \ No newline at end of file
diff --git a/config/p3scan-pf/p3scan-pf.xml b/config/p3scan-pf/p3scan-pf.xml
new file mode 100644
index 00000000..f309cb50
--- /dev/null
+++ b/config/p3scan-pf/p3scan-pf.xml
@@ -0,0 +1,218 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>p3scanpf</name>
+ <version>1.0</version>
+ <title>Services: POP3 Proxy: Main</title>
+ <note>
+ This &lt;acronym title=&quot;Hypertext Markup Language&quot;&gt;HTML&lt;/acronym&gt; page uses default values, hence even if each field is
+ set, you are still required to save this page if you are editing this page
+ for the very first time!
+ </note>
+ <aftersaveredirect>pkg_edit.php?xml=p3scan-pf.xml&amp;id=0</aftersaveredirect>
+ <include_file>p3scan-pf.inc</include_file>
+ <!-- Menu is where this packages menu will appear -->
+ <menu>
+ <name>POP3 Proxy</name>
+ <tooltiptext>A transparent POP3-Proxy with virus-scanning capabilities</tooltiptext>
+ <section>Services</section>
+ <configfile>p3scan-pf.xml</configfile>
+ <url>/pkg_edit.php?xml=p3scan-pf.xml&amp;id=0</url>
+ </menu>
+ <service>
+ <name>p3scan-pf</name>
+ <rcfile>030.p3scan.sh</rcfile>
+ <executable>p3scan</executable>
+ <description>POP3 virus/spam scanner.</description>
+ </service>
+ <tabs>
+ <tab>
+ <text>Daemon Settings</text>
+ <url>/pkg_edit.php?xml=p3scan-pf.xml&amp;id=0</url>
+ <active />
+ </tab>
+ <tab>
+ <text>Transparent Proxy Exclusion</text>
+ <url>/pkg.php?xml=p3scan-pf-transex.xml</url>
+ </tab>
+ <tab>
+ <text>Message Processing</text>
+ <url>/pkg_edit.php?xml=p3scan-pf-msg.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Emergency Contact</text>
+ <url>/pkg.php?xml=p3scan-pf-emer.xml</url>
+ </tab>
+ <tab>
+ <text>Virus Scanner Settings</text>
+ <url>/pkg_edit.php?xml=p3scan-pf-vir.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>SPAM Settings</text>
+ <url>/pkg_edit.php?xml=p3scan-pf-spam.xml&amp;id=0</url>
+ </tab>
+ </tabs>
+ <!--
+ configpath gets expanded out automatically and config items
+ will be stored in that location
+ -->
+ <configpath>['installedpackages']['p3scanpf']['config']</configpath>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/p3scan-pf/p3scan-pf-msg.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/p3scan-pf/p3scan-pf-transex.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/p3scan-pf/p3scan-pf-emer.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/p3scan-pf/p3scan-pf-vir.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/p3scan-pf/p3scan-pf-spam.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/p3scan-pf/p3scan-pf.inc</item>
+ </additional_files_needed>
+ <!--
+ fields gets invoked when the user adds or edits a item. The following items
+ will be parsed and rendered for the user as a gui with input, and selectboxes.
+ -->
+ <fields>
+ <field>
+ <fielddescr>Max Child's</fielddescr>
+ <fieldname>maxchilds</fieldname>
+ <description>The maximum number of connections we will handle at once.</description>
+ <type>input</type>
+ <default_value>10</default_value>
+ </field>
+ <field>
+ <fielddescr>IP Address</fielddescr>
+ <fieldname>ipaddr</fieldname>
+ <description>The &lt;acronym title=&quot;Internet Protocol&quot;&gt;IP&lt;/acronym&gt; Address we listen on.</description>
+ <type>input</type>
+ <required />
+ <default_value>127.0.0.1</default_value>
+ </field>
+ <field>
+ <fielddescr>Port</fielddescr>
+ <fieldname>port</fieldname>
+ <description>The &lt;acronym title=&quot;Transmission Control Protocol&quot;&gt;TCP&lt;/acronym&gt; port on we should listen.</description>
+ <type>input</type>
+ <required />
+ <default_value>8110</default_value>
+ </field>
+ <field>
+ <fielddescr>SSL Port</fielddescr>
+ <fieldname>sslport</fieldname>
+ <description>The TCP &lt;acronym title=&quot;Secure Sockets Layer&quot;&gt;SSL&lt;/acronym&gt; port on we should listen.</description>
+ <type>input</type>
+ <required />
+ <default_value>995</default_value>
+ </field>
+ <field>
+ <fielddescr>Target IP</fielddescr>
+ <fieldname>targetip</fieldname>
+ <description>Target IP is the IP to connect (0.0.0.0 enables transparent mode).</description>
+ <type>input</type>
+ <required />
+ <default_value>0.0.0.0</default_value>
+ </field>
+ <field>
+ <fielddescr>Target Port</fielddescr>
+ <fieldname>targetport</fieldname>
+ <description>Target Port is the port to connect.</description>
+ <type>input</type>
+ <required />
+ <default_value>8110</default_value>
+ </field>
+ <field>
+ <fielddescr>Email Port</fielddescr>
+ <fieldname>emailport</fieldname>
+ <description>The port we should listen on to scan outgoing email messages.</description>
+ <type>input</type>
+ <required />
+ <default_value>25</default_value>
+ </field>
+ <field>
+ <fielddescr>Daemon User</fielddescr>
+ <fieldname>daemonuser</fieldname>
+ <description>The username the daemon should run as.</description>
+ <type>input</type>
+ <required />
+ <default_value>root</default_value>
+ </field>
+ </fields>
+ <!--
+ Arbitrary PHP Code, that gets executed if a certain event gets triggered.
+ -->
+ <custom_delete_php_command>
+ sync_package_p3scan();
+ </custom_delete_php_command>
+ <custom_php_resync_config_command>
+ sync_package_p3scan();
+ </custom_php_resync_config_command>
+ <custom_php_install_command>
+ custom_php_install_command();
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ custom_php_deinstall_command();
+ </custom_php_deinstall_command>
+</packagegui>
diff --git a/config/p3scan.inc b/config/p3scan.inc
new file mode 100644
index 00000000..4f9a025b
--- /dev/null
+++ b/config/p3scan.inc
@@ -0,0 +1,61 @@
+<?php
+require_once('globals.inc');
+require_once('config.inc');
+require_once('util.inc');
+require_once('service-utils.inc');
+require_once('filter.inc');
+
+define('VIRUSDIR', '/var/tmp/p3scan');
+
+function p3scan_install_command() {
+ global $g;
+
+ $pidfile = "{$g['varrun_path']}/p3scan.pid";
+ $rcfile = array();
+ $rcfile['file'] = 'p3scan.sh';
+ $rcfile['start'] = "p3scan -f /usr/local/etc/p3scan.conf -l $pidfile";
+ $rcfile['stop'] = "kill `cat $pidfile`\nrm $pidfile";
+ write_rcfile($rcfile);
+
+ make_dirs(VIRUSDIR);
+ chown(VIRUSDIR, 'proxy');
+ chmod(VIRUSDIR, 0700);
+ make_dirs(VIRUSDIR . '/children');
+ chown(VIRUSDIR, 'proxy');
+ chmod(VIRUSDIR, 0700);
+
+ p3scan_resync();
+}
+
+function p3scan_resync() {
+ global $g, $config;
+
+ $virusdir = VIRUSDIR;
+ $conf = <<<EOD
+ip = 127.0.0.1
+user = proxy
+justdelete
+virusregexp = .*: (.*) FOUND
+virusdir = $virusdir
+spamcheck = /usr/local/bin/spamc
+template = /usr/local/etc/p3scan.mail
+scannertype = basic
+
+EOD;
+
+ if ($config['installedpackages']['sassassin']['config'][0]['enable'] == 'on')
+ $conf .= "checkspam\n";
+
+ $virusen = $config['installedpackages']['clamav']['config'][0]['scan_pop3'];
+ if ($virusen == 'on')
+ $scanner = '/usr/local/bin/clamdscan --no-summary';
+ else
+ $scanner = 'echo';
+ $conf .= "scanner = $scanner\n";
+
+ file_put_contents('/usr/local/etc/p3scan.conf', $conf);
+
+ restart_service('p3scan');
+ filter_configure();
+}
+?>
diff --git a/config/p3scan.mail b/config/p3scan.mail
new file mode 100644
index 00000000..920e5c8c
--- /dev/null
+++ b/config/p3scan.mail
@@ -0,0 +1,15 @@
+To: %MAILTO%
+Date: %MAILDATE%
+Subject: *** VIRUS *** %SUBJECT%
+Content-Transfer-Encoding: 8bit
+Content-Type: text/plain; charset="iso8859-1"
+MIME-Version: 1.0
+
+Your message was scanned by the pfSense virus scanner for POP3, running on %HOSTNAME%.%DOMAINNAME%, and a virus was found. This email has been sent to you instead of the original infected email. The infected message has been deleted.
+
+The virus contained in the original message was %VIRUSNAME%. The sender of the email was %MAILFROM%.
+
+%FILESTATUS%
+
+Contact the system administrator for further details. This is an automated message, please do not reply to it.
+.
diff --git a/config/p3scan.xml b/config/p3scan.xml
new file mode 100644
index 00000000..9bc438ff
--- /dev/null
+++ b/config/p3scan.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>none</name>
+ <version>none</version>
+ <title>none</title>
+ <include_file>p3scan.inc</include_file>
+ <service>
+ <name>p3scan</name>
+ <rcfile>p3scan.sh</rcfile>
+ <executable>p3scan</executable>
+ <description>POP3 virus/spam scanner.</description>
+ </service>
+ <additional_files_needed>
+ <item>http://www.pfsense.org/packages/config/p3scan.inc</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/bin/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.org/packages/All/p3scan</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/etc/</prefix>
+ <item>http://www.pfsense.org/packages/config/p3scan.mail</item>
+ </additional_files_needed>
+ <custom_php_install_command>
+ p3scan_install_command();
+ </custom_php_install_command>
+</packagegui>
diff --git a/config/package_installation_overview.txt b/config/package_installation_overview.txt
new file mode 100644
index 00000000..7c5f40e8
--- /dev/null
+++ b/config/package_installation_overview.txt
@@ -0,0 +1,29 @@
+ Package installation process for pfSense
+
+
+ Client downloads pkg_config.xml
+ |
+ |
+ Client parses pkg_config.xml and generates a interface
+ of installable packages |
+ |
+ |
+ User selects a package to install
+ |
+ |
+ pkg_mgr.php downloads package master configuration files
+ |
+ |
+ pkg_mgr.php downloads master package and installs. pkg_add -r
+ takes care of downloading and installing all dependencies
+ |
+ |
+ pkg_mgr.php downloads "extra" files that are required such
+ as customized helper scripts, etc.
+ |
+ |
+ pkg_mgr.php interates through the menu section installing
+ needed menu items. |
+ |
+ Package and supporting items are now installed. The package
+ will be listed in "Installed Packages"
diff --git a/config/per-user-bandwidth-distribution.xml b/config/per-user-bandwidth-distribution.xml
new file mode 100644
index 00000000..08728380
--- /dev/null
+++ b/config/per-user-bandwidth-distribution.xml
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>peruserbw</name>
+ <version>1.0.2</version>
+ <title>Services: Per User Bandwidth</title>
+ <aftersaveredirect>pkg_edit.php?xml=per-user-bandwidth-distribution.xml&amp;id=0</aftersaveredirect>
+ <menu>
+ <name>PerUserBW</name>
+ <tooltiptext>Enforce a fair use bandwidth policy</tooltiptext>
+ <section>Services</section>
+ <url>pkg_edit.php?xml=per-user-bandwidth-distribution.xml&amp;id=0</url>
+ </menu>
+ <service>
+ <name>PerUserBW</name>
+ <rcfile>per_user_bandwidth_distribution.sh</rcfile>
+ </service>
+ <fields>
+ <field>
+ <fielddescr>Incoming Bandwidth</fielddescr>
+ <fieldname>incoming_bandwidth</fieldname>
+ <description>Enter the bandwidth you would like to distribute fairly among the clients:</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Incoming Bandwidth Type</fielddescr>
+ <fieldname>incoming_bandwidthtype</fieldname>
+ <type>select</type>
+ <options>
+ <option>
+ <name>Kbit/s</name>
+ <value>Kbit/s</value>
+ </option>
+ <option>
+ <name>Kbyte/s</name>
+ <value>Kbyte/s</value>
+ </option>
+ <option>
+ <name>Mbit/s</name>
+ <value>Mbit/s</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Outgoing Bandwidth</fielddescr>
+ <fieldname>outgoing_bandwidth</fieldname>
+ <description>Enter the bandwidth you would like to distribute fairly among the clients:</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Outgoing Bandwidth Type</fielddescr>
+ <fieldname>outgoing_bandwidthtype</fieldname>
+ <type>select</type>
+ <options>
+ <option>
+ <name>Kbit/s</name>
+ <value>Kbit/s</value>
+ </option>
+ <option>
+ <name>Kbyte/s</name>
+ <value>Kbyte/s</value>
+ </option>
+ <option>
+ <name>Mbit/s</name>
+ <value>Mbit/s</value>
+ </option>
+ </options>
+ </field>
+ </fields>
+ <custom_add_php_command>
+ conf_mount_rw();
+ $wanif = get_real_wan_interface();
+ $fd = fopen("/usr/local/etc/rc.d/per_user_bandwidth_distribution.sh","w");
+ fwrite($fd, "# This file was automatically generated by the pfSense\n");
+ fwrite($fd, "# package manager system\n\n");
+ fwrite($fd, "/sbin/kldload ipfw\n");
+ fwrite($fd, "/sbin/kldload dummynet\n");
+ fwrite($fd, "/sbin/ipfw delete 10\n");
+ fwrite($fd, "/sbin/ipfw pipe 101 config mask src-ip 0x000000ff bw {$_POST['incoming_bandwidth']}{$_POST['incoming_bandwidthtype']}\n");
+ fwrite($fd, "/sbin/ipfw pipe 102 config mask dst-ip 0x000000ff bw {$_POST['outgoing_bandwidth']}{$_POST['outgoing_bandwidthtype']}\n");
+ fwrite($fd, "/sbin/ipfw add 10 pipe 102 ip from any to any out via {$wanif}\n");
+ fwrite($fd, "/sbin/ipfw add 10 pipe 101 ip from any to any in via {$wanif}\n");
+ fwrite($fd, "/sbin/ipfw add 10 allow all from any to any\n");
+ fclose($fd);
+ mwexec("chmod a+rx /usr/local/etc/rc.d/per_user_bandwidth_distribution.sh");
+ mwexec_bg("/usr/local/etc/rc.d/per_user_bandwidth_distribution.sh");
+ $config['system']['dummynetshaper'] = true;
+ write_config();
+ conf_mount_ro();
+ </custom_add_php_command>
+ <custom_php_deinstall_command>
+ mwexec("/sbin/ipfw delete 10");
+ mwexec("/sbin/kldunload dummynet");
+ mwexec("/sbin/kldunload ipfw");
+ conf_mount_rw();
+ unlink_if_exists("/usr/local/etc/rc.d/per_user_bandwidth_distribution.sh");
+ unset($config['system']['dummynetshaper']);
+ write_config();
+ conf_mount_ro();
+ </custom_php_deinstall_command>
+</packagegui> \ No newline at end of file
diff --git a/config/pfflowd.xml b/config/pfflowd.xml
new file mode 100644
index 00000000..0a1798e5
--- /dev/null
+++ b/config/pfflowd.xml
@@ -0,0 +1,115 @@
+<packagegui>
+ <name>pfflowd</name>
+ <version>0.6</version>
+ <title>pfflowd: Settings</title>
+ <aftersaveredirect>pkg_edit.php?xml=pfflowd.xml&amp;id=0</aftersaveredirect>
+ <menu>
+ <name>pfflowd</name>
+ <tooltiptext>Modify pfflowd settings.</tooltiptext>
+ <section>Services</section>
+ <configfile>pfflowd.xml</configfile>
+ <url>/pkg_edit.php?xml=pfflowd.xml&amp;id=0</url>
+ </menu>
+ <service>
+ <name>pfflowd</name>
+ <rcfile>pfflowd.sh</rcfile>
+ <executable>pfflowd</executable>
+ </service>
+ <configpath>installedpackages->package->$packagename->configuration->settings</configpath>
+ <fields>
+ <field>
+ <fielddescr>Host</fielddescr>
+ <fieldname>host</fieldname>
+ <description>Specify the host that datagrams are to be sent to.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Port</fielddescr>
+ <fieldname>port</fieldname>
+ <description>Enter the port that datagrams are to be sent to.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>pf rule direction restriction</fielddescr>
+ <fieldname>direction</fieldname>
+ <description>Restrict creation of flow records to states matching a certain direction (in, out, or any).</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>Any</name>
+ <value>any</value>
+ </option>
+ <option>
+ <name>In</name>
+ <value>in</value>
+ </option>
+ <option>
+ <name>Out</name>
+ <value>out</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Netflow version</fielddescr>
+ <fieldname>version</fieldname>
+ <description>Select which version of the NetFlow protocol to use.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>5</name>
+ <value>5</value>
+ </option>
+ <option>
+ <name>4</name>
+ <value>4</value>
+ </option>
+ <option>
+ <name>3</name>
+ <value>3</value>
+ </option>
+ <option>
+ <name>2</name>
+ <value>2</value>
+ </option>
+ <option>
+ <name>1</name>
+ <value>1</value>
+ </option>
+ </options>
+ </field>
+ </fields>
+ <custom_php_global_functions>
+ function sync_package_pfflowd() {
+ conf_mount_rw();
+ config_lock();
+ global $config;
+ foreach($config['installedpackages']['pfflowd']['config'] as $cf) {
+ if($cf['host'] != "") {
+ $start = "\n/sbin/ifconfig pfsync0 up\n";
+ $start .= "/usr/local/sbin/pfflowd ";
+ $start .= " -n {$cf['host']}";
+ if($cf['port'] != "")
+ $start .= ":{$cf['port']}";
+ if($cf['direction'] != "")
+ $start .= " -S {$cf['direction']}";
+ if($cf['version'] != "")
+ $start .= " -v {$cf['version']}";
+ write_rcfile(array(
+ "file" => "pfflowd.sh",
+ "start" => $start,
+ "stop" => "/usr/bin/killall pfflowd"
+ )
+ );
+ restart_service("pfflowd");
+ break;
+ }
+ }
+ conf_mount_ro();
+ config_unlock();
+ }
+ </custom_php_global_functions>
+ <custom_add_php_command>
+ sync_package_pfflowd();
+ </custom_add_php_command>
+</packagegui>
+
diff --git a/config/pfstat.php b/config/pfstat.php
new file mode 100644
index 00000000..e0d25820
--- /dev/null
+++ b/config/pfstat.php
@@ -0,0 +1,70 @@
+#!/usr/local/bin/php
+<?php
+/*
+ pkg.php
+ Copyright (C) 2004 Scott Ullrich
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require("guiconfig.inc");
+
+function gentitle_pkg($pgname) {
+ global $config;
+ return $config['system']['hostname'] . "." . $config['system']['domain'] . " - " . $pgname;
+}
+
+$pgtitle = "Firewall: NAT: Port Forward";
+include("head.inc");
+
+?>
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<?php
+include("fbegin.inc");
+?>
+<p class="pgtitle"><?=$title?></p>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+
+<?php
+if($config['installedpackages']['pfstat']['config'] <> "") {
+ foreach($config['installedpackages']['pfstat']['config'] as $graph) {
+ echo "<table BORDERCOLOR=\"#990000\" width=\"100%\" border=\"1\" cellpadding=\"0\" cellspacing=\"0\">";
+ echo "<tr bgcolor='#990000'><td><center><font color='white'>" . $graph['graphname'] . "</td></tr>\n";
+ echo "<td><center><table width=\"100%\"><tr><td width='100%'>";
+ echo "<center><br><a href=\"/pfstat/" . $graph['imagename'] . "\"><img border=\"0\" width=\"500\" \"height\" src='/pfstat/" . $graph['imagename'] . "'></a>";
+ echo "</td></tr>";
+ echo "<tr bgcolor='#990000'><td><center><font color='white'>" . $graph['description'] . "</td></tr>";
+ echo "</table>\n";
+ echo "</td></tr>\n";
+ echo "</table>&nbsp;<br>";
+ }
+} else {
+
+echo "<center>There are currently no graphs defined.";
+
+}
+?>
+
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/pfstat.xml b/config/pfstat.xml
new file mode 100644
index 00000000..29d52bc2
--- /dev/null
+++ b/config/pfstat.xml
@@ -0,0 +1,324 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>pfstat</name>
+ <version>1.7</version>
+ <title>Services: PFStat Settings</title>
+ <!-- Menu is where this packages menu will appear -->
+ <menu>
+ <name>PFStat Settings</name>
+ <tooltiptext>pfstat is a small utility that collects packet filter statistics and produces graphs.</tooltiptext>
+ <section>Services</section>
+ <configfile>pfstat.xml</configfile>
+ </menu>
+ <menu>
+ <name>PFStat Graphs</name>
+ <tooltiptext>pfstat is a small utility that collects packet filter statistics and produces graphs.</tooltiptext>
+ <section>Status</section>
+ <url>/pfstat.php</url>
+ </menu>
+ <modify_system>
+ <modifyitem>
+ <modifyfilename>/etc/crontab</modifyfilename>
+ <textneeded>
+*/5 * * * * root nice -n 20 /usr/local/bin/pfstat -q >> /var/log/pfstat
+ </textneeded>
+ </modifyitem>
+ <modifyitem>
+ <modifyfilename>/etc/crontab</modifyfilename>
+ <textneeded>
+*/10 * * * * root nice -n 20 /usr/local/bin/pfstat -c /usr/local/etc/pfstat.conf -d /var/log/pfstat
+ </textneeded>
+ </modifyitem>
+ <modifyitem>
+ <modifyfilename>/etc/crontab</modifyfilename>
+ <textneeded>
+1 1 * * 1 root nice -n 20 tail -n 50000 /var/log/pfstat >/tmp/pfstat &amp;&amp; mv /tmp/pfstat /var/log/pfstat
+ </textneeded>
+ </modifyitem>
+ </modify_system>
+ <!-- configpath gets expanded out automatically and config items will be
+ stored in that location -->
+ <configpath>['installedpackages']['pfstat']['config']</configpath>
+ <adddeleteeditpagefields>
+ <columnitem>
+ <fielddescr>Graph Name</fielddescr>
+ <fieldname>graphname</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Description</fielddescr>
+ <fieldname>description</fieldname>
+ </columnitem>
+ </adddeleteeditpagefields>
+
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/pfstat.php</item>
+ </additional_files_needed>
+ <!-- modify system will modify a file and make sure the text needed to run the
+ package is in place. The following example edits /etc/crontab and adds the
+ code necessart to invoke the pfstat command every 5 minutes. -->
+ <!-- adddeleteeditpagefields items will appear on the first page where you can add / delete or edit
+ items. An example of this would be the nat page where you add new nat redirects -->
+ <!-- fields gets invoked when the user adds or edits a item. the following items
+ will be parsed and rendered for the user as a gui with input, and selectboxes. -->
+ <fields>
+ <field>
+ <fielddescr>Graph Name</fielddescr>
+ <fieldname>graphname</fieldname>
+ <description>Enter the name of the graph here</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Graph Description</fielddescr>
+ <fieldname>description</fieldname>
+ <description>Enter the description of the graph here</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Image Name</fielddescr>
+ <fieldname>imagename</fieldname>
+ <description>Enter the filename for this image. Must end in .jpg. ex. filename.jpg</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Graph Size Width</fielddescr>
+ <fieldname>graphsizewidth</fieldname>
+ <description>Graph width in pixels. Recommend 960 for large images, 320 for small images.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Graph Size Height</fielddescr>
+ <fieldname>graphsizeheight</fieldname>
+ <description>Graph height in pixels. Recommend 300 for large images, 200 for small images.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Update interval</fielddescr>
+ <fieldname>from</fieldname>
+ <description></description>
+ <type>input</type>
+ <size>1</size>
+ <value>1</value>
+ <combinefieldsbegin>true</combinefieldsbegin>
+ </field>
+ <field>
+ <fielddescr>Update interval duration</fielddescr>
+ <fieldname>fromclassification</fieldname>
+ <description></description>
+ <type>select</type>
+ <options>
+ <option><name>Minutes</name><value>minutes</value></option>
+ <option><name>Hours</name><value>hours</value></option>
+ <option><name>Days</name><value>days</value></option>
+ <option><name>Weeks</name><value>weeks</value></option>
+ <option><name>Months</name><value>months</value></option>
+ </options>
+ <combinefieldsend>true</combinefieldsend>
+ <dontdisplayname>true</dontdisplayname>
+ <dontcombinecells>true</dontcombinecells>
+ </field>
+ <field>
+ <fielddescr>none</fielddescr>
+ <fieldname>none</fieldname>
+ <type>rowhelper</type>
+ <rowhelper>
+ <rowhelperfield>
+ <fielddescr>Location</fielddescr>
+ <fieldname>location</fieldname>
+ <description>Location of graph</description>
+ <type>select</type>
+ <options>
+ <option><name>Left</name><value>left</value></option>
+ <option><name>Right</name><value>right</value></option>
+ </options>
+ </rowhelperfield>
+ <rowhelperfield>
+ <fielddescr>Graph Source</fielddescr>
+ <fieldname>counters</fieldname>
+ <description></description>
+ <type>select</type>
+ <options>
+ <option><name>Bytes in (IPv4)</name><value>bytes_v4_in</value></option>
+ <option><name>Bytes out (IPv4)</name><value>bytes_v4_out</value></option>
+ <option><name>Bytes in (IPv6)</name><value>bytes_v6_in</value></option>
+ <option><name>Bytes out (IPv6)</name><value>bytes_v6_out</value></option>
+ <option><name>Packets in passed (IPv4)</name><value>packets_v4_in_pass</value></option>
+ <option><name>Packets in dropped (IPv4)</name><value>packets_v4_in_drop</value></option>
+ <option><name>Packets out passed (IPv4)</name><value>packets_v4_out_pass</value></option>
+ <option><name>Packets out dropped (IPv4)</name><value>packets_v4_out_drop</value></option>
+ <option><name>Packets in passed (IPv6)</name><value>packets_v6_in_pass</value></option>
+ <option><name>Packets in dropped (IPv6)</name><value>packets_v6_in_drop</value></option>
+ <option><name>Packets out passed (IPv6)</name><value>packets_v6_out_pass</value></option>
+ <option><name>Packets out dropped (IPv6)</name><value>packets_v6_out_drop</value></option>
+ <option><name>State table entries</name><value>states_entries</value></option>
+ <option><name>State searches</name><value>states_searches</value></option>
+ <option><name>State Table Insertions</name><value>states_inserts</value></option>
+ <option><name>State Table Removals</name><value>states_removals</value></option>
+ <option><name>Match Counter</name><value>counters_match</value></option>
+ <option><name>Bad Offset Counter</name><value>counters_badoffset</value></option>
+ <option><name>Fragment Counter</name><value>counters_fragment</value></option>
+ <option><name>Short Counter</name><value>counters_short</value></option>
+ <option><name>Normalize Counter</name><value>counters_normalize</value></option>
+ <option><name>Memory Counter</name><value>counters_memory</value></option>
+ </options>
+ </rowhelperfield>
+ <rowhelperfield>
+ <fielddescr>Color</fielddescr>
+ <fieldname>color</fieldname>
+ <description>Color of graph</description>
+ <type>select</type>
+ <options>
+ <option><name>Light Hard Azure</name><value>51 153 255</value></option>
+ <option><name>Light Faded Blue</name><value>102 102 255</value></option>
+ <option><name>Blue</name><value>0 0 255</value></option>
+ <option><name>Dark Dull Red</name><value>153 51 51</value></option>
+ <option><name>Pale Weak Red</name><value>255 204 204</value></option>
+ <option><name>Red</name><value>255 204 204</value></option>
+ <option><name>Pale Weak Red</name><value>255 0 0</value></option>
+ <option><name>Light Hard Pink</name><value>255 51 153</value></option>
+ <option><name>Dark Dull Pink</name><value>153 51 102</value></option>
+ <option><name>Light Faded Red</name><value>255 102 102</value></option>
+ <option><name>Pale Weak Green</name><value>204 255 204</value></option>
+ <option><name>Green</name><value>0 255 0</value></option>
+ <option><name>Pale Weak Yellow</name><value>255 255 204</value></option>
+ <option><name>Yellow</name><value>125 125 0</value></option>
+ <option><name>Purple</name><value>72 00 190</value></option>
+ <option><name>Pale Weak Magenta</name><value>255 204 255</value></option>
+ <option><name>Pale Weak Cyan</name><value>204 255 255</value></option>
+ <option><name>Cyan</name><value>00 120 120</value></option>
+ <option><name>Dark Dull Cyan</name><value>51 153 153</value></option>
+ <option><name>Orange</name><value>255 255 0</value></option>
+ <option><name>Dark Dull Orange</name><value>153 102 51</value></option>
+ <option><name>Pale Dull Orange</name><value>255 204 153</value></option>
+ <option><name>Grey</name><value>125 125 125</value></option>
+ <option><name>Pale Gray</name><value>204 204 204</value></option>
+ <option><name>Black</name><value>0 0 0</value></option>
+ </options>
+ </rowhelperfield>
+ <rowhelperfield>
+ <fielddescr>Appearance</fielddescr>
+ <fieldname>appearance</fieldname>
+ <description>Appearance type</description>
+ <type>select</type>
+ <options>
+ <option><name>Filled</name><value>filled</value></option>
+ <option><name>Unfilled</name><value></value></option>
+ </options>
+ </rowhelperfield>
+ </rowhelper>
+ </field>
+ </fields>
+ <custom_php_global_functions>
+ function sync_package_pfstat() {
+ conf_mount_rw();
+ config_lock();
+ global $config;
+ $fout = fopen("/usr/local/etc/pfstat.conf","w");
+ if($config['installedpackages']['pfstat']['config'] != "") {
+ foreach($config['installedpackages']['pfstat']['config'] as $rowhelper) {
+ $leftgraphtext = "";
+ $rightgraphtext = "";
+ $isfirstleft = 0;
+ $isfirstright = 0;
+ $fromclassification = $rowhelper['fromclassification'];
+ $imagename = $rowhelper['imagename'];
+ $pos = strrpos($imagename, ".jpg");
+ if ($pos === false) {
+ $imagename .= ".jpg";
+ }
+ $from = $rowhelper['from'];
+ $graphsizewidth = $rowhelper['graphsizewidth'];
+ $graphsizeheight = $rowhelper['graphsizeheight'];
+ foreach($rowhelper['row'] as $row) {
+ if($row['location'] == "left") {
+ if($isfirstleft == 1) $leftgraphtext .= ",\n";
+ $leftgraphtext .= "graph " . $row['counters'] . " label \"" . $row['counters'] . "\" color " . $row['color'] . " " . $row['appearance'];
+ $isfirstleft = 1;
+ } else {
+ if($isfirstright == 1) $rightgraphtext .= ",\n";
+ $rightgraphtext .= "graph " . $row['counters'] . " label \"" . $row['counters'] . "\" color " . $row['color'] . " " . $row['appearance'];
+ $isfirstright = 1;
+ }
+ }
+ fwrite($fout, "image \"/usr/local/www/pfstat/" . $imagename ."\" { \n");
+ if($from == "") $from = "30";
+ fwrite($fout, "from " . $from . " " . $fromclassification . " to now \n");
+ fwrite($fout, "width " . $graphsizewidth . " height " . $graphsizeheight . " \n");
+ if($leftgraphtext != "") {
+ fwrite($fout, " left \n");
+ fwrite($fout, " " . $leftgraphtext . "\n");
+ }
+ if($rightgraphtext != "") {
+ fwrite($fout, " right \n");
+ fwrite($fout, " " . $rightgraphtext . "\n");
+ }
+ fwrite($fout, "}\n\n");
+ }
+ }
+ fclose($fout);
+ conf_mount_ro();
+ config_unlock();
+ }
+ </custom_php_global_functions>
+ <custom_php_command_before_form>
+ sync_package_pfstat();
+ </custom_php_command_before_form>
+ <custom_php_resync_config_command>
+ sync_package_pfstat();
+ </custom_php_resync_config_command>
+ <custom_php_install_command>
+ make_dirs("/usr/local/www/pfstat");
+ system("/usr/bin/killall cron 2>/dev/null");
+ system("/usr/sbin/cron 2>/dev/null");
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ unlink_if_exists("/usr/local/etc/pfstat");
+ rmdir_recursive("/usr/local/www/pfstat");
+ </custom_php_deinstall_command>
+</packagegui>
diff --git a/config/phpmrss.xml b/config/phpmrss.xml
new file mode 100644
index 00000000..3d144642
--- /dev/null
+++ b/config/phpmrss.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>phpmrss</name>
+ <version>0.13</version>
+ <title>mRSS</title>
+ <custom_delete_php_command>
+ </custom_delete_php_command>
+ <custom_php_resync_config_command>
+ </custom_php_resync_config_command>
+ <custom_php_install_command>
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ </custom_php_deinstall_command>
+</packagegui> \ No newline at end of file
diff --git a/config/phpservice/phpservice.inc b/config/phpservice/phpservice.inc
new file mode 100644
index 00000000..041dfafc
--- /dev/null
+++ b/config/phpservice/phpservice.inc
@@ -0,0 +1,229 @@
+<?php
+/* $Id$ */
+/*
+/* ========================================================================== */
+/*
+ phpservice.inc
+ Copyright (C) 2008 Mark J Crane
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+function pkg_is_service_running($servicename)
+{
+ exec("/bin/ps ax | awk '{ print $5 }'", $psout);
+ array_shift($psout);
+ foreach($psout as $line) {
+ $ps[] = trim(array_pop(explode(' ', array_pop(explode('/', $line)))));
+ }
+ if(is_service_running($servicename, $ps) or is_process_running($servicename) ) {
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+function byte_convert( $bytes ) {
+
+ if ($bytes<=0)
+ return '0 Byte';
+
+ $convention=1000; //[1000->10^x|1024->2^x]
+ $s=array('B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB');
+ $e=floor(log($bytes,$convention));
+ return round($bytes/pow($convention,$e),2).' '.$s[$e];
+}
+
+
+function phpservice_sync_package_php()
+{
+
+ global $config;
+ if($config['installedpackages']['phpservice']['config'] != "") {
+
+ conf_mount_rw();
+ config_unlock();
+
+
+ $tmp = "<?php\n";
+ $tmp .= "\n";
+ $tmp .= "// Set time limit to indefinite execution\n";
+ $tmp .= "set_time_limit (0);\n";
+ $tmp .= "\n";
+ $tmp .= "//run this program as long as the pid file exists\n";
+ $tmp .= "\$filename = '/tmp/phpmonitor.pid';\n";
+ $tmp .= "\$fp = fopen(\$filename, 'w');\n";
+ $tmp .= "fwrite(\$fp, \"If this file is deleted then phpmonitor will stop.\");\n";
+ $tmp .= "fclose(\$fp);\n";
+ $tmp .= "unset(\$filename);\n";
+ $tmp .= "\n";
+ $tmp .= "//require_once(\"config.inc\");\n";
+ $tmp .= "//global \$config;\n";
+ $tmp .= "//\$syslogaddress = \$config['syslog']['remoteserver'];\n";
+ $tmp .= "\$syslogaddress = \"127.0.0.1\";\n";
+ $tmp .= "\$syslogport = 514;\n";
+ $tmp .= "echo \"syslog server: \".\$syslogaddress.\"\\n\";\n";
+ $tmp .= "\n";
+ $tmp .= "\n";
+ $tmp .= "\n";
+ $tmp .= "function send_to_syslog(\$syslogaddress, \$syslogport, \$syslogmsg) {\n";
+ $tmp .= "\n";
+ $tmp .= " \$fp = fsockopen(\"udp://\".\$syslogaddress, \$syslogport, \$errno, \$errstr);\n";
+ $tmp .= " if (!\$fp) {\n";
+ $tmp .= " //echo \"ERROR: \$errno - \$errstr<br />\\n\";\n";
+ $tmp .= " } else {\n";
+ $tmp .= " fwrite(\$fp, \$syslogmsg);\n";
+ $tmp .= " fclose(\$fp);\n";
+ $tmp .= " }\n";
+ $tmp .= "\n";
+ $tmp .= "}\n";
+ $tmp .= "\n";
+ $tmp .= "\n";
+ $tmp .= "//\$msg = \"1.begin loop. \".date('r').\"\\n\";\n";
+ $tmp .= "//\$fp = fopen('/tmp/phpmonitor.txt', 'a');\n";
+ $tmp .= "//fwrite(\$fp, \$msg.\"\\n\");\n";
+ $tmp .= "//fclose(\$fp);\n";
+ $tmp .= "\n";
+ $tmp .= "\$x = 0;\n";
+ $tmp .= "while(\$x == 0) {\n";
+ $tmp .= "\n";
+ $tmp .= "\n";
+ $tmp .= " if(!file_exists('/tmp/phpmonitor.pid')) {\n";
+ $tmp .= " //if the file does not exist then close the program.\n";
+ $tmp .= " echo \"program closing\\n\";\n";
+ $tmp .= " return;\n";
+ $tmp .= " }\n";
+ $tmp .= "\n";
+ $tmp .= "\n";
+ $tmp .= "\n";
+
+ foreach($config['installedpackages']['phpservice']['config'] as $rowhelper) {
+ if ($rowhelper['enabled'] != "false") {
+ $tmp_php = base64_decode($rowhelper['php']);
+ if (strlen($tmp_php) > 0) {
+ $tmp .= "// name: ".$rowhelper['name']." \n";
+ $tmp .= "// description: ".$rowhelper['description']." \n\n";
+ $tmp .= base64_decode($rowhelper['php']);
+ $tmp .= "\n";
+ }
+ }
+
+ }
+
+ $tmp .= "\n";
+ $tmp .= "\n";
+ $tmp .= " //usleep(100000); //micro seconds //2 seconds 2000000\n";
+ $tmp .= " sleep(1); //in seconds\n";
+ $tmp .= " //if (\$x > 60){ exit; } //exit after 60 seconds for testing\n";
+ $tmp .= "} //emd while\n";
+ $tmp .= "\n";
+ $tmp .= "\n";
+ $tmp .= "?>";
+
+ $fout = fopen("/usr/local/pkg/phpservice.php","w");
+ fwrite($fout, $tmp);
+ unset($tmp);
+ fclose($fout);
+
+ conf_mount_ro();
+
+ }
+}
+
+
+function php_sync_package()
+{
+
+ global $config;
+ phpservice_sync_package_php();
+
+}
+
+
+function php_install_command()
+{
+
+ global $config;
+ conf_mount_rw();
+ config_lock();
+
+ if (!is_dir('/usr/local/www/packages/')) {
+ exec("mkdir /usr/local/www/packages/");
+ }
+
+ if (!is_dir('/usr/local/www/packages/phpservice/')) {
+ exec("mkdir /usr/local/www/packages/phpservice/");
+ }
+
+
+ //rename PHP files from .tmp to .php
+ exec("cp /tmp/phpservice_php.tmp /usr/local/www/packages/phpservice/phpservice_php.php");
+ unlink_if_exists("/tmp/phpservice_php.tmp");
+
+ exec("cp /tmp/phpservice_php_edit.tmp /usr/local/www/packages/phpservice/phpservice_php_edit.php");
+ unlink_if_exists("/tmp/phpservice_php_edit.tmp");
+
+
+ //write_config();
+
+
+ write_rcfile(array(
+ "file" => "phpservice.sh",
+ "start" => "/usr/local/bin/php /usr/local/pkg/phpservice.php",
+ "stop" => "rm /tmp/phpmonitor.pid"
+ )
+ );
+
+ php_sync_package();
+ //$handle = popen("/usr/local/etc/rc.d/phpservice.sh start", "r");
+ //pclose($handle);
+
+ //if (pkg_is_service_running('phpservice')) {
+ //documentation purposes
+ //}
+
+ conf_mount_ro();
+ config_unlock();
+
+}
+
+
+function deinstall_command()
+{
+
+ conf_mount_rw();
+ config_lock();
+ $handle = popen("/usr/local/etc/rc.d/phpservice.sh stop", "r");
+ unlink_if_exists("/usr/local/pkg/phpservice.xml");
+ unlink_if_exists("/usr/local/pkg/phpservice.inc");
+ unlink_if_exists("/usr/local/www/phpservice.inc");
+ unlink_if_exists("/usr/local/etc/rc.d/phpservice.sh");
+ conf_mount_ro();
+ config_unlock();
+
+}
+
+?> \ No newline at end of file
diff --git a/config/phpservice/phpservice.xml b/config/phpservice/phpservice.xml
new file mode 100644
index 00000000..e4cff8bc
--- /dev/null
+++ b/config/phpservice/phpservice.xml
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ phpservice.xml
+ Copyright (C) 2008 Mark J Crane
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>PHP Service</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>PHP Service Settings</name>
+ <version>0.3</version>
+ <title>Settings</title>
+ <include_file>/usr/local/pkg/phpservice.inc</include_file>
+ <menu>
+ <name>PHPService</name>
+ <tooltiptext>PHP Service settings.</tooltiptext>
+ <section>Services</section>
+ <configfile>phpservice.xml</configfile>
+ <url>/packages/phpservice/phpservice_php.php</url>
+ </menu>
+ <service>
+ <name>phpservice</name>
+ <rcfile>phpservice.sh</rcfile>
+ <executable>phpservice</executable>
+ <description>PHP run from a command line as a service.</description>
+ </service>
+ <tabs>
+ <tab>
+ <text>Settings</text>
+ <url>/pkg_edit.php?xml=phpservice.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Settings</text>
+ <url>/packages/phpservice_php.php</url>
+ <active/>
+ </tab>
+ </tabs>
+ <configpath>installedpackages->package->$packagename->configuration->phpservice</configpath>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/phpservice/phpservice.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/phpservice/phpservice.inc</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/tmp/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/phpservice/phpservice_php.tmp</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/tmp/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/phpservice/phpservice_php_edit.tmp</item>
+ </additional_files_needed>
+ <fields>
+ <field>
+ <fielddescr>Variable One</fielddescr>
+ <fieldname>var1</fieldname>
+ <description>Enter the variable one here.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Variable Two</fielddescr>
+ <fieldname>var1</fieldname>
+ <description>Enter the variable one here.</description>
+ <type>input</type>
+ </field>
+ </fields>
+ <custom_add_php_command>
+ </custom_add_php_command>
+ <custom_php_resync_config_command>
+ php_sync_package();
+ </custom_php_resync_config_command>
+ <custom_delete_php_command>
+ php_sync_package();
+ </custom_delete_php_command>
+ <custom_php_install_command>
+ php_install_command();
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ deinstall_command();
+ </custom_php_deinstall_command>
+</packagegui> \ No newline at end of file
diff --git a/config/phpservice/phpservice_php.tmp b/config/phpservice/phpservice_php.tmp
new file mode 100644
index 00000000..45ecf425
--- /dev/null
+++ b/config/phpservice/phpservice_php.tmp
@@ -0,0 +1,192 @@
+<?php
+/* $Id$ */
+/*
+ phpservice_php.php
+ Copyright (C) 2008 Mark J Crane
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require("guiconfig.inc");
+require("/usr/local/pkg/phpservice.inc");
+
+$a_phpservice = &$config['installedpackages']['phpservice']['config'];
+
+
+if ($_GET['act'] == "del") {
+ if ($_GET['type'] == 'php') {
+ if ($a_phpservice[$_GET['id']]) {
+ unset($a_phpservice[$_GET['id']]);
+ write_config();
+ header("Location: phpservice_php.php");
+ exit;
+ }
+ }
+}
+
+include("head.inc");
+
+?>
+
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<?php include("fbegin.inc"); ?>
+<p class="pgtitle">PHP Service:</p>
+
+<div id="mainlevel">
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+<tr><td class="tabnavtbl">
+<?php
+
+ $tab_array = array();
+ $tab_array[] = array(gettext("Settings"), false, "/packages/phpservice/phpservice_php.php");
+ display_top_tabs($tab_array);
+
+?>
+</td></tr>
+</table>
+
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabcont" >
+
+<form action="phpservice_php.php" method="post" name="iform" id="iform">
+<?php
+
+if ($config_change == 1) {
+ write_config();
+ $config_change = 0;
+}
+
+//if ($savemsg) print_info_box($savemsg);
+//if (file_exists($d_hostsdirty_path)): echo"<p>";
+//print_info_box_np("This is an info box.");
+//echo"<br />";
+//endif;
+
+?>
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td><p><!--<span class="vexpl"><span class="red"><strong>PHP Service<br></strong></span>-->
+ Is command line PHP designed to run PHP as a Service. The custom PHP code that is defined below is run over and over again inside a continuous loop. There are many possible uses such as monitoring CPU, Memory, File System Space, interacting with Snort, and many others uses that are yet to be discovered.
+ It can send events to the sylog that will can be viewed from the system log or remote syslog server. example: exec("logger This is a test");
+ <br /><br />
+ For more information see: <a href='http://doc.pfsense.org/index.php/PHPService'>http://doc.pfsense.org/index.php/PHPService</a>
+ </p></td>
+ </tr>
+ </table>
+ <br />
+
+ <table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td width="30%" class="listhdrr">Name</td>
+ <td width="20%" class="listhdrr">Enabled</td>
+ <td width="40%" class="listhdr">Description</td>
+ <td width="10%" class="list">
+
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td width="17"></td>
+ <td valign="middle"><a href="phpservice_php_edit.php"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" width="17" height="17" border="0"></a></td>
+ </tr>
+ </table>
+
+ </td>
+ </tr>
+
+
+ <?php
+
+ $i = 0;
+ if (count($a_phpservice) > 0) {
+
+ foreach ($a_phpservice as $ent) {
+
+ ?>
+ <tr>
+ <td class="listr" ondblclick="document.location='phpservice_php_edit.php?id=<?=$i;?>';">
+ <?=$ent['name'];?>&nbsp;
+ </td>
+ <td class="listr" ondblclick="document.location='phpservice_php_edit.php?id=<?=$i;?>';">
+ <?=$ent['enabled'];?>&nbsp;
+ </td>
+ <td class="listbg" ondblclick="document.location='phpservice_php_edit.php?id=<?=$i;?>';">
+ <font color="#FFFFFF"><?=htmlspecialchars($ent['description']);?>&nbsp;
+ </td>
+ <td valign="middle" nowrap class="list">
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td valign="middle"><a href="phpservice_php_edit.php?id=<?=$i;?>"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_e.gif" width="17" height="17" border="0"></a></td>
+ <td><a href="phpservice_php_edit.php?type=php&act=del&id=<?=$i;?>" onclick="return confirm('Do you really want to delete this?')"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_x.gif" width="17" height="17" border="0"></a></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <?php
+
+ $i++;
+ }
+ }
+ ?>
+
+ <tr>
+ <td class="list" colspan="3"></td>
+ <td class="list">
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td width="17"></td>
+ <td valign="middle"><a href="phpservice_php_edit.php"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" width="17" height="17" border="0"></a></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+
+
+ <tr>
+ <td class="list" colspan="3"></td>
+ <td class="list"></td>
+ </tr>
+ </table>
+
+</form>
+
+
+<br>
+<br>
+<br>
+<br>
+<br>
+<br>
+<br>
+<br>
+
+</td>
+</tr>
+</table>
+
+</div>
+
+
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/phpservice/phpservice_php_edit.tmp b/config/phpservice/phpservice_php_edit.tmp
new file mode 100644
index 00000000..070c87d1
--- /dev/null
+++ b/config/phpservice/phpservice_php_edit.tmp
@@ -0,0 +1,213 @@
+<?php
+/* $Id$ */
+/*
+
+ phpservice_php_edit.php
+ Copyright (C) 2008 Mark J Crane
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require("guiconfig.inc");
+require("/usr/local/pkg/phpservice.inc");
+
+
+$a_phpservice = &$config['installedpackages']['phpservice']['config'];
+
+$id = $_GET['id'];
+if (isset($_POST['id'])) {
+ $id = $_POST['id'];
+}
+
+if (isset($id) && $a_phpservice[$id]) {
+
+ $pconfig['name'] = $a_phpservice[$id]['name'];
+ $pconfig['php'] = base64_decode($a_phpservice[$id]['php']);
+ $pconfig['enabled'] = $a_phpservice[$id]['enabled'];
+ $pconfig['description'] = $a_phpservice[$id]['description'];
+
+}
+
+if ($_POST) {
+
+ unset($input_errors);
+ $pconfig = $_POST;
+
+ if (!$input_errors) {
+
+ $ent = array();
+ $ent['name'] = $_POST['name'];
+ $ent['php'] = base64_encode($_POST['php']);
+ $ent['enabled'] = $_POST['enabled'];
+ $ent['description'] = $_POST['description'];
+
+ if (isset($id) && $a_phpservice[$id]) {
+ //update
+ $a_phpservice[$id] = $ent;
+ }
+ else {
+ //add
+ $a_phpservice[] = $ent;
+ }
+
+ write_config();
+ php_sync_package();
+
+ header("Location: phpservice_php.php");
+ exit;
+ }
+}
+
+include("head.inc");
+
+?>
+
+<script type="text/javascript" language="JavaScript">
+
+function show_advanced_config() {
+ document.getElementById("showadvancedbox").innerHTML='';
+ aodiv = document.getElementById('showadvanced');
+ aodiv.style.display = "block";
+</script>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<?php include("fbegin.inc"); ?>
+<p class="pgtitle">PHP Service: Edit</p>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+
+
+<div id="mainlevel">
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+<tr><td class="tabnavtbl">
+<?php
+
+ $tab_array = array();
+ $tab_array[] = array(gettext("Settings"), false, "/packages/phpservice/phpservice_php.php");
+ display_top_tabs($tab_array);
+
+?>
+</td></tr>
+</table>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabcont" >
+
+ <!--
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td><p><span class="vexpl"><span class="red"><strong>PHP<br>
+ </strong></span>
+ </p></td>
+ </tr>
+ </table>
+ -->
+ <br />
+
+ <form action="phpservice_php_edit.php" method="post" name="iform" id="iform">
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+
+ <tr>
+ <td width="25%" valign="top" class="vncellreq">Name</td>
+ <td width="75%" class="vtable">
+ <input name="name" type="text" class="formfld" id="name" size="40" value="<?=htmlspecialchars($pconfig['name']);?>">
+ </td>
+ </tr>
+
+ <tr>
+ <td width="22%" valign="top" class="vncell">PHP</td>
+ <td width="78%" class="vtable">
+ <?php
+ echo "<textarea name=\"php\" id=\"php\" cols=\"70\" rows=\"15\" wrap=\"off\">".htmlspecialchars($pconfig['php'])."</textarea>\n";
+ ?>
+ <!--
+ <br>
+ <select name='dialplan_expression_select' id='dialplan_expression_select' onchange="document.getElementById('dialplan_expression').value += document.getElementById('dialplan_expression_select').value + '\n';" class='formfld'>
+ <option></option>
+ <option value='snortkillsessions'>snort kill sessions</option>
+ </select>
+ <span class="vexpl">
+ <br />
+ </span>
+ -->
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq">Enabled</td>
+ <td width="78%" class="vtable">
+ <?php
+ echo " <select name='enabled' class='formfld'>\n";
+ echo " <option></option>\n";
+ switch (htmlspecialchars($pconfig['enabled'])) {
+ case "true":
+ echo " <option value='true' selected='yes'>true</option>\n";
+ echo " <option value='false'>false</option>\n";
+ break;
+ case "false":
+ echo " <option value='true'>true</option>\n";
+ echo " <option value='false' selected='yes'>false</option>\n";
+
+ break;
+ default:
+ echo " <option value='true' selected='yes'>true</option>\n";
+ echo " <option value='false'>false</option>\n";
+ }
+ echo " </select>\n";
+ ?>
+ </td>
+ </tr>
+ <tr>
+ <td width="25%" valign="top" class="vncellreq">Description</td>
+ <td width="75%" class="vtable">
+ <input name="description" type="text" class="formfld" id="description" size="40" value="<?=htmlspecialchars($pconfig['description']);?>">
+ <br><span class="vexpl">Enter the description here.<br></span>
+ </td>
+ </tr>
+
+ <tr>
+ <td valign="top">&nbsp;</td>
+ <td>
+ <input name="Submit" type="submit" class="formbtn" value="Save"> <input class="formbtn" type="button" value="Cancel" onclick="history.back()">
+ <?php if (isset($id) && $a_phpservice[$id]): ?>
+ <input name="id" type="hidden" value="<?=$id;?>">
+ <?php endif; ?>
+ </td>
+ </tr>
+ </table>
+ </form>
+
+ <br>
+ <br>
+ <br>
+ <br>
+ <br>
+ <br>
+
+ </td>
+ </tr>
+</table>
+
+</div>
+
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/phpsysinfo/phpsysinfo.inc b/config/phpsysinfo/phpsysinfo.inc
new file mode 100644
index 00000000..403b0f97
--- /dev/null
+++ b/config/phpsysinfo/phpsysinfo.inc
@@ -0,0 +1,159 @@
+<?php
+function phpsysinfo_install_deinstall() {
+ conf_mount_rw();
+ config_lock();
+ exec("cd /var/db/pkg/ && pkg_delete `ls | grep mbmon`");
+ exec("rm -d -R /usr/local/www/phpSysInfo");
+ conf_mount_ro();
+ config_unlock();
+}
+
+function phpsysinfo_install_config() {
+global $config, $g;
+ conf_mount_rw();
+ config_lock();
+ exec("cd ..");
+ exec("tar -xzvf /usr/local/pkg/phpsysinfo-2.5.3.tgz");
+
+// link shared libraries
+ if ((!file_exists("/lib/libm.so.4")) AND (file_exists("/lib/libm.so.5"))) {
+ exec("ln -s /lib/libm.so.5 /lib/libm.so.4");
+ }
+
+ /* lines need in config.php */
+$default_lng = en;
+$default_template= pfSense;
+$hide_picklist = "false";
+$show_vhostname = "false";
+$sensor_program = '""';
+$show_mount_point = "false";
+$show_inodes = "false";
+$hide_mounts = "array()";
+$hide_fstypes = "array()";
+$loadbar = "false";
+$showerrors = "false";
+$temperatureformat = '"c-f"';
+$hide_picklist = $config['installedpackages']['phpsysinfo']['config'][0]['hidepicklist'];
+if($hide_picklist)
+ $hide_picklist = "true";
+ else
+ $hide_picklist = "false";
+ $sensor_program = $config['installedpackages']['phpsysinfo']['config'][0]['sensorprogram'];
+if($sensor_program)
+ $sensor_program= "mbmon";
+ else
+ $sensor_program = '""';
+ $show_mount_point = $config['installedpackages']['phpsysinfo']['config'][0]['showmountpoint'];
+if($show_mount_point)
+ $show_mount_point = "true";
+ else
+ $show_mount_point = "false";
+ $hide_fstypes = $config['installedpackages']['phpsysinfo']['config'][0]['hidefstypes'];
+if($hide_fstypes)
+ $hide_fstypes = "$hide_fstypes";
+ $show_inodes = $config['installedpackages']['phpsysinfo']['config'][0]['showinodes'];
+if($show_inodes)
+ $show_inodes = "true";
+ else
+ $show_inodes = "false";
+ $loadbar = $config['installedpackages']['phpsysinfo']['config'][0]['loadbar'];
+if($loadbar)
+ $loadbar = "true";
+ else
+ $loadbar = "false";
+ $showerrors = $config['installedpackages']['phpsysinfo']['config'][0]['showerrors'];
+if($showerrors)
+ $showerrors = "true";
+ else
+ $showerrors = "false";
+ $hf = fopen("/usr/local/www/phpSysInfo/config.php","w");
+if(!$hf) {
+ log_error("could not open /usr/local/www/phpSysInfo/config.php for writing");
+exit;
+}
+
+fwrite($hf, '<?php');
+fwrite($hf, "\n");
+// webpath but not used
+fwrite($hf, '$webpath = "";');
+fwrite($hf, "\n");
+// define the default lang and template here
+fwrite($hf, '$default_lng=');
+fwrite($hf, "'");
+fwrite($hf, $default_lng);
+fwrite($hf, "'");
+fwrite($hf, ';');
+fwrite($hf, "\n");
+fwrite($hf, '$default_template=');
+fwrite($hf, "'");
+fwrite($hf, $default_template);
+fwrite($hf, "'");
+fwrite($hf, ';');
+fwrite($hf, "\n");
+// hide language and template picklist
+// false = display picklist
+// true = do not display picklist
+fwrite($hf, '$hide_picklist = ');
+fwrite($hf, $hide_picklist);
+fwrite($hf, ';');
+fwrite($hf, "\n");
+// display the virtual host name and address
+// default is canonical host name and address
+fwrite($hf, '$show_vhostname = ');
+fwrite($hf, $show_vhostname);
+fwrite($hf, ';');
+fwrite($hf, "\n");
+// define the motherboard monitoring program here
+fwrite($hf, '$sensor_program = ');
+fwrite($hf, $sensor_program);
+fwrite($hf, ';');
+fwrite($hf, "\n");
+// show mount point
+fwrite($hf, '$show_mount_point = ');
+fwrite($hf, $show_mount_point);
+fwrite($hf, ';');
+fwrite($hf, "\n");
+// show bind
+fwrite($hf, '$show_bind = false;');
+fwrite($hf, "\n");
+// show inode usage
+fwrite($hf, '$show_inodes = ');
+fwrite($hf, $show_inodes);
+fwrite($hf, ';');
+fwrite($hf, "\n");
+// show inode usage
+fwrite($hf, '$hide_mounts = ');
+fwrite($hf, $hide_mounts);
+fwrite($hf, ';');
+fwrite($hf, "\n");
+// Hide filesystem typess. Example: 'tmpfs', 'usbfs'
+fwrite($hf, '$hide_fstypes = array(');
+fwrite($hf, $hide_fstypes);
+fwrite($hf, ');');
+fwrite($hf, "\n");
+// show a graph for current cpuload
+fwrite($hf, '$loadbar = ');
+fwrite($hf, $loadbar);
+fwrite($hf, ';');
+fwrite($hf, "\n");
+// e.g. $addpaths = array('/opt/bin', '/opt/sbin');
+fwrite($hf, '$addpaths = array();');
+fwrite($hf, "\n");
+// display error messages at the top of the page
+fwrite($hf, '$showerrors = ');
+fwrite($hf, $showerrors);
+fwrite($hf, ';');
+fwrite($hf, "\n");
+// format in which temperature is displayed
+fwrite($hf, '$temperatureformat = ');
+fwrite($hf, $temperatureformat);
+fwrite($hf, ';');
+fwrite($hf, "\n");
+// The end of the config file
+fwrite($hf, '?>');
+fwrite($hf, "\n");
+fclose($hf);
+ conf_mount_ro();
+ config_unlock();
+}
+?> \ No newline at end of file
diff --git a/config/phpsysinfo/phpsysinfo.xml b/config/phpsysinfo/phpsysinfo.xml
new file mode 100644
index 00000000..ab3d2217
--- /dev/null
+++ b/config/phpsysinfo/phpsysinfo.xml
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>phpsysinfo</name>
+ <version>1.0</version>
+ <title>phpsysinfo</title>
+ <aftersaveredirect>/pkg_edit.php?xml=phpsysinfo.xml&amp;id=0</aftersaveredirect>
+ <include_file>/usr/local/pkg/phpsysinfo.inc</include_file>
+ <menu>
+ <name>phpsysinfo</name>
+ <tooltiptext></tooltiptext>
+ <section>Status</section>
+ <url>/pkg_edit.php?xml=phpsysinfo.xml&amp;id=0</url>
+ </menu>
+ <tabs>
+ <tab>
+ <text>phpsysinfo</text>
+ <url>/pkg_edit.php?xml=phpsysinfo.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Access phpsysinfo</text>
+ <url>/phpSysInfo</url>
+ </tab>
+ </tabs>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0644</chmod>
+ <item>http://www.pfsense.com/packages/config/phpsysinfo/phpsysinfo.inc</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0644</chmod>
+ <item>http://files.pfsense.org/packages/All/phpsysinfo-2.5.3.tgz</item>
+ </additional_files_needed>
+ <fields>
+ <field>
+ <fielddescr>Hide picklist</fielddescr>
+ <fieldname>hidepicklist</fieldname>
+ <description>Hide language and template picklist</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Show mbmon</fielddescr>
+ <fieldname>sensorprogram</fieldname>
+ <description>Define the motherboard monitoring program here. Note that not all motherboards are supported and some only partly.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Show mount point</fielddescr>
+ <fieldname>showmountpoint</fieldname>
+ <description>Show mount point</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Show inodes</fielddescr>
+ <fieldname>showinodes</fieldname>
+ <description>Show inode usage</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Show loadbar</fielddescr>
+ <fieldname>loadbar</fieldname>
+ <description>Show a graph for current cpuload</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Show errors</fielddescr>
+ <fieldname>showerrors</fieldname>
+ <description>Display error messages at the top of the page. Note that vmstat is added in 1.0.1-SNAPSHOT-03-15-2007 and later</description>
+ <type>checkbox</type>
+ </field>
+ </fields>
+ <custom_php_resync_config_command>phpsysinfo_install_config();</custom_php_resync_config_command>
+ <custom_php_install_command>phpsysinfo_install_config();</custom_php_install_command>
+ <custom_php_deinstall_command>phpsysinfo_install_deinstall();</custom_php_deinstall_command>
+</packagegui>
diff --git a/config/postfix.xml b/config/postfix.xml
new file mode 100644
index 00000000..65b4d11f
--- /dev/null
+++ b/config/postfix.xml
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>postfix</name>
+ <version>1.1.12_1</version>
+ <title>Services: Postfix Forwarder</title>
+ <savetext>Change</savetext>
+ <preoutput>yes</preoutput>
+ <aftersaveredirect>pkg_edit.php?xml=postfix.xml&amp;id=1</aftersaveredirect>
+ <menu>
+ <name>Postfix Forwarder</name>
+ <tooltiptext>Configure Postfix Forwarder</tooltiptext>
+ <section>Services</section>
+ <url>pkg_edit.php?xml=postfix.xml&amp;id=1</url>
+ </menu>
+ <fields>
+ <field>
+ <fielddescr>Primary Domain</fielddescr>
+ <fieldname>primarydomain</fieldname>
+ <description>Enter your primary domain. (ex: example.com)</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>My Hostname</fielddescr>
+ <fieldname>hostname</fieldname>
+ <description>Enter the hostname of this system to be used by Postfix. (ex: mail.example.com)</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>none</fielddescr>
+ <fieldname>none</fieldname>
+ <type>rowhelper</type>
+ <rowhelper>
+ <rowhelperfield>
+ <fielddescr>Domain</fielddescr>
+ <fieldname>domain</fieldname>
+ <description>Enter the domain here (ex: example.com)</description>
+ <type>input</type>
+ <size>20</size>
+ </rowhelperfield>
+ <rowhelperfield>
+ <fielddescr>Mail Server IP</fielddescr>
+ <fieldname>mailserverip</fieldname>
+ <description>Enter the mail server IP to forward to here.</description>
+ <type>input</type>
+ <size>20</size>
+ </rowhelperfield>
+ </rowhelper>
+ </field>
+ </fields>
+ <custom_add_php_command>
+ </custom_add_php_command>
+ <start_command>/usr/local/sbin/postfix start</start_command>
+ <restart_command>/usr/local/sbin/postmap /usr/local/etc/postfix/transport ; /usr/local/sbin/postfix reload</restart_command>
+ <custom_php_install_command>
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ </custom_php_deinstall_command>
+ <templates>
+ <template>
+ <filename>/usr/local/etc/postfix/main.cf</filename>
+ <templatecontents>
+myhostname = hostname_fieldvalue \n
+mydomain = primarydomain_fieldvalue \n
+relay_domains = domain_fieldvalue[ ] \n
+ </templatecontents>
+ </template>
+ <template>
+ <filename>/usr/local/etc/postfix/transport</filename>
+ <templatecontents>domain_fieldvalue smtp:[mailserverip_fieldvalue]\n</templatecontents>
+ </template>
+ </templates>
+</packagegui>
diff --git a/config/powerdns.xml b/config/powerdns.xml
new file mode 100644
index 00000000..214da5f4
--- /dev/null
+++ b/config/powerdns.xml
@@ -0,0 +1,248 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>powerdns</name>
+ <version>2.9.16_4</version>
+ <title>Services: PowerDNS</title>
+ <preoutput>yes</preoutput>
+ <donotsave>true</donotsave>
+ <!-- Menu is where this packages menu will appear -->
+ <menu>
+ <name>PowerDNS</name>
+ <tooltiptext></tooltiptext>
+ <section>Services</section>
+ <configfile>powerdns.xml</configfile>
+ </menu>
+ <!-- Do not save invokes a simple input menu and will not update
+ the configuration database. -->
+ <fields>
+ <field>
+ <fielddescr>pgsql Password</fielddescr>
+ <fieldname>password</fieldname>
+ <description>Enter the pgsql users password.</description>
+ <type>password</type>
+ </field>
+ <field>
+ <fielddescr>pgsql Password AGAIN</fielddescr>
+ <fieldname>passwordagain</fieldname>
+ <type>password</type>
+ </field>
+ <field>
+ <fielddescr>IP Address</fielddescr>
+ <fieldname>ipaddress</fieldname>
+ <description>(0.0.0.0 to bind to all)</description>
+ <type>input</type>
+ <value>0.0.0.0</value>
+ </field>
+ <field>
+ <fielddescr>Cache Time to Live</fielddescr>
+ <fieldname>cachettl</fieldname>
+ <description>Recommended value: 20</description>
+ <type>input</type>
+ <value>20</value>
+ </field>
+ <field>
+ <fielddescr>Master</fielddescr>
+ <fieldname>master</fieldname>
+ <type>select</type>
+ <options>
+ <option><name>Yes</name><value>yes</value></option>
+ <option><name>No</name><value>no</value></option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Slave</fielddescr>
+ <fieldname>slave</fieldname>
+ <type>select</type>
+ <options>
+ <option><name>No</name><value>no</value></option>
+ <option><name>Yes</name><value>yes</value></option>
+ </options>
+ </field>
+ </fields>
+ <custom_add_php_command>
+ if($password == $passwordagain) {
+ conf_mount_rw();
+ config_lock();
+ $fd = popen("/usr/sbin/pw usermod -n pgsql -H 0", "w");
+ $salt = md5(time());
+ $crypted_pw = crypt($_POST['password'],$salt);
+ fwrite($fd, $crypted_pw);
+ pclose($fd);
+ $fout = fopen("/usr/local/etc/pdns.conf","w");
+ fwrite($fout, "launch=gpgsql\n");
+ fwrite($fout, "gpgsql-host=127.0.0.1\n");
+ fwrite($fout, "gpgsql-dbname=powerdns\n");
+ fwrite($fout, "gpgsql-user=pgsql\n");
+ fwrite($fout, "gpgsql-password=" . $_POST['password'] . "\n");
+ fwrite($fout, "chroot=/var/empty\n");
+ fwrite($fout, "disable-tcp=no\n");
+ fwrite($fout, "guardian=yes\n");
+ fwrite($fout, "webserver=yes\n");
+ fwrite($fout, "webserver-address=127.0.0.1\n");
+ fwrite($fout, "webserver-port=8081\n");
+ fwrite($fout, "local-address=" . $_POST['ipaddress'] . "\n");
+ fwrite($fout, "master=" . $_POST['master'] . "\n");
+ fwrite($fout, "slave=" . $_POST['slave'] . "\n");
+ fwrite($fout, "cache-ttl=" . $_POST['cachettl'] . "\n");
+ /* XXX: TODO */
+ fwrite($fout, "# allow-axfr-ips=\n");
+ fwrite($fout, "# allow-recursion=\n");
+ fwrite($fout, "# config-dir=/etc\n");
+ fwrite($fout, "# config-name=\n");
+ fwrite($fout, "# control-console=no\n");
+ fwrite($fout, "# default-soa-name=ns.example.com\n");
+ fwrite($fout, "# disable-axfr=no\n");
+ fwrite($fout, "# distributor-threads=3\n");
+ fwrite($fout, "# fancy-records=no\n");
+ fwrite($fout, "# launch=\n");
+ fwrite($fout, "# lazy-recursion=yes\n");
+ fwrite($fout, "# load-modules=\n");
+ fwrite($fout, "# local-ipv6=\n");
+ fwrite($fout, "# local-port=53\n");
+ fwrite($fout, "# log-dns-details=\n");
+ fwrite($fout, "# log-failed-updates=\n");
+ fwrite($fout, "# logfile=pdns.log\n");
+ fwrite($fout, "# logging-facility=\n");
+ fwrite($fout, "# loglevel=4\n");
+ fwrite($fout, "# max-queue-length=5000\n");
+ fwrite($fout, "# max-tcp-connections=10\n");
+ fwrite($fout, "# module-dir=/usr/local/bin/../lib\n");
+ fwrite($fout, "# negquery-cache-ttl=60\n");
+ fwrite($fout, "# only-soa=org\n");
+ fwrite($fout, "# out-of-zone-additional-processing=no\n");
+ fwrite($fout, "# query-cache-ttl=20\n");
+ fwrite($fout, "# query-logging=no\n");
+ fwrite($fout, "# queue-limit=1500\n");
+ fwrite($fout, "# receiver-threads=1\n");
+ fwrite($fout, "# recursive-cache-ttl=10\n");
+ fwrite($fout, "# recursor=no\n");
+ fwrite($fout, "# setgid=\n");
+ fwrite($fout, "# setuid=\n");
+ fwrite($fout, "# skip-cname=no\n");
+ fwrite($fout, "# slave=no\n");
+ fwrite($fout, "# slave-cycle-interval=60\n");
+ fwrite($fout, "# soa-minimum-ttl=3600\n");
+ fwrite($fout, "# soa-serial-offset=0\n");
+ fwrite($fout, "# socket-dir=/var/run\n");
+ fwrite($fout, "# strict-rfc-axfrs=no\n");
+ fwrite($fout, "# urlredirector=127.0.0.1\n");
+ fwrite($fout, "# use-logfile=no\n");
+ fwrite($fout, "# webserver-password=\n");
+ fwrite($fout, "# webserver-print-arguments=no\n");
+ fwrite($fout, "# wildcard-url=no\n");
+ fwrite($fout, "# wildcards=\n");
+ fclose($fout);
+ conf_mount_ro();
+ config_unlock();
+ system("/usr/local/bin/pg_ctl -m smart 2>/dev/null");
+ system("/usr/local/bin/pg_ctl -D /usr/local/pgsql/data -l logfile start 2>/dev/null");
+ } else {
+ echo "Passwords do not much!";
+ exit;
+ }
+ </custom_add_php_command>
+ <custom_php_install_command>
+ echo "&lt;pre&gt;";
+ echo "Creating DB...";
+ system("/usr/bin/su -l pgsql -c initdb");
+ system("/usr/local/etc/rc.d/010.pgsql.sh start");
+ system("/usr/bin/su -l pgsql -c \"dropdb powerdns\" ");
+ system("/usr/bin/su -l pgsql -c \"createdb powerdns\" ");
+ $fout = fopen("/usr/local/pkg/powerdns.schema","w");
+ /* DATABASE SCHEMA */
+ fwrite($fout, "create table domains (\n");
+ fwrite($fout, "id SERIAL PRIMARY KEY,\n");
+ fwrite($fout, "name VARCHAR(255) NOT NULL,\n");
+ fwrite($fout, "master VARCHAR(20) DEFAULT NULL,\n");
+ fwrite($fout, "last_check INT DEFAULT NULL,\n");
+ fwrite($fout, "type VARCHAR(6) NOT NULL,\n");
+ fwrite($fout, "notified_serial INT DEFAULT NULL,\n");
+ fwrite($fout, "account VARCHAR(40) DEFAULT NULL\n");
+ fwrite($fout, ");\n");
+ fwrite($fout, "CREATE UNIQUE INDEX name_index ON domains(name);\n");
+ fwrite($fout, "CREATE TABLE records (\n");
+ fwrite($fout, " id SERIAL PRIMARY KEY,\n");
+ fwrite($fout, " domain_id INT DEFAULT NULL,\n");
+ fwrite($fout, " name VARCHAR(255) DEFAULT NULL,\n");
+ fwrite($fout, " type VARCHAR(6) DEFAULT NULL,\n");
+ fwrite($fout, " content VARCHAR(255) DEFAULT NULL,\n");
+ fwrite($fout, " ttl INT DEFAULT NULL,\n");
+ fwrite($fout, " prio INT DEFAULT NULL,\n");
+ fwrite($fout, " change_date INT DEFAULT NULL,\n");
+ fwrite($fout, " CONSTRAINT domain_exists\n");
+ fwrite($fout, " FOREIGN KEY(domain_id) REFERENCES domains(id)\n");
+ fwrite($fout, " ON DELETE CASCADE\n");
+ fwrite($fout, ");\n");
+ fwrite($fout, "CREATE INDEX rec_name_index ON records(name);\n");
+ fwrite($fout, "CREATE INDEX nametype_index ON records(name,type);\n");
+ fwrite($fout, "CREATE INDEX domain_id ON records(domain_id);\n");
+ fwrite($fout, "create table supermasters (\n");
+ fwrite($fout, " ip VARCHAR(25) NOT NULL,\n");
+ fwrite($fout, " nameserver VARCHAR(255) NOT NULL,\n");
+ fwrite($fout, " account VARCHAR(40) DEFAULT NULL\n");
+ fwrite($fout, ");\n");
+ fwrite($fout, "GRANT SELECT ON supermasters TO pgsql;\n");
+ fwrite($fout, "GRANT ALL ON domains TO pgsql;\n");
+ fwrite($fout, "GRANT ALL ON domains_id_seq TO pgsql;\n");
+ fwrite($fout, "GRANT ALL ON records TO pgsql;\n");
+ fwrite($fout, "GRANT ALL ON records_id_seq TO pgsql;\n");
+ fclose($fout);
+ system("cat /usr/local/pkg/powerdns.schema | /usr/bin/su -l pgsql -c \"psql powerdns\" ");
+ echo "Installation completed!";
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ system("/usr/local/bin/pg_ctl -m immediate");
+ rmdir_recursive("/usr/local/pgsql");
+ system("/usr/sbin/pw userdel pgsql");
+ system("/usr/bin/killall -9 postgres");
+ echo "&lt;p&gt;";
+ echo "Reboot required... One moment...";
+ echo "&lt;p&gt;";
+ /* system("/sbin/shutdown -r now"); */
+ </custom_php_deinstall_command>
+</packagegui>
diff --git a/config/pubkey.xml b/config/pubkey.xml
new file mode 100644
index 00000000..cab2cbb4
--- /dev/null
+++ b/config/pubkey.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ pubkey.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2008 Scott Ullrich
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Updates the pfSense release security certificate</description>
+ <name>pubkey</name>
+ <version>0.1</version>
+ <title>pubkey</title>
+ <custom_php_install_command>
+ $fd = fopen("/etc/pubkey.pem","w");
+ fwrite($fd, "ssh-dss AAAAB3NzaC1kc3MAAACBAN08c22jym3KCRUF8/rKNXgU/J0vv6UC9eCta/ATTNgeW/z2rp/HsjcPkMLx9dLaqufShC0VzsUbGlqCsdQT8jfwBiLG2pjUkX20qTStRG/rs9Tv0rS/8eVNT/DbQ6zL3PTdp+XAIq+KQLucqcBazTqSzyF7ghZ7OVmsX1/ixTP3AAAAFQCYcP378X/dQ08l6u8O5uvEtxbvEwAAAIEAyOOuWttXGrprzBhKrjhop58bZTOZp0J0IMHMwi/J+K3HUuPZnaltGoW21MjqSvVor4m22r/3b8aUIom+jp4I/bmpxTOUgO6owTlCVX614fGPWcCw2M017aghQ/vUa/92DaMLO//FYD8X2b7WgyPNrJh9ckZ14oncBleJUfXmue8AAACBAKw00/IkoMJzTumFfT9+Jb442O1KZvtGyj1YWpyYXf3xbQFGXND7m4rTIS2zPvTcOauCHbZwZ9uBxE4zTdlGJ4XirPEbWwOl1TU71bZ3OqonVesyqSC04LLiuLGlIHyXxyc/UCzg1UL8mCBlLzqmPUkJoL0ZINo8Raqip8WM63KM root@freebsd-nexus-computers.pfsense.org");
+ fclose($fd);
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ </custom_php_deinstall_command>
+</packagegui>
diff --git a/config/pure-ftpd.xml b/config/pure-ftpd.xml
new file mode 100644
index 00000000..7d9a70d6
--- /dev/null
+++ b/config/pure-ftpd.xml
@@ -0,0 +1,149 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>pure-ftpd</name>
+ <version>1.0.20_1</version>
+ <title>Services: PureFTPD Accounts</title>
+ <!-- Menu is where this packages menu will appear -->
+ <menu>
+ <name>Pure FTPD Accounts</name>
+ <tooltiptext>Pure FTPd Server is a fast, production quality, standards-conformant FTP server based on Troll-FTPd. It has no known vulnerability, it is trivial to set up, and it is especially designed for modern kernels. Features include PAM support, IPv6, chroot()ed home directories, virtual domains, built-in 'ls', FXP protocol, anti-warez system, bandwidth throttling, restricted ports for passive downloads, an LDAP backend, XML output, and more.</tooltiptext>
+ <section>Services</section>
+ <configfile>pure-ftpd.xml</configfile>
+ </menu>
+ <menu>
+ <name>Pure FTPD Settings</name>
+ <tooltiptext>Pure FTPd Server is a fast, production quality, standards-conformant FTP server based on Troll-FTPd. It has no known vulnerability, it is trivial to set up, and it is especially designed for modern kernels. Features include PAM support, IPv6, chroot()ed home directories, virtual domains, built-in 'ls', FXP protocol, anti-warez system, bandwidth throttling, restricted ports for passive downloads, an LDAP backend, XML output, and more.</tooltiptext>
+ <section>Services</section>
+ <url>pkg_edit.php?xml=pure-ftpdsettings.xml&amp;id=0</url>
+ </menu>
+ <!-- configpath gets expanded out automatically and config items will be
+ stored in that location seperated with -> -->
+ <configpath>installedpackages->package->$packagename->configuration</configpath>
+ <!-- adddeleteeditpagefields items will appear on the first page where you can add / delete or edit
+ items. An example of this would be the nat page where you add new nat redirects -->
+ <adddeleteeditpagefields>
+ <columnitem>
+ <fielddescr>Username</fielddescr>
+ <fieldname>username</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Description</fielddescr>
+ <fieldname>description</fieldname>
+ </columnitem>
+ </adddeleteeditpagefields>
+
+ <additional_files_needed>
+ <item>http://www.pfsense.com/packages/config/pure-ftpdsettings.xml</item>
+ </additional_files_needed>
+
+ <!-- fields gets invoked when the user adds or edits a item. the following items
+ will be parsed and rendered for the user as a gui with input, and selectboxes. -->
+ <fields>
+ <field>
+ <fielddescr>Username</fielddescr>
+ <fieldname>username</fieldname>
+ <description>Enter the username here</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Password</fielddescr>
+ <fieldname>password</fieldname>
+ <description>Enter the password here</description>
+ <type>password</type>
+ </field>
+ <field>
+ <fielddescr>Username Description</fielddescr>
+ <fieldname>description</fieldname>
+ <description>Enter the description of the user here</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Account Expiration</fielddescr>
+ <fieldname>expiration</fieldname>
+ <description>Amount of days when account expires. Leave blank for never.</description>
+ <type>input</type>
+ </field>
+ </fields>
+ <custom_delete_php_command>
+ rmdir_recursive("/home/" . $username);
+ system("/usr/sbin/pw userdel " . $username);
+ </custom_delete_php_command>
+ <custom_add_php_command>
+ conf_mount_rw();
+ config_lock();
+ $expires = "";
+ if($_POST['expiration']) $expires = " -e " . $_POST['expiration'];
+ mwexec("/bin/mkdir /home/{$_POST['username']}");
+ mwexec("/usr/sbin/chown -R {$_POST['username']}:wheel /home/{$_POST['username']}");
+ mwexec("/usr/sbin/pw useradd " . $_POST['username'] . $expires . " -m -d /home/" . $_POST['username'] . "/./ -s \"/usr/sbin/nologini\"");
+ $fd = popen("/usr/sbin/pw usermod -n " . $_POST['username'] . " -H 0", "w");
+ $salt = md5(time());
+ $crypted_pw = crypt($_POST['password'],$salt);
+ fwrite($fd, $crypted_pw);
+ pclose($fd);
+ mwexec("/usr/sbin/pw usermod " . $_POST['username'] . " -s /nonexistent");
+ conf_mount_ro();
+ config_unlock();
+ $savemsg = "User has been added.";
+ </custom_add_php_command>
+ <custom_php_install_command>
+ $fout = fopen("/usr/local/etc/rc.d/pure-ftpd.sh","w");
+ fwrite($fout, "#!/bin/sh\n\n");
+ fwrite($fout, "# PACKAGE: Pure-FTPD\n");
+ fwrite($fout, "# EXECUTABLE: pure-ftpd\n");
+ fwrite($fout, "/usr/local/sbin/pure-ftpd -A -B /usr/local/etc/pure-ftpd.conf\n");
+ fclose($fout);
+ chmod("/usr/local/etc/rc.d/pure-ftpd.sh", 0755);
+ mwexec("/usr/local/etc/rc.d/pure-ftpd.sh");
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ mwexec("/usr/bin/killall pure-ftpd");
+ rmdir_recursive("/usr/local/etc/pure*");
+ rmdir_recursive("/usr/local/etc/rc.d/pure*");
+ </custom_php_deinstall_command>
+</packagegui>
diff --git a/config/pure-ftpdsettings.xml b/config/pure-ftpdsettings.xml
new file mode 100644
index 00000000..f904545c
--- /dev/null
+++ b/config/pure-ftpdsettings.xml
@@ -0,0 +1,162 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>pure-ftpdsettings</name>
+ <version>none</version>
+ <title>Services: PureFTPD Settings</title>
+ <aftersaveredirect>pkg_edit.php?xml=pure-ftpdsettings.xml&amp;id=0</aftersaveredirect>
+ <!-- Menu is where this packages menu will appear -->
+ <menu>
+ <name>Pure FTPD Settings</name>
+ <tooltiptext>Pure FTPd Server is a fast, production quality, standards-conformant FTP server based on Troll-FTPd. It has no known vulnerability, it is trivial to set up, and it is especially designed for modern kernels. Features include PAM support, IPv6, chroot()ed home directories, virtual domains, built-in 'ls', FXP protocol, anti-warez system, bandwidth throttling, restricted ports for passive downloads, an LDAP backend, XML output, and more.</tooltiptext>
+ <section>Services</section>
+ <configfile>pureftpdsettings.xml</configfile>
+ </menu>
+ <!-- configpath gets expanded out automatically and config items will be
+ stored in that location seperated with -> -->
+ <configpath>installedpackages->package->$packagename->configuration->settings</configpath>
+ <!-- fields gets invoked when the user adds or edits a item. the following items
+ will be parsed and rendered for the user as a gui with input, and selectboxes. -->
+ <fields>
+ <field>
+ <fielddescr>Maximum connections</fielddescr>
+ <fieldname>connections</fieldname>
+ <description>Maximum number of clients allowed</description>
+ <type>input</type>
+ <validationtype>number</validationtype>
+ </field>
+ <field>
+ <fielddescr>Maximum connections per ip address</fielddescr>
+ <fieldname>connectionsperip</fieldname>
+ <description>Maximum number of clients allowed to connect per ip address</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Upload cutoff threshold</fielddescr>
+ <fieldname>cutoffthreshold</fieldname>
+ <description>Disallow upload if the partition is more than percentage full.</description>
+ <type>input</type>
+ <validationtype>number</validationtype>
+ </field>
+ <field>
+ <fielddescr>Begin tcp port range</fielddescr>
+ <fieldname>beginport</fieldname>
+ <description>Specify that client connections begin at this port.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>End tcp port range</fielddescr>
+ <fieldname>endport</fieldname>
+ <description>Specify that client connections end at this port.</description>
+ <type>input</type>
+ <validationtype>number</validationtype>
+ </field>
+ <field>
+ <fielddescr>Limit upload bandwidth</fielddescr>
+ <fieldname>uploadbw</fieldname>
+ <description>Limit the upload bandwdith in KB/s</description>
+ <type>input</type>
+ <validationtype>number</validationtype>
+ </field>
+ <field>
+ <fielddescr>Limit download bandwidth</fielddescr>
+ <fieldname>downloadbw</fieldname>
+ <description>Limit the download bandwdith in KB/s</description>
+ <type>input</type>
+ <validationtype>number</validationtype>
+ </field>
+ <field>
+ <fielddescr>Client File Deletion</fielddescr>
+ <fieldname>filedeletion</fieldname>
+ <description>Allow clients to upload files but disallow their ability to delete uploaded items.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>NAT Workaround mode</fielddescr>
+ <fieldname>natworkaround</fieldname>
+ <description>NAT mode. Force active mode. If your FTP server is behind a NAT box that doesn't support applicative FTP proxying, or if you use port redirection without a transparent FTP proxy, use this. Well... the previous sentence isn't very clear. Okay: if your network looks like this: FTP--NAT.gateway/router--Internet and if you want people coming from the internet to have access to your FTP server, please try without this option first. If Netscape clients can connect without any problem, your NAT gate-way rulez. If Netscape doesn't display directory listings, your NAT gateway sucks.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Chroot environment</fielddescr>
+ <fieldname>chroot</fieldname>
+ <description>Allow users (but root) to only see their ~ and no system files.</description>
+ <type>checkbox</type>
+ </field>
+ </fields>
+ <custom_delete_php_command>
+ </custom_delete_php_command>
+ <custom_add_php_command>
+ conf_mount_rw();
+ config_lock();
+ unlink_if_exists("/usr/local/etc/rc.d/pure-ftp*");
+ $fout = fopen("/usr/local/etc/rc.d/pure-ftpd.sh","w");
+ fwrite($fout, "#!/bin/sh\n\n");
+ $startline = "/usr/local/sbin/pure-ftpd";
+ if($_POST['connections']) $startline .= " -c " . $_POST['connections'];
+ if($_POST['connectionsperip']) $startline .= " -C " . $_POST['connectionsperip'];
+ if($_POST['cutoffthreshold']) $startline .= " -k " . $_POST['cutoffthreshold'];;
+ if($_POST['beginport'] and $_POST['endport']) $startline .= " -p " . $_POST['beginport'] . ":" . $_POST['endport'];
+ if($_POST['uploadbw'] and $_POST['downloadbw']) $startline .= " -T " . $_POST['uploadbw'] . ":" . $_POST['downloadbw'];;
+ if($_POST['natworkaround']) $startline .= " -N";
+ if($_POST['filedeletion']) $startline .= " -K";
+ if($_POST['chroot']) $startline .= " -A";
+ $startline .= " -B /usr/local/etc/pure-ftpd.conf";
+ fwrite($fout, $startline . "\n");
+ fclose($fout);
+ conf_mount_ro();
+ config_unlock();
+ chmod("/usr/local/etc/rc.d/pure-ftpd.sh", 0755);
+ mwexec("killall pure-ftpd");
+ mwexec("/usr/local/etc/rc.d/pure-ftpd.sh");
+ </custom_add_php_command>
+ <custom_php_install_command>
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ </custom_php_deinstall_command>
+</packagegui>
+
diff --git a/config/quagga/quagga.sh b/config/quagga/quagga.sh
new file mode 100644
index 00000000..6a9727d7
--- /dev/null
+++ b/config/quagga/quagga.sh
@@ -0,0 +1,75 @@
+#!/bin/sh
+#
+# Quagga.sh retrofitted for pfSense
+# part of the pfSense quagga project
+#
+# You may also wish to use the following variables to fine-tune startup:
+# quagga_flags="-d"
+# quagga_daemons="zebra ripd ripngd ospfd ospf6d bgpd isisd"
+# Per daemon tuning may be done with daemon_name_flags
+# zebra_flags="-dP 0"
+# bgpd_flags="-dnrP 0" and so on
+#
+# If the quagga daemons require additional shared libraries to start,
+# use the following variable to run ldconfig(8) in advance:
+# quagga_extralibs_path="/usr/local/lib ..."
+#
+
+. /etc/rc.subr
+
+mkdir -p /var/run/quagga
+
+name="quagga"
+rcvar=`set_rcvar`
+
+stop_postcmd=stop_postcmd
+
+stop_postcmd()
+{
+ rm -f $pidfile
+}
+
+# set defaults
+
+load_rc_config $name
+
+quagga_enable="YES"
+quagga_flags="-d"
+quagga_daemons="zebra ripd ripngd ospfd ospf6d bgpd isisd"
+quagga_extralibs_path=""
+
+quagga_cmd=$1
+
+case "$1" in
+ force*)
+ quagga_cmd=${quagga_cmd#force}
+ ;;
+ fast*)
+ quagga_cmd=${quagga_cmd#fast}
+ ;;
+esac
+
+case "${quagga_cmd}" in
+ start)
+ if [ ! -z ${quagga_extralibs_path} ]; then
+ /sbin/ldconfig -m ${quagga_extralibs_path}
+ fi
+ ;;
+ stop)
+ quagga_daemons=$(reverse_list ${quagga_daemons})
+ ;;
+esac
+
+for daemon in ${quagga_daemons}; do
+ command=/usr/local/sbin/${daemon}
+ required_files=/usr/local/etc/quagga/${daemon}.conf
+ pidfile=/var/run/quagga/${daemon}.pid
+ if [ ${quagga_cmd} = "start" -a ! -f ${required_files} ]; then
+ continue
+ fi
+ if [ ${quagga_cmd} = "stop" -a -z $(check_process ${command}) ]; then
+ continue
+ fi
+ eval flags=\$\{${daemon}_flags:-\"${quagga_flags}\"\}
+ run_rc_command "$1"
+done
diff --git a/config/quagga/quagga.xml b/config/quagga/quagga.xml
new file mode 100644
index 00000000..4f4b65dc
--- /dev/null
+++ b/config/quagga/quagga.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>none</name>
+ <version>none</version>
+ <title>none</title>
+ <service>
+ <name>quagga</name>
+ <rcfile>quagga.sh</rcfile>
+ <executable>quagga</executable>
+ <description></description>
+ </service>
+ <additional_files_needed>
+ <prefix>/usr/local/etc/rc.d/</prefix>
+ <chmod>0777</chmod>
+ <item>http://www.pfsense.org/packages/config/quagga/quagga.sh</item>
+ </additional_files_needed>
+ <custom_php_install_command>
+ mwexec("/usr/local/etc/rc.d/quagga.sh start");
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ mwexec("rm /usr/local/etc/rc.d/quagga*");
+ mwexec("rm /usr/local/etc/rc.d/watchquagga");
+ </custom_php_deinstall_command>
+</packagegui>
diff --git a/config/routed/routed.inc b/config/routed/routed.inc
new file mode 100644
index 00000000..59967e8c
--- /dev/null
+++ b/config/routed/routed.inc
@@ -0,0 +1,110 @@
+<?php
+/* $Id$ */
+/*
+ routed.inc
+ Copyright (C) 2006 Bill Marquette
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+function setup_routed() {
+ global $config;
+ $gw = "";
+
+ if (isset($config['installedpackages']['routed']['config'][0]['enable']) &&
+ $config['installedpackages']['routed']['config'][0]['enable'] == "on") {
+ /* if user selected individual interfaces */
+ $ifdescrs = array ("wan", "lan");
+ for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++) {
+ if(isset($config['interfaces']['opt' . $j]['enable']))
+ $ifdescrs['opt' . $j] = "opt" . $j;
+ }
+
+ $ifarr = explode(",", $config['installedpackages']['routed']['config'][0]['iface_array']);
+ if (count($ifarr) != 0) {
+ foreach($ifdescrs as $ifdescr => $ifname) {
+ if (in_array($ifname, $ifarr)) {
+ $gw .= setup_etc_gateways($ifname, 'enable');
+ } else {
+ $gw .= setup_etc_gateways($ifname, 'disable');
+ }
+ }
+ } else {
+ /* setup for all interfaces */
+ $gw = setup_etc_gateways();
+ }
+ $fd = fopen("/etc/gateways", "w");
+ fwrite($fd, $gw);
+ fclose($fd);
+ restart_routed();
+ } else {
+ stop_routed();
+ }
+}
+
+function setup_etc_gateways($iface="", $mode="") {
+ global $config;
+
+ if ($iface != "") {
+ $realif=convert_friendly_interface_to_real_interface_name(strtoupper($iface));
+ $ret = "if={$realif} ";
+ }
+
+ switch($mode) {
+ case "enable":
+ if ($config['installedpackages']['routed']['config'][0]['ripversion'] == "2") {
+ $ret .= "ripv2 ";
+ $passwd = $config['installedpackages']['routed']['config'][0]['passwd'];
+ if ($passwd != "") {
+ $ret .= "passwd={$passwd} ";
+ }
+ }
+ break;
+ case "disable":
+ $ret .= "no_rip ";
+ break;
+
+ default:
+ break;
+
+ }
+ $ret .= "\n";
+
+ return $ret;
+}
+
+function start_routed() {
+ mwexec("/sbin/routed");
+}
+
+function stop_routed() {
+ mwexec("killall routed");
+}
+
+function restart_routed() {
+ stop_routed();
+ start_routed();
+}
+
+?>
diff --git a/config/routed/routed.xml b/config/routed/routed.xml
new file mode 100644
index 00000000..d7767a5b
--- /dev/null
+++ b/config/routed/routed.xml
@@ -0,0 +1,127 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>routed</name>
+ <version>1.1</version>
+ <title>Services: RIP</title>
+ <aftersaveredirect>pkg_edit.php?xml=routed.xml&amp;id=0</aftersaveredirect>
+ <include_file>routed.inc</include_file>
+ <!-- Menu is where this packages menu will appear -->
+ <menu>
+ <name>RIP</name>
+ <section>Services</section>
+ <configfile>routed.xml</configfile>
+ <url>pkg_edit.php?xml=routed.xml&amp;id=0</url>
+ </menu>
+ <tabs>
+ <tab>
+ <text>ROUTED Settings</text>
+ <url>/pkg_edit.php?xml=routed.xml</url>
+ <active/>
+ </tab>
+ </tabs>
+ <!-- configpath gets expanded out automatically and config items will be
+ stored in that location -->
+ <configpath>['installedpackages']['routed']['config']</configpath>
+ <additional_files_needed>
+ <item>http://www.pfsense.org/packages/config/routed/routed.inc</item>
+ </additional_files_needed>
+ <!-- fields gets invoked when the user adds or edits a item. the following items
+ will be parsed and rendered for the user as a gui with input, and selectboxes. -->
+ <fields>
+ <field>
+ <fielddescr>Enable RIP</fielddescr>
+ <fieldname>enable</fieldname>
+ <description>Enables the Routing Information Protocol daemon</description>
+ <type>checkbox</type>
+ <enablefields>iface_array,ripversion,passwd</enablefields>
+ </field>
+ <field>
+ <fielddescr>Interfaces</fielddescr>
+ <fieldname>iface_array</fieldname>
+ <description>Select the interfaces that RIP will bind to. You can use the CTRL or COMMAND key to select multiple interfaces.</description>
+ <type>interfaces_selection</type>
+ <size>3</size>
+ <required />
+ <value>lan</value>
+ <multiple>true</multiple>
+ </field>
+ <field>
+ <fielddescr>RIP Version</fielddescr>
+ <fieldname>ripversion</fieldname>
+ <type>select</type>
+ <required />
+ <default_value>2</default_value>
+ <options>
+ <option><name>RIP Version 1</name><value>1</value></option>
+ <option><name>RIP Version 2</name><value>2</value></option>
+ </options>
+ <typehint>Select which RIP version the daemon will listen/advertise using.</typehint>
+ </field>
+ <field>
+ <fielddescr>RIPv2 password</fielddescr>
+ <fieldname>passwd</fieldname>
+ <description>Specify a RIPv2 password. This password will be sent
+ in the clear on all RIPv2 responses received and sent.
+ </description>
+ <type>input</type>
+ </field>
+ </fields>
+ <custom_php_command_before_form>
+ </custom_php_command_before_form>
+ <custom_delete_php_command>
+ </custom_delete_php_command>
+ <custom_php_resync_config_command>
+ conf_mount_rw();
+ setup_routed();
+ conf_mount_ro();
+ </custom_php_resync_config_command>
+ <custom_php_install_command>
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ </custom_php_deinstall_command>
+</packagegui>
diff --git a/config/sassassin.inc b/config/sassassin.inc
new file mode 100644
index 00000000..040f12ab
--- /dev/null
+++ b/config/sassassin.inc
@@ -0,0 +1,63 @@
+<?php
+require_once('globals.inc');
+require_once('config.inc');
+require_once('service-utils.inc');
+
+function sassassin_install_command() {
+ global $g;
+
+ $oldrc = '/usr/local/etc/rc.d/sa-spamd.sh';
+ if (file_exists($oldrc)) unlink($oldrc);
+
+ $pidfile = "$rundir/spamd.pid";
+ $rcfile = array();
+ $rcfile['file'] = 'spamd.sh';
+ $rcfile['start'] = "mkdir -p $rundir\n\tspamd -u proxy -c -d -r $pidfile";
+ $rcfile['stop'] = "kill `cat $pidfile`";
+ write_rcfile($rcfile);
+}
+
+function sassassin_resync() {
+ global $config;
+
+ $settings = $config['installedpackages']['sassassin']['config'][0];
+
+ $use_bayes = ($settings['bayes'] == 'on' ? 1 : 0);
+ $bayes_auto_learn = ($settings['bayes_learn'] == 'on' ? 1 : 0);
+ $required_score = $settings['threshold'];
+ $rewrite_header = "Subject {$settings['subject']}";
+
+ $report_safe_array = array('donotsend' => 0, 'attachment' => 1, 'plaintext' => 2);
+ $report_safe = $report_safe_array[$settings['send_spam']];
+
+ $local_cf = <<<EOD
+use_bayes $use_bayes
+bayes_auto_learn $bayes_auto_learn
+required_score $required_score
+rewrite_header $rewrite_header
+report_safe $report_safe
+
+EOD;
+
+ foreach (array('whitelist' => 'wl', 'blacklist' => 'bl') as $list => $key) {
+ foreach ($config['installedpackages']["sassassin{$key}"]['config'] as $item) {
+ if (!empty($item))
+ $local_cf .= "{$list}_from {$item['address']}\n";
+ }
+ }
+
+ file_put_contents('/usr/local/etc/mail/spamassassin/local.cf', $local_cf);
+
+ restart_service('spamassassin');
+
+ if (get_pkg_id('p3scan') != -1) {
+ require_once('p3scan.inc');
+ p3scan_resync();
+ }
+}
+
+function sassassin_validate_input($post, $input_errors) {
+ if (!is_numeric($post['threshold']))
+ $input_errors[] = 'The field \'Spam threshold\' should contain a numeric value.';
+}
+?>
diff --git a/config/sassassin.xml b/config/sassassin.xml
new file mode 100644
index 00000000..eb82fd55
--- /dev/null
+++ b/config/sassassin.xml
@@ -0,0 +1,159 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>spamassassin</name>
+ <version>none</version>
+ <title>Antispam: Configuration</title>
+ <include_file>sassassin.inc</include_file>
+ <menu>
+ <name>Antispam</name>
+ <tooltiptext>Configure the Antispam service.</tooltiptext>
+ <section>Services</section>
+ <url>/pkg_edit.php?xml=sassassin.xml&amp;id=0</url>
+ </menu>
+ <service>
+ <name>SpamAssassin</name>
+ <rcfile>spamd.sh</rcfile>
+ <executable>spamd</executable>
+ <description>The SpamAssassin spam detection software.</description>
+ </service>
+ <tabs>
+ <tab>
+ <text>Configuration</text>
+ <url>/pkg_edit.php?xml=sassassin.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Whitelist</text>
+ <url>/pkg.php?xml=sassassin_wl.xml</url>
+ </tab>
+ <tab>
+ <text>Blacklist</text>
+ <url>/pkg.php?xml=sassassin_bl.xml</url>
+ </tab>
+ </tabs>
+ <additional_files_needed>
+ <item>http://www.pfsense.org/packages/config/sassassin_wl.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <item>http://www.pfsense.org/packages/config/sassassin_bl.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <item>http://www.pfsense.org/packages/config/sassassin.inc</item>
+ </additional_files_needed>
+ <fields>
+ <field>
+ <fielddescr>Enable antispam</fielddescr>
+ <fieldname>enable</fieldname>
+ <description>Check to enable the antispam protection.</description>
+ <type>checkbox</type>
+ <enablefields>bayes,bayes_learn,threshold,subject,send_spam</enablefields>
+ <required/>
+ </field>
+ <field>
+ <fielddescr>Bayesian classifier</fielddescr>
+ <fieldname>bayes</fieldname>
+ <description>Check this to enable the Bayesian classifier.</description>
+ <type>checkbox</type>
+ <required/>
+ <default_value>on</default_value>
+ </field>
+ <field>
+ <fielddescr>Bayesian auto-learning</fielddescr>
+ <fieldname>bayes_learn</fieldname>
+ <description>Check this to enable the Bayesian auto-learning system.</description>
+ <type>checkbox</type>
+ <required/>
+ <default_value>on</default_value>
+ </field>
+ <field>
+ <fielddescr>Spam threshold</fielddescr>
+ <fieldname>threshold</fieldname>
+ <description>Set the threshold at which a message is considered spam.</description>
+ <type>input</type>
+ <required/>
+ <default_value>5.0</default_value>
+ </field>
+ <field>
+ <fielddescr>Rewrite subject</fielddescr>
+ <fieldname>subject</fieldname>
+ <description>This is the string that will be added to the subject of spam emails.</description>
+ <type>input</type>
+ <default_value>*** SPAM ***</default_value>
+ </field>
+ <field>
+ <fielddescr>How to send spam messages</fielddescr>
+ <fieldname>send_spam</fieldname>
+ <description>Choose between not sending spam messages, sending them as an RFC-822 MIME attachment (recommended) or as plain text.</description>
+ <type>select</type>
+ <default_value>attachment</default_value>
+ <options>
+ <option>
+ <name>Do not send</name>
+ <value>donotsave</value>
+ </option>
+ <option>
+ <name>Send as an attachment (recommended)</name>
+ <value>attachment</value>
+ </option>
+ <option>
+ <name>Send as plain text</name>
+ <value>plaintext</value>
+ </option>
+ </options>
+ </field>
+ </fields>
+ <custom_php_validation_command>
+ sassassin_validate_input($_POST, &amp;$input_errors);
+ </custom_php_validation_command>
+ <custom_php_resync_config_command>
+ sassassin_resync();
+ </custom_php_resync_config_command>
+ <custom_php_install_command>
+ sassassin_install_command();
+ </custom_php_install_command>
+</packagegui>
diff --git a/config/sassassin_bl.xml b/config/sassassin_bl.xml
new file mode 100644
index 00000000..850d971c
--- /dev/null
+++ b/config/sassassin_bl.xml
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>sassassinbl</name>
+ <version>none</version>
+ <title>AntiSPAM: Blacklist</title>
+ <include_file>sassassin.inc</include_file>
+ <tabs>
+ <tab>
+ <text>Configuration</text>
+ <url>/pkg_edit.php?xml=sassassin.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Whitelist</text>
+ <url>/pkg.php?xml=sassassin_wl.xml</url>
+ </tab>
+ <tab>
+ <text>Blacklist</text>
+ <url>/pkg.php?xml=sassassin_bl.xml</url>
+ <active/>
+ </tab>
+ </tabs>
+ <adddeleteeditpagefields>
+ <columnitem>
+ <fielddescr>Address</fielddescr>
+ <fieldname>address</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Description</fielddescr>
+ <fieldname>description</fieldname>
+ </columnitem>
+ </adddeleteeditpagefields>
+ <fields>
+ <field>
+ <fielddescr>Address</fielddescr>
+ <fieldname>address</fieldname>
+ <description>This is the email address that will be added to the blacklist (valid wildcards: *, ?).</description>
+ <type>input</type>
+ <required/>
+ </field>
+ <field>
+ <fielddescr>Description</fielddescr>
+ <fieldname>description</fieldname>
+ <description>You may enter a description here for your reference (not parsed).</description>
+ <type>input</type>
+ </field>
+ </fields>
+ <custom_php_resync_config_command>
+ sassassin_resync();
+ </custom_php_resync_config_command>
+</packagegui>
diff --git a/config/sassassin_wl.xml b/config/sassassin_wl.xml
new file mode 100644
index 00000000..132f3e16
--- /dev/null
+++ b/config/sassassin_wl.xml
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>sassassinwl</name>
+ <version>none</version>
+ <title>AntiSPAM: Whitelist</title>
+ <include_file>sassassin.inc</include_file>
+ <tabs>
+ <tab>
+ <text>Configuration</text>
+ <url>/pkg_edit.php?xml=sassassin.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Whitelist</text>
+ <url>/pkg.php?xml=sassassin_wl.xml</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Blacklist</text>
+ <url>/pkg.php?xml=sassassin_bl.xml</url>
+ </tab>
+ </tabs>
+ <adddeleteeditpagefields>
+ <columnitem>
+ <fielddescr>Address</fielddescr>
+ <fieldname>address</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Description</fielddescr>
+ <fieldname>description</fieldname>
+ </columnitem>
+ </adddeleteeditpagefields>
+ <fields>
+ <field>
+ <fielddescr>Address</fielddescr>
+ <fieldname>address</fieldname>
+ <description>This is the email address that will be added to the whitelist (valid wildcards: *, ?).</description>
+ <type>input</type>
+ <required/>
+ </field>
+ <field>
+ <fielddescr>Description</fielddescr>
+ <fieldname>description</fieldname>
+ <description>You may enter a description here for your reference (not parsed).</description>
+ <type>input</type>
+ </field>
+ </fields>
+ <custom_php_resync_config_command>
+ sassassin_resync();
+ </custom_php_resync_config_command>
+</packagegui>
diff --git a/config/schema/packages.dtd b/config/schema/packages.dtd
new file mode 100644
index 00000000..abb4cd6a
--- /dev/null
+++ b/config/schema/packages.dtd
@@ -0,0 +1,224 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- ...................................................................... -->
+<!-- pfSense Package DTD V1.0 ............................................. -->
+<!-- File package.dtd ..................................................... -->
+<!--
+/* $Id$ */
+/* ========================================================================== */
+/*
+ package.dtd
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+-->
+<!--
+ |
+ | May be parsed using http://dtdparse.sourceforge.net/ to generate an
+ | HTML document that describes this DTD.
+ |
+-->
+<!-- Indicates the version of a package -->
+<!ELEMENT version (#PCDATA)>
+<!-- Indicates where to get more informations about this package -->
+<!ELEMENT url (#PCDATA)>
+<!-- needs to be documented -->
+<!ELEMENT depends_on_service (#PCDATA)>
+<!-- needs to be documented -->
+<!ELEMENT tooltiptext (#PCDATA)>
+<!-- The title of a particular package -->
+<!ELEMENT title (#PCDATA)>
+<!-- needs to be documented -->
+<!ELEMENT textneeded (#PCDATA)>
+<!-- Categroy of a particular package (e.g. System) -->
+<!ELEMENT category (#PCDATA)>
+<!-- needs to be documented -->
+<!ELEMENT note (#PCDATA)>
+<!-- needs to be documented -->
+<!ELEMENT savetext (#PCDATA)>
+<!-- needs to be documented -->
+<!ELEMENT preoutput (#PCDATA)>
+<!-- needs to be documented -->
+<!ELEMENT donotsave (#PCDATA)>
+<!-- needs to be documented -->
+<!ELEMENT text (#PCDATA)>
+<!-- Container element. Contains several tab elements -->
+<!ELEMENT tabs ((tab*))>
+<!-- A specific tab that is part of a tab pane -->
+<!ELEMENT tab ((text, url, active?))>
+<!-- A service that may be executed while starting the system -->
+<!ELEMENT service ((name, rcfile?, executable?, description?))>
+<!-- needs to be documented -->
+<!ELEMENT section (#PCDATA)>
+<!-- Indicates what particular kind of components may be required to run this package -->
+<!ELEMENT requirements (#PCDATA)>
+<!-- Shell script that is beeing used to start and stop a service -->
+<!ELEMENT rcfile (#PCDATA)>
+<!-- Executable that represents a service -->
+<!ELEMENT executable (#PCDATA)>
+<!-- needs to be documented -->
+<!ELEMENT prefix (#PCDATA)>
+<!-- Root node of a package definition. Container element -->
+<!ELEMENT packagegui ((copyright, description, requirements, faq, name, version, title, category?, note?, savetext?, preoutput?, donotsave?, aftersaveredirect?, include_file?, backup_file?, delete_string?, addedit_string?, menu*, service*, modify_system?, tabs?, configpath?, adddeleteeditpagefields?, additional_files_needed*, fields?, custom_php_global_functions?, custom_php_command_before_form?, custom_delete_php_command?, custom_add_php_command?, custom_php_resync_config_command?, custom_php_validation_command?, custom_add_php_command_late?, start_command?, restart_command?, process_kill_command?, custom_php_after_form_command?, custom_php_resync_config_command?, custom_php_install_command?, custom_php_deinstall_command?, custom_php_before_form_command?, custom_php_after_head_command?, templates?))>
+<!-- A particular name -->
+<!ELEMENT name (#PCDATA)>
+<!-- Menu item. Container element -->
+<!ELEMENT menu ((name, tooltiptext?, section?, configfile?, url?, depends_on_service?))>
+<!-- needs to be documented -->
+<!ELEMENT modifyitem ((modifyfilename?, textneeded?))>
+<!-- needs to be documented -->
+<!ELEMENT item (#PCDATA)>
+<!-- A PHP file that needs to be included prior to executing arbitrary PHP code -->
+<!ELEMENT include_file (#PCDATA)>
+<!-- needs to be documented -->
+<!ELEMENT backup_file (#PCDATA)>
+<!-- needs to be documented -->
+<!ELEMENT delete_string (#PCDATA)>
+<!-- needs to be documented -->
+<!ELEMENT addedit_string (#PCDATA)>
+<!-- needs to be documented -->
+<!ELEMENT aftersaveredirect (#PCDATA)>
+<!-- FAQ items or an URL that points to certain FAQ items -->
+<!ELEMENT faq (#PCDATA)>
+<!-- needs to be documented -->
+<!ELEMENT modifyfilename (#PCDATA)>
+<!-- needs to be documented -->
+<!ELEMENT modify_system ((modifyitem+))>
+<!-- needs to be documented -->
+<!ELEMENT rowhelperfield ((fielddescr, fieldname, description, type, size?, options?))>
+<!-- needs to be documented -->
+<!ELEMENT rowhelper ((rowhelperfield+))>
+<!-- needs to be documented -->
+<!ELEMENT size (#PCDATA)>
+<!-- needs to be documented -->
+<!ELEMENT donotdisable (#PCDATA)>
+<!-- needs to be documented -->
+<!ELEMENT enablefields (#PCDATA)>
+<!-- needs to be documented -->
+<!ELEMENT required EMPTY>
+<!-- needs to be documented -->
+<!ELEMENT multiple (#PCDATA)>
+<!-- needs to be documented -->
+<!ELEMENT default_value (#PCDATA)>
+<!-- needs to be documented -->
+<!ELEMENT value (#PCDATA)>
+<!-- needs to be documented -->
+<!ELEMENT type (#PCDATA)>
+<!-- needs to be documented -->
+<!ELEMENT cols (#PCDATA)>
+<!-- needs to be documented -->
+<!ELEMENT rows (#PCDATA)>
+<!-- needs to be documented -->
+<!ELEMENT combinefieldsbegin (#PCDATA)>
+<!-- needs to be documented -->
+<!ELEMENT combinefieldsend (#PCDATA)>
+<!-- needs to be documented -->
+<!ELEMENT dontdisplayname (#PCDATA)>
+<!-- needs to be documented -->
+<!ELEMENT dontcombinecells (#PCDATA)>
+<!-- needs to be documented -->
+<!ELEMENT onchange (#PCDATA)>
+<!-- needs to be documented -->
+<!ELEMENT encoding (#PCDATA)>
+<!-- needs to be documented -->
+<!ELEMENT typehint (#PCDATA)>
+<!-- needs to be documented -->
+<!ELEMENT options ((option+))>
+<!-- needs to be documented -->
+<!ELEMENT option ((name, value))>
+<!-- needs to be documented -->
+<!ELEMENT fields ((field*))>
+<!-- needs to be documented -->
+<!ELEMENT filename (#PCDATA)>
+<!-- needs to be documented -->
+<!ELEMENT fieldname (#PCDATA)>
+<!-- needs to be documented -->
+<!ELEMENT fielddescr (#PCDATA)>
+<!-- needs to be documented -->
+<!ELEMENT validationtype (#PCDATA)>
+<!-- needs to be documented -->
+<!ELEMENT field ((fielddescr, fieldname, description?, type, donotdisable?, enablefields?, size?, required?, default_value?, value?, multiple?, options?, cols?, rows?, typehint?, onchange?, encoding?, combinefieldsend?, combinefieldsbegin?, rowhelper?, dontdisplayname?, dontcombinecells?, validationtype?))>
+<!-- needs to be documented -->
+<!ELEMENT description (#PCDATA)>
+<!-- needs to be documented -->
+<!ELEMENT custom_php_global_functions (#PCDATA)>
+<!-- needs to be documented -->
+<!ELEMENT custom_php_command_before_form (#PCDATA)>
+<!-- needs to be documented -->
+<!ELEMENT custom_delete_php_command (#PCDATA)>
+<!-- needs to be documented -->
+<!ELEMENT custom_add_php_command (#PCDATA)>
+<!-- needs to be documented -->
+<!ELEMENT custom_php_resync_config_command (#PCDATA)>
+<!-- needs to be documented -->
+<!ELEMENT custom_php_validation_command (#PCDATA)>
+<!-- needs to be documented -->
+<!ELEMENT custom_add_php_command_late (#PCDATA)>
+<!-- needs to be documented -->
+<!ELEMENT process_kill_command (#PCDATA)>
+<!-- needs to be documented -->
+<!ELEMENT start_command (#PCDATA)>
+<!-- needs to be documented -->
+<!ELEMENT restart_command (#PCDATA)>
+<!-- needs to be documented -->
+<!ELEMENT custom_php_after_form_command (#PCDATA)>
+<!-- needs to be documented -->
+<!ELEMENT custom_php_install_command (#PCDATA)>
+<!-- needs to be documented -->
+<!ELEMENT custom_php_deinstall_command (#PCDATA)>
+<!-- needs to be documented -->
+<!ELEMENT custom_php_after_head_command (#PCDATA)>
+<!-- needs to be documented -->
+<!ELEMENT custom_php_before_form_command (#PCDATA)>
+<!-- needs to be documented -->
+<!ELEMENT copyright (#PCDATA)>
+<!-- needs to be documented -->
+<!ELEMENT configpath (#PCDATA)>
+<!-- needs to be documented -->
+<!ELEMENT configfile (#PCDATA)>
+<!-- needs to be documented -->
+<!ELEMENT chmod (#PCDATA)>
+<!-- needs to be documented -->
+<!ELEMENT columnitem ((fielddescr, fieldname))>
+<!-- needs to be documented -->
+<!ELEMENT adddeleteeditpagefields ((columnitem+))>
+<!-- needs to be documented -->
+<!ELEMENT additional_files_needed ((prefix?, chmod?, item))>
+<!-- needs to be documented -->
+<!ELEMENT active EMPTY>
+<!-- needs to be documented -->
+<!ELEMENT templates ((template+))>
+<!-- needs to be documented -->
+<!ELEMENT templatecontents (#PCDATA)>
+<!-- needs to be documented -->
+<!ELEMENT template ((filename, templatecontents))>
+<!-- End of pfSense package DTD V1.0 ...................................... -->
+<!-- ...................................................................... -->
diff --git a/config/siproxd.inc b/config/siproxd.inc
new file mode 100644
index 00000000..ee1230c9
--- /dev/null
+++ b/config/siproxd.inc
@@ -0,0 +1,172 @@
+<?php
+/* $Id$ */
+/*
+ siproxd.inc
+ Copyright (C) 2006 Scott Ullrich
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+function siproxd_generate_rules($type) {
+ global $config;
+
+ $siproxd_conf = &$config['installedpackages']['siproxdsettings']['config'][0];
+ if (!is_service_running('siproxd')) {
+ log_error("Sipproxd is installed but not started. Not installing redirect rules.");
+ return;
+ }
+
+ /* proxy is turned off in package settings */
+ if($siproxd_conf['rtpenable'] == "0") {
+ log_error("WARNING: siproxd RTP proxy has not been enabled. Not installing rules.");
+ return "\n";
+ }
+
+ $ifaces = explode(",", $siproxd_conf['if_inbound']);
+ $ifaces = array_map('convert_friendly_interface_to_real_interface_name', $ifaces);
+ $rtplower = ($siproxd_conf['rtplower'] ? $siproxd_conf['rtplower'] : 7070);
+ $rtpupper = ($siproxd_conf['rtpupper'] ? $siproxd_conf['rtpupper'] : 7079);
+ $port = ($siproxd_conf['proxy_port'] ? $siproxd_conf['proxy_port'] : 5060);
+
+ switch($type) {
+ case 'nat':
+ $rules .= "\n# Setup Sipproxd proxy redirect\n";
+ foreach ($ifaces as $iface) {
+ $rules .= "rdr on {$iface} proto udp from any to !($iface) port {$port} -> 127.0.0.1 port {$port}\n";
+ }
+ break;
+ case 'filter':
+ foreach ($ifaces as $iface) {
+ $rules .= "# allow SIP signaling and RTP traffic\n";
+ $rules .= "pass in quick on {$iface} proto udp from any to any port = {$port}\n";
+ $rules .= "pass in quick on {$iface} proto udp from any to any port {$rtplower}:{$rtpupper}\n";
+ }
+ break;
+ default:
+ log_error("Siproxd.inc -- error -- should not hit default case statement.");
+ break;
+ }
+
+ return $rules;
+}
+
+function sync_package_siproxd() {
+ global $config;
+
+ unlink_if_exists("/usr/local/etc/rc.d/siproxd");
+
+ $conf = &$config['installedpackages']['siproxd']['config'][0];
+ $fout = fopen("/usr/local/etc/siproxd.conf","w");
+
+ fwrite($fout, "# This file was automatically generated by the pfSense\n");
+ fwrite($fout, "# package management system.\n\n");
+
+ /* proxy is turned off in package settings */
+ if($_POST['rtpenable'] == "0") {
+ fclose($fout);
+ return;
+ }
+
+ if($_POST['if_inbound'] != "") {
+ fwrite($fout, "if_inbound = " . convert_friendly_interface_to_real_interface_name($_POST['if_inbound']) . "\n");
+ }
+
+ if($_POST['if_outbound'] != "") {
+ if($config['interfaces'][$_POST['if_outbound']]['ipaddr'] == "pppoe") {
+ fwrite($fout, "if_outbound = ng0\n");
+ } else {
+ fwrite($fout, "if_outbound = " . convert_friendly_interface_to_real_interface_name($_POST['if_outbound']) . "\n");
+ }
+ }
+
+ if($_POST['port'] != "") {
+ fwrite($fout, "sip_listen_port = " . $_POST['port'] . "\n");
+ } else {
+ fwrite($fout, "sip_listen_port = 5060\n");
+ }
+
+ fwrite($fout, "daemonize = 1\n");
+ fwrite($fout, "silence_log = 0\n");
+ fwrite($fout, "log_calls = 1\n");
+ fwrite($fout, "user = nobody\n");
+ fwrite($fout, "chrootjail = /usr/local/siproxd/\n");
+ fwrite($fout, "registration_file = siproxd_registrations\n");
+ fwrite($fout, "pid_file = siproxd.pid\n");
+
+ if($_POST['rtpenable'] != "") {
+ fwrite($fout, "rtp_proxy_enable = " . $_POST['rtpenable'] . "\n");
+ } else {
+ fwrite($fout, "rtp_proxy_enable = 1\n");
+ }
+
+ if($_POST['rtplower'] != "") {
+ if($_POST['rtpupper'] != "") {
+ fwrite($fout, "rtp_port_low = " . $_POST['rtplower'] . "\n");
+ fwrite($fout, "rtp_port_high = " . $_POST['rtpupper'] . "\n");
+ }
+ }
+
+ if($_POST['rtptimeout'] != "") {
+ fwrite($fout, "rtp_timeout = " . $_POST['rtptimeout'] . "\n");
+ } else {
+ fwrite($fout, "rtp_timeout = 300\n");
+ }
+
+ if($_POST['defaulttimeout'] != "") {
+ fwrite($fout, "default_expires = " . $_POST['defaulttimeout'] . "\n");
+ } else {
+ fwrite($fout, "default_expires = 600\n");
+ }
+
+ if($_POST['authentication']) {
+ fwrite($fout, "proxy_auth_realm = Authentication_Realm\n");
+ fwrite($fout, "proxy_auth_pwfile = /usr/local/etc/siproxd_passwd.cfg\n");
+ }
+
+ fwrite($fout, "debug_level = 0x00000000\n");
+ if($_POST['outboundproxyhost'] != "") {
+ if($_POST['outboundproxyport'] != "") {
+ fwrite($fout, "outbound_proxy_host = " . $_POST['outboundproxyhost'] . "\n");
+ fwrite($fout, "outbound_proxy_port = " . $_POST['outboundproxyport'] . "\n");
+ }
+ }
+
+ fclose($fout);
+
+ write_rcfile(array(
+ "file" => "siproxd.sh",
+ "start" => "/usr/local/sbin/siproxd -c /usr/local/etc/siproxd.conf &",
+ "stop" => "/usr/bin/killall siproxd"
+ )
+ );
+
+ exec("killall siproxd");
+
+ sleep(1);
+
+ start_service("siproxd");
+
+ filter_configure();
+ }
+
+?> \ No newline at end of file
diff --git a/config/siproxd.xml b/config/siproxd.xml
new file mode 100644
index 00000000..5fb56f5e
--- /dev/null
+++ b/config/siproxd.xml
@@ -0,0 +1,166 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ siproxd.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2008 Scott Ullrich
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>siproxdsettings</name>
+ <version>0.5.13_pfs2</version>
+ <title>siproxd: Settings</title>
+ <include_file>/usr/local/pkg/siproxd.inc</include_file>
+ <aftersaveredirect>/pkg_edit.php?xml=siproxd.xml&amp;id=0</aftersaveredirect>
+ <menu>
+ <name>siproxd</name>
+ <tooltiptext>Modify siproxd users and settings.</tooltiptext>
+ <section>Services</section>
+ <url>/pkg_edit.php?xml=siproxd.xml&amp;id=0</url>
+ </menu>
+ <service>
+ <name>siproxd</name>
+ <rcfile>siproxd.sh</rcfile>
+ <executable>siproxd</executable>
+ </service>
+ <tabs>
+ <tab>
+ <text>Settings</text>
+ <url>/pkg_edit.php?xml=siproxd.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Users</text>
+ <url>/pkg.php?xml=siproxdusers.xml</url>
+ </tab>
+ </tabs>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>077</chmod>
+ <item>http://www.pfsense.com/packages/config/siproxdusers.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>077</chmod>
+ <item>http://www.pfsense.com/packages/config/siproxd.inc</item>
+ </additional_files_needed>
+ <fields>
+ <field>
+ <fielddescr>Inbound interface</fielddescr>
+ <fieldname>if_inbound</fieldname>
+ <description>Select the inbound interface.</description>
+ <type>interfaces_selection</type>
+ </field>
+ <field>
+ <fielddescr>Outbound interface</fielddescr>
+ <fieldname>if_outbound</fieldname>
+ <description>Select the outbound interface.</description>
+ <type>interfaces_selection</type>
+ </field>
+ <field>
+ <fielddescr>Listening port</fielddescr>
+ <fieldname>port</fieldname>
+ <description>Enter the port on which to listen for SIP traffic (default 5060). Do not change this unless you know what you're doing.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Enable RTP proxy</fielddescr>
+ <fieldname>rtpenable</fieldname>
+ <description>Enable or disable the RTP proxy. (default is enabled)</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>Enable</name>
+ <value>1</value>
+ </option>
+ <option>
+ <name>Disable</name>
+ <value>0</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>RTP port range (lower)</fielddescr>
+ <fieldname>rtplower</fieldname>
+ <description>Enter the bottom edge of the port range siproxd will allocate for incoming RTP traffic. This range must be one not blocked by the firewall (default 7070).</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>RTP port range (upper)</fielddescr>
+ <fieldname>rtpupper</fieldname>
+ <description>Enter the top edge of the port range siproxd will allocate for incoming RTP traffic. This range must be one not blocked by the firewall (default 7079).</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>RTP stream timeout</fielddescr>
+ <fieldname>rtptimeout</fieldname>
+ <description>After this number of seconds, an RTP stream is considered dead and proxying it will be stopped (default 300sec).</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Default expiration timeout</fielddescr>
+ <fieldname>defaulttimeout</fieldname>
+ <description>If a REGISTER request dose not contain an Expires header or expires= parameter, this number of seconds will be used and reported back to the UA in the answer.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Enable proxy authentication</fielddescr>
+ <fieldname>authentication</fieldname>
+ <description>If this is checked, clients will be forced to authenticate themselves at the proxy (for registration only).</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Outbound proxy hostname</fielddescr>
+ <fieldname>outboundproxyhost</fieldname>
+ <description>Enter the hostname of an outbound proxy to send all traffic to. This is only useful if you have multiple masquerading firewalls to cross.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Outbound proxy port</fielddescr>
+ <fieldname>outboundproxyport</fieldname>
+ <description>Enter the port of the outbound proxy to send all traffic to. This is only useful if you have multiple masquerading firewalls to cross.</description>
+ <type>input</type>
+ </field>
+ </fields>
+ <custom_php_global_functions>
+ </custom_php_global_functions>
+ <custom_add_php_command>
+ sync_package_siproxd();
+ </custom_add_php_command>
+ <custom_php_resync_config_command>
+ </custom_php_resync_config_command>
+</packagegui> \ No newline at end of file
diff --git a/config/siproxdusers.xml b/config/siproxdusers.xml
new file mode 100644
index 00000000..a25418f9
--- /dev/null
+++ b/config/siproxdusers.xml
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>siproxdusers</name>
+ <version>0.5.9</version>
+ <title>siproxd: Users</title>
+ <tabs>
+ <tab>
+ <text>Settings</text>
+ <url>/pkg_edit.php?xml=siproxd.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Users</text>
+ <url>/pkg.php?xml=siproxdusers.xml</url>
+ <active/>
+ </tab>
+ </tabs>
+ <configpath>installedpackages->package->$packagename->configuration->settings</configpath>
+ <adddeleteeditpagefields>
+ <columnitem>
+ <fielddescr>Username</fielddescr>
+ <fieldname>username</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Description</fielddescr>
+ <fieldname>description</fieldname>
+ </columnitem>
+ </adddeleteeditpagefields>
+ <fields>
+ <field>
+ <fielddescr>Username</fielddescr>
+ <fieldname>username</fieldname>
+ <description>Enter the username here</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Password</fielddescr>
+ <fieldname>password</fieldname>
+ <description>Enter the password here</description>
+ <type>password</type>
+ </field>
+ <field>
+ <fielddescr>Username Description</fielddescr>
+ <fieldname>description</fieldname>
+ <description>Enter the description of the user here</description>
+ <type>input</type>
+ </field>
+ </fields>
+ <custom_add_php_command>
+ function sync_package_sipproxd_users()
+ {
+ conf_mount_rw();
+ config_lock();
+ global $config;
+ $fout = fopen("/usr/local/etc/siproxd_passwd.cfg","w");
+ fwrite($fout, "# This file was automatically generated by the pfSense\n# package management system.\n\n");
+ if($config['installedpackages']['siproxdusers']['config'] != "") {
+ foreach($config['installedpackages']['siproxdusers']['config'] as $rowhelper) {
+ fwrite($fout, $rowhelper['username'] . " " . $rowhelper['password'] . "\n");
+ }
+ }
+ fclose($fout);
+ conf_mount_ro();
+ config_unlock();
+ system("/usr/bin/killall -HUP siproxd");
+ }
+ sync_package_sipproxd_users();
+ </custom_add_php_command>
+ <custom_php_resync_config_command>
+ sync_package_sipproxd_users();
+ </custom_php_resync_config_command>
+</packagegui>
+
diff --git a/config/snort/bin/snort2c b/config/snort/bin/snort2c
new file mode 100755
index 00000000..fdc91ac8
--- /dev/null
+++ b/config/snort/bin/snort2c
Binary files differ
diff --git a/config/snort/snort.inc b/config/snort/snort.inc
new file mode 100644
index 00000000..a8b16681
--- /dev/null
+++ b/config/snort/snort.inc
@@ -0,0 +1,751 @@
+<?php
+/* $Id$ */
+/*
+ snort.inc
+ Copyright (C) 2006 Scott Ullrich
+ part of pfSense
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+require_once("pfsense-utils.inc");
+
+/* define oinkid */
+if($config['installedpackages']['snort'])
+ $oinkid = $config['installedpackages']['snort']['config'][0]['oinkmastercode'];
+
+function sync_package_snort_reinstall()
+{
+ global $config;
+ if(!$config['installedpackages']['snort'])
+ return;
+
+ /* create snort configuration file */
+ create_snort_conf();
+
+ /* start snort service */
+ start_service("snort");
+}
+
+function sync_package_snort()
+{
+ global $config, $g;
+
+ mwexec("mkdir -p /var/log/snort/");
+
+ if(!file_exists("/var/log/snort/alert"))
+ touch("/var/log/snort/alert");
+
+ /* snort -> advanced features */
+ $bpfbufsize = $config['installedpackages']['snortadvanced']['config'][0]['bpfbufsize'];
+ $bpfmaxbufsize = $config['installedpackages']['snortadvanced']['config'][0]['bpfmaxbufsize'];
+ $bpfmaxinsns = $config['installedpackages']['snortadvanced']['config'][0]['bpfmaxinsns'];
+
+ /* set the snort performance model */
+ if($config['installedpackages']['snort']['config'][0]['performance'])
+ $snort_performance = $config['installedpackages']['snort']['config'][0]['performance'];
+ else
+ $snort_performance = "ac-bnfa";
+
+ conf_mount_rw();
+ /* create a few directories and ensure the sample files are in place */
+ exec("/bin/mkdir -p /usr/local/etc/snort");
+ exec("/bin/mkdir -p /var/log/snort");
+ exec("/bin/cp /usr/local/etc/snort/unicode.map-sample /usr/local/etc/snort/unicode.map");
+ exec("/bin/cp /usr/local/etc/snort/classification.config-sample /usr/local/etc/snort/classification.config");
+ exec("/bin/cp /usr/local/etc/snort/gen-msg.map-sample /usr/local/etc/snort/gen-msg.map");
+ exec("/bin/cp /usr/local/etc/snort/generators-sample /usr/local/etc/snort/generators");
+ exec("/bin/cp /usr/local/etc/snort/reference.config-sample /usr/local/etc/snort/reference.config");
+ exec("/bin/cp /usr/local/etc/snort/sid-msg.map-sample /usr/local/etc/snort/sid-msg.map");
+ exec("/bin/cp /usr/local/etc/snort/sid-sample /usr/local/etc/snort/sid");
+ exec("/bin/cp /usr/local/etc/snort/threshold.conf-sample /usr/local/etc/snort/threshold.conf");
+ exec("/bin/cp /usr/local/etc/snort/unicode.map-sample /usr/local/etc/snort/unicode.map");
+ exec("/bin/rm -f /usr/local/etc/rc.d/snort");
+
+ $first = 0;
+ $snortInterfaces = array(); /* -gtm */
+
+ $if_list = $config['installedpackages']['snort']['config'][0]['iface_array'];
+ $if_array = split(',', $if_list);
+ //print_r($if_array);
+ if($if_array) {
+ foreach($if_array as $iface) {
+ $if = convert_friendly_interface_to_real_interface_name($iface);
+
+ if($config['interfaces'][$iface]['ipaddr'] == "pppoe") {
+ $if = "ng0";
+ }
+
+ /* build a list of user specified interfaces -gtm */
+ if($if){
+ array_push($snortInterfaces, $if);
+ $first = 1;
+ }
+ }
+
+ if (count($snortInterfaces) < 1) {
+ //log_error("Snort will not start. You must select an interface for it to listen on.");
+ echo "Snort will not start. You must select an interface for it to listen on.";
+ return;
+ }
+ }
+ //print_r($snortInterfaces);
+
+ /* create log directory */
+ $start = "/bin/mkdir -p /var/log/snort";
+
+ /* snort advanced features - bpf tuning */
+ if($bpfbufsize)
+ $start .= ";sysctl net.bpf.bufsize={$bpfbufsize}";
+ if($bpfmaxbufsize)
+ $start .= ";sysctl net.bpf.maxbufsize={$bpfmaxbufsize}";
+ if($bpfmaxinsns)
+ $start .= ";sysctl net.bpf.maxinsns={$bpfmaxinsns}";
+
+ /* go ahead and issue bpf changes */
+ if($bpfbufsize)
+ mwexec_bg("sysctl net.bpf.bufsize={$bpfbufsize}");
+ if($bpfmaxbufsize)
+ mwexec_bg("sysctl net.bpf.maxbufsize={$bpfmaxbufsize}");
+ if($bpfmaxinsns)
+ mwexec_bg("sysctl net.bpf.maxinsns={$bpfmaxinsns}");
+
+ /* always stop snort2c before starting snort -gtm */
+ $start .= ";/usr/bin/killall snort2c";
+
+ /* start a snort process for each interface -gtm */
+ /* Note the sleep delay. Seems to help getting mult interfaces to start -gtm */
+ foreach($snortInterfaces as $snortIf)
+ {
+ $start .= ";sleep 8;snort -c /usr/local/etc/snort/snort.conf -l /var/log/snort -i {$snortIf} -A fast -D";
+ }
+
+ /* if block offenders is checked, start snort2c */
+ if($_POST['blockoffenders'])
+ $start .= ";sleep 8;snort2c -w /var/db/whitelist -a /var/log/snort/alert";
+
+ $sample_before = "\nBEFORE_MEM=`top | grep Free | grep Wired | awk '{print \$10}'`\n";
+ $sample_after = "\nAFTER_MEM=`top | grep Free | grep Wired | awk '{print \$10}'`\n";
+ $sleep_before_final = "\necho \"Sleeping before final memory sampling...\"\nsleep 17";
+ $total_free_after = "\nTOTAL_USAGE=`top | grep snort | grep -v grep | awk '{ print \$6 }'`\n";
+ $echo_usage = "\necho \"Ram free BEFORE starting Snort: \${BEFORE_MEM} -- Ram free AFTER starting Snort: \${AFTER_MEM}\" -- Mode {$snort_performance} -- Snort memory usage: \$TOTAL_USAGE | logger -p daemon.info -i -t SnortStartup\n";
+
+ /* write out rc.d start/stop file */
+ write_rcfile(array(
+ "file" => "snort.sh",
+ "start" => "{$sample_before}{$start}{$sleep_before_final}{$sample_after}{$echo_usage}",
+ "stop" => "/usr/bin/killall snort; killall snort2c"
+ )
+ );
+
+ /* create snort configuration file */
+ create_snort_conf();
+
+ /* start snort service */
+ conf_mount_ro();
+ start_service("snort");
+}
+
+function create_snort_conf() {
+ global $config, $g;
+ /* write out snort.conf */
+ $snort_conf_text = generate_snort_conf();
+ conf_mount_rw();
+ $conf = fopen("/usr/local/etc/snort/snort.conf", "w");
+ if(!$conf) {
+ log_error("Could not open /usr/local/etc/snort/snort.conf for writing.");
+ exit;
+ }
+ fwrite($conf, $snort_conf_text);
+ fclose($conf);
+ conf_mount_ro();
+}
+
+function snort_deinstall() {
+ $text_ww = "*/60\t* \t 1\t *\t *\t root\t /usr/bin/nice -n20 /usr/local/pkg/snort_check_for_rule_updates.php";
+ $filenamea = "/etc/crontab";
+ /* remove auto rules update helper */
+ remove_text_from_file($filenamea, $text_ww);
+ /* remove custom sysctl */
+ remove_text_from_file("/etc/sysctl.conf", "sysctl net.bpf.bufsize=20480");
+ /* decrease bpf buffers back to 4096, from 20480 */
+ exec("/sbin/sysctl net.bpf.bufsize=4096");
+ exec("/usr/bin/killall snort");
+ sleep(5);
+ exec("/usr/bin/killall -9 snort");
+ exec("rm -f /usr/local/etc/rc.d/snort*");
+ exec("rm -rf /usr/local/etc/snort*");
+ exec("cd /var/db/pkg && pkg_delete `ls | grep snort`");
+}
+
+function generate_snort_conf() {
+ global $config, $g;
+ conf_mount_rw();
+ /* obtain external interface */
+ /* XXX: make multi wan friendly */
+ $snort_ext_int = $config['installedpackages']['snort']['config'][0]['iface_array'][0];
+
+ $snort_config_pass_thru = $config['installedpackages']['snortadvanced']['config'][0]['configpassthru'];
+
+ /* add auto update scripts to /etc/crontab */
+ $text_ww = "*/60\t* \t 1\t *\t *\t root\t /usr/bin/nice -n20 /usr/local/pkg/snort_check_for_rule_updates.php";
+ $filenamea = "/etc/crontab";
+ remove_text_from_file($filenamea, $text_ww);
+ add_text_to_file($filenamea, $text_ww);
+ exec("killall -HUP cron");
+
+ /* should we install a automatic update crontab entry? */
+ $automaticrulesupdate = $config['installedpackages']['snort']['config'][0]['automaticrulesupdate'];
+
+ /* if user is on pppoe, we really want to use ng0 interface */
+ if($config['interfaces'][$snort_ext_int]['ipaddr'] == "pppoe")
+ $snort_ext_int = "ng0";
+
+ /* set the snort performance model */
+ if($config['installedpackages']['snort']['config'][0]['performance'])
+ $snort_performance = $config['installedpackages']['snort']['config'][0]['performance'];
+ else
+ $snort_performance = "ac-bnfa";
+
+ /* open snort2c's whitelist for writing */
+ $whitelist = fopen("/var/db/whitelist", "w");
+ if(!$whitelist) {
+ log_error("Could not open /var/db/whitelist for writing.");
+ return;
+ }
+
+ /* build an interface array list */
+ $int_array = array('lan');
+ for ($j = 1; isset ($config['interfaces']['opt' . $j]); $j++)
+ if(isset($config['interfaces']['opt' . $j]['enable']))
+ if(!$config['interfaces']['opt' . $j]['gateway'])
+ $int_array[] = "opt{$j}";
+
+ /* if user has defined a custom ssh port, use it */
+ if($config['system']['ssh']['port'])
+ $ssh_port = $config['system']['ssh']['port'];
+ else
+ $ssh_port = "22";
+
+ /* iterate through interface list and write out whitelist items
+ * and also compile a home_net list for snort.
+ */
+ foreach($int_array as $int) {
+ /* calculate interface subnet information */
+ $ifcfg = &$config['interfaces'][$int];
+ $subnet = gen_subnet($ifcfg['ipaddr'], $ifcfg['subnet']);
+ $subnetmask = gen_subnet_mask($ifcfg['subnet']);
+ if($subnet == "pppoe" or $subnet == "dhcp") {
+ $subnet = find_interface_ip("ng0");
+ if($subnet)
+ $home_net .= "{$subnet} ";
+ } else {
+ if ($subnet)
+ if($ifcfg['subnet'])
+ $home_net .= "{$subnet}/{$ifcfg['subnet']} ";
+ }
+ }
+
+ /* add all WAN ips to the whitelist */
+ $wan_if = get_real_wan_interface();
+ $ip = find_interface_ip($wan_if);
+ if($ip)
+ $home_net .= "{$ip} ";
+
+ /* Add Gateway on WAN interface to whitelist (For RRD graphs) */
+ $int = convert_friendly_interface_to_real_interface_name("WAN");
+ $gw = get_interface_gateway($int);
+ if($gw)
+ $home_net .= "{$gw} ";
+
+ /* Add DNS server for WAN interface to whitelist */
+ $dns_servers = get_dns_servers();
+ foreach($dns_servers as $dns) {
+ if($dns)
+ $home_net .= "{$dns} ";
+ }
+
+ /* Add loopback to whitelist (ftphelper) */
+ $home_net .= "127.0.0.1 ";
+
+ /* iterate all vips and add to whitelist */
+ if($config['virtualip'])
+ foreach($config['virtualip']['vip'] as $vip)
+ if($vip['subnet'])
+ $home_net .= $vip['subnet'] . " ";
+
+ if($config['installedpackages']['snortwhitelist'])
+ foreach($config['installedpackages']['snortwhitelist']['config'] as $snort)
+ if($snort['ip'])
+ $home_net .= $snort['ip'] . " ";
+
+ /* write out whitelist, convert spaces to carriage returns */
+ $whitelist_home_net = str_replace(" ", " ", $home_net);
+ $whitelist_home_net = str_replace(" ", "\n", $home_net);
+
+ /* make $home_net presentable to snort */
+ $home_net = trim($home_net);
+ $home_net = str_replace(" ", ",", $home_net);
+ $home_net = "[{$home_net}]";
+
+ /* foreach through whitelist, writing out to file */
+ $whitelist_split = split("\n", $whitelist_home_net);
+ foreach($whitelist_split as $wl)
+ if(trim($wl))
+ fwrite($whitelist, trim($wl) . "\n");
+
+ /* should we whitelist vpns? */
+ $whitelistvpns = $config['installedpackages']['snort']['config'][0]['whitelistvpns'];
+
+ /* grab a list of vpns and whitelist if user desires */
+ if($whitelistvpns) {
+ $vpns_list = get_vpns_list();
+ $whitelist_vpns = split(" ", $vpns_list);
+ foreach($whitelist_split as $wl)
+ if(trim($wl))
+ fwrite($whitelist, trim($wl) . "\n");
+ }
+
+ /* close file */
+ fclose($whitelist);
+
+ /* generate rule sections to load */
+ $enabled_rulesets = $config['installedpackages']['snort']['rulesets'];
+ if($enabled_rulesets) {
+ $selected_rules_sections = "";
+ $enabled_rulesets_array = split("\|\|", $enabled_rulesets);
+ foreach($enabled_rulesets_array as $enabled_item)
+ $selected_rules_sections .= "include \$RULE_PATH/{$enabled_item}\n";
+ }
+
+ conf_mount_ro();
+
+ /* build snort configuration file */
+ $snort_conf_text = <<<EOD
+
+# snort configuration file
+# generated by the pfSense
+# package manager system
+# see /usr/local/pkg/snort.inc
+# for more information
+
+var HOME_NET {$home_net}
+var EXTERNAL_NET !\$HOME_NET
+
+var DNS_SERVERS \$HOME_NET
+var SMTP_SERVERS \$HOME_NET
+var HTTP_SERVERS \$HOME_NET
+var SQL_SERVERS \$HOME_NET
+var TELNET_SERVERS \$HOME_NET
+var SNMP_SERVERS \$HOME_NET
+var FTP_SERVERS \$HOME_NET
+var SSH_SERVERS \$HOME_NET
+var POP_SERVERS \$HOME_NET
+var IMAP_SERVERS \$HOME_NET
+var RPC_SERVERS \$HOME_NET
+var WWW_SERVERS \$HOME_NET
+var AIM_SERVERS \
+[64.12.24.0/23,64.12.28.0/23,64.12.161.0/24,64.12.163.0/24,64.12.200.0/24,205.188.3.0/24,205.188.5.0/24,205.188.7.0/24,205.188.9.0/24,205.188.153.0/24,205.188.179.0/24,205.188.248.0/24]
+
+portvar HTTP_PORTS 80
+portvar SHELLCODE_PORTS !80
+portvar ORACLE_PORTS 1521
+portvar AUTH_PORTS 113
+portvar DNS_PORTS 53
+portvar FINGER_PORTS 79
+portvar FTP_PORTS 21
+portvar IMAP_PORTS 143
+portvar IRC_PORTS [6665,6666,6667,6668,6669,7000]
+portvar MSSQL_PORTS 1433
+portvar NNTP_PORTS 119
+portvar POP2_PORTS 109
+portvar POP3_PORTS 110
+portvar SUNRPC_PORTS [111,32770,32771,32772,32773,32774,32775,32776,32777,32778,32779]
+portvar RLOGIN_PORTS 513
+portvar RSH_PORTS 514
+portvar SMB_PORTS [139,445]
+portvar SMTP_PORTS 25
+portvar SNMP_PORTS 161
+portvar SSH_PORTS {$ssh_port}
+portvar TELNET_PORTS 23
+portvar MAIL_PORTS [25,143,465,691]
+portvar SSL_PORTS [25,443,465,636,993,995]
+
+var RULE_PATH /usr/local/etc/snort/rules
+
+# Configure the snort decoder
+config checksum_mode: all
+config disable_decode_alerts
+config disable_tcpopt_experimental_alerts
+config disable_tcpopt_obsolete_alerts
+config disable_ttcp_alerts
+config disable_tcpopt_alerts
+config disable_ipopt_alerts
+config disable_decode_drops
+
+#Configure the detection engine
+#Use lower memory models
+config detection: search-method {$snort_performance}
+config detection: max_queue_events 5
+config event_queue: max_queue 8 log 3 order_events content_length
+
+#Configure dynamic loaded libraries
+dynamicpreprocessor file /usr/local/lib/snort/dynamicpreprocessor/libsf_dcerpc_preproc.so
+dynamicpreprocessor file /usr/local/lib/snort/dynamicpreprocessor/libsf_dns_preproc.so
+dynamicpreprocessor file /usr/local/lib/snort/dynamicpreprocessor/libsf_ftptelnet_preproc.so
+dynamicpreprocessor file /usr/local/lib/snort/dynamicpreprocessor/libsf_smtp_preproc.so
+dynamicpreprocessor file /usr/local/lib/snort/dynamicpreprocessor/libsf_ssh_preproc.so
+
+dynamicengine /usr/local/lib/snort/dynamicengine/libsf_engine.so
+
+#Flow and stream
+
+preprocessor frag3_global: max_frags 8192
+preprocessor frag3_engine: policy last detect_anomalies
+preprocessor stream5_global: max_tcp 8192, track_tcp yes, \
+track_udp yes, track_icmp yes
+preprocessor stream5_tcp: policy BSD, ports both all, use_static_footprint_sizes
+preprocessor stream5_udp
+preprocessor stream5_icmp
+
+#HTTP Inspect
+preprocessor http_inspect: global iis_unicode_map unicode.map 1252
+
+preprocessor http_inspect_server: server default \
+ ports { 80 8080 3128 } \
+ no_alerts \
+ non_strict \
+ non_rfc_char { 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 } \
+ flow_depth 0 \
+ apache_whitespace yes \
+ directory no \
+ iis_backslash no \
+ u_encode yes \
+ ascii no \
+ chunk_length 500000 \
+ bare_byte yes \
+ double_decode yes \
+ iis_unicode yes \
+ iis_delimiter yes \
+ multi_slash no
+
+#Other preprocs
+preprocessor rpc_decode: 111 32770 32771 32772 32773 32774 32775 32776 32777 32778 32779
+preprocessor bo
+
+preprocessor ftp_telnet: global \
+inspection_type stateless
+preprocessor ftp_telnet_protocol: \
+ ftp server default \
+ def_max_param_len 100 \
+ ports { 21 } \
+ ftp_cmds { USER PASS ACCT CWD SDUP SMNT QUIT REIN PORT PASV TYPE STRU MODE } \
+ ftp_cmds { RETR STOR STOU APPE ALLO REST RNFR RNTO ABOR DELE RMD MKD PWD } \
+ ftp_cmds { LIST NLST SITE SYST STAT HELP NOOP } \
+ ftp_cmds { AUTH ADAT PROT PBSZ CONF ENC } \
+ ftp_cmds { FEAT OPTS CEL CMD MACB } \
+ ftp_cmds { MDTM REST SIZE MLST MLSD } \
+ ftp_cmds { XPWD XCWD XCUP XMKD XRMD TEST CLNT } \
+ alt_max_param_len 0 { CDUP QUIT REIN PASV STOU ABOR PWD SYST NOOP } \
+ alt_max_param_len 100 { MDTM CEL XCWD SITE USER PASS REST DELE RMD SYST TEST STAT MACB EPSV CLNT LPRT } \
+ alt_max_param_len 200 { XMKD NLST ALLO STOU APPE RETR STOR CMD RNFR HELP } \
+ alt_max_param_len 256 { RNTO CWD } \
+ alt_max_param_len 400 { PORT } \
+ alt_max_param_len 512 { SIZE } \
+ chk_str_fmt { USER PASS ACCT CWD SDUP SMNT PORT TYPE STRU MODE } \
+ chk_str_fmt { RETR STOR STOU APPE ALLO REST RNFR RNTO DELE RMD MKD } \
+ chk_str_fmt { LIST NLST SITE SYST STAT HELP } \
+ chk_str_fmt { AUTH ADAT PROT PBSZ CONF ENC } \
+ chk_str_fmt { FEAT CEL CMD } \
+ chk_str_fmt { MDTM REST SIZE MLST MLSD } \
+ chk_str_fmt { XPWD XCWD XCUP XMKD XRMD TEST CLNT } \
+ cmd_validity MODE < char ASBCZ > \
+ cmd_validity STRU < char FRP > \
+ cmd_validity ALLO < int [ char R int ] > \
+ cmd_validity TYPE < { char AE [ char NTC ] | char I | char L [ number ] } > \
+ cmd_validity MDTM < [ date nnnnnnnnnnnnnn[.n[n[n]]] ] string > \
+ cmd_validity PORT < host_port >
+preprocessor ftp_telnet_protocol: ftp client default \
+ max_resp_len 100
+
+preprocessor SMTP: \
+ ports { 25 465 691 } \
+ inspection_type stateful \
+ normalize cmds \
+ valid_cmds { MAIL RCPT HELP HELO ETRN EHLO EXPN VRFY ATRN SIZE BDAT DEBUG EMAL ESAM ESND ESOM EVFY IDENT NOOP RSET SEND SAML SOML AUTH TURN ETRN PIPELINING \
+CHUNKING DATA DSN RSET QUIT ONEX QUEU STARTTLS TICK TIME TURNME VERB X-EXPS X-LINK2STATE XADR XAUTH XCIR XEXCH50 XGEN XLICENSE XQUEU XSTA XTRN XUSR } \
+ normalize_cmds { MAIL RCPT HELP HELO ETRN EHLO EXPN VRFY ATRN SIZE BDAT DEBUG EMAL ESAM ESND ESOM EVFY IDENT NOOP RSET SEND SAML SOML AUTH TURN ETRN \
+PIPELINING CHUNKING DATA DSN RSET QUIT ONEX QUEU STARTTLS TICK TIME TURNME VERB X-EXPS X-LINK2STATE XADR XAUTH XCIR XEXCH50 XGEN XLICENSE XQUEU XSTA XTRN XUSR } \
+ max_header_line_len 1000 \
+ max_response_line_len 512 \
+ alt_max_command_line_len 260 { MAIL } \
+ alt_max_command_line_len 300 { RCPT } \
+ alt_max_command_line_len 500 { HELP HELO ETRN EHLO } \
+ alt_max_command_line_len 255 { EXPN VRFY ATRN SIZE BDAT DEBUG EMAL ESAM ESND ESOM EVFY IDENT NOOP RSET } \
+ alt_max_command_line_len 246 { SEND SAML SOML AUTH TURN ETRN PIPELINING CHUNKING DATA DSN RSET QUIT ONEX } \
+ alt_max_command_line_len 246 { QUEU STARTTLS TICK TIME TURNME VERB X-EXPS X-LINK2STATE XADR } \
+ alt_max_command_line_len 246 { XAUTH XCIR XEXCH50 XGEN XLICENSE XQUEU XSTA XTRN XUSR } \
+ xlink2state { enable }
+
+
+
+
+#sf Portscan
+preprocessor sfportscan: proto { all } \
+ scan_type { all } \
+ sense_level { low } \
+ ignore_scanners { \$HOME_NET }
+
+preprocessor dcerpc: \
+ autodetect \
+ max_frag_size 3000 \
+ memcap 100000
+
+preprocessor dns: ports { 53 } enable_rdata_overflow
+
+#Output plugins
+#output database: alert
+output alert_syslog: LOG_AUTH LOG_ALERT LOG_CONS LOG_NDELAY LOG_PERROR LOG_PID
+
+output alert_unified: filename alert
+
+#Required files
+include /usr/local/etc/snort/classification.config
+include /usr/local/etc/snort/reference.config
+
+# Include any thresholding or suppression commands. See threshold.conf in the
+# include threshold.conf
+
+# Snort user pass through configuration
+{$snort_config_pass_thru}
+
+#Rulesets, all optional
+{$selected_rules_sections}
+
+EOD;
+
+ return $snort_conf_text;
+}
+
+/* check downloaded text from snort.org to make sure that an error did not occur
+ * for example, if you are not a premium subscriber you can only download rules
+ * so often, etc.
+ */
+function check_for_common_errors($filename) {
+ global $snort_filename, $snort_filename_md5, $console_mode;
+ ob_flush();
+ $contents = file_get_contents($filename);
+ if(stristr($contents, "You don't have permission")) {
+ if(!$console_mode) {
+ update_all_status("An error occured. Scroll down to inspect it's contents.");
+ hide_progress_bar_status();
+ } else {
+ log_error("An error occured. Scroll down to inspect it's contents.");
+ echo "An error occured. Scroll down to inspect it's contents.";
+ }
+ if(!$console_mode) {
+ echo "
+ <center>
+ <div id='error' style='background:white;width:90%'>
+ <!-- TODO: The below paragraphs are kind of stupid. Use CSS instead -->
+ <p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p>
+ <p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p>
+ <p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p>
+ <p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p>
+ <p>The following error occured while downloading the snort rules file from snort.org:</p>
+ {$contents}
+ <p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p>
+ </div>
+ </center>
+ ";
+ } else {
+ $contents = strip_tags($contents);
+ log_error("Error downloading snort rules: {$contents}");
+ echo "Error downloading snort rules: {$contents}";
+ }
+ scroll_down_to_bottom_of_page();
+ exit;
+ }
+}
+
+/* force browser to scroll all the way down */
+function scroll_down_to_bottom_of_page() {
+ global $snort_filename, $console_mode;
+ ob_flush();
+ if(!$console_mode)
+ echo "\n<script type=\"text/javascript\">parent.scrollTo(0,1500);\n</script>";
+}
+
+/* ensure downloaded file looks sane */
+function verify_downloaded_file($filename) {
+ global $snort_filename, $snort_filename_md5, $console_mode;
+ ob_flush();
+ if(filesize($filename)<9500) {
+ if(!$console_mode) {
+ update_all_status("Checking {$filename}...");
+ check_for_common_errors($filename);
+ }
+ }
+ update_all_status("Verifying {$filename}...");
+ if(!file_exists($filename)) {
+ if(!$console_mode) {
+ update_all_status("Could not fetch snort rules ({$filename}). Check oinkid key and dns and try again.");
+ hide_progress_bar_status();
+ } else {
+ log_error("Could not fetch snort rules ({$filename}). Check oinkid key and dns and try again.");
+ echo "Could not fetch snort rules ({$filename}). Check oinkid key and dns and try again.";
+ }
+ exit;
+ }
+ update_all_status("Verifyied {$filename}.");
+}
+
+/* extract rules */
+function extract_snort_rules_md5($tmpfname) {
+ global $snort_filename, $snort_filename_md5, $console_mode;
+ ob_flush();
+ if(!$console_mode) {
+ $static_output = gettext("Extracting snort rules...");
+ update_all_status($static_output);
+ }
+ exec("/usr/bin/tar xzf {$tmpfname}/{$snort_filename} -C /usr/local/etc/snort/");
+ if(!$console_mode) {
+ $static_output = gettext("Snort rules extracted.");
+ update_all_status($static_output);
+ } else {
+ log_error("Snort rules extracted.");
+ echo "Snort rules extracted.";
+ }
+}
+
+/* verify MD5 against downloaded item */
+function verify_snort_rules_md5($tmpfname) {
+ global $snort_filename, $snort_filename_md5, $console_mode;
+ ob_flush();
+ if(!$console_mode) {
+ $static_output = gettext("Verifying md5 signature...");
+ update_all_status($static_output);
+ }
+ $md5 = file_get_contents("{$tmpfname}/{$snort_filename_md5}");
+ $file_md5_ondisk = `/sbin/md5 {$tmpfname}/{$snort_filename} | /usr/bin/awk '{ print $4 }'`;
+ if($md5 <> $file_md5_ondisk) {
+ if(!$console_mode) {
+ $static_output = gettext("snort rules: md5 signature of rules mismatch.");
+ update_all_status($static_output);
+ hide_progress_bar_status();
+ } else {
+ log_error("snort rules: md5 signature of rules mismatch.");
+ echo "snort rules: md5 signature of rules mismatch.";
+ }
+ exit;
+ }
+}
+
+/* hide progress bar */
+function hide_progress_bar_status() {
+ global $snort_filename, $snort_filename_md5, $console_mode;
+ ob_flush();
+ if(!$console_mode)
+ echo "\n<script type=\"text/javascript\">document.progressbar.style.visibility='hidden';\n</script>";
+}
+
+/* update both top and bottom text box during an operation */
+function update_all_status($status) {
+ global $snort_filename, $snort_filename_md5, $console_mode;
+ ob_flush();
+ if(!$console_mode) {
+ update_status($status);
+ update_output_window($status);
+ }
+}
+
+/* obtain alert description for an ip address */
+function get_snort_alert($ip) {
+ global $snort_alert_file_split, $snort_config;
+ if(!file_exists("/var/log/snort/alert"))
+ return;
+ if(!$snort_config)
+ $snort_config = read_snort_config_cache();
+ if($snort_config[$ip])
+ return $snort_config[$ip];
+ if(!$snort_alert_file_split)
+ $snort_alert_file_split = split("\n", file_get_contents("/var/log/snort/alert"));
+ foreach($snort_alert_file_split as $fileline) {
+ if (preg_match("/\[\*\*\] (\[.*\]) (.*) (\[\*\*\])/", $fileline, $matches))
+ $alert_title = $matches[2];
+ if (preg_match("/(\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b)/", $fileline, $matches))
+ $alert_ip = $matches[0];
+ if($alert_ip == $ip) {
+ if(!$snort_config[$ip])
+ $snort_config[$ip] = $alert_title;
+ return $alert_title;
+ }
+ }
+ return "n/a";
+}
+
+function make_clickable($buffer) {
+ global $config, $g;
+ /* if clickable urls is disabled, simply return buffer back to caller */
+ $clickablalerteurls = $config['installedpackages']['snort']['config'][0]['oinkmastercode'];
+ if(!$clickablalerteurls)
+ return $buffer;
+ $buffer = eregi_replace("(^|[ \n\r\t])((http(s?)://)(www\.)?([a-z0-9_-]+(\.[a-z0-9_-]+)+)(/[^/ \n\r]*)*)","\\1<a href=\"\\2\" target=\"_blank\">\\2</a>", $buffer);
+ $buffer = eregi_replace("(^|[ \n\r\t])((ftp://)(www\.)?([a-z0-9_-]+(\.[a-z0-9_-]+)+)(/[^/ \n\r]*)*)","\\1<a href=\"\\2\" target=\"_blank\">\\2</a>", $buffer);
+ $buffer = eregi_replace("([a-z_-][a-z0-9\._-]*@[a-z0-9_-]+(\.[a-z0-9_-]+)+)","<a href=\"mailto:\\1\">\\1</a>", $buffer);
+ $buffer = eregi_replace("(^|[ \n\r\t])(www\.([a-z0-9_-]+(\.[a-z0-9_-]+)+)(/[^/ \n\r]*)*)","\\1<a href=\"http://\\2\" target=\"_blank\">\\2</a>", $buffer);
+ $buffer = eregi_replace("(^|[ \n\r\t])(ftp\.([a-z0-9_-]+(\.[a-z0-9_-]+)+)(/[^/ \n\r]*)*)","\\1<a href=\"ftp://\\2\" target=\"_blank\">\\2</a>", $buffer);
+
+ return $buffer;
+}
+
+function read_snort_config_cache() {
+ global $g, $config, $snort_config;
+ if($snort_config)
+ return $snort_config;
+ if(file_exists($g['tmp_path'] . '/snort_config.cache')) {
+ $snort_config = unserialize(file_get_contents($g['tmp_path'] . '/snort_config.cache'));
+ return $snort_config;
+ }
+ return;
+}
+
+function write_snort_config_cache($snort_config) {
+ global $g, $config;
+ conf_mount_rw();
+ $configcache = fopen($g['tmp_path'] . '/snort_config.cache', "w");
+ if(!$configcache) {
+ log_error("Could not open {$g['tmp_path']}/snort_config.cache for writing.");
+ return false;
+ }
+ fwrite($configcache, serialize($snort_config));
+ fclose($configcache);
+ conf_mount_ro();
+ return true;
+}
+
+function snort_advanced() {
+ global $g, $config;
+ sync_package_snort();
+}
+
+?>
diff --git a/config/snort/snort.xml b/config/snort/snort.xml
new file mode 100644
index 00000000..6ba362c0
--- /dev/null
+++ b/config/snort/snort.xml
@@ -0,0 +1,274 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfsense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>Snort</name>
+ <version>2.8.2.2</version>
+ <title>Services: Snort</title>
+ <include_file>/usr/local/pkg/snort.inc</include_file>
+ <menu>
+ <name>Snort</name>
+ <tooltiptext>Setup snort specific settings</tooltiptext>
+ <section>Services</section>
+ <url>/pkg_edit.php?xml=snort.xml&amp;id=0</url>
+ </menu>
+ <service>
+ <name>snort</name>
+ <rcfile>snort.sh</rcfile>
+ <executable>snort</executable>
+ </service>
+ <tabs>
+ <tab>
+ <text>Settings</text>
+ <url>/pkg_edit.php?xml=snort.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Update Rules</text>
+ <url>/snort_download_rules.php</url>
+ </tab>
+ <tab>
+ <text>Categories</text>
+ <url>/snort_rulesets.php</url>
+ </tab>
+ <tab>
+ <text>Rules</text>
+ <url>/snort_rules.php</url>
+ </tab>
+ <tab>
+ <text>Blocked</text>
+ <url>/snort_blocked.php</url>
+ </tab>
+ <tab>
+ <text>Whitelist</text>
+ <url>/pkg.php?xml=snort_whitelist.xml</url>
+ </tab>
+ <tab>
+ <text>Alerts</text>
+ <url>/snort_alerts.php</url>
+ </tab>
+ <tab>
+ <text>Advanced</text>
+ <url>/pkg_edit.php?xml=snort_advanced.xml&amp;id=0</url>
+ </tab>
+ </tabs>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>077</chmod>
+ <item>http://www.pfsense.com/packages/config/snort/snort.inc</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/bin/</prefix>
+ <chmod>077</chmod>
+ <item>http://www.pfsense.com/packages/config/snort/bin/snort2c</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/bin/</prefix>
+ <chmod>077</chmod>
+ <item>http://www.pfsense.com/packages/config/snort/bin/mons2c</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>077</chmod>
+ <item>http://www.pfsense.com/packages/config/snort/snort_download_rules.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>077</chmod>
+ <item>http://www.pfsense.com/packages/config/snort/snort_rules.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>077</chmod>
+ <item>http://www.pfsense.com/packages/config/snort/snort_rules_edit.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>077</chmod>
+ <item>http://www.pfsense.com/packages/config/snort/snort_rulesets.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>077</chmod>
+ <item>http://www.pfsense.com/packages/config/snort/snort_whitelist.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>077</chmod>
+ <item>http://www.pfsense.com/packages/config/snort/snort_blocked.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>077</chmod>
+ <item>http://www.pfsense.com/packages/config/snort/snort_check_for_rule_updates.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>077</chmod>
+ <item>http://www.pfsense.com/packages/config/snort/snort_alerts.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>077</chmod>
+ <item>http://www.pfsense.com/packages/config/snort/snort_dynamic_ip_reload.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>077</chmod>
+ <item>http://www.pfsense.com/packages/config/snort/snort_advanced.xml</item>
+ </additional_files_needed>
+ <fields>
+ <field>
+ <fielddescr>Interface</fielddescr>
+ <fieldname>iface_array</fieldname>
+ <description>Select the interface(s) Snort will listen on.</description>
+ <type>interfaces_selection</type>
+ <size>3</size>
+ <value>lan</value>
+ <multiple>true</multiple>
+ </field>
+ <field>
+ <fielddescr>Performance</fielddescr>
+ <fieldname>performance</fieldname>
+ <description>ac method is the fastest startup but consumes a lot more memory. acs/ac-banded and ac-sparsebands/mwm/lowmem methods use quite a bit less. ac-sparsebands is recommended.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>ac-bnfa</name>
+ <value>ac-bnfa</value>
+ </option>
+ <option>
+ <name>lowmem</name>
+ <value>lowmem</value>
+ </option>
+ <option>
+ <name>ac-std</name>
+ <value>ac-std</value>
+ </option>
+ <option>
+ <name>ac</name>
+ <value>ac</value>
+ </option>
+ <option>
+ <name>ac-banded</name>
+ <value>ac-banded</value>
+ </option>
+ <option>
+ <name>ac-sparsebands</name>
+ <value>ac-sparsebands</value>
+ </option>
+ <option>
+ <name>acs</name>
+ <value>acs</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Oinkmaster code</fielddescr>
+ <fieldname>oinkmastercode</fieldname>
+ <description>Obtain a snort.org Oinkmaster code and paste here.</description>
+ <type>input</type>
+ <size>60</size>
+ <value></value>
+ </field>
+ <field>
+ <fielddescr>Snort.org subscriber</fielddescr>
+ <fieldname>subscriber</fieldname>
+ <description>Check this box if you are a Snort.org subscriber (premium rules).</description>
+ <type>checkbox</type>
+ <size>60</size>
+ </field>
+ <field>
+ <fielddescr>Block offenders</fielddescr>
+ <fieldname>blockoffenders</fieldname>
+ <description>Checking this option will automatically block hosts that generate a snort alert.</description>
+ <type>checkbox</type>
+ <size>60</size>
+ </field>
+ <field>
+ <fielddescr>Update rules automatically</fielddescr>
+ <fieldname>automaticrulesupdate</fieldname>
+ <description>Checking this option will automatically check for and update rules once a week from snort.org.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Whitelist VPNs automatically</fielddescr>
+ <fieldname>whitelistvpns</fieldname>
+ <description>Checking this option will install whitelists for all VPNs.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Convert Snort alerts urls to clickable links</fielddescr>
+ <fieldname>clickablalerteurls</fieldname>
+ <description>Checking this option will automatically convert URLs in the Snort alerts tab to clickable links.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Associate events on Blocked tab</fielddescr>
+ <fieldname>associatealertip</fieldname>
+ <description>Checking this option will automatically associate the blocked reason from the snort alerts file.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Sync Snort configuration to secondary cluster members</fielddescr>
+ <fieldname>syncxmlrpc</fieldname>
+ <description>Checking this option will automatically sync the snort configuration via XMLRPC to CARP cluster members.</description>
+ <type>checkbox</type>
+ </field>
+ </fields>
+ <custom_add_php_command>
+ sync_package_snort();
+ </custom_add_php_command>
+ <custom_php_resync_config_command>
+ sync_package_snort();
+ </custom_php_resync_config_command>
+ <custom_php_install_command>
+ sync_package_snort_reinstall();
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ snort_deinstall();
+ </custom_php_deinstall_command>
+</packagegui>
diff --git a/config/snort/snort_advanced.xml b/config/snort/snort_advanced.xml
new file mode 100644
index 00000000..35db6945
--- /dev/null
+++ b/config/snort/snort_advanced.xml
@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>SnortAdvanced</name>
+ <version>none</version>
+ <title>Services: Snort Advanced</title>
+ <include_file>/usr/local/pkg/snort.inc</include_file>
+ <tabs>
+ <tab>
+ <text>Settings</text>
+ <url>/pkg_edit.php?xml=snort.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Update Rules</text>
+ <url>/snort_download_rules.php</url>
+ </tab>
+ <tab>
+ <text>Categories</text>
+ <url>/snort_rulesets.php</url>
+ </tab>
+ <tab>
+ <text>Rules</text>
+ <url>/snort_rules.php</url>
+ </tab>
+ <tab>
+ <text>Blocked</text>
+ <url>/snort_blocked.php</url>
+ </tab>
+ <tab>
+ <text>Whitelist</text>
+ <url>/pkg.php?xml=snort_whitelist.xml</url>
+ </tab>
+ <tab>
+ <text>Alerts</text>
+ <url>/snort_alerts.php</url>
+ </tab>
+ <tab>
+ <text>Advanced</text>
+ <url>/pkg_edit.php?xml=snort_advanced.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ </tabs>
+ <fields>
+ <field>
+ <fielddescr>BPF Buffer size</fielddescr>
+ <fieldname>bpfbufsize</fieldname>
+ <description>Changing this option adjusts the system BPF buffer size. Leave blank if you do not know what this does. Default is 1024.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Maximum BPF buffer size</fielddescr>
+ <fieldname>bpfmaxbufsize</fieldname>
+ <description>Changing this option adjusts the system maximum BPF buffer size. Leave blank if you do not know what this does. Default is 524288. This value should never be set above hardware cache size. The best (optimal size) is 50% - 80% of the hardware cache size.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Maximum BPF inserts</fielddescr>
+ <fieldname>bpfmaxinsns</fieldname>
+ <description>Changing this option adjusts the system maximum BPF insert size. Leave blank if you do not know what this does. Default is 512.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Advanced configuration pass through</fielddescr>
+ <fieldname>configpassthru</fieldname>
+ <description>Add items to here will be automatically inserted into the running snort configuration</description>
+ <type>textarea</type>
+ <cols>40</cols>
+ <rows>5</rows>
+ </field>
+ </fields>
+ <custom_php_deinstall_command>
+ snort_advanced();
+ </custom_php_deinstall_command>
+</packagegui>
diff --git a/config/snort/snort_alerts.php b/config/snort/snort_alerts.php
new file mode 100644
index 00000000..70b53656
--- /dev/null
+++ b/config/snort/snort_alerts.php
@@ -0,0 +1,117 @@
+<?php
+/* $Id$ */
+/*
+ snort_alerts.php
+ part of pfSense
+
+ Copyright (C) 2005 Bill Marquette <bill.marquette@gmail.com>.
+ Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require("globals.inc");
+require("guiconfig.inc");
+require("/usr/local/pkg/snort.inc");
+
+$snort_logfile = "{$g['varlog_path']}/snort/alert";
+
+$nentries = $config['syslog']['nentries'];
+if (!$nentries)
+ $nentries = 50;
+
+if ($_POST['clear']) {
+ exec("killall syslogd");
+ exec("rm {$snort_logfile}; touch {$snort_logfile}");
+ system_syslogd_start();
+ exec("/usr/bin/killall -HUP snort");
+ exec("/usr/bin/killall snort2c");
+ if ($config['installedpackages']['snort']['config'][0]['blockoffenders'] == 'on')
+ exec("/usr/local/bin/snort2c -w /var/db/whitelist -a /var/log/snort/alert");
+}
+
+$pgtitle = "Services: Snort: Snort Alerts";
+include("head.inc");
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<?php include("fbegin.inc"); ?>
+<p class="pgtitle"><?=$pgtitle?></p>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr><td>
+<?php
+ $tab_array = array();
+ $tab_array[] = array(gettext("Settings"), false, "/pkg_edit.php?xml=snort.xml&id=0");
+ $tab_array[] = array(gettext("Update Rules"), false, "/snort_download_rules.php");
+ $tab_array[] = array(gettext("Categories"), false, "/snort_rulesets.php");
+ $tab_array[] = array(gettext("Rules"), false, "/snort_rules.php");
+ $tab_array[] = array(gettext("Blocked"), false, "/snort_blocked.php");
+ $tab_array[] = array(gettext("Whitelist"),false, "/pkg.php?xml=snort_whitelist.xml");
+ $tab_array[] = array(gettext("Alerts"), true, "/snort_alerts.php");
+ $tab_array[] = array(gettext("Advanced"), false, "/pkg_edit.php?xml=snort_advanced.xml&id=0");
+ display_top_tabs($tab_array);
+?>
+ </td></tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <table class="tabcont" width="100%" border="0" cellspacing="0" cellpadding="0">
+ <tr>
+ <td colspan="2" class="listtopic">
+ Last <?=$nentries;?> Snort Alert entries</td>
+ </tr>
+ <?php dump_log_file($snort_logfile, $nentries); ?>
+ <tr><td><br><form action="snort_alerts.php" method="post">
+ <input name="clear" type="submit" class="formbtn" value="Clear log"></td></tr>
+ </table>
+ </div>
+ </form>
+ </td>
+ </tr>
+</table>
+<?php include("fend.inc"); ?>
+<meta http-equiv="refresh" content="60;url=<?php print $_SERVER['SCRIPT_NAME']; ?>">
+</body>
+</html>
+<!-- <?php echo $snort_logfile; ?> -->
+
+<?php
+
+function dump_log_file($logfile, $tail, $withorig = true, $grepfor = "", $grepinvert = "") {
+ global $g, $config;
+ $logarr = "";
+ exec("cat {$logfile} | /usr/bin/tail -n {$tail}", $logarr);
+ foreach ($logarr as $logent) {
+ if(!logent)
+ continue;
+ $ww_logent = $logent;
+ $ww_logent = str_replace("[", " [ ", $ww_logent);
+ $ww_logent = str_replace("]", " ] ", $ww_logent);
+ echo "<tr valign=\"top\">\n";
+ echo "<td colspan=\"2\" class=\"listr\">" . make_clickable($ww_logent) . "&nbsp;</td>\n";
+ echo "</tr>\n";
+ }
+}
+
+?> \ No newline at end of file
diff --git a/config/snort/snort_blocked.php b/config/snort/snort_blocked.php
new file mode 100644
index 00000000..29ecf38c
--- /dev/null
+++ b/config/snort/snort_blocked.php
@@ -0,0 +1,138 @@
+<?php
+/* $Id$ */
+/*
+ snort_blocked.php
+ Copyright (C) 2006 Scott Ullrich
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require("guiconfig.inc");
+require("/usr/local/pkg/snort.inc");
+
+if($_POST['todelete'] or $_GET['todelete']) {
+ if($_POST['todelete'])
+ $ip = $_POST['todelete'];
+ if($_GET['todelete'])
+ $ip = $_GET['todelete'];
+ exec("/sbin/pfctl -t snort2c -T delete {$ip}");
+}
+
+$pgtitle = "Snort: Snort Blocked";
+include("head.inc");
+
+?>
+
+<body link="#000000" vlink="#000000" alink="#000000">
+<?php include("fbegin.inc"); ?>
+
+<p class="pgtitle"><?=$pgtitle?></font></p>
+
+<form action="snort_rulesets.php" method="post" name="iform" id="iform">
+<script src="/row_toggle.js" type="text/javascript"></script>
+<script src="/javascript/sorttable.js" type="text/javascript"></script>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+<table width="99%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td>
+<?php
+ $tab_array = array();
+ $tab_array[] = array(gettext("Settings"), false, "/pkg_edit.php?xml=snort.xml&id=0");
+ $tab_array[] = array(gettext("Update Rules"), false, "/snort_download_rules.php");
+ $tab_array[] = array(gettext("Categories"), false, "/snort_rulesets.php");
+ $tab_array[] = array(gettext("Rules"), false, "/snort_rules.php");
+ $tab_array[] = array(gettext("Blocked"), true, "/snort_blocked.php");
+ $tab_array[] = array(gettext("Whitelist"), false, "/pkg.php?xml=snort_whitelist.xml");
+ $tab_array[] = array(gettext("Alerts"), false, "/snort_alerts.php");
+ $tab_array[] = array(gettext("Advanced"), false, "/pkg_edit.php?xml=snort_advanced.xml&id=0");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <table id="maintable" class="tabcont" width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td>
+ <table id="sortabletable1" class="sortable" width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr id="frheader">
+ <td width="5%" class="listhdrr">Remove</td>
+ <td class="listhdrr">IP</td>
+ <td class="listhdrr">Alert Description</td>
+ </tr>
+<?php
+
+ $associatealertip = $config['installedpackages']['snort']['config'][0]['associatealertip'];
+ $ips = `/sbin/pfctl -t snort2c -T show`;
+ $ips_array = split("\n", $ips);
+ $counter = 0;
+ foreach($ips_array as $ip) {
+ if(!$ip)
+ continue;
+ $ww_ip = str_replace(" ", "", $ip);
+ $counter++;
+ if($associatealertip)
+ $alert_description = get_snort_alert($ww_ip);
+ else
+ $alert_description = "";
+ echo "\n<tr>";
+ echo "\n<td align=\"center\" valign=\"top\"'><a href='snort_blocked.php?todelete=" . trim(urlencode($ww_ip)) . "'>";
+ echo "\n<img title=\"Delete\" border=\"0\" name='todelete' id='todelete' alt=\"Delete\" src=\"./themes/{$g['theme']}/images/icons/icon_x.gif\"></a></td>";
+ echo "\n<td>&nbsp;{$ww_ip}</td>";
+ echo "\n<td>&nbsp;{$alert_description}<!-- |{$ww_ip}| get_snort_alert($ww_ip); --></td>";
+ echo "\n</tr>";
+ }
+ echo "\n<tr><td colspan='3'>&nbsp;</td></tr>";
+ if($counter < 1)
+ echo "\n<tr><td colspan='3' align=\"center\" valign=\"top\">There are currently no items being blocked by snort.</td></tr>";
+ else
+ echo "\n<tr><td colspan='3' align=\"center\" valign=\"top\">{$counter} items listed.</td></tr>";
+
+?>
+
+ </table>
+ </td>
+ </tr>
+ </table>
+ </div>
+ </td>
+ </tr>
+</table>
+
+</form>
+
+<p>
+
+This page lists hosts that have been blocked by Snort. Hosts are automatically deleted every 60 minutes.
+<?php include("fend.inc"); ?>
+
+</body>
+</html>
+
+<?php
+
+/* write out snort cache */
+write_snort_config_cache($snort_config);
+
+?> \ No newline at end of file
diff --git a/config/snort/snort_check_for_rule_updates.php b/config/snort/snort_check_for_rule_updates.php
new file mode 100644
index 00000000..92f32900
--- /dev/null
+++ b/config/snort/snort_check_for_rule_updates.php
@@ -0,0 +1,111 @@
+#!/usr/local/bin/php -f
+<?php
+
+/* $Id$ */
+/*
+ snort_check_for_rule_updates.php
+ Copyright (C) 2006 Scott Ullrich
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+$console_mode = true;
+
+require_once("config.inc");
+require_once("functions.inc");
+require_once("/usr/local/pkg/snort.inc");
+require_once("service-utils.inc");
+
+/* check to see if carp settings exist, and get a handle */
+if($config['installedpackages']['carpsettings']) {
+ $carp = &$config['installedpackages']['carpsettings']['config'][0];
+ $password = $carp['password'];
+}
+
+/* if we are not a CARP cluster master, sleep for a random
+ * amount of time allowing for other members to download the configuration
+ */
+if(!$password) {
+ $sleepietime = rand(5,700);
+ sleep($sleepietime);
+}
+
+$last_ruleset_download = $config['installedpackages']['snort']['last_ruleset_download'];
+ini_set('user_agent','Mozilla/4.0 (compatible; MSIE 6.0)');
+$text = file_get_contents("http://www.snort.org/pub-bin/downloads.cgi");
+if (preg_match_all("/.*RELEASED\: (.*)\</", $text, $matches))
+ $last_update_date = trim($matches[1][0]);
+$date1ts = strtotime($last_update_date);
+$date2ts = strtotime($last_ruleset_download);
+/* is there a newer ruleset available? */
+if($date1ts > $date2ts or !$last_ruleset_download) {
+ log_error("There is a new set of Snort rules posted. Downloading...");
+ if(!$oinkid) {
+ log_error("Oinkid is not defined. We cannot automatically update the ruleset.");
+ echo "Oinkid is not defined. We cannot automatically update the ruleset.";
+ exit;
+ }
+ echo "Downloading snort rule updates...";
+ /* setup some variables */
+ $snort_filename = "snortrules-snapshot-CURRENT.tar.gz";
+ $snort_filename_md5 = "snortrules-snapshot-CURRENT.tar.gz.md5";
+ ini_set('user_agent','Mozilla/4.0 (compatible; MSIE 6.0)');
+ $dl = "http://www.snort.org/pub-bin/oinkmaster.cgi/{$oinkid}/{$snort_filename}";
+ $dl_md5 = "http://www.snort.org/pub-bin/oinkmaster.cgi/{$oinkid}/{$snort_filename_md5}";
+
+ /* multi user system, request new filename and create directory */
+ $tmpfname = tempnam("/tmp", "snortRules");
+ exec("/bin/rm -rf {$tmpfname};/bin/mkdir -p {$tmpfname}");
+
+ /* download snort rules */
+ exec("fetch -q -o {$tmpfname}/{$snort_filename} $dl");
+ verify_downloaded_file($tmpfname . "/{$snort_filename}");
+
+ /* download snort rules md5 file */
+ $static_output = gettext("Downloading current snort rules md5... ");
+ exec("fetch -q -o {$tmpfname}/{$snort_filename_md5} $dl_md5");
+ verify_downloaded_file($tmpfname . "/{$snort_filename_md5}");
+
+ /* verify downloaded rules signature */
+ verify_snort_rules_md5($tmpfname);
+
+ /* extract rules */
+ extract_snort_rules_md5($tmpfname);
+
+ $config['installedpackages']['snort']['last_ruleset_download'] = date("Y-m-d");
+ write_config();
+
+ stop_service("snort");
+ sleep(2);
+ start_service("snort");
+
+ /* cleanup temporary directory */
+ exec("/bin/rm -rf {$tmpfname};");
+ echo "Rules are now up to date.\n";
+ log_error("Snort rules updated. New version: {$last_update_date}.");
+} else {
+ echo "Rules are up to date.\n";
+ log_error("Snort rules are up to date. Not updating.");
+}
+
+?> \ No newline at end of file
diff --git a/config/snort/snort_download_rules.php b/config/snort/snort_download_rules.php
new file mode 100644
index 00000000..6326a5fe
--- /dev/null
+++ b/config/snort/snort_download_rules.php
@@ -0,0 +1,240 @@
+<?php
+/* $Id$ */
+/*
+ snort_download_rules.php
+ part of pfSense (http://www.pfsense.com)
+ Copyright (C) 2005 Scott Ullrich
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+/* do not require all of this if we already have. */
+if(!$start_me_up) {
+ require_once("guiconfig.inc");
+ require_once("functions.inc");
+ require_once("service-utils.inc");
+ require("/usr/local/pkg/snort.inc");
+}
+
+$pgtitle = "Services: Snort: Update Rules";
+
+/* define oinkid */
+if($config['installedpackages']['snort'])
+ $oinkid = $config['installedpackages']['snort']['config'][0]['oinkmastercode'];
+
+if($_GET['start'] or $_POST['start'])
+ $start_me_up = true;
+else
+ $start_me_up = false;
+
+if(!is_dir("/usr/local/etc/snort/rules"))
+ $start_me_up = true;
+
+include("head.inc");
+
+?>
+<script src="/javascript/scriptaculous/prototype.js" type="text/javascript"></script>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<?php include("fbegin.inc"); ?>
+
+<p class="pgtitle"><?=$pgtitle?></font></p>
+
+<form action="snort_download_rules.php" method="post">
+<div id="inputerrors"></div>
+
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td>
+<?php
+ $tab_array = array();
+ $tab_array[] = array(gettext("Settings"), false, "/pkg_edit.php?xml=snort.xml&id=0");
+ $tab_array[] = array(gettext("Update Rules"), true, "/snort_download_rules.php");
+ $tab_array[] = array(gettext("Categories"), false, "/snort_rulesets.php");
+ $tab_array[] = array(gettext("Rules"), false, "/snort_rules.php");
+ $tab_array[] = array(gettext("Blocked"), false, "/snort_blocked.php");
+ $tab_array[] = array(gettext("Whitelist"), false, "/pkg.php?xml=snort_whitelist.xml");
+ $tab_array[] = array(gettext("Alerts"), false, "/snort_alerts.php");
+ $tab_array[] = array(gettext("Advanced"), false, "/pkg_edit.php?xml=snort_advanced.xml&id=0");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+<?php
+ if($start_me_up == false) {
+ echo "<tr>\n";
+ echo "<td>\n";
+ echo "<div id=\"mainarea\">\n";
+ echo "<table class=\"tabcont\" width=\"100%\" border=\"0\" cellpadding=\"6\" cellspacing=\"0\">\n";
+ echo "<tr>\n";
+ echo "<td>\n";
+ $last_ruleset_download = $config['installedpackages']['snort']['last_ruleset_download'];
+ echo "<div id='loading' name='loading'>\n";
+ echo "<img src=\"/themes/metallic/images/misc/loader_tab.gif\"> Getting release information from snort.org...\n";
+ echo "</div>\n";
+ ob_flush();
+ sleep(1);
+ ini_set('user_agent','Mozilla/4.0 (compatible; MSIE 6.0)');
+ $text = file_get_contents("http://www.snort.org/pub-bin/downloads.cgi");
+ echo "<script type=\"text/javascript\">\n";
+ echo "$('loading').style.visibility = 'hidden';\n";
+ echo "</script>\n";
+ if (preg_match_all("/.*RELEASED\: (.*)\</", $text, $matches))
+ $last_update_date = trim($matches[1][0]);
+ echo "<table>\n";
+ if($last_update_date)
+ echo "<tr><td><b>Last snort.org rule update:</b></td><td>{$last_update_date}</td></tr>\n";
+ if($last_ruleset_download)
+ echo "<tr><td><b>You last updated the ruleset:</b></td><td>{$last_ruleset_download}</td></tr>\n";
+ else
+ echo "<tr><td><b>You last updated the ruleset:</b></td><td>NEVER</td></tr>\n";
+ echo "</td></tr></table>";
+ if(!$oinkid) {
+ echo "<tr><td colspan='2'>You must obtain an oinkid from snort.org and set its value in the Snort settings tab in order to start the download process.</td></tr>\n";
+ } else {
+ /* get time stamps for comparison operations */
+ $date1ts = strtotime($last_update_date);
+ $date2ts = strtotime($last_ruleset_download);
+ /* is there a newer ruleset available? */
+ if($date1ts > $date2ts or !$last_ruleset_download)
+ echo "<tr><td colspan='2'>Press <a href='snort_download_rules.php?start=yes'>here</a> to start download.</td></tr>\n";
+ else
+ echo "<tr><td colspan='2'>Your snort rulesets are <b>up to date</b>.</td></tr>\n";
+ }
+ echo "</td>\n";
+ echo " </tr>\n";
+ echo " </table>\n";
+ echo " </div>\n";
+ echo "</td>\n";
+ echo "</tr>\n";
+ echo "</table>\n";
+ include("fend.inc");
+ exit;
+ }
+?>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <table class="tabcont" width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td align="center" valign="top">
+ <!-- progress bar -->
+ <table id="progholder" width='420' style='border-collapse: collapse; border: 1px solid #000000;' cellpadding='2' cellspacing='2'>
+ <tr>
+ <td>
+ <img border='0' src='./themes/<?= $g['theme']; ?>/images/misc/progress_bar.gif' width='280' height='23' name='progressbar' id='progressbar' alt='' />
+ </td>
+ </tr>
+ </table>
+ <br />
+ <!-- status box -->
+ <textarea cols="60" rows="1" name="status" id="status" wrap="hard">
+ <?=gettext("Initializing...");?>
+ </textarea>
+ <!-- command output box -->
+ <textarea cols="60" rows="25" name="output" id="output" wrap="hard">
+ </textarea>
+ </td>
+ </tr>
+ </table>
+ </div>
+ </td>
+ </tr>
+</table>
+</form>
+<?php include("fend.inc"); ?>
+<?php
+
+if(!$oinkid) {
+ $static_output = gettext("You must obtain an oinkid from snort.org and set its value in the Snort settings tab.");
+ update_all_status($static_output);
+ hide_progress_bar_status();
+ exit;
+}
+
+/* send current buffer */
+ob_flush();
+
+/* setup some variables */
+$premium_subscriber = "";
+if($config['installedpackages']['snortadvanced']['config'][0]['subscriber'])
+ $premium_subscriber = "_s";
+$snort_filename = "snortrules-snapshot-CURRENT{$premium_subscriber}.tar.gz";
+$snort_filename_md5 = "snortrules-snapshot-CURRENT.tar.gz.md5";
+ini_set('user_agent','Mozilla/4.0 (compatible; MSIE 6.0)');
+$dl = "http://www.snort.org/pub-bin/oinkmaster.cgi/{$oinkid}/{$snort_filename}";
+$dl_md5 = "http://www.snort.org/pub-bin/oinkmaster.cgi/{$oinkid}/{$snort_filename_md5}";
+
+/* multi user system, request new filename and create directory */
+$tmpfname = tempnam("/tmp", "snortRules");
+exec("/bin/rm -rf {$tmpfname};/bin/mkdir -p {$tmpfname}");
+
+/* download snort rules */
+$static_output = gettext("Downloading current snort rules... ");
+update_all_status($static_output);
+download_file_with_progress_bar($dl, $tmpfname . "/{$snort_filename}");
+verify_downloaded_file($tmpfname . "/{$snort_filename}");
+
+/* download snort rules md5 file */
+$static_output = gettext("Downloading current snort rules md5... ");
+update_all_status($static_output);
+download_file_with_progress_bar($dl_md5, $tmpfname . "/{$snort_filename_md5}");
+verify_downloaded_file($tmpfname . "/{$snort_filename_md5}");
+
+/* verify downloaded rules signature */
+verify_snort_rules_md5($tmpfname);
+
+/* extract rules */
+extract_snort_rules_md5($tmpfname);
+
+$static_output = gettext("Your snort rules are now up to date.");
+update_all_status($static_output);
+
+$config['installedpackages']['snort']['last_ruleset_download'] = date("Y-m-d");
+write_config();
+
+stop_service("snort");
+sleep(2);
+start_service("snort");
+
+/* cleanup temporary directory */
+exec("/bin/rm -rf {$tmpfname};");
+
+/* hide progress bar and lets end this party */
+hide_progress_bar_status();
+
+?>
+
+</body>
+</html>
+
+<script type="text/javascript">
+ document.location.href='snort_download_rules.php?ran=1';
+</script>
+
+<?php
+
+
+
+?> \ No newline at end of file
diff --git a/config/snort/snort_dynamic_ip_reload.php b/config/snort/snort_dynamic_ip_reload.php
new file mode 100644
index 00000000..dbd6d015
--- /dev/null
+++ b/config/snort/snort_dynamic_ip_reload.php
@@ -0,0 +1,46 @@
+<?php
+
+/* $Id$ */
+/*
+ snort_dynamic_ip_reload.php
+ Copyright (C) 2006 Scott Ullrich
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/* NOTE: this file gets included from the pfSense filter.inc plugin process */
+
+require_once("/usr/local/pkg/snort.inc");
+require_once("service-utils.inc");
+require_once("config.inc");
+
+
+if($config['interfaces']['wan']['ipaddr'] == "pppoe" or
+ $config['interfaces']['wan']['ipaddr'] == "dhcp") {
+ create_snort_conf();
+ mwexec("/sbin/pfctl -t snort2c -T flush");
+ exec("killall -HUP snort");
+ exec("/usr/bin/killall snort2c; snort2c -w /var/db/whitelist -a /var/log/snort/alert");
+}
+
+?> \ No newline at end of file
diff --git a/config/snort/snort_rules.php b/config/snort/snort_rules.php
new file mode 100644
index 00000000..f1b29f83
--- /dev/null
+++ b/config/snort/snort_rules.php
@@ -0,0 +1,506 @@
+<?php
+/* $Id$ */
+/*
+ edit_snortrule.php
+ Copyright (C) 2004, 2005 Scott Ullrich
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+require("guiconfig.inc");
+
+if(!is_dir("/usr/local/etc/snort/rules"))
+ Header("Location: snort_download_rules.php");
+
+function get_middle($source, $beginning, $ending, $init_pos) {
+ $beginning_pos = strpos($source, $beginning, $init_pos);
+ $middle_pos = $beginning_pos + strlen($beginning);
+ $ending_pos = strpos($source, $ending, $beginning_pos);
+ $middle = substr($source, $middle_pos, $ending_pos - $middle_pos);
+ return $middle;
+}
+
+function write_rule_file($content_changed, $received_file)
+{
+ //read snort file with writing enabled
+ $filehandle = fopen($received_file, "w");
+
+ //delimiter for each new rule is a new line
+ $delimiter = "\n";
+
+ //implode the array back into a string for writing purposes
+ $fullfile = implode($delimiter, $content_changed);
+
+ //write data to file
+ fwrite($filehandle, $fullfile);
+
+ //close file handle
+ fclose($filehandle);
+
+}
+
+function load_rule_file($incoming_file)
+{
+
+ //read snort file
+ $filehandle = fopen($incoming_file, "r");
+
+ //read file into string, and get filesize
+ $contents = fread($filehandle, filesize($incoming_file));
+
+ //close handler
+ fclose ($filehandle);
+
+ //string for populating category select
+ $currentruleset = substr($file, 27);
+
+ //delimiter for each new rule is a new line
+ $delimiter = "\n";
+
+ //split the contents of the string file into an array using the delimiter
+ $splitcontents = explode($delimiter, $contents);
+
+ return $splitcontents;
+
+}
+
+$ruledir = "/usr/local/etc/snort/rules/";
+$dh = opendir($ruledir);
+
+$message_reload = "The Snort rule configuration has been changed.<br>You must apply the changes in order for them to take effect.";
+
+while (false !== ($filename = readdir($dh)))
+{
+ //only populate this array if its a rule file
+ $isrulefile = strstr($filename, ".rules");
+ if ($isrulefile !== false)
+ {
+ $files[] = $filename;
+ }
+}
+
+sort($files);
+
+if ($_GET['openruleset'])
+{
+ $file = $_GET['openruleset'];
+}
+else
+{
+ $file = $ruledir.$files[0];
+
+}
+
+//Load the rule file
+$splitcontents = load_rule_file($file);
+
+if ($_POST)
+{
+ if (!$_POST['apply']) {
+ //retrieve POST data
+ $post_lineid = $_POST['lineid'];
+ $post_enabled = $_POST['enabled'];
+ $post_src = $_POST['src'];
+ $post_srcport = $_POST['srcport'];
+ $post_dest = $_POST['dest'];
+ $post_destport = $_POST['destport'];
+
+ //clean up any white spaces insert by accident
+ $post_src = str_replace(" ", "", $post_src);
+ $post_srcport = str_replace(" ", "", $post_srcport);
+ $post_dest = str_replace(" ", "", $post_dest);
+ $post_destport = str_replace(" ", "", $post_destport);
+
+ //copy rule contents from array into string
+ $tempstring = $splitcontents[$post_lineid];
+
+ //search string
+ $findme = "# alert"; //find string for disabled alerts
+
+ //find if alert is disabled
+ $disabled = strstr($tempstring, $findme);
+
+ //if find alert is false, then rule is disabled
+ if ($disabled !== false)
+ {
+ //has rule been enabled
+ if ($post_enabled == "yes")
+ {
+ //move counter up 1, so we do not retrieve the # in the rule_content array
+ $tempstring = str_replace("# alert", "alert", $tempstring);
+ $counter2 = 1;
+ }
+ else
+ {
+ //rule is staying disabled
+ $counter2 = 2;
+ }
+ }
+ else
+ {
+ //has rule been disabled
+ if ($post_enabled != "yes")
+ {
+ //move counter up 1, so we do not retrieve the # in the rule_content array
+ $tempstring = str_replace("alert", "# alert", $tempstring);
+ $counter2 = 2;
+ }
+ else
+ {
+ //rule is staying enabled
+ $counter2 = 1;
+ }
+ }
+
+ //explode rule contents into an array, (delimiter is space)
+ $rule_content = explode(' ', $tempstring);
+
+ //insert new values
+ $counter2++;
+ $rule_content[$counter2] = $post_src;//source location
+ $counter2++;
+ $rule_content[$counter2] = $post_srcport;//source port location
+ $counter2 = $counter2+2;
+ $rule_content[$counter2] = $post_dest;//destination location
+ $counter2++;
+ $rule_content[$counter2] = $post_destport;//destination port location
+
+ //implode the array back into string
+ $tempstring = implode(' ', $rule_content);
+
+ //copy string into file array for writing
+ $splitcontents[$post_lineid] = $tempstring;
+
+ //write the new .rules file
+ write_rule_file($splitcontents, $file);
+
+ //once file has been written, reload file
+ $splitcontents = load_rule_file($file);
+
+ $stopMsg = true;
+ }
+
+ if ($_POST['apply']) {
+ stop_service("snort");
+ sleep(2);
+ start_service("snort");
+ $savemsg = "The snort rules selections have been saved. Restarting Snort.";
+ $stopMsg = false;
+ }
+
+}
+else if ($_GET['act'] == "toggle")
+{
+ $toggleid = $_GET['id'];
+
+ //copy rule contents from array into string
+ $tempstring = $splitcontents[$toggleid];
+
+ //explode rule contents into an array, (delimiter is space)
+ $rule_content = explode(' ', $tempstring);
+
+ //search string
+ $findme = "# alert"; //find string for disabled alerts
+
+ //find if alert is disabled
+ $disabled = strstr($tempstring, $findme);
+
+ //if find alert is false, then rule is disabled
+ if ($disabled !== false)
+ {
+ //rule has been enabled
+ //move counter up 1, so we do not retrieve the # in the rule_content array
+ $tempstring = str_replace("# alert", "alert", $tempstring);
+
+ }
+ else
+ {
+ //has rule been disabled
+ //move counter up 1, so we do not retrieve the # in the rule_content array
+ $tempstring = str_replace("alert", "# alert", $tempstring);
+
+ }
+
+ //copy string into array for writing
+ $splitcontents[$toggleid] = $tempstring;
+
+ //write the new .rules file
+ write_rule_file($splitcontents, $file);
+
+ //once file has been written, reload file
+ $splitcontents = load_rule_file($file);
+
+ $stopMsg = true;
+}
+
+
+$pgtitle = "Snort: Rules";
+require("guiconfig.inc");
+include("head.inc");
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<?php include("fbegin.inc"); ?>
+<p class="pgtitle"><?=$pgtitle?></p>
+<form action="snort_rules.php" method="post" name="iform" id="iform">
+<?php if ($savemsg){print_info_box($savemsg);} else if ($stopMsg){print_info_box_np($message_reload);}?>
+<br>
+</form>
+<script type="text/javascript" language="javascript" src="row_toggle.js">
+ <script src="/javascript/sorttable.js" type="text/javascript">
+</script>
+
+<script language="javascript" type="text/javascript">
+<!--
+function go()
+{
+ var agt=navigator.userAgent.toLowerCase();
+ if (agt.indexOf("msie") != -1) {
+ box = document.forms.selectbox;
+ } else {
+ box = document.forms[1].selectbox;
+ }
+ destination = box.options[box.selectedIndex].value;
+ if (destination)
+ location.href = destination;
+}
+// -->
+</script>
+
+<table width="99%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td>
+<?php
+ $tab_array = array();
+ $tab_array[] = array(gettext("Settings"), false, "/pkg_edit.php?xml=snort.xml&id=0");
+ $tab_array[] = array(gettext("Update Rules"), false, "/snort_download_rules.php");
+ $tab_array[] = array(gettext("Categories"), false, "/snort_rulesets.php");
+ $tab_array[] = array(gettext("Rules"), true, "/snort_rules.php");
+ $tab_array[] = array(gettext("Blocked"), false, "/snort_blocked.php");
+ $tab_array[] = array(gettext("Whitelist"), false, "/pkg.php?xml=snort_whitelist.xml");
+ $tab_array[] = array(gettext("Alerts"), false, "/snort_alerts.php");
+ $tab_array[] = array(gettext("Advanced"), false, "/pkg_edit.php?xml=snort_advanced.xml&id=0");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <table id="maintable" class="tabcont" width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td>
+ <table id="ruletable1" class="sortable" width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr id="frheader">
+ <td width="3%" class="list">&nbsp;</td>
+ <td width="5%" class="listhdr">SID</td>
+ <td width="6%" class="listhdrr">Proto</td>
+ <td width="15%" class="listhdrr">Source</td>
+ <td width="10%" class="listhdrr">Port</td>
+ <td width="15%" class="listhdrr">Destination</td>
+ <td width="10%" class="listhdrr">Port</td>
+ <td width="32%" class="listhdrr">Message</td>
+
+ </tr>
+ <tr>
+ <?php
+
+ echo "<br>Category: ";
+
+ //string for populating category select
+ $currentruleset = substr($file, 27);
+ ?>
+ <form name="forms">
+ <select name="selectbox" class="formfld" onChange="go()">
+ <?php
+ $i=0;
+ foreach ($files as $value)
+ {
+ $selectedruleset = "";
+ if ($files[$i] === $currentruleset)
+ $selectedruleset = "selected";
+ ?>
+ <option value="?&openruleset=<?=$ruledir;?><?=$files[$i];?>" <?=$selectedruleset;?>><?=$files[$i];?></option>"
+ <?php
+ $i++;
+
+ }
+ ?>
+ </select>
+ </form>
+ </tr>
+ <?php
+
+ $counter = 0;
+ $printcounter = 0;
+
+ foreach ( $splitcontents as $value )
+ {
+
+ $counter++;
+ $disabled = "False";
+ $comments = "False";
+
+ $tempstring = $splitcontents[$counter];
+ $findme = "# alert"; //find string for disabled alerts
+
+ //find alert
+ $disabled_pos = strstr($tempstring, $findme);
+
+
+ //do soemthing, this rule is enabled
+ $counter2 = 1;
+
+ //retrieve sid value
+ $sid = get_middle($tempstring, 'sid:', ';', 0);
+
+ //check to see if the sid is numberical
+ $is_sid_num = is_numeric($sid);
+
+ //if SID is numerical, proceed
+ if ($is_sid_num)
+ {
+
+ //if find alert is false, then rule is disabled
+ if ($disabled_pos !== false){
+ $counter2 = $counter2+1;
+ $textss = "<span class=\"gray\">";
+ $textse = "</span>";
+ $iconb = "icon_block_d.gif";
+ }
+ else
+ {
+ $textss = $textse = "";
+ $iconb = "icon_block.gif";
+ }
+
+ $rule_content = explode(' ', $tempstring);
+
+ $protocol = $rule_content[$counter2];//protocol location
+ $counter2++;
+ $source = $rule_content[$counter2];//source location
+ $counter2++;
+ $source_port = $rule_content[$counter2];//source port location
+ $counter2 = $counter2+2;
+ $destination = $rule_content[$counter2];//destination location
+ $counter2++;
+ $destination_port = $rule_content[$counter2];//destination port location
+
+ $message = get_middle($tempstring, 'msg:"', '";', 0);
+
+ echo "<tr>";
+ echo "<td class=\"listt\">";
+ echo $textss;
+ ?>
+ <a href="?&openruleset=<?=$file;?>&act=toggle&id=<?=$counter;?>"><img src="./themes/<?= $g['theme']; ?>/images/icons/<?=$iconb;?>" width="11" height="11" border="0" title="click to toggle enabled/disabled status"></a>
+ <?php
+ echo $textse;
+ echo "</td>";
+
+
+ echo "<td class=\"listlr\">";
+ echo $textss;
+ echo $sid;
+ echo $textse;
+ echo "</td>";
+
+ echo "<td class=\"listlr\">";
+ echo $textss;
+ echo $protocol;
+ $printcounter++;
+ echo $textse;
+ echo "</td>";
+ echo "<td class=\"listlr\">";
+ echo $textss;
+ echo $source;
+ echo $textse;
+ echo "</td>";
+ echo "<td class=\"listlr\">";
+ echo $textss;
+ echo $source_port;
+ echo $textse;
+ echo "</td>";
+ echo "<td class=\"listlr\">";
+ echo $textss;
+ echo $destination;
+ echo $textse;
+ echo "</td>";
+ echo "<td class=\"listlr\">";
+ echo $textss;
+ echo $destination_port;
+ echo $textse;
+ echo "</td>";
+ ?>
+ <td class="listbg"><font color="white">
+ <?php
+ echo $textss;
+ echo $message;
+ echo $textse;
+ echo "</td>";
+ ?>
+ <td valign="middle" nowrap class="list">
+ <table border="0" cellspacing="0" cellpadding="1">
+ <tr>
+ <td><a href="snort_rules_edit.php?openruleset=<?=$file;?>&id=<?=$counter;?>"><img src="./themes/<?= $g['theme']; ?>/images/icons/icon_e.gif" title="edit rule" width="17" height="17" border="0"></a></td>
+ </tr>
+ </table>
+ </td>
+ <?php
+ }
+ }
+ echo " ";
+ echo "There are ";
+ echo $printcounter;
+ echo " rules in this category. <br><br>";
+ ?>
+ </table>
+ </td>
+ </tr>
+ <table class="tabcont" width="100%" border="0" cellspacing="0" cellpadding="0">
+ <tr>
+ <td width="16"><img src="./themes/<?= $g['theme']; ?>/images/icons/icon_block.gif" width="11" height="11"></td>
+ <td>Rule Enabled</td>
+ </tr>
+ <tr>
+ <td><img src="./themes/<?= $g['theme']; ?>/images/icons/icon_block_d.gif" width="11" height="11"></td>
+ <td nowrap>Rule Disabled</td>
+
+
+ </tr>
+ <tr>
+ <td colspan="10">
+ <p>
+ <!--<strong><span class="red">Warning:<br>
+ </span></strong>Editing these r</p>-->
+ </td>
+ </tr>
+ </table>
+ </table>
+
+ </td>
+ </tr>
+</table>
+
+
+<?php include("fend.inc"); ?>
+</div></body>
+</html> \ No newline at end of file
diff --git a/config/snort/snort_rules_edit.php b/config/snort/snort_rules_edit.php
new file mode 100644
index 00000000..d393a309
--- /dev/null
+++ b/config/snort/snort_rules_edit.php
@@ -0,0 +1,202 @@
+<?php
+/* $Id$ */
+/*
+ snort_rules_edit.php
+ Copyright (C) 2004, 2005 Scott Ullrich
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+function get_middle($source, $beginning, $ending, $init_pos) {
+ $beginning_pos = strpos($source, $beginning, $init_pos);
+ $middle_pos = $beginning_pos + strlen($beginning);
+ $ending_pos = strpos($source, $ending, $beginning_pos);
+ $middle = substr($source, $middle_pos, $ending_pos - $middle_pos);
+ return $middle;
+}
+
+
+$file = $_GET['openruleset'];
+
+//read snort file
+$filehandle = fopen($file, "r");
+
+//get rule id
+$lineid = $_GET['id'];
+
+//read file into string, and get filesize
+$contents = fread($filehandle, filesize($file));
+
+//close handler
+fclose ($filehandle);
+
+//delimiter for each new rule is a new line
+$delimiter = "\n";
+
+//split the contents of the string file into an array using the delimiter
+$splitcontents = explode($delimiter, $contents);
+
+//copy rule contents from array into string
+$tempstring = $splitcontents[$lineid];
+
+//explode rule contents into an array, (delimiter is space)
+$rule_content = explode(' ', $tempstring);
+
+//search string
+$findme = "# alert"; //find string for disabled alerts
+
+//find if alert is disabled
+$disabled = strstr($tempstring, $findme);
+
+//get sid
+$sid = get_middle($tempstring, 'sid:', ';', 0);
+
+
+//if find alert is false, then rule is disabled
+if ($disabled !== false)
+{
+ //move counter up 1, so we do not retrieve the # in the rule_content array
+ $counter2 = 2;
+}
+else
+{
+ $counter2 = 1;
+}
+
+
+$protocol = $rule_content[$counter2];//protocol location
+$counter2++;
+$source = $rule_content[$counter2];//source location
+$counter2++;
+$source_port = $rule_content[$counter2];//source port location
+$counter2++;
+$direction = $rule_content[$counter2];
+$counter2++;
+$destination = $rule_content[$counter2];//destination location
+$counter2++;
+$destination_port = $rule_content[$counter2];//destination port location
+$message = get_middle($tempstring, 'msg:"', '";', 0);
+
+$content = get_middle($tempstring, 'content:"', '";', 0);
+$classtype = get_middle($tempstring, 'classtype:', ';', 0);
+$revision = get_middle($tempstring, 'rev:', ';',0);
+
+$pgtitle = "Snort: Edit Rule";
+require("guiconfig.inc");
+include("head.inc");
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+
+<?php include("fbegin.inc"); ?>
+<p class="pgtitle"><?=$pgtitle?></p>
+<table width="99%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td>
+<?php
+ $tab_array = array();
+ $tab_array[] = array(gettext("Settings"), false, "/pkg_edit.php?xml=snort.xml&id=0");
+ $tab_array[] = array(gettext("Update Rules"), false, "/snort_download_rules.php");
+ $tab_array[] = array(gettext("Categories"), false, "/snort_rulesets.php");
+ $tab_array[] = array(gettext("Rules"), true, "/snort_rules.php?openruleset=/usr/local/etc/snort/rules/attack-responses.rules");
+ $tab_array[] = array(gettext("Blocked"), false, "/snort_blocked.php");
+ $tab_array[] = array(gettext("Whitelist"), false, "/pkg.php?xml=snort_whitelist.xml");
+ $tab_array[] = array(gettext("Alerts"), false, "/snort_alerts.php");
+ $tab_array[] = array(gettext("Advanced"), false, "/pkg_edit.php?xml=snort_advanced.xml&id=0");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <table id="maintable" class="tabcont" width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td>
+ <form action="snort_rules.php?openruleset=<?=$file;?>&id=<?=$lineid;?>" target="" method="post" name="editform" id="editform">
+ <table id="edittable" class="sortable" width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="listhdr" width="10%">Enabled: </td>
+ <td class="listlr" width="30%"><input name="enabled" type="checkbox" id="enabled" value="yes" <?php if ($disabled === false) echo "checked";?>></td>
+ </tr>
+ <tr>
+ <td class="listhdr" width="10%">SID: </td>
+ <td class="listlr" width="30%"><?php echo $sid; ?></td>
+ </tr>
+ <tr>
+ <td class="listhdr" width="10%">Protocol: </td>
+ <td class="listlr" width="30%"><?php echo $protocol; ?></td>
+ </tr>
+ <tr>
+ <td class="listhdr" width="10%">Source: </td>
+ <td class="listlr" width="30%"><input name="src" type="text" id="src" size="20" value="<?php echo $source;?>"></td>
+ </tr>
+ <tr>
+ <td class="listhdr" width="10%">Source Port: </td>
+ <td class="listlr" width="30%"><input name="srcport" type="text" id="srcport" size="20" value="<?php echo $source_port;?>"></td>
+ </tr>
+ <tr>
+ <td class="listhdr" width="10%">Direction:</td>
+ <td class="listlr" width="30%"><?php echo $direction;?></td>
+ </tr>
+ <tr>
+ <td class="listhdr" width="10%">Destination:</td>
+ <td class="listlr" width="30%"><input name="dest" type="text" id="dest" size="20" value="<?php echo $destination;?>"></td>
+ </tr>
+ <tr>
+ <td class="listhdr" width="10%">Destination Port: </td>
+ <td class="listlr" width="30%"><input name="destport" type="text" id="destport" size="20" value="<?php echo $destination_port;?>"></td>
+ </tr>
+ <tr>
+ <td class="listhdr" width="10%">Message: </td>
+ <td class="listlr" width="30%"><?php echo $message; ?></td>
+ </tr>
+ <tr>
+ <td class="listhdr" width="10%">Content: </td>
+ <td class="listlr" width="30%"><?php echo $content; ?></td>
+ </tr>
+ <tr>
+ <td class="listhdr" width="10%">Classtype: </td>
+ <td class="listlr" width="30%"><?php echo $classtype; ?></td>
+ </tr>
+ <tr>
+ <td class="listhdr" width="10%">Revision: </td>
+ <td class="listlr" width="30%"><?php echo $revision; ?></td>
+ </tr>
+ <tr><td>&nbsp</td></tr>
+ <tr>
+ <td><input name="lineid" type="hidden" value="<?=$lineid;?>"></td>
+ <td><input class="formbtn" value="Save" type="submit" name="editsave" id="editsave">&nbsp&nbsp&nbsp<input type="button" class="formbtn" value="Cancel" onclick="history.back()"></td>
+ </tr>
+ </table>
+ </form>
+ </td>
+ </tr>
+ </table>
+ </td>
+</tr>
+</table>
+
+<?php include("fend.inc"); ?>
+</div></body>
+</html> \ No newline at end of file
diff --git a/config/snort/snort_rulesets.php b/config/snort/snort_rulesets.php
new file mode 100644
index 00000000..a06ba106
--- /dev/null
+++ b/config/snort/snort_rulesets.php
@@ -0,0 +1,162 @@
+<?php
+/* $Id$ */
+/*
+ snort_rulesets.php
+ Copyright (C) 2006 Scott Ullrich
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+if(!is_dir("/usr/local/etc/snort/rules"))
+ Header("Location: snort_download_rules.php");
+
+require("guiconfig.inc");
+require_once("service-utils.inc");
+require("/usr/local/pkg/snort.inc");
+
+if($_POST) {
+ $enabled_items = "";
+ $isfirst = true;
+ foreach($_POST['toenable'] as $toenable) {
+ if(!$isfirst)
+ $enabled_items .= "||";
+ $enabled_items .= "{$toenable}";
+ $isfirst = false;
+ }
+ $config['installedpackages']['snort']['rulesets'] = $enabled_items;
+ write_config();
+ stop_service("snort");
+ create_snort_conf();
+ sleep(2);
+ start_service("snort");
+ $savemsg = "The snort ruleset selections have been saved.";
+}
+
+$enabled_rulesets = $config['installedpackages']['snort']['rulesets'];
+if($enabled_rulesets)
+ $enabled_rulesets_array = split("\|\|", $enabled_rulesets);
+
+$pgtitle = "Snort: Categories";
+include("head.inc");
+
+?>
+
+<body link="#000000" vlink="#000000" alink="#000000">
+<?php include("fbegin.inc"); ?>
+
+<p class="pgtitle"><?=$pgtitle?></font></p>
+
+<form action="snort_rulesets.php" method="post" name="iform" id="iform">
+<script src="/row_toggle.js" type="text/javascript"></script>
+<script src="/javascript/sorttable.js" type="text/javascript"></script>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+<table width="99%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td>
+<?php
+ $tab_array = array();
+ $tab_array[] = array(gettext("Settings"), false, "/pkg_edit.php?xml=snort.xml&id=0");
+ $tab_array[] = array(gettext("Update Rules"), false, "/snort_download_rules.php");
+ $tab_array[] = array(gettext("Categories"), true, "/snort_rulesets.php");
+ $tab_array[] = array(gettext("Rules"), false, "/snort_rules.php");
+ $tab_array[] = array(gettext("Blocked"), false, "/snort_blocked.php");
+ $tab_array[] = array(gettext("Whitelist"), false, "/pkg.php?xml=snort_whitelist.xml");
+ $tab_array[] = array(gettext("Alerts"), false, "/snort_alerts.php");
+ $tab_array[] = array(gettext("Advanced"), false, "/pkg_edit.php?xml=snort_advanced.xml&id=0");
+ display_top_tabs($tab_array);
+?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <table id="maintable" class="tabcont" width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td>
+ <table id="sortabletable1" class="sortable" width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr id="frheader">
+ <td width="5%" class="listhdrr">Enabled</td>
+ <td class="listhdrr">Ruleset</td>
+ <!-- <td class="listhdrr">Description</td> -->
+ </tr>
+<?php
+ $dir = "/usr/local/etc/snort/rules/";
+ $dh = opendir($dir);
+ while (false !== ($filename = readdir($dh))) {
+ $files[] = $filename;
+ }
+ sort($files);
+ foreach($files as $file) {
+ if(!stristr($file, ".rules"))
+ continue;
+ echo "<tr>";
+ echo "<td align=\"center\" valign=\"top\">";
+ if(is_array($enabled_rulesets_array))
+ if(in_array($file, $enabled_rulesets_array)) {
+ $CHECKED = " checked=\"checked\"";
+ } else {
+ $CHECKED = "";
+ }
+ else
+ $CHECKED = "";
+ echo " <input type='checkbox' name='toenable[]' value='$file' {$CHECKED} />";
+ echo "</td>";
+ echo "<td>";
+ echo "<a href='snort_rules.php?openruleset=/usr/local/etc/snort/rules/" . urlencode($file) . "'>{$file}</a>";
+ echo "</td>";
+ //echo "<td>";
+ //echo "description";
+ //echo "</td>";
+ }
+
+?>
+ </table>
+ </td>
+ </tr>
+ <tr><td>&nbsp;</td></tr>
+ <tr><td>Check the rulesets that you would like Snort to load at startup.</td></tr>
+ <tr><td>&nbsp;</td></tr>
+ <tr><td><input value="Save" type="submit" name="save" id="save" /></td></tr>
+ </table>
+ </div>
+ </td>
+ </tr>
+</table>
+
+</form>
+
+<p><b>NOTE:</b> You can click on a ruleset name to edit the ruleset.
+
+<?php include("fend.inc"); ?>
+
+</body>
+</html>
+
+<?php
+
+ function get_snort_rule_file_description($filename) {
+ $filetext = file_get_contents($filename);
+
+ }
+
+?> \ No newline at end of file
diff --git a/config/snort/snort_whitelist.xml b/config/snort/snort_whitelist.xml
new file mode 100644
index 00000000..5ac41802
--- /dev/null
+++ b/config/snort/snort_whitelist.xml
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>snort-whitelist</name>
+ <version>0.1.0</version>
+ <title>Snort: Whitelist</title>
+ <include_file>/usr/local/pkg/snort.inc</include_file>
+ <!-- Menu is where this packages menu will appear -->
+ <tabs>
+ <tab>
+ <text>Settings</text>
+ <url>/pkg_edit.php?xml=snort.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Update Rules</text>
+ <url>/snort_download_rules.php</url>
+ </tab>
+ <tab>
+ <text>Categories</text>
+ <url>/snort_rulesets.php</url>
+ </tab>
+ <tab>
+ <text>Rules</text>
+ <url>/snort_rules.php</url>
+ </tab>
+ <tab>
+ <text>Blocked</text>
+ <url>/snort_blocked.php</url>
+ </tab>
+ <tab>
+ <text>Whitelist</text>
+ <url>/pkg.php?xml=snort_whitelist.xml</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Alerts</text>
+ <url>/snort_alerts.php</url>
+ </tab>
+ <tab>
+ <text>Advanced</text>
+ <url>/pkg_edit.php?xml=snort_advanced.xml&amp;id=0</url>
+ </tab>
+ </tabs>
+ <adddeleteeditpagefields>
+ <columnitem>
+ <fielddescr>Whitelisted IP</fielddescr>
+ <fieldname>ip</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Description</fielddescr>
+ <fieldname>description</fieldname>
+ </columnitem>
+ </adddeleteeditpagefields>
+ <fields>
+ <field>
+ <fielddescr>Whitelisted IP</fielddescr>
+ <fieldname>ip</fieldname>
+ <description>Enter the IP or network to whitelist from snort blocking. Network items should be expressed in CIDR notation. Example: 0.0.0.0/24 or 0.0.0.0/32</description>
+ <type>input</type>
+ <size>40</size>
+ </field>
+ <field>
+ <fielddescr>Description</fielddescr>
+ <fieldname>description</fieldname>
+ <description>Enter the description for this item</description>
+ <type>input</type>
+ <size>60</size>
+ </field>
+ </fields>
+ <custom_php_command_before_form>
+ </custom_php_command_before_form>
+ <custom_delete_php_command>
+ </custom_delete_php_command>
+ <custom_php_resync_config_command>
+ create_snort_conf();
+ </custom_php_resync_config_command>
+</packagegui> \ No newline at end of file
diff --git a/config/snort/snort_xmlrpc_sync.php b/config/snort/snort_xmlrpc_sync.php
new file mode 100644
index 00000000..db8b3f3e
--- /dev/null
+++ b/config/snort/snort_xmlrpc_sync.php
@@ -0,0 +1,114 @@
+<?php
+
+/* $Id$ */
+/*
+ snort_xmlrpc_sync.php
+ Copyright (C) 2006 Scott Ullrich
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/* NOTE: this file gets included from the pfSense filter.inc plugin process */
+
+require_once("/usr/local/pkg/snort.inc");
+require_once("service-utils.inc");
+
+if(!$config) {
+ log_error("\$config is not enabled!!");
+} else {
+ if(!$g['booting'])
+ snort_do_xmlrpc_sync();
+}
+
+function snort_do_xmlrpc_sync() {
+
+ return; /* need to fix the bug which whipes out carp sync settings, etc */
+
+ global $config, $g;
+ $syncxmlrpc = $config['installedpackages']['snort']['config'][0]['syncxmlrpc'];
+ /* option enabled? */
+ if(!$syncxmlrpc)
+ return;
+
+ $carp = &$config['installedpackages']['carpsettings']['config'][0];
+ $password = $carp['password'];
+
+ if(!$carp['synchronizetoip'])
+ return;
+
+ log_error("[SNORT] snort_xmlrpc_sync.php is starting.");
+ $xmlrpc_sync_neighbor = $carp['synchronizetoip'];
+ if($config['system']['webgui']['protocol'] != "") {
+ $synchronizetoip = $config['system']['webgui']['protocol'];
+ $synchronizetoip .= "://";
+ }
+ $port = $config['system']['webgui']['port'];
+ /* if port is empty lets rely on the protocol selection */
+ if($port == "") {
+ if($config['system']['webgui']['protocol'] == "http") {
+ $port = "80";
+ } else {
+ $port = "443";
+ }
+ }
+ $synchronizetoip .= $carp['synchronizetoip'];
+
+ /* xml will hold the sections to sync */
+ $xml = array();
+ $xml['installedpackages']['snort'] = &$config['installedpackages']['snort'];
+ $xml['installedpackages']['snortwhitelist'] = &$config['installedpackages']['snortwhitelist'];
+
+ /* assemble xmlrpc payload */
+ $params = array(
+ XML_RPC_encode($password),
+ XML_RPC_encode($xml)
+ );
+
+ /* set a few variables needed for sync code borrowed from filter.inc */
+ $url = $synchronizetoip;
+ $method = 'pfsense.restore_config_section';
+
+ /* Sync! */
+ log_error("Beginning Snort XMLRPC sync to {$url}:{$port}.");
+ $msg = new XML_RPC_Message($method, $params);
+ $cli = new XML_RPC_Client('/xmlrpc.php', $url, $port);
+ $cli->setCredentials('admin', $password);
+ if($g['debug'])
+ $cli->setDebug(1);
+ /* send our XMLRPC message and timeout after 240 seconds */
+ $resp = $cli->send($msg, "999");
+ if(!$resp) {
+ $error = "A communications error occured while attempting Snort XMLRPC sync with {$url}:{$port}.";
+ log_error($error);
+ file_notice("sync_settings", $error, "Snort Settings Sync", "");
+ } elseif($resp->faultCode()) {
+ $error = "An error code was received while attempting Snort XMLRPC sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString();
+ log_error($error);
+ file_notice("sync_settings", $error, "Snort Settings Sync", "");
+ } else {
+ log_error("Snort XMLRPC sync successfully completed with {$url}:{$port}.");
+ }
+ log_error("[SNORT] snort_xmlrpc_sync.php is ending.");
+}
+
+?> \ No newline at end of file
diff --git a/config/spamd.inc b/config/spamd.inc
new file mode 100644
index 00000000..3088d037
--- /dev/null
+++ b/config/spamd.inc
@@ -0,0 +1,289 @@
+<?php
+/* $Id$ */
+/*
+ spamd.inc
+ part of the SpamD package for pfSense
+ Copyright (C) 2008 Scott Ullrich
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+*/
+function sync_package_spamd() {
+ global $config, $g;
+
+ conf_mount_rw();
+ config_lock();
+ $fd = fopen("/etc/spamd.conf","w");
+ /* all header */
+ fwrite($fd, "all:\\\n\t:whitelist:blacklist");
+ if($config['installedpackages']['spamdsources']['config']) {
+ foreach($config['installedpackages']['spamdsources']['config'] as $spamd) {
+ if($spamd['providername']) {
+ fwrite($fd, ":" . remove_spaces($spamd['providername']));
+ }
+ }
+ }
+ fwrite($fd, ":\n\n");
+ fwrite($fd, "whitelist:\\\n");
+ fwrite($fd, "\t:method=file:\\\n");
+ fwrite($fd, "\t:white:\\\n");
+ fwrite($fd, "\t:file=/var/db/whitelist.txt:\n");
+ fwrite($fd, "\n");
+ fwrite($fd, "blacklist:\\\n");
+ fwrite($fd, "\t:black:\\\n");
+ fwrite($fd, "\t:msg=\"Sorry, you spammed us before.\":\\\n");
+ fwrite($fd, "\t:method=file:\\\n");
+ fwrite($fd, "\t:file=/var/db/blacklist.txt:\n\n");
+ log_error("Looping through each item and write out its configuration");
+ /* loop through each item and write out its configuration */
+ if($config['installedpackages']['spamdsources']['config'] != "") {
+ foreach($config['installedpackages']['spamdsources']['config'] as $spamd) {
+ if(remove_spaces($spamd['providername'])) {
+ if($spamd['providername']) {
+ fwrite($fd, remove_spaces($spamd['providername']) . ":\\\n");
+ fwrite($fd, "\t:" . remove_spaces($spamd['providertype']) . ":\\\n");
+ fwrite($fd, "\t:msg=\"" . rtrim($spamd['rejectmessage']) . "\":\\\n");
+ fwrite($fd, "\t:method=" . remove_spaces($spamd['providermethod']) . ":\\\n");
+ $providerurl = $spamd['providerurl'];
+ $providerurl = str_replace("http://", "", $providerurl);
+ $providerurl = str_replace("https://", "", $providerurl);
+ fwrite($fd, "\t:file=" . remove_spaces($providerurl) . ":\n\n");
+ }
+ }
+ }
+ }
+ fclose($fd);
+ log_error("Creating /var/db/whitelist.txt");
+ $fd = fopen("/var/db/whitelist.txt","w");
+ if($config['installedpackages']['spamdwhitelist']['config'] != "") {
+ foreach($config['installedpackages']['spamdwhitelist']['config'] as $spamd) {
+ if($spamd['ip'])
+ fwrite($fd, $spamd['ip'] . "\n");
+ }
+ }
+ fclose($fd);
+ $passtime = "5";
+ $greyexp = "4";
+ $whiteexp = "864";
+ $identifier = "";
+ $maxcon = "";
+ $maxblack = "";
+ $stuttersecs = "";
+ $delaysecs = "";
+ log_error("Looping through spamdsettings");
+ if($config['installedpackages']['spamdsettings']['config']) {
+ foreach($config['installedpackages']['spamdsettings']['config'] as $ss) {
+ if($ss['nextmta'] <> "")
+ $nextmta = $ss['nextmta'];
+ if($ss['greylistingparms'] <> "")
+ $passtime = " -G " . $ss['greylistingparms'];
+ if($ss['identifier'] <> "")
+ $identifier = " -n \"" . $ss['identifier'] . "\"";
+ // Default is greylisting, turn on blacklisting if not checked.
+ if($ss['greylisting'] <> "on")
+ $greylisting = " -b";
+ if($ss['maxblack'] <> "")
+ $maxblack = " -B " . $ss['maxblack'];
+ if($ss['maxcon'] <> "")
+ $maxcon = " -c " . $ss['maxcon'];
+ if($ss['stuttersecs'] <> "")
+ $stuttersecs = " -S " . $ss['stuttersecs'];
+ if($ss['delaysecs'] <> "")
+ $delaysecs = " -s " . $ss['delaysecs'];
+ if($ss['window'] <> "")
+ $window = " -w " . $ss['window'];
+ if($ss['passtime'] <> "")
+ $passtime = $ss['passtime'];
+ if($ss['greyexp'] <> "")
+ $greyexp = $ss['greyexp'];
+ if($ss['whiteexp'] <> "")
+ $whiteexp = $ss['whiteexp'];
+ }
+ }
+ $greyparms = " -G {$passtime}:{$greyexp}:{$whiteexp}";
+ $start = "if [ `mount | grep -v grep | grep fdescfs | wc -l` -lt 1 ]; then \n" .
+ "/sbin/mount -t fdescfs fdescfs /dev/fd\n" .
+ "fi\n" .
+ "/usr/local/sbin/spamd-setup -d &\n" .
+ "/sbin/pflogd &\n" .
+ "/usr/local/libexec/spamd {$greyparms}{$identifier}{$greylisting}{$maxcon}{$maxblack}{$window}{$replysmtperror} 127.0.0.1 &\n" .
+ "/usr/local/libexec/spamlogd\n";
+ $stop = "/usr/bin/killall spamd-setup\n" .
+ "/usr/bin/killall spamlogd\n" .
+ "/usr/bin/killall spamd\n" .
+ "/usr/bin/killall pflogd\n" .
+ "sleep 2";
+ log_error("Writing rc_file");
+ write_rcfile(array(
+ "file" => "spamd.sh",
+ "start" => $start,
+ "stop" => $stop
+ )
+ );
+ log_error("Installing CRON");
+ spamd_install_cron(true);
+ log_error("Mounting RO");
+ conf_mount_ro();
+ log_error("Unlocking config");
+ config_unlock();
+ log_error("Restart cron");
+ mwexec("killall -HUP cron");
+ log_error("Setting up spamd.conf symlink");
+ mwexec("ln -s /etc/spamd.conf /usr/local/etc/spamd/spamd.conf");
+ log_error("Stopping spamd");
+ mwexec("/usr/local/etc/rc.d/spamd.sh stop");
+ sleep(1);
+ log_error("Starting spamd");
+ mwexec_bg("/usr/local/etc/rc.d/spamd.sh start");
+ log_error("Reconfiguring filter");
+ filter_configure();
+ log_error("SpamD setup completed");
+}
+
+function remove_spaces($string) {
+ $string = str_replace(" ", "", $string);
+ return $string;
+}
+
+function sync_spamd_config_to_backup() {
+ global $g, $config;
+ if(is_array($config['installedpackages']['carpsettings']['config'])) {
+ foreach($config['installedpackages']['carpsettings']['config'] as $carp) {
+ if($carp['synchronizetoip'] != "" ) {
+ $synctoip = $carp['synchronizetoip'];
+ $password = $carp['password'];
+ if($config['system']['username'])
+ $username = $config['system']['username'];
+ else
+ $username = "admin";
+ }
+ }
+ }
+ if($synctoip and $password) {
+ if($config['system']['webgui']['protocol'] != "") {
+ $synchronizetoip = $config['system']['webgui']['protocol'];
+ $synchronizetoip .= "://";
+ }
+ $port = $config['system']['webgui']['port'];
+ /* if port is empty lets rely on the protocol selection */
+ if($port == "") {
+ if($config['system']['webgui']['protocol'] == "http") {
+ $port = "80";
+ } else {
+ $port = "443";
+ }
+ }
+ $params = array(XML_RPC_encode($password),XML_RPC_encode($xml));
+ /* create files to sync array */
+ $filetosync = array("/var/db/spamd", "/var/db/whitelist.txt");
+ /* loop through files to sync list and sync them up */
+ foreach($filetosync as $f2s) {
+ $f2c_contents = file_get_contents($f2s);
+ xmlrpc_sync_file($url, $password, $f2s, $f2c_contents, $port);
+ }
+ /* signal remote process config reload */
+ xmlrpc_exec_shell($url, $password, "/usr/bin/killall -HUP spamlogd", $port);
+ xmlrpc_exec_shell($url, $password, "/usr/bin/killall -HUP spamd", $port);
+ }
+}
+
+function custom_php_install_command() {
+ global $config, $g;
+ system("touch /var/db/whitelist.txt");
+ system("touch /var/db/blacklist.txt");
+ sync_package_spamd();
+}
+
+function custom_php_deinstall_command() {
+ global $config, $g;
+ conf_mount_rw();
+ exec("killall -9 spamd");
+ unlink_if_exists("/usr/local/pkg/pf/spamd_rules.php");
+ unlink_if_exists("/usr/local/www/spamd_rules.php");
+ unlink_if_exists("/usr/local/etc/rc.d/spamd.sh");
+ spamd_install_cron(false);
+ conf_mount_ro();
+ filter_configure();
+}
+
+function spamd_install_cron($should_install) {
+ global $config, $g;
+ $is_installed = false;
+ if(!$config['cron']['item'])
+ return;
+ $x=0;
+ foreach($config['cron']['item'] as $item) {
+ if(strstr($item['command'], "spamd-setup")) {
+ $is_installed = true;
+ break;
+ }
+ $x++;
+ }
+ switch($should_install) {
+ case true:
+ if(!$is_installed) {
+ $cron_item = array();
+ $cron_item['minute'] = "*/120";
+ $cron_item['hour'] = "*";
+ $cron_item['mday'] = "*";
+ $cron_item['month'] = "*";
+ $cron_item['wday'] = "*";
+ $cron_item['who'] = "root";
+ $cron_item['command'] = "/usr/bin/nice -n20 /usr/local/sbin/spamd-setup";
+ $config['cron']['item'][] = $cron_item;
+ write_config("Installed SPAMD crontab entries.");
+ configure_cron();
+ }
+ break;
+ case false:
+ if($is_installed == true) {
+ if($x > 0) {
+ unset($config['cron']['item'][$x]);
+ write_config();
+ }
+ configure_cron();
+ }
+ break;
+ }
+}
+
+function spamd_validate_input($post, $input_errors) {
+ global $config, $g;
+ $nextmta = str_replace("$", "", $post['nextmta']);
+ if(stristr($nextmta, "{")) {
+ /* item is an alias, make sure the name exists */
+ $nextmta = str_replace("$", "", $nextmta);
+ $found = false;
+ if($config['aliases']['alias']) {
+ foreach($config['aliases']['alias'] as $alias) {
+ if($alias['name'] == $nextmta) {
+ $found = true;
+ }
+ }
+ }
+ if($found == false)
+ $intput_errors = "Could not locate alias named " . htmlentities($nextmta);
+ }
+}
+
+?> \ No newline at end of file
diff --git a/config/spamd.xml b/config/spamd.xml
new file mode 100644
index 00000000..a065c0a8
--- /dev/null
+++ b/config/spamd.xml
@@ -0,0 +1,210 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ spamd.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2008 Scott Ullrich
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>spamdsources</name>
+ <version>4.2</version>
+ <title>SpamD: External Sources</title>
+ <include_file>/usr/local/pkg/spamd.inc</include_file>
+ <backup_file>/var/db/spamd</backup_file>
+ <!-- Menu is where this packages menu will appear -->
+ <menu>
+ <name>SpamD</name>
+ <section>Services</section>
+ <configfile>spamd.xml</configfile>
+ </menu>
+ <service>
+ <name>spamd</name>
+ <rcfile>/usr/local/etc/rc.d/spamd.sh</rcfile>
+ </service>
+ <tabs>
+ <tab>
+ <text>SpamD External Sources</text>
+ <url>/pkg.php?xml=spamd.xml</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>SpamD Whitelist</text>
+ <url>/pkg.php?xml=spamd_whitelist.xml</url>
+ </tab>
+ <tab>
+ <text>SpamD Settings</text>
+ <url>/pkg_edit.php?xml=spamd_settings.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>SpamD Database</text>
+ <url>/spamd_db.php</url>
+ </tab>
+ </tabs>
+ <!-- configpath gets expanded out automatically and config items will be
+ stored in that location -->
+ <configpath>['installedpackages']['spamd']['config']</configpath>
+ <adddeleteeditpagefields>
+ <columnitem>
+ <fielddescr>Provider Name</fielddescr>
+ <fieldname>providername</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Provider Type</fielddescr>
+ <fieldname>providertype</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Description</fielddescr>
+ <fieldname>providerdescription</fieldname>
+ </columnitem>
+ </adddeleteeditpagefields>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/spamd_rules.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/spamd_whitelist.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/spamd_outlook.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/spamd.inc</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/spamd_settings.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/spamd_db.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/spamd_db_ext.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/bin/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/spamd_gather_stats.php</item>
+ </additional_files_needed>
+
+ <!-- fields gets invoked when the user adds or edits a item. the following items
+ will be parsed and rendered for the user as a gui with input, and selectboxes. -->
+ <fields>
+ <field>
+ <fielddescr>Provider Name</fielddescr>
+ <fieldname>providername</fieldname>
+ <description>Enter the name of the source</description>
+ <type>input</type>
+ <size>30</size>
+ </field>
+ <field>
+ <fielddescr>Provider Type</fielddescr>
+ <fieldname>providertype</fieldname>
+ <description>Select the Provider Type</description>
+ <type>select</type>
+ <size>1</size>
+ <value>black</value>
+ <options>
+ <option><name>Black List</name><value>black</value></option>
+ <option><name>White List</name><value>white</value></option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Provider Description</fielddescr>
+ <fieldname>providerdescription</fieldname>
+ <description>Enter the description for this item</description>
+ <type>textarea</type>
+ <size>30</size>
+ <cols>40</cols>
+ <rows>4</rows>
+ </field>
+ <field>
+ <fielddescr>Reject message</fielddescr>
+ <fieldname>rejectmessage</fieldname>
+ <description>Enter the message to display to emailing parties that are on this providers list</description>
+ <type>textarea</type>
+ <size>30</size>
+ <cols>40</cols>
+ <rows>2</rows>
+ </field>
+ <field>
+ <fielddescr>Provider Method</fielddescr>
+ <fieldname>providermethod</fieldname>
+ <description>Select the Provider Method</description>
+ <type>select</type>
+ <size>1</size>
+ <value>http</value>
+ <options>
+ <option><name>File</name><value>file</value></option>
+ <option><name>URL</name><value>http</value></option>
+ <option><name>Execute command</name><value>exec</value></option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Provider URL or Filename</fielddescr>
+ <fieldname>providerurl</fieldname>
+ <description>Enter the URL to the provider.</description>
+ <type>textarea</type>
+ <cols>40</cols>
+ <rows>4</rows>
+ </field>
+ </fields>
+ <custom_delete_php_command>
+ sync_package_spamd();
+ </custom_delete_php_command>
+ <custom_php_resync_config_command>
+ sync_package_spamd();
+ </custom_php_resync_config_command>
+ <custom_php_install_command>
+ custom_php_install_command();
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ custom_php_deinstall_command();
+ </custom_php_deinstall_command>
+</packagegui> \ No newline at end of file
diff --git a/config/spamd_db.php b/config/spamd_db.php
new file mode 100644
index 00000000..112fdd71
--- /dev/null
+++ b/config/spamd_db.php
@@ -0,0 +1,457 @@
+<?php
+/* $Id$ */
+/*
+ spamd_db.php
+ part of the pfSense project
+ Copyright (C) 2006, 2007, 2008 Scott Ullrich
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require("guiconfig.inc");
+
+if($_POST['filter'])
+ $filter = $_POST['filter'];
+if($_POST['not'])
+ $not = true;
+if($_POST['limit'])
+ $limit = intval($_POST['limit']);
+else
+ $limit = "25";
+
+/* handle AJAX operations */
+if($_GET['action'] or $_POST['action']) {
+ /* echo back buttonid so it can be turned
+ * back off when request is completed.
+ */
+ echo $_GET['buttonid'] . "|";
+ if($_GET['action'])
+ $action = escapeshellarg($_GET['action']);
+ if($_POST['action'])
+ $action = escapeshellarg($_POST['action']);
+ if($_GET['srcip'])
+ $srcip = $_GET['srcip'];
+ if($_POST['srcip'])
+ $srcip = $_POST['srcip'];
+ if($_POST['toaddress'])
+ $toaddress = escapeshellarg($_POST['toaddress']);
+ $srcip = str_replace("<","",$srcip);
+ $srcip = str_replace(">","",$srcip);
+ $srcip = str_replace(" ","",$srcip);
+ // Make input safe
+ $srcip = escapeshellarg($srcip);
+ /* execute spamdb command */
+ if($action == "'whitelist'") {
+ exec("/usr/local/sbin/spamdb -d {$srcip}");
+ exec("/usr/local/sbin/spamdb -d {$srcip} -T");
+ exec("/usr/local/sbin/spamdb -d {$srcip} -t");
+ delete_from_blacklist($srcip);
+ mwexec("/sbin/pfctl -q -t blacklist -T replace -f /var/db/blacklist.txt");
+ exec("echo spamdb -a {$srcip} > /tmp/tmp");
+ exec("/usr/local/sbin/spamdb -a {$srcip}");
+ } else if($action == "'delete'") {
+ exec("/usr/local/sbin/spamdb -d {$srcip}");
+ exec("/usr/local/sbin/spamdb -d {$srcip} -T");
+ exec("/usr/local/sbin/spamdb -d {$srcip} -t");
+ delete_from_blacklist($srcip);
+ mwexec("/sbin/pfctl -q -t spamd -T delete $srcip");
+ mwexec("/sbin/pfctl -q -t blacklist -T replace -f /var/db/blacklist.txt");
+ } else if($action == "'spamtrap'") {
+ exec("/usr/local/sbin/spamdb -d {$srcip}");
+ exec("/usr/local/sbin/spamdb -d {$srcip} -T");
+ exec("/usr/local/sbin/spamdb -d {$srcip} -t");
+ exec("/usr/local/sbin/spamdb -a {$srcip} -T");
+ } else if($action == "'trapped'") {
+ exec("/usr/local/sbin/spamdb -T -d {$toaddress}");
+ exec("/usr/local/sbin/spamdb -T -a '{$toaddress}'");
+ }
+ /* signal a reload for real time effect. */
+ mwexec("killall -HUP spamlogd");
+ exit;
+}
+
+/* spam trap e-mail address */
+if($_POST['spamtrapemail'] <> "") {
+ $spamtrapemail = escapeshellarg($_POST['spamtrapemail']);
+ exec("/usr/local/sbin/spamdb -d {$spamtrapemail}");
+ exec("/usr/local/sbin/spamdb -d -T {$spamtrapemail}");
+ exec("/usr/local/sbin/spamdb -d -t {$spamtrapemail}");
+ exec("/usr/local/sbin/spamdb -T -a '{$toaddress}'");
+
+ mwexec("killall -HUP spamlogd");
+ $savemsg = htmlentities($_POST['spamtrapemail']) . " added to spam trap database.";
+}
+
+if($_GET['getstatus'] <> "") {
+ $status = exec("/usr/local/sbin/spamdb | grep \"{$_GET['getstatus']}\"");
+ if(stristr($status, "WHITE") == true) {
+ echo "WHITE";
+ } else if(stristr($status, "TRAPPED") == true) {
+ echo "TRAPPED";
+ } else if(stristr($status, "GREY") == true) {
+ echo "GREY";
+ } else if(stristr($status, "SPAMTRAP") == true) {
+ echo "SPAMTRAP";
+ } else {
+ echo "NOT FOUND";
+ }
+ exit;
+}
+
+/* spam trap e-mail address */
+if($_GET['spamtrapemail'] <> "") {
+ $spamtrapemail = escapeshellarg($_GET['spamtrapemail']);
+ $status = exec("spamdb -T -a {$spamtrapemail}");
+ mwexec("killall -HUP spamlogd");
+ if($status)
+ echo $status;
+ else
+ echo htmlentities($_POST['spamtrapemail']) . " added to spam trap database.";
+ exit;
+}
+
+/* whitelist e-mail address */
+if($_GET['whitelist'] <> "") {
+ $spamtrapemail = escapeshellarg($_GET['spamtrapemail']);
+ $status = exec("spamdb -a {$spamtrapemail}");
+ mwexec("killall -HUP spamlogd");
+ if($status)
+ echo $status;
+ else
+ echo htmlentities($_POST['spamtrapemail']) . " added to whitelist database.";
+ exit;
+}
+
+function delete_from_blacklist($srcip) {
+ config_lock();
+ $blacklist = split("\n", file_get_contents("/var/db/blacklist.txt"));
+ $fd = fopen("/var/db/blacklist.txt", "w");
+ foreach($blacklist as $bl) {
+ if($bl <> "")
+ if(!stristr($bl, $srcip))
+ fwrite($fd, "{$bl}\n");
+ }
+ fclose($fd);
+ mwexec("/sbin/pfctl -q -t spamd -T delete {$srcip}");
+ mwexec("/sbin/pfctl -q -t blacklist -T replace -f /var/db/blacklist.txt");
+ config_unlock();
+}
+
+function delete_from_whitelist($srcip) {
+ config_lock();
+ $whitelist = split("\n", file_get_contents("/var/db/whitelist.txt"));
+ $fd = fopen("/var/db/whitelist.txt", "w");
+ foreach($whitelist as $wl) {
+ if($wl <> "")
+ if(!stristr($wl, $srcip))
+ fwrite($fd, "{$wl}\n");
+ }
+ fclose($fd);
+ mwexec("/sbin/pfctl -q -t spamd -T delete $srcip");
+ mwexec("/sbin/pfctl -q -t whitelist -T replace -f /var/db/whitelist.txt");
+ config_unlock();
+}
+
+$pgtitle = "SpamD: Database";
+include("head.inc");
+
+if(file_exists("/var/db/whitelist.txt"))
+ $whitelist_items = `cat /var/db/whitelist.txt | wc -l`;
+else
+ $whitelist_items = 0;
+
+if(file_exists("/var/db/blacklist.txt"))
+ $blacklist_items = `cat /var/db/blacklist.txt | wc -l`;
+else
+ $blacklist_items = 0;
+
+// Get an overall count of the database
+$spamdb_items = `/usr/local/sbin/spamdb | wc -l`;
+
+// Get blacklist and whitelist count from database
+$spamdb_white = `/usr/local/sbin/spamdb | grep WHITE | wc -l`;
+$spamdb_black = `/usr/local/sbin/spamdb | grep BLACK | wc -l`;
+$spamdb_grey = `/usr/local/sbin/spamdb | grep GREY | wc -l`;
+
+// Now count the user contributed whitelist and blacklist count
+$whitelist_items = $whitelist_items + $spamdb_white;
+$blacklist_items = $blacklist_items + $spamdb_black;
+
+?>
+<body link="#000000" vlink="#000000" alink="#000000">
+<?php include("fbegin.inc"); ?>
+<p class="pgtitle"><?=$pgtitle?></font></p>
+<form action="spamd_db.php" method="post" name="iform">
+<script src="/javascript/scriptaculous/prototype.js" type="text/javascript"></script>
+<script src="/javascript/scriptaculous/scriptaculous.js" type="text/javascript"></script>
+<script type="text/javascript" language="javascript" src="row_toggle.js"></script>
+<script src="/javascript/sorttable.js"></script>
+<script language="javascript">
+function outputrule(req) {
+ if(req.content != '') {
+ /* response is split by | */
+ var itemsplit = req.content.split("|");
+ /* turn back off the button */
+ toggle_off(itemsplit[0]);
+ /* uh oh, we've got an error of some sort */
+ if(itemsplit[1] != "")
+ alert('An error was detected.\n\n' + req.content);
+ }
+}
+/* toggle button to be on during AJAX request */
+function toggle_on(button, image) {
+ var item = document.getElementById(button);
+ item.src = image;
+}
+/* turn off button by stripping _p out */
+function toggle_off(button) {
+ /* no text back? thats bad. */
+ if(button == '')
+ return;
+ var item = document.getElementById(button);
+ var currentbutton = item.src;
+ currentbutton = currentbutton.replace("_p.", ".");
+ item.src = currentbutton;
+ new Effect.Shake(item);
+}
+/* delete a row */
+function delete_row_db(row) {
+ row++;
+ var el = document.getElementById('maintable');
+ el.deleteRow(row);
+}
+/* standard issue AJAX handler */
+if (typeof getURL == 'undefined') {
+ getURL = function(url, callback) {
+ if (!url)
+ throw 'No URL for getURL';
+ try {
+ if (typeof callback.operationComplete == 'function')
+ callback = callback.operationComplete;
+ } catch (e) {}
+ if (typeof callback != 'function')
+ throw 'No callback function for getURL';
+ var http_request = null;
+ if (typeof XMLHttpRequest != 'undefined') {
+ http_request = new XMLHttpRequest();
+ }
+ else if (typeof ActiveXObject != 'undefined') {
+ try {
+ http_request = new ActiveXObject('Msxml2.XMLHTTP');
+ } catch (e) {
+ try {
+ http_request = new ActiveXObject('Microsoft.XMLHTTP');
+ } catch (e) {}
+ }
+ }
+ if (!http_request)
+ throw 'Both getURL and XMLHttpRequest are undefined';
+ http_request.onreadystatechange = function() {
+ if (http_request.readyState == 4) {
+ callback( { success : true,
+ content : http_request.responseText,
+ contentType : http_request.getResponseHeader("Content-Type") } );
+ }
+ }
+ http_request.open('GET', url, true);
+ http_request.send(null);
+ }
+}
+</script>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+<?php if (file_exists($d_natconfdirty_path)): ?><p>
+<?php endif; ?>
+<table width="99%" border="0" cellpadding="0" cellspacing="0">
+ <tr><td>
+<?php
+ $tab_array = array();
+ $tab_array[] = array("SpamD External Sources", false, "/pkg.php?xml=spamd.xml");
+ $tab_array[] = array("SpamD Whitelist", false, "/pkg.php?xml=spamd_whitelist.xml");
+ $tab_array[] = array("SpamD Settings", false, "/pkg_edit.php?xml=spamd_settings.xml&id=0");
+ $tab_array[] = array("SpamD Database", true, "/spamd_db.php");
+ display_top_tabs($tab_array);
+?>
+ </td></tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <table id="maintable" name="maintable" class="tabcont" width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr><td>
+
+
+<table>
+<tr><td align="right">Filter by test:</td><td><input name="filter" value="<?=$filter?>"></input></td><td><input type="submit" value="Filter"></td><td>&nbsp;&nbsp;Inverse filter (NOT):</td><td><input type="checkbox" id="not" name="not" <?php if($not) echo " CHECKED"; ?>></td></tr>
+<tr><td align="right">Limit:</td><td><input name="limit" value="<?=$limit?>"></input></td></tr>
+<tr><td>&nbsp;</td></tr>
+<tr><td align="right">* Add spam trap E-mail address:</td><td><input name="spamtrapemail" value="<?=$spamtrapemail?>"></input></td><td><input type="submit" value="Add"></td></tr>
+</table><br>
+
+
+
+ <table id="sortabletable1" name="sortabletable1" class="sortable" width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr id="frheader">
+ <td class="listhdrr">Type</td>
+ <td class="listhdrr">IP</td>
+ <td class="listhdrr">From</td>
+ <td class="listhdrr">To</td>
+ <td class="listhdr">Attempts</td>
+ <td class="list"></td>
+ </tr>
+<?php
+ if($filter) {
+ if($not) {
+ $fd = fopen("/tmp/spamdb", "w");
+ $cmd = "/usr/local/sbin/spamdb | grep -v \"" . escapeshellarg($filter) . "\" | tail -n {$limit}";
+ fwrite($fd, $cmd);
+ fclose($fd);
+ $pkgdb = split("\n", `$cmd`);
+ if(file_exists("/var/db/blacklist.txt")) {
+ $cmd = "cat /var/db/blacklist.txt | grep -v \"" . escapeshellarg($filter) . "\" ";
+ $pkgdba = split("\n", `$cmd`);
+ foreach($pkgdba as $pkg) {
+ $pkgdb[] = "TRAPPED|{$pkg}|1149324397";
+ }
+ }
+ } else {
+
+ $cmd = "/usr/local/sbin/spamdb | grep " . escapeshellarg($filter) . " | tail -n {$limit}";
+
+ $pkgdb = split("\n", `$cmd`);
+ if(file_exists("/var/db/blacklist.txt")) {
+ $cmd = "cat /var/db/blacklist.txt | grep " . escapeshellarg($filter);
+ $pkgdba = split("\n", `$cmd`);
+ foreach($pkgdba as $pkg) {
+ $pkgdb[] = "TRAPPED|{$pkg}|1149324397";
+ }
+ echo "<!-- $pkgdb -->";
+ }
+ }
+ } else {
+ $pkgdb = split("\n", `/usr/local/sbin/spamdb | tail -n {$limit}`);
+ }
+ $rows = 0;
+ $lastseenip = "";
+ $srcip = "|";
+ foreach($pkgdb as $pkgdb_row) {
+
+ if($rows > $limit)
+ break;
+ $dontdisplay = false;
+ if(!$pkgdb_row)
+ continue;
+ $pkgdb_split = split("\|", $pkgdb_row);
+
+ /*
+
+ For TRAPPED entries the format is:
+
+ type|ip|expire
+
+ where type will be TRAPPED, IP will be the IP address blacklisted due to
+ hitting a spamtrap, and expire will be when the IP is due to be removed
+ from the blacklist.
+
+ For GREY entries, the format is:
+
+ type|source IP|helo|from|to|first|pass|expire|block|pass
+
+ For WHITE entries, the format is:
+
+ type|source IP|||first|pass|expire|block|pass
+
+ */
+ switch($pkgdb_split[0]) {
+ case "SPAMTRAP":
+ $recordtype = htmlentities($pkgdb_split[0]);
+ $srcip = htmlentities($pkgdb_split[1]);
+ $fromaddress = htmlentities($pkgdb_split[3]);
+ $toaddress = htmlentities($pkgdb_split[4]);
+ $attempts = htmlentities($pkgdb_split[8]);
+ break;
+ case "TRAPPED":
+ $recordtype = htmlentities($pkgdb_split[0]);
+ $srcip = htmlentities($pkgdb_split[1]);
+ $fromaddress = "";
+ $toaddress = "";
+ $attempts = "";
+ break;
+ case "GREY":
+ $recordtype = htmlentities($pkgdb_split[0]);
+ $srcip = htmlentities($pkgdb_split[1]);
+ $fromaddress = htmlentities($pkgdb_split[3]);
+ $toaddress = htmlentities($pkgdb_split[4]);
+ $attempts = htmlentities($pkgdb_split[8]);
+ break;
+ case "WHITE":
+ $recordtype = htmlentities($pkgdb_split[0]);
+ $srcip = htmlentities($pkgdb_split[1]);
+ $fromaddress = "";
+ $toaddress = "";
+ $attempts = htmlentities($pkgdb_split[8]);
+ break;
+ }
+ if($srcip == "" and $fromaddress == "" and $toaddress == "")
+ continue;
+ echo "<tr id=\"{$rows}\">";
+ echo "<td class=\"listr\">{$recordtype}</td>";
+ echo "<td class=\"listr\">{$srcip}</td>";
+ echo "<td class=\"listr\">{$fromaddress}</td>";
+ echo "<td class=\"listr\">{$toaddress}</td>";
+ echo "<td class=\"listr\">{$attempts}</td>";
+ echo "<td>";
+ $rowtext = "<NOBR><a href='javascript:toggle_on(\"w{$rows}\", \"/themes/{$g['theme']}/images/icons/icon_plus_p.gif\"); getURL(\"spamd_db.php?buttonid=w{$rows}&srcip={$srcip}&action=whitelist\", outputrule);'><img title=\"Add to whitelist\" name='w{$rows}' id='w{$rows}' border=\"0\" alt=\"Add to whitelist\" src=\"/themes/{$g['theme']}/images/icons/icon_plus.gif\"></a> ";
+ $rowtext .= "<a href='javascript:toggle_on(\"b{$rows}\", \"/themes/{$g['theme']}/images/icons/icon_trapped_p.gif\");getURL(\"spamd_db.php?buttonid=b{$rows}&srcip={$srcip}&action=trapped\", outputrule);'><img title=\"Blacklist\" name='b{$rows}' id='b{$rows}' border=\"0\" alt=\"Blacklist\" src=\"/themes/{$g['theme']}/images/icons/icon_trapped.gif\"></a> ";
+ $rowtext .= "<a href='javascript:toggle_on(\"d{$rows}\", \"/themes/{$g['theme']}/images/icons/icon_x_p.gif\");getURL(\"spamd_db.php?buttonid=d{$rows}&srcip={$srcip}&action=delete\", outputrule);'><img title=\"Delete\" border=\"0\" name='d{$rows}' id='d{$rows}' alt=\"Delete\" src=\"./themes/{$g['theme']}/images/icons/icon_x.gif\"></a>";
+ $rowtext .= "<a href='javascript:toggle_on(\"s{$rows}\", \"/themes/{$g['theme']}/images/icons/icon_plus_bl_p.gif\");getURL(\"spamd_db.php?buttonid=s{$rows}&spamtrapemail={$toaddress}&action=spamtrap\", outputrule);'><img title=\"Spamtrap\" name='s{$rows}' id='s{$rows}' border=\"0\" alt=\"Spamtrap\" src=\"./themes/{$g['theme']}/images/icons/icon_plus_bl.gif\"></a> ";
+
+ echo $rowtext;
+
+ echo "</td></tr>";
+
+ $rows++;
+ }
+?> </td></tr></table>
+ <tr><td>
+ <?php echo "<font face=\"arial\"><p><b>" . $rows . "</b> rows returned."; ?>
+ <p>
+ * NOTE: adding an e-mail address to the spamtrap automatically traps any server trying to send e-mail to this address.
+ </td></tr>
+ </table>
+ </div>
+ </td>
+ </tr>
+</table>
+</form>
+<br>
+<span class="vexpl"><strong><span class="red">Note:</span> Clicking on the action icons will invoke a AJAX query and the page will not refresh. Click refresh in you're browser if you wish to view the changes in status.</strong></span>
+<br>
+ <p><font size="-2"><b>Database totals:</b><br><font size="-3"><br>
+ <?php
+ echo "{$whitelist_items} total items in the whitelist.<br>";
+ echo "{$blacklist_items} total items in the blacklist.<br>";
+ echo "{$spamdb_grey} total items in the greylist.<br>";
+ echo "{$spamdb_items} total items in the SpamDB.<br>";
+ ?>
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/spamd_db_ext.php b/config/spamd_db_ext.php
new file mode 100644
index 00000000..e029f676
--- /dev/null
+++ b/config/spamd_db_ext.php
@@ -0,0 +1,239 @@
+<?php
+/* $Id$ */
+/*
+ spamd_db_ext.php
+ Copyright (C) 2008 Scott Ullrich
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require("guiconfig.inc");
+
+/* this script is no longer supported */
+exit;
+
+if($_GET['loginname'])
+ $loginname = " Username: " . $_GET['loginname'];
+if($_GET['username'])
+ $username = $_GET['username'];
+if($_GET['password'])
+ $password = $_GET['password'];
+if($_POST['username'])
+ $username = $_POST['username'];
+if($_POST['password'])
+ $password = $_POST['password'];
+
+foreach($config['installedpackages']['spamdoutlook']['config'] as $outlook) {
+ if($outlook['username'] <> $username) {
+ echo "550. INVALID USERNAME {$username}.";
+ exit;
+ }
+ if($outlook['password'] <> $password) {
+ echo "550. INVALID PASSWORD {$password}.";
+ exit;
+ }
+}
+
+exec("echo {$_GET['action']} > /tmp/tmp");
+
+/* handle AJAX operations */
+if($_GET['action'] or $_POST['action']) {
+ if($_GET['action'])
+ $action = escapeshellarg(trim($_GET['action']));
+ if($_POST['action'])
+ $action = escapeshellarg(trim($_POST['action']));
+ if($_GET['srcip'])
+ $srcip = escapeshellarg(trim($_GET['srcip']));
+ if($_POST['srcip'])
+ $srcip = escapeshellarg(trim($_POST['srcip']));
+ if($_POST['email'])
+ $email = escapeshellarg(trim($_POST['email']));
+ if($_GET['email'])
+ $email = escapeshellarg(trim($_GET['email']));
+ /* execute spamdb command */
+ if($action == "whitelist") {
+ delete_from_spamd_db($srcip);
+ usleep(100);
+ exec("/usr/local/sbin/spamdb -a {$srcip}");
+ mwexec("/sbin/pfctl -q -t blacklist -T replace -f /var/db/blacklist.txt");
+ delete_from_blacklist($srcip);
+ log_error("spamd: {$srcip} has been whitelisted by {$_SERVER['REMOTE_ADDR']} {$loginname}");
+ hup_spamd();
+ exit;
+ } else if($action == "delete") {
+ delete_from_spamd_db($srcip);
+ usleep(100);
+ hup_spamd();
+ mwexec("/sbin/pfctl -q -t spamd -T delete $srcip");
+ mwexec("/sbin/pfctl -q -t blacklist -T replace -f /var/db/blacklist.txt");
+ delete_from_blacklist($srcip);
+ delete_from_whitelist($srcip);
+ log_error("spamd: {$srcip} has been deleted by {$_SERVER['REMOTE_ADDR']} {$loginname}");
+ exit;
+ } else if($action == "spamtrap") {
+ delete_from_spamd_db($email);
+ delete_from_whitelist($srcip);
+ usleep(100);
+ exec("/usr/local/sbin/spamdb -a \"{$email}\" -T");
+ hup_spamd();
+ mwexec("/sbin/pfctl -q -t blacklist -T add -f /var/db/blacklist.txt");
+ log_error("spamd: {$srcip} has been blacklisted by {$_SERVER['REMOTE_ADDR']} {$loginname}");
+ exit;
+ } else if($action == "trapped") {
+ delete_from_spamd_db($srcip);
+ delete_from_whitelist($srcip);
+ usleep(100);
+ exec("/usr/local/sbin/spamdb -a {$srcip} -t");
+ add_to_blacklist($srcip);
+ log_error("spamd: {$srcip} has been trapped by {$_SERVER['REMOTE_ADDR']} {$loginname}");
+ hup_spamd();
+ exit;
+ }
+ /* signal a reload for real time effect. */
+ hup_spamd();
+ exit;
+}
+
+/* spam trap e-mail address */
+if($_POST['spamtrapemail'] <> "") {
+ $spamtrapemail = escapeshellarg($_POST['spamtrapemail']);
+ exec("/usr/local/sbin/spamdb -d {$spamtrapemail}");
+ exec("/usr/local/sbin/spamdb -d -T \"{$spamtrapemail}\"");
+ exec("/usr/local/sbin/spamdb -d -t \"{$spamtrapemail}\"");
+ mwexec("/usr/local/sbin/spamdb -T -a \"{$spamtrapemail}\"");
+ mwexec("killall -HUP spamlogd");
+ $savemsg = htmlentities($_POST['spamtrapemail']) . " added to spam trap database.";
+}
+
+if($_GET['getstatus'] <> "") {
+ $getstatus = escapeshellarg($_GET['getstatus']);
+ $status = exec("/usr/local/sbin/spamdb | grep \"{$getstatus}\"");
+ if(stristr($status, "WHITE") == true) {
+ echo "WHITE";
+ } else if(stristr($status, "TRAPPED") == true) {
+ echo "TRAPPED";
+ } else if(stristr($status, "GREY") == true) {
+ echo "GREY";
+ } else if(stristr($status, "SPAMTRAP") == true) {
+ echo "SPAMTRAP";
+ } else {
+ echo "NOT FOUND";
+ }
+ exit;
+}
+
+/* spam trap e-mail address */
+if($_GET['spamtrapemail'] <> "") {
+ $spamtrapemail = escapeshellarg($_GET['spamtrapemail']);
+ $status = exec("spamdb -T -a \"{$spamtrapemail}\"");
+ mwexec("killall -HUP spamlogd");
+ if($status)
+ echo $status;
+ else
+ echo htmlentities($_POST['spamtrapemail']) . " added to spam trap database.";
+ exit;
+}
+
+/* spam trap e-mail address */
+if($_GET['whitelist'] <> "") {
+ $spamtrapemail = escapeshellarg($_GET['spamtrapemail']);
+ $status = exec("spamdb -a \"{$spamtrapemail}\"");
+ mwexec("killall -HUP spamlogd");
+ if($status)
+ echo $status;
+ else
+ echo htmlentities($_POST['spamtrapemail']) . " added to whitelist database.";
+ exit;
+}
+
+function delete_from_spamd_db($srcip) {
+ config_lock();
+ $fd = fopen("/tmp/execcmds", "w");
+ fwrite($fd, "#!/bin/sh\n");
+ fwrite($fd, "/usr/local/sbin/spamdb -d {$srcip}\n");
+ fwrite($fd, "/usr/local/sbin/spamdb -d {$srcip} -T\n");
+ fwrite($fd, "/usr/local/sbin/spamdb -d {$srcip} -t\n");
+ fwrite($fd, "/usr/local/sbin/spamdb -d \"{$srcip}\" -t\n");
+ fwrite($fd, "/usr/local/sbin/spamdb -d \"{$srcip}\" -T\n");
+ fclose($fd);
+ exec("/bin/chmod a+rx /tmp/execcmds");
+ system("/bin/sh /tmp/execcmds");
+ mwexec("/usr/bin/killall -HUP spamlogd");
+ mwexec("/sbin/pfctl -q -t blacklist -T replace -f /var/db/blacklist.txt");
+ config_unlock();
+}
+
+function basic_auth_prompt(){
+ header("WWW-Authenticate: Basic realm=\".\"");
+ header("HTTP/1.0 401 Unauthorized");
+ echo "You must enter valid credentials to access this resource.";
+ exit;
+}
+
+function add_to_blacklist($srcip) {
+ config_lock();
+ $fd = fopen("/var/db/blacklist.txt", "a");
+ fwrite($fd, "{$srcip}\n");
+ fclose($fd);
+ mwexec("/sbin/pfctl -q -t spamd -T add -f /var/db/blacklist.txt");
+ mwexec("/sbin/pfctl -q -t blacklist -T add -f /var/db/blacklist.txt");
+ config_unlock();
+}
+
+function delete_from_blacklist($srcip) {
+ config_lock();
+ $blacklist = split("\n", file_get_contents("/var/db/blacklist.txt"));
+ $fd = fopen("/var/db/blacklist.txt", "w");
+ foreach($blacklist as $bl) {
+ if($bl <> "")
+ if(!stristr($bl, $srcip))
+ fwrite($fd, "{$bl}\n");
+ }
+ fclose($fd);
+ mwexec("/sbin/pfctl -q -t spamd -T delete $srcip");
+ mwexec("/sbin/pfctl -q -t blacklist -T replace -f /var/db/blacklist.txt");
+ config_unlock();
+}
+
+function delete_from_whitelist($srcip) {
+ config_lock();
+ $whitelist = split("\n", file_get_contents("/var/db/whitelist.txt"));
+ $fd = fopen("/var/db/whitelist.txt", "w");
+ foreach($whitelist as $wl) {
+ if($wl <> "")
+ if(!stristr($wl, $srcip))
+ fwrite($fd, "{$wl}\n");
+ }
+ fclose($fd);
+ mwexec("/sbin/pfctl -q -t spamd -T delete $srcip");
+ mwexec("/sbin/pfctl -q -t whitelist -T replace -f /var/db/whitelist.txt");
+ config_unlock();
+}
+
+function hup_spamd() {
+ mwexec("killall -HUP spamlogd");
+}
+
+exit;
+
+?> \ No newline at end of file
diff --git a/config/spamd_exchexp.asp b/config/spamd_exchexp.asp
new file mode 100644
index 00000000..56b0c629
--- /dev/null
+++ b/config/spamd_exchexp.asp
@@ -0,0 +1,50 @@
+<%
+
+dim server
+server = "SERVERNAME"
+
+Sub ExportUsers(oObject)
+ Dim oUser
+ For Each oUser in oObject
+ Select Case oUser.Class
+ Case "user"
+ If oUser.mail <> "" then
+
+ for each email in oUser.proxyAddresses
+ If (lcase(left(email,4))="smtp") Then
+ 'userFile.WriteLine Mid(email,6)
+ document.write Mid(email,6) & vbCrLf
+ End If
+ next
+ End if
+ Case "organizationalUnit" , "container"
+ If UsersinOU (oUser) then
+ ExportUsers(oUser)
+ End if
+ End select
+ Next
+End Sub
+
+Function UsersinOU (oObject)
+ Dim oUser
+ UsersinOU = False
+ for Each oUser in oObject
+ Select Case oUser.Class
+ Case "organizationalUnit" , "container"
+ UsersinOU = UsersinOU(oUser)
+ Case "user"
+ UsersinOU = True
+
+ End select
+ Next
+End Function
+
+Dim rootDSE, domainObject
+Set rootDSE=GetObject("LDAP://" & server & "/RootDSE")
+domainContainer = rootDSE.Get("defaultNamingContext")
+Set domainObject = GetObject("LDAP://" & domainContainer)
+
+ExportUsers(domainObject)
+Set oDomain = Nothing
+
+%> \ No newline at end of file
diff --git a/config/spamd_gather_stats.php b/config/spamd_gather_stats.php
new file mode 100644
index 00000000..a95e2596
--- /dev/null
+++ b/config/spamd_gather_stats.php
@@ -0,0 +1,82 @@
+#!/usr/local/bin/php -q
+
+<?php
+/* $Id$ */
+/*
+ spamd_gather_stats.php
+ Copyright (C) 2006 Scott Ullrich
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/* read in spamd log file */
+if(file_exists("/var/log/spamd.log"))
+ $log_array = split("\n", file_get_contents("/var/log/spamd.log"));
+
+/* variable to keep track of connections */
+$connections = array();
+
+/* array to track average connection time */
+$connect_times = array();
+
+foreach($log_array as $la) {
+ /* no watson, this is not the city of angels */
+ if (preg_match("/.*spamd\[.*\]\:\s(.*)\: connected\s\((.*)\/(.*)\)/", $la, $matches)) {
+ /* we matched a connect */
+ $ip = $matches[1];
+ $current_connections = $matches[2];
+ $max_connections = $matches[2];
+ $connections[$ip] = false;
+ } else if (preg_match("/.*spamd\[.*\]\:\s(.*)\: disconnected\safter\s(.*)\sseconds\./", $la, $matches)) {
+ /* we matched a disconnect */
+ $ip = $matches[1];
+ $connect_time = $matches[2];
+ $connections[$ip] = true;
+ $connect_times[$ip] = $connect_time;
+ }
+}
+
+$open_connections = 0;
+$average_connect_time = 0;
+
+$total_connections = count($connect_times);
+
+/* loop through, how many connections are open */
+foreach($connections as $c) {
+ if($c == true)
+ $open_connections++;
+}
+
+/* loop through, how many connections are open */
+foreach($connect_times as $c) {
+ $average_connect_time = $average_connect_time + $c;
+}
+
+echo "N:";
+echo $open_connections;
+echo ":";
+echo round(($average_connect_time / $total_connections));
+
+exit;
+
+?> \ No newline at end of file
diff --git a/config/spamd_outlook.xml b/config/spamd_outlook.xml
new file mode 100644
index 00000000..5e94701f
--- /dev/null
+++ b/config/spamd_outlook.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>spamdoutlook</name>
+ <version>0.1.0</version>
+ <title>SpamD Outlook</title>
+ <aftersaveredirect>pkg_edit.php?xml=spamd_outlook.xml&amp;id=0</aftersaveredirect>
+ <tabs>
+ <tab>
+ <text>SpamD External Sources</text>
+ <url>/pkg.php?xml=spamd.xml</url>
+ </tab>
+ <tab>
+ <text>SpamD Whitelist</text>
+ <url>/pkg.php?xml=spamd_whitelist.xml</url>
+ </tab>
+ <tab>
+ <text>SpamD Settings</text>
+ <url>/pkg_edit.php?xml=spamd_settings.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>SpamD Database</text>
+ <url>/spamd_db.php</url>
+ </tab>
+ </tabs>
+ <!-- configpath gets expanded out automatically and config items will be
+ stored in that location -->
+ <configpath>['installedpackages']['spamd']['config']</configpath>
+ <!-- fields gets invoked when the user adds or edits a item. the following items
+ will be parsed and rendered for the user as a gui with input, and selectboxes. -->
+ <fields>
+ <field>
+ <fielddescr>Username</fielddescr>
+ <fieldname>username</fieldname>
+ <description>Enter the username the outlook clients will use to connect with.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Password</fielddescr>
+ <fieldname>password</fieldname>
+ <description>Enter the password the outlook clients will use to connect with.</description>
+ <type>password</type>
+ </field>
+
+ </fields>
+</packagegui> \ No newline at end of file
diff --git a/config/spamd_rules.php b/config/spamd_rules.php
new file mode 100644
index 00000000..27ac850a
--- /dev/null
+++ b/config/spamd_rules.php
@@ -0,0 +1,34 @@
+
+/*
+ spamd_rules.inc
+ part of pfSense (www.pfSense.com)
+ Copyright (C) 2004 Scott Ullrich (sullrich@gmail.com)
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+$wanif = get_real_wan_interface();
+$anchor = "natearly";
+$natrules .= "rdr pass on {$wanif} proto tcp from <spamd> to port smtp -> 127.0.0.1 port spamd\n";
+$natrules .= "rdr pass on {$wanif} proto tcp from !<spamd-white> to port smtp -> 127.0.0.1 port spamd\n";
+$label = "spamd";
+add_rule_to_anchor($anchor, $rule, $label);
diff --git a/config/spamd_settings.xml b/config/spamd_settings.xml
new file mode 100644
index 00000000..95c343d1
--- /dev/null
+++ b/config/spamd_settings.xml
@@ -0,0 +1,192 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ spamd_settings.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2008 Scott Ullrich
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>spamdsettings</name>
+ <version>0.1.0</version>
+ <title>SpamD Settings</title>
+ <aftersaveredirect>pkg_edit.php?xml=spamd_settings.xml&amp;id=0</aftersaveredirect>
+ <include_file>/usr/local/pkg/spamd.inc</include_file>
+ <!-- Menu is where this packages menu will appear -->
+ <menu>
+ <name>SpamD</name>
+ <section>Services</section>
+ <configfile>spamd.xml</configfile>
+ </menu>
+ <service>
+ <name>spamd</name>
+ <rcfile>spamd.sh</rcfile>
+ </service>
+ <tabs>
+ <tab>
+ <text>SpamD External Sources</text>
+ <url>/pkg.php?xml=spamd.xml</url>
+ </tab>
+ <tab>
+ <text>SpamD Whitelist</text>
+ <url>/pkg.php?xml=spamd_whitelist.xml</url>
+ </tab>
+ <tab>
+ <text>SpamD Settings</text>
+ <url>/pkg_edit.php?xml=spamd_settings.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>SpamD Database</text>
+ <url>/spamd_db.php</url>
+ </tab>
+ </tabs>
+ <!-- configpath gets expanded out automatically and config items will be
+ stored in that location -->
+ <configpath>['installedpackages']['spamd']['config']</configpath>
+ <!-- fields gets invoked when the user adds or edits a item. the following items
+ will be parsed and rendered for the user as a gui with input, and selectboxes. -->
+ <fields>
+ <field>
+ <fielddescr>Identifier</fielddescr>
+ <fieldname>identifier</fieldname>
+ <description>The SMTP version banner that is reported upon initial connection.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Maximum blacklisted connections</fielddescr>
+ <fieldname>maxblack</fieldname>
+ <description>The maximum number of concurrent blacklisted connections to allow in greylisting mode. This value may not be greater than maxcon (see below). The default is maxcon - 100.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Max concurrent connections</fielddescr>
+ <fieldname>maxcon</fieldname>
+ <description>The maximum number of concurrent connections to allow. The default is 800.</description>
+ <type>input</type>
+ <value>800</value>
+ </field>
+ <field>
+ <fielddescr>Grey listing</fielddescr>
+ <fieldname>greylisting</fieldname>
+ <description>Connections from addresses not blacklisted on the black lists tab will be considered for greylisting. Such connections will not be stuttered at (though see the stutter secs option) or delayed, and will receive the pleasantly innocuous temporary failure. After passtime if the host returns it will be added to the white list.</description>
+ <type>checkbox</type>
+ <value>yes</value>
+ </field>
+ <field>
+ <fielddescr>Passtime</fielddescr>
+ <fieldname>passtime</fieldname>
+ <description>Adjust the three time parameters for greylisting. Passtime defaults to 25 (minutes). After passtime minutes if spamd sees a retried attempt to deliver mail for the same tuple, spamd will whitelist the connecting address by adding it as a whitelist entry.</description>
+ <type>input</type>
+ <size>30</size>
+ <value>25:4:864</value>
+ </field>
+ <field>
+ <fielddescr>Grey Expiration</fielddescr>
+ <fieldname>greyexp</fieldname>
+ <description>Adjust the three time parameters for greylisting. Grey expiration defaults to 4. SpamD removes connection entries from the database if delivery has not been retried within greyexp hours from the initial time a connection is seen.</description>
+ <type>input</type>
+ <size>30</size>
+ <value>25:4:864</value>
+ </field>
+ <field>
+ <fielddescr>White Exp</fielddescr>
+ <fieldname>whiteexp</fieldname>
+ <description>Adjust the three time parameters for greylisting. White expiration defaults to 864 (hours, approximately 36 days). SpamD removes whitelist entries from the database if no mail delivery activity has been seen from the whitelisted address within whiteexp hours from the initial time an address is whitelisted.</description>
+ <type>input</type>
+ <size>30</size>
+ <value>25:4:864</value>
+ </field>
+ <field>
+ <fielddescr>Stutter Secs</fielddescr>
+ <fieldname>stuttersecs</fieldname>
+ <description>Stutter at greylisted connections for the specified amount of seconds, after which the connection is not stuttered at. Defaults to 10.</description>
+ <type>input</type>
+ <value>10</value>
+ </field>
+ <field>
+ <fielddescr>Delay Secs</fielddescr>
+ <fieldname>delaysecs</fieldname>
+ <description>Delay each character sent to the client by the specified amount of seconds. Defaults to 1.</description>
+ <type>input</type>
+ <value>1</value>
+ </field>
+ <field>
+ <fielddescr>Window Size</fielddescr>
+ <fieldname>window</fieldname>
+ <description>Set the socket receive buffer to this many bytes, adjusting the window size.</description>
+ <type>input</type>
+ <value></value>
+ </field>
+ <!--
+ <field>
+ <fielddescr>Reply SMTP error</fielddescr>
+ <fieldname>replysmtperror</fieldname>
+ <description>The SMTP error to return to the spammer, i.e. 450, 451, 550. This defaults to 450.</description>
+ <type>select</type>
+ <size>1</size>
+ <value>450</value>
+ <options>
+ <option><name></name><value></value></option>
+ <option><name>450</name><value>450</value></option>
+ <option><name>451</name><value>451</value></option>
+ <option><name>550</name><value>550</value></option>
+ </options>
+ </field>
+ -->
+ <field>
+ <fielddescr>NextMTA</fielddescr>
+ <fieldname>nextmta</fieldname>
+ <description>Automatically sends messages after being processed by SpamD to IP Address. You may enter an alias if you like, simply prepend $ to the alias name. example: $mailservers. Note, if you have postfix package installed enter 127.0.0.1 here.</description>
+ <type>input</type>
+ <value>1</value>
+ </field>
+ <field>
+ <fielddescr>Enable RRD graphing</fielddescr>
+ <fieldname>enablerrd</fieldname>
+ <description>Enables the graphing of SpamD connection and disconnection statistics.</description>
+ <type>checkbox</type>
+ <value></value>
+ </field>
+ </fields>
+ <custom_php_validation_command>
+ spamd_validate_input($_POST, &amp;$input_errors);
+ </custom_php_validation_command>
+ <custom_php_resync_config_command>
+ sync_package_spamd();
+ </custom_php_resync_config_command>
+</packagegui> \ No newline at end of file
diff --git a/config/spamd_verify_to_address.php b/config/spamd_verify_to_address.php
new file mode 100644
index 00000000..56821370
--- /dev/null
+++ b/config/spamd_verify_to_address.php
@@ -0,0 +1,144 @@
+#!/usr/local/bin/php -q
+<?php
+/*
+ * pfSense spamd mousetrap
+ * (C)2006 Scott Ullrich
+ *
+ * Reads in an external list of c/r
+ * seperated valid e-mail addresses
+ * and then looks to see waiting grey-
+ * listed servers. if the server is
+ * sending to an invalid e-mail address
+ * then add them to spamtrap.
+ *
+ * Directions for usage:
+ * 1. Download this script to the /root/ directory on your pfSense installation.
+ * 2. chmod a+rx spamd_verify_to_address.php
+ * 3. Edit $server_to_pull_data_from to point to a location containing a list of
+ * all valid email addresses c/r seperated.
+ * 4. Add spamd_verify_to_address.php to cron or run it by invoking
+ * ./spamd_verify_to_address.php manually.
+ *
+ * XXX/TODO:
+ * * Add flag to blacklist a server after receiving X
+ * attempts at a delivery with invalid to: addresses.
+ *
+ */
+
+require("config.inc");
+require("functions.inc");
+
+/* path to script that outputs c/r seperated e-mail addresses */
+$server_to_pull_data_from = "http://10.0.0.11/spamd_exchexp.asp";
+
+/* to enable debugging, change false to true */
+$debug = true;
+
+if($debug)
+ echo "Downloading current valid email list...\n";
+/* fetch down the latest list from server */
+if($debug) {
+ /* fetch without quiet mode */
+ system("fetch -o /tmp/emaillist.txt {$server_to_pull_data_from}");
+} else {
+ /* fetch with quiet mode */
+ system("fetch -q -o /tmp/emaillist.txt {$server_to_pull_data_from}");
+}
+
+/* test if file exists, if not, bail. */
+if(!file_exists("/tmp/emaillist.txt")) {
+ if($debug)
+ echo "Could not fetch $server_to_pull_data_from\n";
+ exit;
+}
+
+/* clean up and split up results */
+$fetched_file = strtolower(file_get_contents("/tmp/emaillist.txt"));
+$valid_list = split("\n", $fetched_file);
+$grey_hosts = split("\n", `spamdb | grep GREY`);
+
+if($fetched_file == "")
+ exit(-1);
+
+if($debug) {
+ /* echo out all our valid hosts */
+ foreach($valid_list as $valid)
+ echo "VALID: ||$valid||\n";
+}
+
+/* suck custom blacklist into array */
+$current_blacklist = split("\n", `cat /var/db/blacklist.txt`);
+/* suck current spamtrap emails into array */
+$current_spamtrap = split("\n", `/usr/local/sbin/spamdb | grep SPAMTRAP | cut -d"|" -f2`);
+/* eliminate <> from email addresses */
+for($x=0; isset($current_spamtrap[$x]); $x++) {
+ $current_spamtrap[$x] = str_replace("<", "", $current_spamtrap[$x]);
+ $current_spamtrap[$x] = str_replace(">", "", $current_spamtrap[$x]);
+}
+
+/* traverse list and find the dictionary attackers, etc */
+foreach($grey_hosts as $grey) {
+ if(trim($grey) == "")
+ continue;
+ /* clean up and further break down values */
+ $grey_lower = strtolower($grey);
+ $grey_lower = str_replace("<","",$grey_lower);
+ $grey_lower = str_replace(">","",$grey_lower);
+ $grey_split = split("\|", $grey_lower);
+ $email_from = strtolower($grey_split[2]);
+ $email_to = strtolower($grey_split[3]);
+ $server_ip = strtolower($grey_split[1]);
+ if(in_array($server_ip, $current_blacklist)) {
+ if($debug)
+ echo "$server_ip already in blacklist.\n";
+ continue;
+ }
+ if(in_array($email_to, $current_spamtrap)) {
+ if($email_to)
+ echo "$email_to already in blacklist.\n";
+ continue;
+ }
+ if($debug)
+ echo "Testing $email_from | $email_to \n";
+ if (in_array($email_to, $valid_list)) {
+ if($debug)
+ echo "$email_to is in the valid list\n";
+ } else {
+ /* spammer picked the wrong person to mess with */
+ if($server_ip) {
+ if($debug)
+ echo "/usr/local/sbin/spamdb -a $server_ip -t\n";
+ exec("/usr/local/sbin/spamdb -d {$server_ip} 2>/dev/null");
+ exec("/usr/local/sbin/spamdb -d {$server_ip} -T 2>/dev/null");
+ exec("/usr/local/sbin/spamdb -d {$server_ip} -t 2>/dev/null");
+ if($debug)
+ echo "/usr/local/sbin/spamdb -a \"<$email_to>\" -T\n";
+ exec("/usr/local/sbin/spamdb -a \"<$email_to>\" -T");
+ config_lock();
+ system("echo $server_ip >> /var/db/blacklist.txt");
+ config_unlock();
+ $result = mwexec("/usr/local/sbin/spamdb -a $server_ip -t");
+ } else {
+ if($debug)
+ echo "Could not locate server ip address.";
+ }
+ if($debug)
+ echo "Script result code: {$result}\n";
+ }
+}
+
+mwexec("killall -HUP spamlogd");
+
+if($debug) {
+ echo "\nSearch completed.\n\n";
+ echo "Items trapped: ";
+ system("/usr/local/sbin/spamdb | grep TRAPPED | wc -l");
+ echo "Items spamtrapped: ";
+ system("/usr/local/sbin/spamdb | grep SPAMTRAP | wc -l");
+ echo "Items in blacklist.txt: ";
+ system("/sbin/pfctl -t blacklist -T show | wc -l");
+}
+
+mwexec("/sbin/pfctl -q -t blacklist -T replace -f /var/db/blacklist.txt");
+
+?> \ No newline at end of file
diff --git a/config/spamd_whitelist.xml b/config/spamd_whitelist.xml
new file mode 100644
index 00000000..f7b3f4fe
--- /dev/null
+++ b/config/spamd_whitelist.xml
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>spamd-whitelist</name>
+ <version>0.1.0</version>
+ <title>SpamD: Whitelist</title>
+ <!-- Menu is where this packages menu will appear -->
+ <menu>
+ <name>SpamD Whitelist</name>
+ <tooltiptext></tooltiptext>
+ <section>Services</section>
+ <configfile>spamd.xml</configfile>
+ </menu>
+ <tabs>
+ <tab>
+ <text>SpamD External Sources</text>
+ <url>/pkg.php?xml=spamd.xml</url>
+ </tab>
+ <tab>
+ <text>SpamD Whitelist</text>
+ <url>/pkg.php?xml=spamd_whitelist.xml</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>SpamD Settings</text>
+ <url>/pkg_edit.php?xml=spamd_settings.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>SpamD Database</text>
+ <url>/spamd_db.php</url>
+ </tab>
+ </tabs>
+ <!-- configpath gets expanded out automatically and config items will be
+ stored in that location -->
+ <configpath>['installedpackages']['spamdwhitelist']['config']</configpath>
+ <adddeleteeditpagefields>
+ <columnitem>
+ <fielddescr>Exempted IP</fielddescr>
+ <fieldname>ip</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Description</fielddescr>
+ <fieldname>description</fieldname>
+ </columnitem>
+ </adddeleteeditpagefields>
+ <!-- fields gets invoked when the user adds or edits a item. the following items
+ will be parsed and rendered for the user as a gui with input, and selectboxes. -->
+ <fields>
+ <field>
+ <fielddescr>Exempted IP</fielddescr>
+ <fieldname>ip</fieldname>
+ <description>Enter the IP to exempt from blacklisting</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Description</fielddescr>
+ <fieldname>description</fieldname>
+ <description>Enter the description for this item</description>
+ <type>input</type>
+ </field>
+ </fields>
+ <custom_php_command_before_form>
+ function sync_package_spamd_whitelist() {
+ global $config;
+ conf_mount_rw();
+ config_lock();
+ /* write out ip to the whitelist db */
+ $fd = fopen("/var/db/whitelist.txt","w");
+ if($config['installedpackages']['spamdwhitelist']['config'] != "") {
+ foreach($config['installedpackages']['spamdwhitelist']['config'] as $spamd) {
+ fwrite($fd, $spamd['ip'] . "\n");
+ }
+ }
+ fclose($fd);
+ /* signal a reload of all files */
+ mwexec("/usr/bin/killall -HUP spamlogd");
+ mwexec("/sbin/pfctl -t spamd-white -T add {$spamd['ip']}");
+ conf_mount_ro();
+ config_unlock();
+ }
+ </custom_php_command_before_form>
+ <custom_delete_php_command>
+ sync_package_spamd_whitelist();
+ </custom_delete_php_command>
+ <custom_php_resync_config_command>
+ sync_package_spamd_whitelist();
+ </custom_php_resync_config_command>
+</packagegui> \ No newline at end of file
diff --git a/config/squid-head/squid.inc b/config/squid-head/squid.inc
new file mode 100644
index 00000000..08cf3121
--- /dev/null
+++ b/config/squid-head/squid.inc
@@ -0,0 +1,862 @@
+<?php
+require_once('globals.inc');
+require_once('config.inc');
+require_once('util.inc');
+require_once('pfsense-utils.inc');
+require_once('pkg-utils.inc');
+require_once('filter.inc');
+require_once('service-utils.inc');
+
+define('RC_BASE', '/usr/local/etc/rc.d');
+define('SQUID_CONFBASE', '/usr/local/etc/squid');
+define('SQUID_LOGDIR', '/var/squid/log');
+define('SQUID_CACHEDIR', '/var/squid/cache');
+define('SQUID_ACLDIR', '/var/squid/acl');
+define('SQUID_PASSWD', '/var/etc/squid.passwd');
+define('MSNTAUTH_CONF', '/usr/local/etc/squid/msntauth.conf');
+
+$valid_acls = array();
+
+
+function squid_get_real_interface_address($iface) {
+ global $config;
+
+ $iface = convert_friendly_interface_to_real_interface_name($iface);
+ $line = trim(shell_exec("ifconfig $iface | grep inet | grep -v inet6"));
+ list($dummy, $ip, $dummy2, $netmask) = explode(' ', $line);
+
+ return array($ip, long2ip(hexdec($netmask)));
+}
+
+function squid_chown_recursive($dir, $user, $group) {
+ chown($dir, $user);
+ chgrp($dir, $group);
+ $handle = opendir($dir) ;
+ while (($item = readdir($handle)) !== false) {
+ if (($item != ".") && ($item != "..")) {
+ $path = "$dir/$item";
+ if (is_dir($path))
+ squid_chown_recursive($path, $user, $group);
+ else {
+ chown($path, $user);
+ chgrp($path, $group);
+ }
+ }
+ }
+}
+
+function squid_is_valid_acl($acl) {
+ global $valid_acls;
+
+ return in_array($acl, $valid_acls);
+}
+
+function squid_install_command() {
+ /* Create cache */
+ update_output_window('Initializing cache... This may take a moment...');
+ mwexec('/usr/local/sbin/squid -z');
+
+ $rc = array();
+ $rc['file'] = 'squid.sh';
+ $rc['start'] = '/usr/local/sbin/squid -D';
+ $rc['stop'] = RC_BASE . "/proxy_monitor.sh stop\n";
+ $rc['stop'] .= <<<EOD
+/usr/local/sbin/squid -k shutdown
+# Just to be sure...
+killall squid 2>/dev/null
+sleep 1
+killall squid 2>/dev/null
+
+EOD;
+ $rc['restart'] = <<<EOD
+if [ -z "`pgrep squid`" ]; then
+ /usr/local/sbin/squid -D
+ else
+ /usr/local/sbin/squid -k reconfigure
+ fi
+
+EOD;
+ write_rcfile($rc);
+
+ $rc = array();
+ $rc['file'] = 'proxy_monitor.sh';
+ $rc['start'] = '/usr/local/bin/squid_monitor.sh';
+ $rc['stop'] = 'killall squid_monitor.sh';
+ write_rcfile($rc);
+
+ foreach (array( SQUID_CONFBASE,
+ SQUID_LOGDIR,
+ SQUID_ACLDIR,
+ SQUID_CACHEDIR,
+ ) as $dir) {
+ make_dirs($dir);
+ squid_chown_recursive($dir, 'proxy', 'proxy');
+ }
+
+ restart_service('squid');
+ sleep(1);
+ restart_service('proxy_monitor');
+
+ if (!file_exists(SQUID_CONFBASE . '/mime.conf') && file_exists(SQUID_CONFBASE . '/mime.conf.default'))
+ copy(SQUID_CONFBASE . '/mime.conf.default', SQUID_CONFBASE . '/mime.conf');
+}
+
+function squid_deinstall_command() {
+ stop_service('proxy_monitor');
+ stop_service('squid');
+
+ filter_configure();
+
+ mwexec('rm -rf ' . SQUID_CACHEDIR);
+}
+
+function squid_before_form_general($pkg) {
+ $values = get_dir(SQUID_CONFBASE . '/errors/');
+ // Get rid of '..' and '.'
+ array_shift($values);
+ array_shift($values);
+ $name = array();
+ foreach ($values as $value)
+ $names[] = implode(' ', explode('_', $value));
+
+ $i = 0;
+ foreach ($pkg['fields']['field'] as $field) {
+ if ($field['fieldname'] == 'error_language')
+ break;
+ $i++;
+ }
+ $field = &$pkg['fields']['field'][$i];
+
+ for ($i = 0; $i < count($values) - 1; $i++)
+ $field['options']['option'][] = array('name' => $names[$i], 'value' => $values[$i]);
+}
+
+function squid_validate_general($post, $input_errors) {
+ $icp_port = trim($post['icp_port']);
+ if (!empty($icp_port) && !is_port($icp_port))
+ $input_errors[] = 'You must enter a valid port number in the \'ICP port\' field';
+
+ $children = $post['redirect_children'];
+ if (!empty($children) && !is_numeric($children))
+ $input_errors[] = 'You must enter a valid number for the \'Redirect children\' field';
+}
+
+function squid_validate_upstream($post, $input_errors) {
+ if ($post['proxy_forwarding'] == 'on') {
+ $addr = trim($post['proxy_addr']);
+ if (empty($addr))
+ $input_errors[] = 'The field \'Hostname\' is required';
+ else {
+ if (!is_ipaddr($addr) && !is_domain($addr))
+ $input_errors[] = 'You must enter a valid IP address or host name in the \'Proxy hostname\' field';
+ }
+
+ foreach (array('proxy_port' => 'TCP port', 'icp_port' => 'ICP port') as $field => $name) {
+ $port = trim($post[$field]);
+ if (empty($port))
+ $input_errors[] = "The field '$name' is required";
+ else {
+ if (!is_port($port))
+ $input_errors[] = "The field '$name' must contain a valid port number, between 0 and 65535";
+ }
+ }
+ }
+}
+
+function squid_validate_cache($post, $input_errors) {
+ $num_fields = array( 'harddisk_cache_size' => 'Hard disk cache size',
+ 'memory_cache_size' => 'Memory cache size',
+ 'maximum_object_size' => 'Maximum object size',
+ );
+ foreach ($num_fields as $field => $name) {
+ $value = trim($post[$field]);
+ if (!is_numeric($value) || ($value < 1))
+ $input_errors[] = "You must enter a valid value for '$field'";
+ }
+
+ $value = trim($post['minimum_object_size']);
+ if (!is_numeric($value) || ($value < 0))
+ $input_errors[] = 'You must enter a valid value for \'Minimum object size\'';
+
+ foreach (explode(',', $post['donotcache']) as $host) {
+ $host = trim($host);
+ if (!is_ipaddr($host) && !is_domain($host))
+ $input_errors[] = "$host is not a valid IP or host name";
+ }
+}
+
+function squid_validate_nac($post, $input_errors) {
+ $allowed_subnets = explode(',', trim($post['allowed_subnets']));
+ foreach ($allowed_subnets as $subnet) {
+ $subnet = trim($subnet);
+ if (!empty($subnet) && !is_subnet($subnet))
+ $input_errors[] = "'$subnet' is not a valid CIDR range";
+ }
+
+ foreach (array( 'unrestricted_hosts',
+ 'banned_hosts',
+ 'whitelist',
+ 'blacklist',
+ ) as $hosts) {
+ foreach (explode(',', $post[$hosts]) as $host) {
+ $host = trim($host);
+ if (!empty($host) && !is_ipaddr($host))
+ $input_errors[] = "'$host' is not a valid IP address";
+ }
+ }
+
+ foreach (array('unrestricted_macs', 'banned_macs') as $macs) {
+ foreach (explode(',', $post[$macs]) as $mac) {
+ $mac = trim($mac);
+ if (!empty($mac) && !is_macaddr($mac))
+ $input_errors[] = "'$mac' is not a valid MAC address";
+ }
+ }
+
+ foreach (explode(',', $post['timelist']) as $time) {
+ $time = trim($time);
+ if (!empty($time) && !squid_is_timerange($time))
+ $input_errors[] = "'$time' is not a valid time range";
+ }
+}
+
+function squid_validate_traffic($post, $input_errors) {
+ $num_fields = array(
+ 'max_download_size' => 'Maximum download size',
+ 'max_upload_size' => 'Maximum upload size',
+ 'perhost_capping' => 'Per-host bandwidth capping',
+ 'overall_capping' => 'Overall bandwidth capping',
+ 'perhost_throttling' => 'Per-host bandwidth throttling',
+ 'overall_throttling' => 'Overall bandwidth throttling',
+ 'initial_bucket_level' => 'Initial bucket level',
+ );
+ foreach ($num_fields as $field => $name) {
+ $value = trim($post[$field]);
+ if (!is_numeric($value) || ($value < 0))
+ $input_errors[] = "The field '$name' must contain a positive number";
+ }
+}
+
+function squid_validate_auth($post, $input_errors) {
+ $num_fields = array( array('auth_processes', 'Authentication processes', 1),
+ array('auth_ttl', 'Authentication TTL', 0),
+ );
+ foreach ($num_fields as $field) {
+ $value = trim($post[$field[0]]);
+ if (!empty($value) && (!is_numeric($value) || ($value < $field[2])))
+ $input_errors[] = "The field '{$field[1]}' must contain a valid number greater than {$field[2]}";
+ }
+
+ $auth_method = $post['auth_method'];
+ if (($auth_method != 'none') && ($auth_method != 'local')) {
+ $server = trim($post['auth_server']);
+ if (empty($server))
+ $input_errors[] = 'The field \'Authentication server\' is required';
+ else if (!is_ipaddr($server) && !is_domain($server))
+ $input_errors[] = 'The field \'Authentication server\' must contain a valid IP address or domain name';
+
+ $port = trim($post['auth_server_port']);
+ if (!empty($port) && !is_port($port))
+ $input_errors[] = 'The field \'Authentication server port\' must contain a valid port number';
+
+ switch ($auth_method) {
+ case 'ldap':
+ $required = array(
+ 'ldap_basedn' => 'LDAP base DN',
+ 'ldap_filter' => 'LDAP filter',
+ );
+ foreach ($required as $field => $descr) {
+ $value = trim($post[$field]);
+ if (empty($value))
+ $input_errors[] = "The field '$descr' is required";
+ }
+
+ $user = trim($post['ldap_user']);
+ $password = trim($post['ldap_password']);
+ if (!empty($password) && empty($user))
+ $input_errors[] = 'You must specify an username if you specify a password';
+
+ break;
+ case 'radius':
+ $secret = trim($post['radius_secret']);
+ if (empty($secret))
+ $input_errors[] = 'The field \'RADIUS secret\' is required';
+ break;
+ case 'msnt':
+ $bdc = $post['msnt_bdc'];
+ if (!empty($bdc) && !is_ipaddr($bdc) && !is_domain($bdc))
+ $input_errors[] = "'$bdc' isn't a valid IP address or domain name";
+ $domain = $post['msnt_domain'];
+ if (empty($domain) || !is_domain($domain))
+ $input_errors[] = 'You must enter a valid domain name in the \'NT domain\' field';
+ break;
+ }
+
+ $no_auth = explode(',', trim($post['no_auth_hosts']));
+ foreach ($no_auth as $host) {
+ $host = trim($host);
+ if (!empty($host) && !is_subnet($host))
+ $input_errors[] = "'$host' isn't a valid CIDR range";
+ }
+ }
+}
+
+function squid_resync_general() {
+ global $g, $config, $valid_acls;
+
+ $settings = $config['installedpackages']['squid']['config'][0];
+ $conf = '';
+
+ if ($settings['transparent_proxy'] == 'on') {
+ $conf .= <<<EOD
+httpd_accel_host virtual
+httpd_accel_port 80
+httpd_accel_with_proxy on
+httpd_accel_uses_host_header on
+
+EOD;
+ }
+
+ $port = $settings['proxy_port'] ? $settings['proxy_port'] : 3128;
+ $ifaces = $settings['active_interface'] ? $settings['active_interface'] : 'lan';
+ $real_ifaces = array();
+ foreach (explode(',', $ifaces) as $i => $iface) {
+ $real_ifaces[] = squid_get_real_interface_address($iface);
+ if (!empty($real_ifaces[$i][0]))
+ $conf .= "http_port {$real_ifaces[$i][0]}:$port\n";
+ }
+
+ $icp_port = $settings['icp_port'] ? $settings['icp_port'] : 0;
+
+ $pidfile = "{$g['varrun_path']}/squid.pid";
+ $language = $settings['error_language'] ? $settings['error_language'] : 'English';
+ $errordir = SQUID_CONFBASE . '/errors/' . $language;
+ $hostname = $settings['visible_hostname'] ? $settings['visible_hostname'] : 'localhost';
+ $email = $settings['admin_email'] ? $settings['admin_email'] : 'admin@localhost';
+
+ $logdir_cache = SQUID_LOGDIR . '/cache.log';
+ $logdir_access = $settings['log_enabled'] == 'on' ? SQUID_LOGDIR . '/access.log' : '/dev/null';
+
+ $conf .= <<<EOD
+icp_port $icp_port
+
+pid_filename $pidfile
+cache_effective_user proxy
+cache_effective_group proxy
+error_directory $errordir
+visible_hostname $hostname
+cache_mgr $email
+
+cache_access_log $logdir_access
+cache_log $logdir_cache
+cache_store_log none
+
+EOD;
+
+ if ($settings['allow_interface'] == 'on') {
+ $src = '';
+ foreach ($real_ifaces as $iface) {
+ list($ip, $mask) = $iface;
+ $ip = long2ip(ip2long($ip) & ip2long($mask));
+ $src .= " $ip/$mask";
+ }
+ $conf .= "acl localnet src $src\n";
+ $valid_acls[] = 'localnet';
+ }
+
+ restart_service('proxy_monitor');
+
+ return $conf;
+}
+
+function squid_resync_cache() {
+ global $config;
+
+ $settings = $config['installedpackages']['squidcache']['config'][0];
+
+ $cachedir = SQUID_CACHEDIR;
+ $disk_cache_size = $settings['harddisk_cache_size'] ? $settings['harddisk_cache_size'] : 100;
+ $level1 = $settings['level1_subdirs'] ? $settings['level1_subdirs'] : 16;
+ $memory_cache_size = $settings['memory_cache_size'] ? $settings['memory_cache_size'] : 8;
+ $max_objsize = $settings['maximum_object_size'] ? $settings['maximum_object_size'] : 4;
+ $min_objsize = $settings['minimum_object_size'] ? $settings['minimum_object_size'] : 0;
+ $cache_policy = $settings['cache_replacement_policy'] ? $settings['cache_replacement_policy'] : 'heap LFUDA';
+ $memory_policy = $settings['memory_replacement_policy'] ? $settings['memory_replacement_policy'] : 'heap GDSF';
+ $offline_mode = $settings['enable_offline'] == 'on' ? 'on' : 'off';
+
+ $conf = <<<EOD
+cache_dir diskd $cachedir $disk_cache_size $level1 256
+cache_mem $memory_cache_size MB
+maximum_object_size $max_objsize KB
+minimum_object_size $min_objsize KB
+cache_replacement_policy $cache_policy
+memory_replacement_policy $memory_policy
+offline_mode $offline_mode
+
+EOD;
+
+ $donotcache = trim(implode("\n", array_map('trim', explode(',', $settings['donotcache']))));
+ if (!empty($donotcache)) {
+ file_put_contents(SQUID_ACLDIR . '/donotcache.acl', $donotcache);
+ $conf .= 'acl donotcache dstdomain "' . SQUID_ACLDIR . "/donotcache.acl\"\n";
+ $conf .= 'no_cache deny donotcache';
+ }
+
+ return $conf;
+}
+
+function squid_resync_upstream() {
+ global $config;
+ $settings = $config['installedpackages']['squidupstream']['config'][0];
+
+ $conf = '';
+ if ($settings['proxy_forwarding'] == 'on') {
+ $conf .= "cache_peer {$settings['proxy_addr']} parent {$settings['proxy_port']} {$settings['icp_port']} ";
+
+ if (!empty($settings['username']))
+ $conf .= " login={$settings['username']}";
+ if (!empty($settings['password']))
+ $conf .= ":{$settings['password']}";
+ }
+
+ return $conf;
+}
+
+function squid_resync_redirector() {
+ global $config;
+
+ $httpav_enabled = $config['installedpackages']['clamav']['config'][0]['scan_http'] == 'on';
+ if ($httpav_enabled)
+ return ('redirect_program /usr/local/bin/squirm');
+ return '# No redirector configured';
+}
+
+function squid_resync_nac() {
+ global $config, $valid_acls;
+
+ $settings = $config['installedpackages']['squidnac']['config'][0];
+
+ $conf = <<<EOD
+acl all src 0.0.0.0/0
+acl localhost src 127.0.0.1
+acl safeports port 21 70 80 210 280 443 488 563 591 631 777 901 1025-65535
+acl sslports port 443 563
+acl manager proto cache_object
+acl purge method PURGE
+acl connect method CONNECT
+acl dynamic urlpath_regex cgi-bin \?
+
+EOD;
+
+ $allowed = implode(' ', array_map('trim', explode(',', $settings['allowed_subnets'])));
+ if (!empty($allowed)) {
+ $conf .= "acl allowed_subnets src $allowed\n";
+ $valid_acls[] = 'allowed_subnets';
+ }
+
+ $options = array( 'unrestricted_hosts' => 'src',
+ 'unrestricted_macs' => 'arp',
+ 'banned_hosts' => 'src',
+ 'banned_macs' => 'arp',
+ 'whitelist' => 'url_regex -i',
+ 'blacklist' => 'url_regex -i',
+ );
+ foreach ($options as $option => $directive) {
+ $contents = trim(implode("\n", array_map('trim', explode(',', $settings[$option]))));
+ if (!empty($contents)) {
+ file_put_contents(SQUID_ACLDIR . "/$option.acl", $contents);
+ $conf .= "acl $option $directive \"" . SQUID_ACLDIR . "/$option.acl\"\n";
+ $valid_acls[] = $option;
+ }
+ }
+
+ $conf .= <<<EOD
+no_cache deny dynamic
+http_access allow manager localhost
+http_access deny manager
+http_access allow purge localhost
+http_access deny purge
+http_access deny !safeports
+http_access deny CONNECT !sslports
+
+http_access allow localhost
+
+EOD;
+
+ return $conf;
+}
+
+function squid_resync_traffic() {
+ global $config, $valid_acls;
+
+ $settings = $config['installedpackages']['squidtraffic']['config'][0];
+ $conf = '';
+
+ $up_limit = $settings['max_upload_size'] ? $settings['max_upload_size'] : 0;
+ $down_limit = $settings['max_download_size'] ? $settings['max_download_size'] : 0;
+ $conf .= "request_body_max_size $up_limit KB\n";
+ $conf .= 'reply_body_max_size ' . ($down_limit * 1024) . " allow all\n";
+
+ foreach (array('perhost', 'overall') as $field) {
+ $capping = $settings["{$field}_capping"];
+ $throttling = $settings["{$field}_throttling"];
+
+ if (!isset($capping) || $capping == 0)
+ $capping = '-1';
+ else
+ $capping *= 1024; // Kbytes
+
+ if (!isset($throttling) || $throttling == 0) {
+ if ($capping == '-1')
+ $throttling = '-1';
+ else
+ $throttling = $capping;
+ } else {
+ $throttling *= 1024; // Kbytes
+ }
+
+ $$field = "$throttling/$capping";
+ }
+
+ $initial_bucket_level = $settings['initial_bucket_level'];
+ if (!isset($initial_bucket_level) || $initial_bucket_level == 0)
+ $initial_bucket_level = '100%';
+ else
+ $initial_bucket_level *= 1024; // Kbytes
+
+ $conf .= <<<EOD
+delay_initial_bucket_level $initial_bucket_level
+delay_pools 1
+delay_class 1 2
+delay_parameters 1 $overall $perhost
+
+EOD;
+
+ foreach (array('unrestricted_hosts', 'unrestricted_macs') as $item) {
+ if (in_array($item, $valid_acls))
+ $conf .= "delay_access 1 deny $item\n";
+ }
+
+ if ($settings['throttle_specific'] == 'on') {
+ $exts = array();
+ $binaries = 'bin,cab,sea,ar,arj,tar,tgz,gz,tbz,bz2,zip,exe,com';
+ $cdimages = 'iso,bin,mds,nrg,gho,bwt,b5t,pqi';
+ $multimedia = 'aiff?,asf,avi,divx,mov,mp3,mp4,mpe?g,qt,ra?m';
+ foreach (array( 'throttle_binaries' => $binaries,
+ 'throttle_cdimages' => $cdimages,
+ 'throttle_multimedia' => $multimedia) as $field => $set) {
+ if ($settings[$field] == 'on')
+ $exts = array_merge($exts, explode(',', $set));
+ }
+
+ foreach (explode(',', $settings['throttle_others']) as $ext) {
+ if (!empty($ext)) $exts[] = $ext;
+ }
+
+ $contents = '';
+ foreach ($exts as $ext)
+ $contents .= "\.$ext\$\n";
+ file_put_contents(SQUID_ACLDIR . '/throttle_exts.acl', $contents);
+
+ if (!empty($contents)) { // avoid crashing Squid
+ $conf .= 'acl throttle_exts url_regex -i "' . SQUID_ACLDIR . "/throttle_exts.acl\"\n";
+ $conf .= "delay_access 1 allow throttle_exts\n";
+ $conf .= "delay_access 1 deny all\n";
+ }
+ }
+ else
+ $conf .= "delay_access 1 allow all\n";
+
+ return $conf;
+}
+
+function squid_resync_auth() {
+ global $config, $valid_acls;
+
+ $settings = $config['installedpackages']['squidauth']['config'][0];
+ $conf = '';
+
+ // Deny the banned guys before allowing the good guys
+ $banned = array( 'banned_hosts',
+ 'banned_macs',
+ );
+ $banned = array_filter($banned, 'squid_is_valid_acl');
+ foreach ($banned as $acl)
+ $conf .= "http_access deny $acl\n";
+
+ // Whitelist and blacklist also take precendence
+ if (squid_is_valid_acl('whitelist'))
+ $conf .= "http_access allow whitelist\n";
+ if (squid_is_valid_acl('blacklist'))
+ $conf .= "http_access deny blacklist\n";
+
+ $transparent_proxy = $config['installedpackages']['squid']['config'][0]['transparent_proxy'] == 'on';
+ $auth_method = ($settings['auth_method'] && !$transparent_proxy) ? $settings['auth_method'] : 'none';
+
+ // Allow the remaining ACLs if no authentication is set
+ if ($auth_method == 'none') {
+ $allowed = array('localnet', 'allowed_subnets', 'unrestricted_hosts', 'unrestricted_macs');
+ $allowed = array_filter($allowed, 'squid_is_valid_acl');
+ foreach ($allowed as $acl)
+ $conf .= "http_access allow $acl\n";
+ }
+
+ else {
+ $noauth = implode(' ', array_map('trim', explode(',', $settings['no_auth_hosts'])));
+ if (!empty($noauth)) {
+ $conf .= "acl noauth src $noauth\n";
+ $valid_acls[] = 'noauth';
+ }
+
+ // Set up the external authentication programs
+ $auth_ttl = $settings['auth_ttl'] ? $settings['auth_ttl'] : 60;
+ $processes = $settings['auth_processes'] ? $settings['auth_processes'] : 5;
+ $prompt = $settings['auth_prompt'] ? $settings['auth_prompt'] : 'Please enter your credentials to access the proxy';
+ switch ($auth_method) {
+ case 'local':
+ $conf .= 'auth_param basic program /usr/local/libexec/squid/ncsa_auth ' . SQUID_PASSWD . "\n";
+ break;
+ case 'ldap':
+ $port = isset($settings['auth_port']) ? ":{$settings['auth_port']}" : '';
+ $user = isset($settings['ldap_user']) ? "-D {$settings['ldap_user']}" : '';
+ $password = isset($settings['ldap_password']) ? "-w '{$settings['ldap_password']}'" : '';
+ $filter = isset($settings['ldap_filter']) ? "-f '{$settings['ldap_filter']}'" : '';
+ $conf .= "auth_param basic program /usr/local/libexec/squid/squid_ldap_auth -b {$settings['ldap_basedn']} $user $password $filter {$settings['auth_server']}$port\n";
+ break;
+ case 'radius':
+ $port = isset($settings['auth_port']) ? "-p {$settings['auth_server_port']}" : '';
+ $conf .= "auth_param basic program /usr/local/libexec/squid/squid_radius_auth -w {$settings['radius_secret']} -h {$settings['auth_server']} $port\n";
+ break;
+ case 'msnt':
+ $conf .= "auth_param basic program /usr/local/libexec/squid/msnt_auth\n";
+
+ $bdc = trim($settings['msnt_bdc']);
+ if (empty($bdc)) $bdc = $settings['auth_server'];
+ $msntauth_conf = "server {$settings['auth_server']} $bdc {$settings['msnt_domain']}\n";
+ file_put_contents(MSNTAUTH_CONF, $msntauth_conf);
+
+ break;
+ }
+ $conf .= <<<EOD
+auth_param basic children $processes
+auth_param basic realm $prompt
+auth_param basic credentialsttl $auth_ttl minutes
+acl password proxy_auth REQUIRED
+
+EOD;
+
+ // Onto the ACLs
+ $password = array('localnet', 'allowed_subnets');
+ $passwordless = array('unrestricted_hosts', 'unrestricted_macs');
+ if ($settings['unrestricted_auth'] == 'on') {
+ // Even the unrestricted hosts should authenticate
+ $password = array_merge($password, $passwordless);
+ $passwordless = array();
+ }
+ $passwordless[] = 'noauth';
+ $password = array_filter($password, 'squid_is_valid_acl');
+ $passwordless = array_filter($passwordless, 'squid_is_valid_acl');
+
+ // Allow the ACLs that don't need to authenticate
+ foreach ($passwordless as $acl)
+ $conf .= "http_access allow $acl\n";
+
+ // Allow the other ACLs as long as they authenticate
+ foreach ($password as $acl)
+ $conf .= "http_access allow password $acl\n";
+ }
+
+
+ $conf .= "http_access deny all\n";
+
+ return $conf;
+}
+
+function squid_resync_users() {
+ global $config;
+
+ $users = $config['installedpackages']['squidusers']['config'];
+ $contents = '';
+ if (is_array($users)) {
+ foreach ($users as $user)
+ $contents .= $user['username'] . ':' . crypt($user['password'], base64_encode($user['password'])) . "\n";
+ }
+ file_put_contents(SQUID_PASSWD, $contents);
+ chown(SQUID_PASSWD, 'proxy');
+ chmod(SQUID_PASSWD, 0600);
+}
+
+function squid_resync() {
+ $conf = squid_resync_general() . "\n";
+ $conf .= squid_resync_cache() . "\n";
+ $conf .= squid_resync_redirector() . "\n";
+ $conf .= squid_resync_upstream() . "\n";
+ $conf .= squid_resync_nac() . "\n";
+ $conf .= squid_resync_traffic() . "\n";
+ $conf .= squid_resync_auth();
+ squid_resync_users();
+
+ file_put_contents(SQUID_CONFBASE . '/squid.conf', $conf);
+
+ if (!is_dir(SQUID_CACHEDIR . '/0/0')) {
+ log_error(SQUID_CACHEDIR . ' does not exist. Creating.');
+ mwexec('/usr/local/sbin/squid -z');
+ }
+
+ restart_service('squid');
+ sleep(1);
+ restart_service('proxy_monitor');
+
+ filter_configure();
+}
+
+function squid_print_javascript_auth() {
+ global $config;
+ $transparent_proxy = $config['installedpackages']['squid']['config'][0]['transparent_proxy'] == 'on';
+
+ // No authentication for transparent proxy
+ if ($transparent_proxy) {
+ $javascript = <<<EOD
+<script language="JavaScript">
+<!--
+function on_auth_method_changed() {
+ document.iform.auth_method.disabled = 1;
+ document.iform.auth_server.disabled = 1;
+ document.iform.auth_server_port.disabled = 1;
+ document.iform.ldap_user.disabled = 1;
+ document.iform.ldap_password.disabled = 1;
+ document.iform.ldap_basedn.disabled = 1;
+ document.iform.ldap_filter.disabled = 1;
+ document.iform.radius_secret.disabled = 1;
+ document.iform.msnt_bdc.disabled = 1;
+ document.iform.msnt_domain.disabled = 1;
+ document.iform.auth_prompt.disabled = 1;
+ document.iform.auth_processes.disabled = 1;
+ document.iform.auth_ttl.disabled = 1;
+ document.iform.unrestricted_auth.disabled = 1;
+ document.iform.no_auth_hosts.disabled = 1;
+}
+-->
+</script>
+
+EOD;
+ }
+ else {
+ $javascript = <<<EOD
+<script language="JavaScript">
+<!--
+function on_auth_method_changed() {
+ var field = document.iform.auth_method;
+ var auth_method = field.options[field.selectedIndex].value;
+
+ if (auth_method == 'none') {
+ document.iform.auth_server.disabled = 1;
+ document.iform.auth_server_port.disabled = 1;
+ document.iform.ldap_user.disabled = 1;
+ document.iform.ldap_password.disabled = 1;
+ document.iform.ldap_basedn.disabled = 1;
+ document.iform.ldap_filter.disabled = 1;
+ document.iform.radius_secret.disabled = 1;
+ document.iform.msnt_bdc.disabled = 1;
+ document.iform.msnt_domain.disabled = 1;
+ document.iform.auth_prompt.disabled = 1;
+ document.iform.auth_processes.disabled = 1;
+ document.iform.auth_ttl.disabled = 1;
+ document.iform.unrestricted_auth.disabled = 1;
+ document.iform.no_auth_hosts.disabled = 1;
+ }
+ else {
+ document.iform.auth_prompt.disabled = 0;
+ document.iform.auth_processes.disabled = 0;
+ document.iform.auth_ttl.disabled = 0;
+ document.iform.unrestricted_auth.disabled = 0;
+ document.iform.no_auth_hosts.disabled = 0;
+ }
+
+ switch (auth_method) {
+ case 'local':
+ document.iform.auth_server.disabled = 1;
+ document.iform.auth_server_port.disabled = 1;
+ document.iform.ldap_user.disabled = 1;
+ document.iform.ldap_password.disabled = 1;
+ document.iform.ldap_basedn.disabled = 1;
+ document.iform.ldap_filter.disabled = 1;
+ document.iform.radius_secret.disabled = 1;
+ document.iform.msnt_bdc.disabled = 1;
+ document.iform.msnt_domain.disabled = 1;
+ break;
+ case 'ldap':
+ document.iform.auth_server.disabled = 0;
+ document.iform.auth_server_port.disabled = 0;
+ document.iform.ldap_user.disabled = 0;
+ document.iform.ldap_password.disabled = 0;
+ document.iform.ldap_basedn.disabled = 0;
+ document.iform.ldap_filter.disabled = 0;
+ document.iform.radius_secret.disabled = 1;
+ document.iform.msnt_bdc.disabled = 1;
+ document.iform.msnt_domain.disabled = 1;
+ break;
+ case 'radius':
+ document.iform.auth_server.disabled = 0;
+ document.iform.auth_server_port.disabled = 0;
+ document.iform.ldap_user.disabled = 1;
+ document.iform.ldap_password.disabled = 1;
+ document.iform.ldap_basedn.disabled = 1;
+ document.iform.ldap_filter.disabled = 1;
+ document.iform.radius_secret.disabled = 0;
+ document.iform.msnt_bdc.disabled = 1;
+ document.iform.msnt_domain.disabled = 1;
+ break;
+ case 'msnt':
+ document.iform.auth_server.disabled = 0;
+ document.iform.auth_server_port.disabled = 1;
+ document.iform.ldap_user.disabled = 1;
+ document.iform.ldap_password.disabled = 1;
+ document.iform.ldap_basedn.disabled = 1;
+ document.iform.ldap_filter.disabled = 1;
+ document.iform.radius_secret.disabled = 1;
+ document.iform.msnt_bdc.disabled = 0;
+ document.iform.msnt_domain.disabled = 0;
+ break;
+ }
+}
+-->
+</script>
+
+EOD;
+ }
+
+ print($javascript);
+}
+
+function squid_print_javascript_auth2() {
+ print("<script language=\"JavaScript\">on_auth_method_changed()</script>\n");
+}
+
+function squid_generate_rules($type) {
+ global $config;
+
+ $squid_conf = $config['installedpackages']['squid']['config'][0];
+ if (!is_service_running('squid') || ($squid_conf['transparent_proxy'] != 'on')) {
+ log_error('Squid is installed but not started. Not installing redirect rules.');
+ return;
+ }
+
+ $port = isset($squid_conf['proxy_port']) ? $squid_conf['proxy_port'] : 3128;
+ $ifaces = explode(',', $squid_conf['active_interface']);
+ $ifaces = array_map('convert_friendly_interface_to_real_interface_name', $ifaces);
+
+ switch($type) {
+ case 'nat':
+ foreach ($ifaces as $iface)
+ $rules .= "rdr on $iface inet proto tcp from any to !($iface) port 80 -> ($iface) port $port\n";
+ break;
+ case 'filter':
+ foreach ($ifaces as $iface)
+ $rules .= "pass quick on $iface inet proto tcp from any to !($iface) port 80 flags S/SA keep state\n";
+ break;
+ }
+
+ return $rules;
+}
+?>
diff --git a/config/squid-head/squid.xml b/config/squid-head/squid.xml
new file mode 100644
index 00000000..67f4c2aa
--- /dev/null
+++ b/config/squid-head/squid.xml
@@ -0,0 +1,215 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>squid</name>
+ <version>none</version>
+ <title>Proxy server: General settings</title>
+ <include_file>squid.inc</include_file>
+
+ <menu>
+ <name>Web proxy cache</name>
+ <tooltiptext>Modify the web proxy cache's settings</tooltiptext>
+ <section>Services</section>
+ <url>/pkg_edit.php?xml=squid.xml&amp;id=0</url>
+ </menu>
+ <service>
+ <name>Squid</name>
+ <rcfile>squid.sh</rcfile>
+ <executable>squid</executable>
+ <description>Web proxy cache.</description>
+ </service>
+ <tabs>
+ <tab>
+ <text>General settings</text>
+ <url>/pkg_edit.php?xml=squid.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Upstream proxy</text>
+ <url>/pkg_edit.php?xml=squid_upstream.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Cache management</text>
+ <url>/pkg_edit.php?xml=squid_cache.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Access control</text>
+ <url>/pkg_edit.php?xml=squid_nac.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Traffic management</text>
+ <url>/pkg_edit.php?xml=squid_traffic.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Auth settings</text>
+ <url>/pkg_edit.php?xml=squid_auth.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Local users</text>
+ <url>/pkg.php?xml=squid_users.xml</url>
+ </tab>
+ </tabs>
+ <!-- Installation -->
+ <additional_files_needed>
+ <item>http://www.pfsense.org/packages/config/squid.inc</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <item>http://www.pfsense.org/packages/config/squid_cache.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <item>http://www.pfsense.org/packages/config/squid_nac.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <item>http://www.pfsense.org/packages/config/squid_traffic.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <item>http://www.pfsense.org/packages/config/squid_upstream.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <item>http://www.pfsense.org/packages/config/squid_auth.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <item>http://www.pfsense.org/packages/config/squid_users.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/bin/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.org/packages/All/squid_monitor.sh</item>
+ </additional_files_needed>
+ <fields>
+ <field>
+ <fielddescr>Proxy interface</fielddescr>
+ <fieldname>active_interface</fieldname>
+ <description>The interface(s) the proxy server will bind to.</description>
+ <type>interfaces_selection</type>
+ <required/>
+ <default_value>lan</default_value>
+ <multiple/>
+ </field>
+ <field>
+ <fielddescr>Allow users on interface</fielddescr>
+ <fieldname>allow_interface</fieldname>
+ <description>If this field is checked, the users connected to the interface selected in the 'Proxy interface' field will be allowed to use the proxy, i.e., there will be no need to add the interface's subnet to the list of allowed subnets. This is just a shortcut.</description>
+ <type>checkbox</type>
+ <required/>
+ <default_value>on</default_value>
+ </field>
+ <field>
+ <fielddescr>Transparent proxy</fielddescr>
+ <fieldname>transparent_proxy</fieldname>
+ <description>If transparent mode is enabled, all requests for destination port 80 will be forwarded to the proxy server without any additional configuration necessary.</description>
+ <type>checkbox</type>
+ <required/>
+ </field>
+ <field>
+ <fielddescr>Enabled logging</fielddescr>
+ <fieldname>log_enabled</fieldname>
+ <description>This will enable the access log. Don't switch this on if you don't have much disk space left.</description>
+ <type>checkbox</type>
+ <enablefields>log_query_terms,log_user_agents</enablefields>
+ </field>
+ <field>
+ <fielddescr>Proxy port</fielddescr>
+ <fieldname>proxy_port</fieldname>
+ <description>This is the port the proxy server will listen on.</description>
+ <type>input</type>
+ <size>5</size>
+ <required/>
+ <default_value>3128</default_value>
+ </field>
+ <field>
+ <fielddescr>ICP port</fielddescr>
+ <fieldname>icp_port</fieldname>
+ <description>This is the port the proxy server will send and receive ICP queries to and from neighbor caches. Leave this blank if you don't want the proxy server to communicate with neighbor caches through ICP.</description>
+ <type>input</type>
+ <size>5</size>
+ </field>
+ <field>
+ <fielddescr>Visible hostname</fielddescr>
+ <fieldname>visible_hostname</fieldname>
+ <description>This is the hostname to be displayed in proxy server error messages.</description>
+ <type>input</type>
+ <default_value>localhost</default_value>
+ </field>
+ <field>
+ <fielddescr>Administrator email</fielddescr>
+ <fieldname>admin_email</fieldname>
+ <description>This is the email address displayed in error messages to the users.</description>
+ <type>input</type>
+ <default_value>admin@localhost</default_value>
+ </field>
+ <field>
+ <fielddescr>Language</fielddescr>
+ <fieldname>error_language</fieldname>
+ <description>Select the language in which the proxy server will display error messages to users.</description>
+ <type>select</type>
+ <default_value>English</default_value>
+ </field>
+ <field>
+ <fielddescr>Redirect children</fielddescr>
+ <fieldname>redirect_children</fieldname>
+ <description>Specify the number of redirectors to spawn (if using redirectors at all) when launching Squid. If you leave this field blank, Squid will start 5 redirector processes. If your network load is high, feel free to increase this value (at the expense of a higher memory consumption).</description>
+ <type>input</type>
+ <default_value>5</default_value>
+ </field>
+ </fields>
+ <custom_php_command_before_form>
+ squid_before_form_general(&amp;$pkg);
+ </custom_php_command_before_form>
+ <custom_php_validation_command>
+ squid_validate_general($_POST, &amp;$input_errors);
+ </custom_php_validation_command>
+<custom_php_resync_config_command>
+ squid_resync();
+ </custom_php_resync_config_command>
+ <custom_php_install_command>
+ squid_install_command();
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ squid_deinstall_command();
+ </custom_php_deinstall_command>
+</packagegui>
diff --git a/config/squid-head/squid_auth.xml b/config/squid-head/squid_auth.xml
new file mode 100644
index 00000000..15910f97
--- /dev/null
+++ b/config/squid-head/squid_auth.xml
@@ -0,0 +1,202 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>squidauth</name>
+ <version>none</version>
+ <title>Proxy server: Authentication</title>
+ <include_file>squid.inc</include_file>
+ <tabs>
+ <tab>
+ <text>General settings</text>
+ <url>/pkg_edit.php?xml=squid.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Upstream proxy</text>
+ <url>/pkg_edit.php?xml=squid_upstream.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Cache management</text>
+ <url>/pkg_edit.php?xml=squid_cache.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Access control</text>
+ <url>/pkg_edit.php?xml=squid_nac.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Traffic management</text>
+ <url>/pkg_edit.php?xml=squid_traffic.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Auth settings</text>
+ <url>/pkg_edit.php?xml=squid_auth.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Local users</text>
+ <url>/pkg.php?xml=squid_users.xml</url>
+ </tab>
+ </tabs>
+ <fields>
+ <field>
+ <fielddescr>Authentication method</fielddescr>
+ <fieldname>auth_method</fieldname>
+ <description>Select an authentication method. This will allow users to be authenticated by local or external services.</description>
+ <type>select</type>
+ <default_value>none</default_value>
+ <options>
+ <option><name>None</name><value>none</value></option>
+ <option><name>Local</name><value>local</value></option>
+ <option><name>LDAP</name><value>ldap</value></option>
+ <option><name>RADIUS</name><value>radius</value></option>
+ <option><name>NT domain</name><value>msnt</value></option>
+ </options>
+ <onchange>on_auth_method_changed()</onchange>
+ </field>
+ <field>
+ <fielddescr>Authentication server</fielddescr>
+ <fieldname>auth_server</fieldname>
+ <description>Enter here the IP or hostname of the server that will perform the authentication. For NT domain authentication, this is the Primary Domain Controller (PDC).</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Authentication server port</fielddescr>
+ <fieldname>auth_server_port</fieldname>
+ <description>Enter here the port to use to connect to the authentication server. Leave this field blank to use the authentication method's default port.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>LDAP server user DN</fielddescr>
+ <fieldname>ldap_user</fieldname>
+ <description>Enter here the user distinguished name (DN) to bind to connect to the LDAP server (e.g., "cn=Administrator,cn=Users,dc=foobar,dc=com"). You can leave this field blank if you don't want to use authentication.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>LDAP password</fielddescr>
+ <fieldname>ldap_password</fieldname>
+ <description>Enter here the password to use to connect to the LDAP server. You may leave this field unfilled.</description>
+ <type>password</type>
+ </field>
+ <field>
+ <fielddescr>LDAP base DN</fielddescr>
+ <fieldname>ldap_basedn</fieldname>
+ <description>For LDAP authentication, enter here the base DN for the search (e.g., "cn=Users,dc=foobar,dc=com").</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>LDAP filter</fielddescr>
+ <fieldname>ldap_filter</fieldname>
+ <description>Enter the string to be used to filter the results of the search, or leave this blank to get the results unfiltered. This must be in compliance with RFC 2254, and ocurrences of the string "%s" will be set to the username given to the proxy. You generally want something like '(sAMAccountName=%s)' here.</description>
+ <type>input</type>
+ <default_value>(sAMAccountName=%s)</default_value>
+ </field>
+ <field>
+ <fielddescr>RADIUS secret</fielddescr>
+ <fieldname>radius_secret</fieldname>
+ <description>The RADIUS secret for RADIUS authentication.</description>
+ <type>password</type>
+ </field>
+ <field>
+ <fielddescr>Backup Domain Controller</fielddescr>
+ <fieldname>msnt_bdc</fieldname>
+ <description>Enter the address of the Backup Domain Controller (BDC) or leave this field blank if you don't want to use a backup controller.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>NT domain</fielddescr>
+ <fieldname>msnt_domain</fieldname>
+ <description>Enter the NT domain to be used.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Authentication prompt</fielddescr>
+ <fieldname>auth_prompt</fieldname>
+ <description>This string will be displayed at the top of the authentication request window.</description>
+ <type>input</type>
+ <default_value>Please enter your credentials to access the proxy</default_value>
+ </field>
+ <field>
+ <fielddescr>Authentication processes</fielddescr>
+ <fieldname>auth_processes</fieldname>
+ <description>The number of authenticator processes to spawn. If many authentications are expected within a short timeframe, increase this number accordingly.</description>
+ <type>input</type>
+ <default_value>5</default_value>
+ </field>
+ <field>
+ <fielddescr>Authentication TTL</fielddescr>
+ <fieldname>auth_ttl</fieldname>
+ <description>This specifies for how long (in minutes) the proxy server assumes an externally validated username and password combination is valid (Time To Live). When the TTL expires, the user will be prompted for credentials again.</description>
+ <type>input</type>
+ <default_value>60</default_value>
+ </field>
+ <field>
+ <fielddescr>Requiere authentication for unrestricted hosts</fielddescr>
+ <fieldname>unrestricted_auth</fieldname>
+ <description>If this option is enabled, even users tagged as unrestricted through access control are required to authenticate to use the proxy.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Subnets that don't need authentication</fielddescr>
+ <fieldname>no_auth_hosts</fieldname>
+ <description>A comma-separated list of subnets (in CIDR range, e.g.: 10.5.0.0/16, 192.168.1.50/32) whose hosts won't be asked for authentication to access the proxy.</description>
+ <type>textarea</type>
+ <cols>50</cols>
+ <rows>5</rows>
+ </field>
+ </fields>
+ <custom_php_validation_command>
+ squid_validate_auth($_POST, &amp;$input_errors);
+ </custom_php_validation_command>
+ <custom_php_after_form_command>
+ squid_print_javascript_auth2();
+ </custom_php_after_form_command>
+ <custom_php_resync_config_command>
+ squid_resync();
+ </custom_php_resync_config_command>
+ <custom_php_after_head_command>
+ squid_print_javascript_auth();
+ </custom_php_after_head_command>
+</packagegui>
diff --git a/config/squid-head/squid_cache.xml b/config/squid-head/squid_cache.xml
new file mode 100644
index 00000000..3fe0475f
--- /dev/null
+++ b/config/squid-head/squid_cache.xml
@@ -0,0 +1,180 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>squidcache</name>
+ <version>none</version>
+ <title>Proxy server: Cache management</title>
+ <include_file>squid.inc</include_file>
+ <tabs>
+ <tab>
+ <text>General settings</text>
+ <url>/pkg_edit.php?xml=squid.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Upstream proxy</text>
+ <url>/pkg_edit.php?xml=squid_upstream.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Cache management</text>
+ <url>/pkg_edit.php?xml=squid_cache.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Access control</text>
+ <url>/pkg_edit.php?xml=squid_nac.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Traffic management</text>
+ <url>/pkg_edit.php?xml=squid_traffic.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Auth settings</text>
+ <url>/pkg_edit.php?xml=squid_auth.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Local users</text>
+ <url>/pkg.php?xml=squid_users.xml</url>
+ </tab>
+ </tabs>
+ <fields>
+ <field>
+ <fielddescr>Hard disk cache size</fielddescr>
+ <fieldname>harddisk_cache_size</fieldname>
+ <description>This is the amount of disk space (in megabytes) to use for cached objects.</description>
+ <type>input</type>
+ <required/>
+ <default_value>100</default_value>
+ </field>
+ <field>
+ <fielddescr>Memory cache size</fielddescr>
+ <fieldname>memory_cache_size</fieldname>
+ <description>This is the amount of physical RAM (in megabytes) to be used for negative cache and in-transit objects. This value should not exceed more than 50% of the installed RAM. The minimum value is 1MB.</description>
+ <type>input</type>
+ <required/>
+ <default_value>8</default_value>
+ </field>
+ <field>
+ <fielddescr>Minimum object size</fielddescr>
+ <fieldname>minimum_object_size</fieldname>
+ <description>Objects smaller than the size specified (in kilobytes) will not be saved on disk. The default value is 0, meaning there is no minimum.</description>
+ <type>input</type>
+ <required/>
+ <default_value>0</default_value>
+ </field>
+ <field>
+ <fielddescr>Maximum object size</fielddescr>
+ <fieldname>maximum_object_size</fieldname>
+ <description>Objects larger than the size specified (in kilobytes) will not be saved on disk. If you wish to increase speed more than you want to save bandwidth, this should be set to a low value.</description>
+ <type>input</type>
+ <required/>
+ <default_value>4</default_value>
+ </field>
+ <field>
+ <fielddescr>Level 1 subdirectories</fielddescr>
+ <fieldname>level1_subdirs</fieldname>
+ <description>Each level 1 (L1) directory contains 256 subdirectories, so a value of 256 L1 directories will use a total of 65536 directories for the hard disk cache. This will significantly slow down the startup process of the proxy service, but can speed up the caching under certain conditions.</description>
+ <type>select</type>
+ <default_value>16</default_value>
+ <options>
+ <option><name>4</name><value>4</value></option>
+ <option><name>8</name><value>8</value></option>
+ <option><name>16</name><value>16</value></option>
+ <option><name>32</name><value>32</value></option>
+ <option><name>64</name><value>64</value></option>
+ <option><name>128</name><value>128</value></option>
+ <option><name>256</name><value>256</value></option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Memory replacement policy</fielddescr>
+ <fieldname>memory_replacement</fieldname>
+ <description>The memory replacement policy determines which objects are purged from memory when space is needed. The default policy for memory replacement is GDSF.</description>
+ <type>select</type>
+ <default_value>heap GDSF</default_value>
+ <options>
+ <option><name>LRU</name><value>LRU</value></option>
+ <option><name>Heap LRU</name><value>heap LRU</value></option>
+ <option><name>Heap LFUDA</name><value>heap LFUDA</value></option>
+ <option><name>Heap GDSF</name><value>heap GDSF</value></option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Cache replacement policy</fielddescr>
+ <fieldname>cache_replacement</fieldname>
+ <description>The cache replacement policy decides which objects will remain in cache and which objects are replaced to create space for the new objects. The default policy for cache replacement is LFUDA.</description>
+ <type>select</type>
+ <default_value>heap LFUDA</default_value>
+ <options>
+ <option><name>LRU</name><value>lru</value></option>
+ <option><name>Heap LRU</name><value>heap LRU</value></option>
+ <option><name>Heap LFUDA</name><value>heap LFUDA</value></option>
+ <option><name>Heap GDSF</name><value>heap GDSF</value></option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Do not cache</fielddescr>
+ <fieldname>donotcache</fieldname>
+ <description>The specified domains or IP addresses (separated by commas) will never be cached.</description>
+ <type>textarea</type>
+ <cols>50</cols>
+ <rows>5</rows>
+ </field>
+ <field>
+ <fielddescr>Enable offline mode</fielddescr>
+ <fieldname>enable_offline</fieldname>
+ <description>Enable this option and the proxy server will never try to validate cached objects. The offline mode also gives access to more cached information than the proposed feature would allow (stale cached versions, where the origin server should have been contacted).</description>
+ <type>checkbox</type>
+ <required/>
+ </field>
+ </fields>
+ <custom_php_validation_command>
+ squid_validate_cache($_POST, &amp;$input_errors);
+ </custom_php_validation_command>
+ <custom_php_resync_config_command>
+ squid_resync();
+ </custom_php_resync_config_command>
+</packagegui>
diff --git a/config/squid-head/squid_monitor.sh b/config/squid-head/squid_monitor.sh
new file mode 100644
index 00000000..d0035d1a
--- /dev/null
+++ b/config/squid-head/squid_monitor.sh
@@ -0,0 +1,69 @@
+#!/bin/sh
+# $Id$ */
+#
+# proxy_monitor.sh
+# Copyright (C) 2006 Scott Ullrich
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+set -e
+
+LOOP_SLEEP=300
+
+if [ -f /var/run/squid_alarm ]; then
+ rm /var/run/squid_alarm
+fi
+
+# Squid monitor 1.0
+while [ /bin/true ]; do
+ if [ ! -f /var/run/squid_alarm ]; then
+ NUM_PROCS=`ps awux | grep "squid -D" | grep -v "grep" | wc -l | awk '{ print $1 }'`
+ if [ $NUM_PROCS -lt 1 ]; then
+ # squid is down
+ echo "Squid has exited. Reconfiguring filter." | \
+ logger -p daemon.info -i -t Squid_Alarm
+ echo "Attempting restart..." | logger -p daemon.info -i -t Squid_Alarm
+ /usr/local/etc/rc.d/squid.sh start
+ sleep 3
+ echo "Reconfiguring filter..." | logger -p daemon.info -i -t Squid_Alarm
+ /etc/rc.filter_configure_sync
+ touch /var/run/squid_alarm
+ fi
+ fi
+ NUM_PROCS=`ps awux | grep "squid -D" | grep -v "grep" | wc -l | awk '{ print $1 }'`
+ if [ $NUM_PROCS -gt 0 ]; then
+ if [ -f /var/run/squid_alarm ]; then
+ echo "Squid has resumed. Reconfiguring filter." | \
+ logger -p daemon.info -i -t Squid_Alarm
+ /etc/rc.filter_configure_sync
+ rm /var/run/squid_alarm
+ fi
+ fi
+ sleep $LOOP_SLEEP
+done
+
+if [ -f /var/run/squid_alarm ]; then
+ rm /var/run/squid_alarm
+fi
+
diff --git a/config/squid-head/squid_nac.xml b/config/squid-head/squid_nac.xml
new file mode 100644
index 00000000..db49a1ba
--- /dev/null
+++ b/config/squid-head/squid_nac.xml
@@ -0,0 +1,147 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>squidnac</name>
+ <version>none</version>
+ <title>Proxy server: Access control</title>
+ <include_file>squid.inc</include_file>
+ <tabs>
+ <tab>
+ <text>General settings</text>
+ <url>/pkg_edit.php?xml=squid.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Upstream proxy</text>
+ <url>/pkg_edit.php?xml=squid_upstream.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Cache management</text>
+ <url>/pkg_edit.php?xml=squid_cache.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Access control</text>
+ <url>/pkg_edit.php?xml=squid_nac.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Traffic management</text>
+ <url>/pkg_edit.php?xml=squid_traffic.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Auth settings</text>
+ <url>/pkg_edit.php?xml=squid_auth.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Local users</text>
+ <url>/pkg.php?xml=squid_users.xml</url>
+ </tab>
+ </tabs>
+ <fields>
+ <field>
+ <fielddescr>Allowed subnets</fielddescr>
+ <fieldname>allowed_subnets</fieldname>
+ <description>Those are the subnets (separated by commas) that are allowed to use the proxy. The subnets must be expressed as CIDR ranges (e.g.: 192.168.1.0/24). Note that the proxy interface subnet is already an allowed subnet. All the other subnets won't be able to use the proxy.</description>
+ <type>textarea</type>
+ <cols>50</cols>
+ <rows>5</rows>
+ </field>
+ <field>
+ <fielddescr>Unrestricted IPs</fielddescr>
+ <fieldname>unrestricted_hosts</fieldname>
+ <description>The IP addresses specified here (separated by commas) won't be filtered out by the other access control directives set in this page.</description>
+ <type>textarea</type>
+ <cols>50</cols>
+ <rows>5</rows>
+ </field>
+ <field>
+ <fielddescr>Unrestricted MAC Addresses</fielddescr>
+ <fieldname>unrestricted_macs</fieldname>
+ <description>The MAC addresses specified here (separated by commas) won't be filtered out by the other access control directives set in this page.</description>
+ <type>textarea</type>
+ <cols>50</cols>
+ <rows>5</rows>
+ </field>
+ <field>
+ <fielddescr>Banned host addresses</fielddescr>
+ <fieldname>banned_hosts</fieldname>
+ <description>The IP addresses specified here (separated by commas) won't be allowed to use the proxy.</description>
+ <type>textarea</type>
+ <cols>50</cols>
+ <rows>5</rows>
+ </field>
+ <field>
+ <fielddescr>Banned MAC addresses</fielddescr>
+ <fieldname>banned_macs</fieldname>
+ <description>The MAC addresses specified here (separated by commas) won't be allowed to use the proxy.</description>
+ <type>textarea</type>
+ <cols>50</cols>
+ <rows>5</rows>
+ </field>
+ <field>
+ <fielddescr>Whitelist</fielddescr>
+ <fieldname>whitelist</fieldname>
+ <description>Those are the sites (separated by commas) that will be accessable to the users that are allowed to use the proxy.</description>
+ <type>textarea</type>
+ <cols>50</cols>
+ <rows>5</rows>
+ </field>
+ <field>
+ <fielddescr>Blacklist</fielddescr>
+ <fieldname>blacklist</fieldname>
+ <description>Those are the sites (separated by commas) that will be blocked to the users that are allowed to use the proxy.</description>
+ <type>textarea</type>
+ <cols>50</cols>
+ <rows>5</rows>
+ </field>
+ </fields>
+ <custom_php_validation_command>
+ squid_validate_nac($_POST, &amp;$input_errors);
+ </custom_php_validation_command>
+ <custom_php_resync_config_command>
+ squid_resync();
+ </custom_php_resync_config_command>
+</packagegui>
diff --git a/config/squid-head/squid_traffic.xml b/config/squid-head/squid_traffic.xml
new file mode 100644
index 00000000..d69f2510
--- /dev/null
+++ b/config/squid-head/squid_traffic.xml
@@ -0,0 +1,179 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>squidtraffic</name>
+ <version>none</version>
+ <title>Proxy server: Traffic management</title>
+ <include_file>squid.inc</include_file>
+ <tabs>
+ <tab>
+ <text>General settings</text>
+ <url>/pkg_edit.php?xml=squid.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Upstream proxy</text>
+ <url>/pkg_edit.php?xml=squid_upstream.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Cache management</text>
+ <url>/pkg_edit.php?xml=squid_cache.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Access control</text>
+ <url>/pkg_edit.php?xml=squid_nac.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Traffic management</text>
+ <url>/pkg_edit.php?xml=squid_traffic.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Auth settings</text>
+ <url>/pkg_edit.php?xml=squid_auth.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Local users</text>
+ <url>/pkg.php?xml=squid_users.xml</url>
+ </tab>
+ </tabs>
+ <fields>
+ <field>
+ <fielddescr>Maximum download size</fielddescr>
+ <fieldname>max_download_size</fieldname>
+ <description>Limit the maximum total download size to the size specified here (in kilobytes). Downloads bigger than the specified size will be denied. Set to 0 to disable.</description>
+ <type>input</type>
+ <required/>
+ <default_value>0</default_value>
+ </field>
+ <field>
+ <fielddescr>Maximum upload size</fielddescr>
+ <fieldname>max_upload_size</fieldname>
+ <description>Limit the maximum total upload size to the size specified here (in kilobytes). Uploads bigger than the specified size will be denied. Set to 0 to disable.</description>
+ <type>input</type>
+ <required/>
+ <default_value>0</default_value>
+ </field>
+ <field>
+ <fielddescr>Overall capping</fielddescr>
+ <fieldname>overall_capping</fieldname>
+ <description>Caps the download speeds of the network that connects to the proxy as a whole at the specified size (in kilobytes per second). Set to 0 to disable.</description>
+ <type>input</type>
+ <required/>
+ <default_value>0</default_value>
+ </field>
+ <field>
+ <fielddescr>Per-host capping</fielddescr>
+ <fieldname>perhost_capping</fieldname>
+ <description>Caps the download speeds of each user that connects to the proxy at the specified size (in kilobytes per second). Set to 0 to disable.</description>
+ <type>input</type>
+ <required/>
+ <default_value>0</default_value>
+ </field>
+ <field>
+ <fielddescr>Overall bandwidth throttling</fielddescr>
+ <fieldname>overall_throttling</fieldname>
+ <description>This value specifies (in kilobytes per second) the bandwidth throttle for downloads. Users will gradually have their download speed increased according to this value. Set to 0 to disable bandwidth throttling.</description>
+ <type>input</type>
+ <required/>
+ <default_value>0</default_value>
+ </field>
+ <field>
+ <fielddescr>Per-host throttling</fielddescr>
+ <fieldname>perhost_throttling</fieldname>
+ <description>This value specifies the download throttling per host. Set to 0 to disable this.</description>
+ <type>input</type>
+ <required/>
+ <default_value>0</default_value>
+ </field>
+ <field>
+ <fielddescr>Initial bucket level</fielddescr>
+ <fieldname>initial_bucket_level</fieldname>
+ <description>The initial bucket level is used to determine how much is put in each bucket when a connection is established. Set to 0 to set the initial bucket level to 100%.</description>
+ <type>input</type>
+ <required/>
+ <default_value>0</default_value>
+ </field>
+ <field>
+ <fielddescr>Throttle only specific extensions</fielddescr>
+ <fieldname>throttle_specific</fieldname>
+ <description>Leave this checked to be able to choose the extensions that throttling will be applied to. Otherwise, all files will be throttled.</description>
+ <type>checkbox</type>
+ <enablefields>throttle_binaries,throttle_cdimages,throttle_multimedia,throttle_others</enablefields>
+ <default_value>on</default_value>
+ </field>
+ <field>
+ <fielddescr>Throttle binary files</fielddescr>
+ <fieldname>throttle_binaries</fieldname>
+ <description>Check this to apply bandwidth throttle to binary files. This includes compressed archives and executables.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Throttle CD images</fielddescr>
+ <fieldname>throttle_cdimages</fieldname>
+ <description>Check this to apply bandwidth throttle to CD image files.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Throttle multimedia files</fielddescr>
+ <fieldname>throttle_multimedia</fieldname>
+ <description>Check this to apply bandwidth throttle to multimedia files, such as movies or songs.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Throttle other extensions</fielddescr>
+ <fieldname>throttle_others</fieldname>
+ <description>Comma-separated list of extensions to apply bandwidth throttle to.</description>
+ <type>input</type>
+ </field>
+ </fields>
+ <custom_php_validation_command>
+ squid_validate_traffic($_POST, &amp;$input_errors);
+ </custom_php_validation_command>
+ <custom_php_resync_config_command>
+ squid_resync();
+ </custom_php_resync_config_command>
+</packagegui>
diff --git a/config/squid-head/squid_upstream.xml b/config/squid-head/squid_upstream.xml
new file mode 100644
index 00000000..b02a21b4
--- /dev/null
+++ b/config/squid-head/squid_upstream.xml
@@ -0,0 +1,133 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>squidupstream</name>
+ <version>none</version>
+ <title>Proxy server: Upstream proxy settings</title>
+ <include_file>squid.inc</include_file>
+ <tabs>
+ <tab>
+ <text>General settings</text>
+ <url>/pkg_edit.php?xml=squid.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Upstream proxy</text>
+ <url>/pkg_edit.php?xml=squid_upstream.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Cache management</text>
+ <url>/pkg_edit.php?xml=squid_cache.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Access control</text>
+ <url>/pkg_edit.php?xml=squid_nac.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Traffic management</text>
+ <url>/pkg_edit.php?xml=squid_traffic.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Auth settings</text>
+ <url>/pkg_edit.php?xml=squid_auth.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Local users</text>
+ <url>/pkg.php?xml=squid_users.xml</url>
+ </tab>
+ </tabs>
+ <fields>
+ <field>
+ <fielddescr>Enable forwarding</fielddescr>
+ <fieldname>proxy_forwarding</fieldname>
+ <description>This option enables the proxy server to forward requests to an upstream server.</description>
+ <type>checkbox</type>
+ <enablefields>proxy_addr,proxy_port,icp_port,username,password</enablefields>
+ <required/>
+ </field>
+ <field>
+ <fielddescr>Hostname</fielddescr>
+ <fieldname>proxy_addr</fieldname>
+ <description>Enter here the IP address or host name of the upstream proxy.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>TCP port</fielddescr>
+ <fieldname>proxy_port</fieldname>
+ <description>Enter the port to use to connect to the upstream proxy.</description>
+ <type>input</type>
+ <size>5</size>
+ <default_value>3128</default_value>
+ </field>
+ <field>
+ <fielddescr>ICP port</fielddescr>
+ <fieldname>icp_port</fieldname>
+ <description>Enter the port to connect to the upstream proxy for the ICP protocol. Use port number 7 to disable ICP communication between the proxies.</description>
+ <type>input</type>
+ <size>5</size>
+ <default_value>7</default_value>
+ </field>
+ <field>
+ <fielddescr>Username</fielddescr>
+ <fieldname>username</fieldname>
+ <description>If the upstream proxy requires a username, specify it here.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Password</fielddescr>
+ <fieldname>password</fieldname>
+ <description>If the upstream proxy requires a password, specify it here.</description>
+ <type>password</type>
+ </field>
+ </fields>
+ <custom_php_validation_command>
+ squid_validate_upstream($_POST, &amp;$input_errors);
+ </custom_php_validation_command>
+ <custom_php_resync_config_command>
+ squid_resync();
+ </custom_php_resync_config_command>
+</packagegui>
diff --git a/config/squid-head/squid_users.xml b/config/squid-head/squid_users.xml
new file mode 100644
index 00000000..34260817
--- /dev/null
+++ b/config/squid-head/squid_users.xml
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>squidusers</name>
+ <version>none</version>
+ <title>Proxy server: Local users</title>
+ <include_file>squid.inc</include_file>
+ <delete_string>A proxy server user has been deleted.</delete_string>
+ <addedit_string>A proxy server user has been created/modified.</addedit_string>
+ <tabs>
+ <tab>
+ <text>General settings</text>
+ <url>/pkg_edit.php?xml=squid.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Upstream proxy</text>
+ <url>/pkg_edit.php?xml=squid_upstream.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Cache management</text>
+ <url>/pkg_edit.php?xml=squid_cache.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Access control</text>
+ <url>/pkg_edit.php?xml=squid_nac.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Traffic management</text>
+ <url>/pkg_edit.php?xml=squid_traffic.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Auth settings</text>
+ <url>/pkg_edit.php?xml=squid_auth.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Local users</text>
+ <url>/pkg.php?xml=squid_users.xml</url>
+ <active/>
+ </tab>
+ </tabs>
+ <adddeleteeditpagefields>
+ <columnitem>
+ <fielddescr>Username</fielddescr>
+ <fieldname>username</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Description</fielddescr>
+ <fieldname>description</fieldname>
+ </columnitem>
+ </adddeleteeditpagefields>
+ <fields>
+ <field>
+ <fielddescr>Username</fielddescr>
+ <fieldname>username</fieldname>
+ <description>Enter the username here.</description>
+ <type>input</type>
+ <required/>
+ </field>
+ <field>
+ <fielddescr>Password</fielddescr>
+ <fieldname>password</fieldname>
+ <description>Enter the password here.</description>
+ <type>password</type>
+ <required/>
+ </field>
+ <field>
+ <fielddescr>Description</fielddescr>
+ <fieldname>description</fieldname>
+ <description>You may enter a description here for your reference (not parsed).</description>
+ <type>input</type>
+ </field>
+ </fields>
+ <custom_php_resync_config_command>
+ squid_resync_users();
+ </custom_php_resync_config_command>
+</packagegui>
diff --git a/config/squid/proxy_monitor.sh b/config/squid/proxy_monitor.sh
new file mode 100644
index 00000000..fab2ee54
--- /dev/null
+++ b/config/squid/proxy_monitor.sh
@@ -0,0 +1,72 @@
+#!/bin/sh
+# $Id$ */
+#
+# proxy_monitor.sh
+# Copyright (C) 2006 Scott Ullrich
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+set -e
+
+LOOP_SLEEP=55
+
+if [ -f /var/run/squid_alarm ]; then
+ rm /var/run/squid_alarm
+fi
+
+# Sleep 5 seconds on startup not to mangle with existing boot scripts.
+sleep 5
+
+# Squid monitor 1.2
+while [ /bin/true ]; do
+ if [ ! -f /var/run/squid_alarm ]; then
+ NUM_PROCS=`ps auxw | grep "[s]quid -D"|awk '{print $2}'| wc -l | awk '{ print $1 }'`
+ if [ $NUM_PROCS -lt 1 ]; then
+ # squid is down
+ echo "Squid has exited. Reconfiguring filter." | \
+ logger -p daemon.info -i -t Squid_Alarm
+ echo "Attempting restart..." | logger -p daemon.info -i -t Squid_Alarm
+ /usr/local/etc/rc.d/squid.sh start
+ sleep 3
+ echo "Reconfiguring filter..." | logger -p daemon.info -i -t Squid_Alarm
+ /etc/rc.filter_configure_sync
+ touch /var/run/squid_alarm
+ fi
+ fi
+ NUM_PROCS=`ps auxw | grep "[s]quid -D"|awk '{print $2}'| wc -l | awk '{ print $1 }'`
+ if [ $NUM_PROCS -gt 0 ]; then
+ if [ -f /var/run/squid_alarm ]; then
+ echo "Squid has resumed. Reconfiguring filter." | \
+ logger -p daemon.info -i -t Squid_Alarm
+ /etc/rc.filter_configure_sync
+ rm /var/run/squid_alarm
+ fi
+ fi
+ sleep $LOOP_SLEEP
+done
+
+if [ -f /var/run/squid_alarm ]; then
+ rm /var/run/squid_alarm
+fi
+
diff --git a/config/squid/squid.inc b/config/squid/squid.inc
new file mode 100644
index 00000000..456524e2
--- /dev/null
+++ b/config/squid/squid.inc
@@ -0,0 +1,1263 @@
+<?php
+/* $Id$ */
+/*
+ squid.inc
+ Copyright (C) 2006 Scott Ullrich
+ Copyright (C) 2006 Fernando Lemos
+ Copyright (C) 2008 Martin Fuchs
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require_once('globals.inc');
+require_once('config.inc');
+require_once('util.inc');
+require_once('pfsense-utils.inc');
+require_once('pkg-utils.inc');
+require_once('filter.inc');
+require_once('service-utils.inc');
+
+define('SQUID_CONFBASE', '/usr/local/etc/squid');
+define('SQUID_ACLDIR', '/var/squid/acl');
+define('SQUID_PASSWD', '/var/etc/squid.passwd');
+
+$valid_acls = array();
+
+function squid_get_real_interface_address($iface) {
+ global $config;
+
+ $iface = convert_friendly_interface_to_real_interface_name($iface);
+ $line = trim(shell_exec("ifconfig $iface | grep inet | grep -v inet6"));
+ list($dummy, $ip, $dummy2, $netmask) = explode(" ", $line);
+
+ return array($ip, long2ip(hexdec($netmask)));
+}
+
+function squid_chown_recursive($dir, $user, $group) {
+ chown($dir, $user);
+ chgrp($dir, $group);
+ $handle = opendir($dir) ;
+ while (($item = readdir($handle)) !== false) {
+ if (($item != ".") && ($item != "..")) {
+ $path = "$dir/$item";
+ if (is_dir($path))
+ squid_chown_recursive($path, $user, $group);
+ else {
+ chown($path, $user);
+ chgrp($path, $group);
+ }
+ }
+ }
+}
+
+/* setup cache */
+function squid_dash_z() {
+ global $config;
+ $settings = $config['installedpackages']['squidcache']['config'][0];
+ $cachedir =($settings['harddisk_cache_location'] ? $settings['harddisk_cache_location'] : '/var/squid/cache');
+
+ if(!is_dir($cachedir.'/')) {
+ log_error("Creating Squid cache dir $cachedir");
+ make_dirs($cachedir);
+ squid_chown_recursive($cachedir, 'proxy', 'proxy');
+ }
+
+ if(!is_dir($cachedir.'/00/')) {
+ log_error("Creating squid cache subdirs in $cachedir");
+ mwexec("/usr/local/sbin/squid -k shutdown");
+ sleep(5);
+ mwexec("/usr/local/sbin/squid -k kill");
+ mwexec("/usr/local/sbin/squid -z");
+ }
+
+ exec("chmod a+rw /var/squid/cache/swap.state");
+
+}
+
+function squid_is_valid_acl($acl) {
+ global $valid_acls;
+ if(!is_array($valid_acls))
+ return;
+ return in_array($acl, $valid_acls);
+}
+
+function squid_install_command() {
+ global $config;
+ /* migrate existing csv config fields */
+ $settingsauth = $config['installedpackages']['squidauth']['config'][0];
+ $settingscache = $config['installedpackages']['squidcache']['config'][0];
+ $settingsnac = $config['installedpackages']['squidnac']['config'][0];
+
+ /* migrate auth settings */
+ if (!empty($settingsauth['no_auth_hosts'])) {
+ if(strstr($settingsauth['no_auth_hosts'], ",")) {
+ $settingsauth['no_auth_hosts'] = base64_encode(implode("\n", explode(",", $settingsauth['no_auth_hosts'])));
+ $config['installedpackages']['squidauth']['config'][0]['no_auth_hosts'] = $settingsauth['no_auth_hosts'];
+ }
+ }
+
+ /* migrate cache settings */
+ if (!empty($settingscache['donotcache'])) {
+ if(strstr($settingscache['donotcache'], ",")) {
+ $settingscache['donotcache'] = base64_encode(implode("\n", explode(",", $settingscache['donotcache'])));
+ $config['installedpackages']['squidcache']['config'][0]['donotcache'] = $settingscache['donotcache'];
+ }
+ }
+
+ /* migrate nac settings */
+ if(! empty($settingsnac['allowed_subnets'])) {
+ if(strstr($settingsnac['allowed_subnets'], ",")) {
+ $settingsnac['allowed_subnets'] = base64_encode(implode("\n", explode(",", $settingsnac['allowed_subnets'])));
+ $config['installedpackages']['squidnac']['config'][0]['allowed_subnets'] = $settingsnac['allowed_subnets'];
+ }
+ }
+ if(! empty($settingsnac['banned_hosts'])) {
+ if(strstr($settingsnac['banned_hosts'], ",")) {
+ $settingsnac['banned_hosts'] = base64_encode(implode("\n", explode(",", $settingsnac['banned_hosts'])));
+ $config['installedpackages']['squidnac']['config'][0]['banned_hosts'] = $settingsnac['banned_hosts'];
+ }
+ }
+ if(! empty($settingsnac['banned_macs'])) {
+ if(strstr($settingsnac['banned_macs'], ",")) {
+ $settingsnac['banned_macs'] = base64_encode(implode("\n", explode(",", $settingsnac['banned_macs'])));
+ $config['installedpackages']['squidnac']['config'][0]['banned_macs'] = $settingsnac['banned_macs'];
+ }
+ }
+ if(! empty($settingsnac['unrestricted_hosts'])) {
+ if(strstr($settingsnac['unrestricted_hosts'], ",")) {
+ $settingsnac['unrestricted_hosts'] = base64_encode(implode("\n", explode(",", $settingsnac['unrestricted_hosts'])));
+ $config['installedpackages']['squidnac']['config'][0]['unrestricted_hosts'] = $settingsnac['unrestricted_hosts'];
+ }
+ }
+ if(! empty($settingsnac['unrestricted_macs'])) {
+ if(strstr($settingsnac['unrestricted_macs'], ",")) {
+ $settingsnac['unrestricted_macs'] = base64_encode(implode("\n", explode(",", $settingsnac['unrestricted_macs'])));
+ $config['installedpackages']['squidnac']['config'][0]['unrestricted_macs'] = $settingsnac['unrestricted_macs'];
+ }
+ }
+ if(! empty($settingsnac['whitelist'])) {
+ if(strstr($settingsnac['whitelist'], ",")) {
+ $settingsnac['whitelist'] = base64_encode(implode("\n", explode(",", $settingsnac['whitelist'])));
+ $config['installedpackages']['squidnac']['config'][0]['whitelist'] = $settingsnac['whitelist'];
+ }
+ }
+ if(! empty($settingsnac['blacklist'])) {
+ if(strstr($settingsnac['blacklist'], ",")) {
+ $settingsnac['blacklist'] = base64_encode(implode("\n", explode(",", $settingsnac['blacklist'])));
+ $config['installedpackages']['squidnac']['config'][0]['blacklist'] = $settingsnac['blacklist'];
+ }
+ }
+
+ update_status("Writing configuration... One moment please...");
+
+ write_config();
+
+ /* create cache */
+ update_status("Creating squid cache pools... One moment please...");
+ squid_dash_z();
+ /* make sure pinger is executable */
+ if(file_exists("/usr/local/libexec/squid/pinger"))
+ exec("/bin/chmod a+x /usr/local/libexec/squid/pinger");
+ if(file_exists("/usr/local/etc/rc.d/squid"))
+ exec("/bin/rm /usr/local/etc/rc.d/squid");
+ $rc = array();
+ $rc['file'] = 'squid.sh';
+ $rc['start'] = <<<EOD
+if [ -z "`ps auxw | grep "[s]quid -D"|awk '{print $2}'`" ];then
+ /usr/local/sbin/squid -D
+fi
+
+EOD;
+ $rc['stop'] = <<<EOD
+/usr/local/sbin/squid -k shutdown
+# Just to be sure...
+sleep 5
+killall -9 squid 2>/dev/null
+killall pinger 2>/dev/null
+
+EOD;
+ $rc['restart'] = <<<EOD
+if [ -z "`ps auxw | grep "[s]quid -D"|awk '{print $2}'`" ];then
+ /usr/local/sbin/squid -D
+ else
+ /usr/local/sbin/squid -k reconfigure
+ fi
+
+EOD;
+ update_status("Writing rc files... One moment please...");
+ write_rcfile($rc);
+
+ exec("chmod a+rx /usr/local/libexec/squid/dnsserver");
+
+ foreach (array( SQUID_CONFBASE,
+ SQUID_ACLDIR,
+ ) as $dir) {
+ make_dirs($dir);
+ squid_chown_recursive($dir, 'proxy', 'proxy');
+ }
+
+ /* kill any running proxy alarm scripts */
+ update_status("Checking for running processes... One moment please...");
+ log_error("Stopping any running proxy monitors");
+ mwexec("ps awux | grep \"proxy_monitor\" | grep -v \"grep\" | grep -v \"php\" | awk '{ print $2 }' | xargs kill");
+ sleep(1);
+
+ if (!file_exists(SQUID_CONFBASE . '/mime.conf') && file_exists(SQUID_CONFBASE . '/mime.conf.default'))
+ copy(SQUID_CONFBASE . '/mime.conf.default', SQUID_CONFBASE . '/mime.conf');
+
+ update_status("Checking cache... One moment please...");
+ squid_dash_z();
+
+ if (!is_service_running('squid')) {
+ update_status("Starting... One moment please...");
+ log_error("Starting Squid");
+ mwexec_bg("/usr/local/sbin/squid -D");
+ } else {
+ update_status("Reloading Squid for configuration sync... One moment please...");
+ log_error("Reloading Squid for configuration sync");
+ mwexec("/usr/local/sbin/squid -k reconfigure");
+ }
+
+ /* restart proxy alarm scripts */
+ log_error("Starting a proxy monitor script");
+ mwexec_bg("/usr/local/etc/rc.d/proxy_monitor.sh");
+
+ update_status("Reconfiguring filter... One moment please...");
+ filter_configure();
+}
+
+function squid_deinstall_command() {
+ global $config;
+ squid_install_cron(false);
+ $settings = $config['installedpackages']['squidcache']['config'][0];
+ $cachedir =($settings['harddisk_cache_location'] ? $settings['harddisk_cache_location'] : '/var/squid/cache');
+ $logdir = ($settings['log_dir'] ? $settings['log_dir'] : '/var/squid/log');
+ mwexec('rm -rf $cachedir');
+ mwexec('rm -rf $logdir');
+ mwexec('rm -f /usr/local/etc/rc.d/proxy_monitor.sh');
+ mwexec("ps awux | grep \"proxy_monitor\" | grep -v \"grep\" | grep -v \"php\" | awk '{ print $2 }' | xargs kill");
+ mwexec("ps awux | grep \"squid\" | grep -v \"grep\" | awk '{ print $2 }' | xargs kill");
+ mwexec("ps awux | grep \"dnsserver\" | grep -v \"grep\" | awk '{ print $2 }' | xargs kill");
+ mwexec("ps awux | grep \"unlinkd\" | grep -v \"grep\" | awk '{ print $2 }' | xargs kill");
+ filter_configure();
+}
+
+function squid_before_form_general($pkg) {
+ $values = get_dir(SQUID_CONFBASE . '/errors/');
+ // Get rid of '..' and '.'
+ array_shift($values);
+ array_shift($values);
+ $name = array();
+ foreach ($values as $value)
+ $names[] = implode(" ", explode("_", $value));
+
+ $i = 0;
+ foreach ($pkg['fields']['field'] as $field) {
+ if ($field['fieldname'] == 'error_language')
+ break;
+ $i++;
+ }
+ $field = &$pkg['fields']['field'][$i];
+
+ for ($i = 0; $i < count($values) - 1; $i++)
+ $field['options']['option'][] = array('name' => $names[$i], 'value' => $values[$i]);
+}
+
+function squid_validate_general($post, $input_errors) {
+ global $config;
+ $icp_port = trim($post['icp_port']);
+ if (!empty($icp_port) && !is_port($icp_port))
+ $input_errors[] = 'You must enter a valid port number in the \'ICP port\' field';
+
+ if (substr($post['log_dir'], -1, 1) == '/')
+ $input_errors[] = 'You may not end log location with an / mark';
+
+ if ($post['log_dir']{0} != '/')
+ $input_errors[] = 'You must start log location with a / mark';
+ if (strlen($post['log_dir']) <= 3)
+ $input_errors[] = "That is not a valid log location dir";
+
+ $log_rotate = trim($post['log_rotate']);
+ if (!empty($log_rotate) && (!is_numeric($log_rotate) or ($log_rotate < 1)))
+ $input_errors[] = 'You must enter a valid number of days \'Log rotate\' field';
+
+ $webgui_port = $config['system']['webgui']['port'];
+ if(($config['system']['webgui']['port'] == "") && ($config['system']['webgui']['protocol'] == "http")) {
+ $webgui_port = 80;
+ }
+ if(($config['system']['webgui']['port'] == "") && ($config['system']['webgui']['protocol'] == "https")) {
+ $webgui_port = 443;
+ }
+
+ if (($post['transparent_proxy'] != 'on') && ($port == $webgui_port)) {
+ $input_errors[] = "You can not run squid on the same port as the webgui";
+ }
+
+ if (($post['transparent_proxy'] != 'on') && ($post['private_subnet_proxy_off'] == 'on')) {
+ $input_errors[] = "You can not bypass traffic to private subnets without using the transparent proxy.";
+ }
+
+ if (($post['transparent_proxy'] != 'on') && !empty($post['defined_ip_proxy_off'])) {
+ $input_errors[] = "You can not bypass traffic from specific IPs without using the transparent proxy.";
+ }
+
+ foreach (array('defined_ip_proxy_off') as $hosts) {
+ foreach (explode(";", $post[$hosts]) as $host) {
+ $host = trim($host);
+ if (!empty($host) && !is_ipaddr($host))
+ $input_errors[] = "The entry '$host' is not a valid IP address";
+ }
+ }
+
+ if(!empty($post['dns_nameservers'])) {
+ $altdns = explode(";", ($post['dns_nameservers']));
+ foreach ($altdns as $dnssrv) {
+ if (!is_ipaddr($dnssrv))
+ $input_errors[] = 'You must enter a valid IP address in the \'Alternate DNS servers\' field';
+ }}
+}
+
+function squid_validate_upstream($post, $input_errors) {
+ if ($post['proxy_forwarding'] == 'on') {
+ $addr = trim($post['proxy_addr']);
+ if (empty($addr))
+ $input_errors[] = 'The field \'Hostname\' is required';
+ else {
+ if (!is_ipaddr($addr) && !is_domain($addr))
+ $input_errors[] = 'You must enter a valid IP address or host name in the \'Proxy hostname\' field';
+ }
+
+ foreach (array('proxy_port' => 'TCP port', 'icp_port' => 'ICP port') as $field => $name) {
+ $port = trim($post[$field]);
+ if (empty($port))
+ $input_errors[] = "The field '$name' is required";
+ else {
+ if (!is_port($port))
+ $input_errors[] = "The field '$name' must contain a valid port number, between 0 and 65535";
+ }
+ }
+ }
+}
+
+function squid_validate_cache($post, $input_errors) {
+ $num_fields = array( 'harddisk_cache_size' => 'Hard disk cache size',
+ 'memory_cache_size' => 'Memory cache size',
+ 'maximum_object_size' => 'Maximum object size',
+ );
+ foreach ($num_fields as $field => $name) {
+ $value = trim($post[$field]);
+ if (!is_numeric($value) || ($value < 0))
+ $input_errors[] = "You must enter a valid value for '$field'";
+ }
+
+ $value = trim($post['minimum_object_size']);
+ if (!is_numeric($value) || ($value < 0))
+ $input_errors[] = 'You must enter a valid value for \'Minimum object size\'';
+
+ if (!empty($post['cache_swap_low'])) {
+ $value = trim($post['cache_swap_low']);
+ if (!is_numeric($value) || ($value > 100))
+ $input_errors[] = 'You must enter a valid value for \'Low-water-mark\'';
+ }
+
+ if (!empty($post['cache_swap_high'])) {
+ $value = trim($post['cache_swap_high']);
+ if (!is_numeric($value) || ($value > 100))
+ $input_errors[] = 'You must enter a valid value for \'High-water-mark\'';
+ }
+
+ if ($post['donotcache'] != "") {
+ foreach (split("\n", $post['donotcache']) as $host) {
+ $host = trim($host);
+ if (!is_ipaddr($host) && !is_domain($host))
+ $input_errors[] = "The host '$host' is not a valid IP or host name";
+ }
+ }
+
+ squid_dash_z();
+
+}
+
+function squid_validate_nac($post, $input_errors) {
+ $allowed_subnets = explode("\n", $post['allowed_subnets']);
+ foreach ($allowed_subnets as $subnet) {
+ $subnet = trim($subnet);
+ if (!empty($subnet) && !is_subnet($subnet))
+ $input_errors[] = "The subnet '$subnet' is not a valid CIDR range";
+ }
+
+ foreach (array( 'unrestricted_hosts', 'banned_hosts') as $hosts) {
+ foreach (explode("\n", $post[$hosts]) as $host) {
+ $host = trim($host);
+ if (!empty($host) && !is_ipaddr($host))
+ $input_errors[] = "The host '$host' is not a valid IP address";
+ }
+ }
+
+ foreach (array('unrestricted_macs', 'banned_macs') as $macs) {
+ foreach (explode("\n", $post[$macs]) as $mac) {
+ $mac = trim($mac);
+ if (!empty($mac) && !is_macaddr($mac))
+ $input_errors[] = "The mac '$mac' is not a valid MAC address";
+ }
+ }
+
+ foreach (explode(",", $post['timelist']) as $time) {
+ $time = trim($time);
+ if (!empty($time) && !squid_is_timerange($time))
+ $input_errors[] = "The time range '$time' is not a valid time range";
+ }
+
+ if(!empty($post['ext_cachemanager'])) {
+ $extmgr = explode(";", ($post['ext_cachemanager']));
+ foreach ($extmgr as $mgr) {
+ if (!is_ipaddr($mgr))
+ $input_errors[] = 'You must enter a valid IP address in the \'External Cache Manager\' field';
+ }}
+}
+
+function squid_validate_traffic($post, $input_errors) {
+ $num_fields = array( 'max_download_size' => 'Maximum download size',
+ 'max_upload_size' => 'Maximum upload size',
+ 'perhost_throttling' => 'Per-host bandwidth throttling',
+ 'overall_throttling' => 'Overall bandwidth throttling',
+ );
+ foreach ($num_fields as $field => $name) {
+ $value = trim($post[$field]);
+ if (!is_numeric($value) || ($value < 0))
+ $input_errors[] = "The field '$name' must contain a positive number";
+ }
+
+ if (!empty($post['quick_abort_min'])) {
+ $value = trim($post['quick_abort_min']);
+ if (!is_numeric($value))
+ $input_errors[] = "The field 'Finish when remaining KB' must contain a positive number";
+ }
+
+ if (!empty($post['quick_abort_max'])) {
+ $value = trim($post['quick_abort_max']);
+ if (!is_numeric($value))
+ $input_errors[] = "The field 'Abort when remaining KB' must contain a positive number";
+ }
+
+ if (!empty($post['quick_abort_pct'])) {
+ $value = trim($post['quick_abort_pct']);
+ if (!is_numeric($value) || ($value > 100))
+ $input_errors[] = "The field 'Finish when remaining %' must contain a percentaged value";
+ }
+
+}
+
+function squid_validate_auth($post, $input_errors) {
+ $num_fields = array( array('auth_processes', 'Authentication processes', 1),
+ array('auth_ttl', 'Authentication TTL', 0),
+ );
+ foreach ($num_fields as $field) {
+ $value = trim($post[$field[0]]);
+ if (!empty($value) && (!is_numeric($value) || ($value < $field[2])))
+ $input_errors[] = "The field '{$field[1]}' must contain a valid number greater than {$field[2]}";
+ }
+
+ $auth_method = $post['auth_method'];
+ if (($auth_method != 'none') && ($auth_method != 'local')) {
+ $server = trim($post['auth_server']);
+ if (empty($server))
+ $input_errors[] = 'The field \'Authentication server\' is required';
+ else if (!is_ipaddr($server) && !is_domain($server))
+ $input_errors[] = 'The field \'Authentication server\' must contain a valid IP address or domain name';
+
+ $port = trim($post['auth_server_port']);
+ if (!empty($port) && !is_port($port))
+ $input_errors[] = 'The field \'Authentication server port\' must contain a valid port number';
+
+ switch ($auth_method) {
+ case 'ldap':
+ $user = trim($post['ldap_user']);
+ if (empty($user))
+ $input_errors[] = 'The field \'LDAP server user DN\' is required';
+ else if (!$user)
+ $input_errors[] = 'The field \'LDAP server user DN\' must be a valid domain name';
+ break;
+ case 'radius':
+ $secret = trim($post['radius_secret']);
+ if (empty($secret))
+ $input_errors[] = 'The field \'RADIUS secret\' is required';
+ break;
+ case 'msnt':
+ foreach (explode(",", trim($post['msnt_secondary'])) as $server) {
+ if (!empty($server) && !is_ipaddr($server) && !is_domain($server))
+ $input_errors[] = "The host '$server' is not a valid IP address or domain name";
+ }
+ break;
+ }
+
+ $no_auth = explode("\n", $post['no_auth_hosts']);
+ foreach ($no_auth as $host) {
+ $host = trim($host);
+ if (!empty($host) && !is_subnet($host))
+ $input_errors[] = "The host '$host' is not a valid CIDR range";
+ }
+ }
+}
+
+function squid_install_cron($should_install) {
+ global $config, $g;
+ if($g['booting']==true)
+ return;
+ $is_installed = false;
+ if(!$config['cron']['item'])
+ return;
+ $x=0;
+ foreach($config['cron']['item'] as $item) {
+ if(strstr($item['command'], "/usr/local/sbin/squid")) {
+ $is_installed = true;
+ break;
+ }
+ $x++;
+ }
+ switch($should_install) {
+ case true:
+ if(!$is_installed) {
+ $cron_item = array();
+ $cron_item['minute'] = "0";
+ $cron_item['hour'] = "0";
+ $cron_item['mday'] = "*";
+ $cron_item['month'] = "*";
+ $cron_item['wday'] = "*";
+ $cron_item['who'] = "root";
+ $cron_item['command'] = "/usr/local/sbin/squid -k rotate";
+ $config['cron']['item'][] = $cron_item;
+ parse_config(true);
+ write_config("Squid Log Rotation");
+ configure_cron();
+ }
+ break;
+ case false:
+ if($is_installed == true) {
+ if($x > 0) {
+ unset($config['cron']['item'][$x]);
+ parse_config(true);
+ write_config();
+ }
+ configure_cron();
+ }
+ break;
+ }
+}
+
+function squid_resync_general() {
+ global $g, $config, $valid_acls;
+
+ $settings = $config['installedpackages']['squid']['config'][0];
+ $conf = "# This file is automatically generated by pfSense\n";
+ $conf = "# Do not edit manually !\n";
+
+ $port = ($settings['proxy_port'] ? $settings['proxy_port'] : 3128);
+ $ifaces = ($settings['active_interface'] ? $settings['active_interface'] : 'lan');
+ $real_ifaces = array();
+ foreach (explode(",", $ifaces) as $i => $iface) {
+ $real_ifaces[] = squid_get_real_interface_address($iface);
+ if($real_ifaces[$i][0]) {
+ $conf .= "http_port {$real_ifaces[$i][0]}:$port\n";
+ }
+ }
+ if (($settings['transparent_proxy'] == 'on')) {
+ $conf .= "http_port 127.0.0.1:80 transparent\n";
+ }
+ $icp_port = ($settings['icp_port'] ? $settings['icp_port'] : 0);
+
+ $pidfile = "{$g['varrun_path']}/squid.pid";
+ $language = ($settings['error_language'] ? $settings['error_language'] : 'English');
+ $errordir = SQUID_CONFBASE . '/errors/' . $language;
+ $icondir = SQUID_CONFBASE . '/icons';
+ $hostname = ($settings['visible_hostname'] ? $settings['visible_hostname'] : 'localhost');
+ $email = ($settings['admin_email'] ? $settings['admin_email'] : 'admin@localhost');
+
+ $logdir = ($settings['log_dir'] ? $settings['log_dir'] : '/var/squid/log');
+
+ $logdir_cache = $logdir . '/cache.log';
+ $logdir_access = ($settings['log_enabled'] == 'on' ? $logdir . '/access.log' : '/dev/null');
+
+ $conf .= <<<EOD
+icp_port $icp_port
+
+pid_filename $pidfile
+cache_effective_user proxy
+cache_effective_group proxy
+error_directory $errordir
+icon_directory $icondir
+visible_hostname $hostname
+cache_mgr $email
+access_log $logdir_access
+cache_log $logdir_cache
+cache_store_log none
+
+EOD;
+
+ if (!empty($settings['log_rotate'])) {
+ $conf .= "logfile_rotate {$settings['log_rotate']}\n";
+ squid_install_cron(true);
+ }
+ else {
+ squid_install_cron(false);
+ }
+
+ $conf .= <<<EOD
+shutdown_lifetime 3 seconds
+
+EOD;
+
+ if ($settings['allow_interface'] == 'on') {
+ $src = '';
+ foreach ($real_ifaces as $iface) {
+ list($ip, $mask) = $iface;
+ $ip = long2ip(ip2long($ip) & ip2long($mask));
+ $src .= " $ip/$mask";
+ }
+ $conf .= "# Allow local network(s) on interface(s)\n";
+ $conf .= "acl localnet src $src\n";
+ $valid_acls[] = 'localnet';
+ }
+ if ($settings['disable_xforward']) $conf .= "forwarded_for off\n";
+ if ($settings['disable_via']) $conf .= "via off\n";
+ if ($settings['disable_squidversion']) $conf .= "httpd_suppress_version_string on\n";
+ if (!empty($settings['uri_whitespace'])) $conf .= "uri_whitespace {$settings['uri_whitespace']}\n";
+ else $conf .= "uri_whitespace strip\n"; //only used for first run
+
+ if(!empty($settings['dns_nameservers'])) {
+ $altdns = explode(";", ($settings['dns_nameservers']));
+ $conf .= "dns_nameservers ";
+ foreach ($altdns as $dnssrv) {
+ $conf .= $dnssrv." ";
+ }
+// $conf .= "\n"; //Kill blank line after DNS-Servers
+ }
+
+ return $conf;
+}
+
+
+function squid_resync_cache() {
+ global $config;
+
+ $settings = $config['installedpackages']['squidcache']['config'][0];
+
+ $cachedir =($settings['harddisk_cache_location'] ? $settings['harddisk_cache_location'] : '/var/squid/cache');
+ $disk_cache_size = ($settings['harddisk_cache_size'] ? $settings['harddisk_cache_size'] : 100);
+ $disk_cache_system = ($settings['harddisk_cache_system'] ? $settings['harddisk_cache_system'] : 'aufs');
+ $level1 = ($settings['level1_subdirs'] ? $settings['level1_subdirs'] : 16);
+ $memory_cache_size = ($settings['memory_cache_size'] ? $settings['memory_cache_size'] : 8);
+ $max_objsize = ($settings['maximum_object_size'] ? $settings['maximum_object_size'] : 10);
+ $min_objsize = ($settings['minimum_object_size'] ? $settings['minimum_object_size'] : 0);
+ $cache_policy = ($settings['cache_replacement_policy'] ? $settings['cache_replacement_policy'] : 'heap LFUDA');
+ $memory_policy = ($settings['memory_replacement_policy'] ? $settings['memory_replacement_policy'] : 'heap GDSF');
+ $offline_mode = ($settings['enable_offline'] == 'on' ? 'on' : 'off');
+
+ $conf = <<<EOD
+cache_dir $disk_cache_system $cachedir $disk_cache_size $level1 256
+cache_mem $memory_cache_size MB
+maximum_object_size $max_objsize KB
+minimum_object_size $min_objsize KB
+cache_replacement_policy $cache_policy
+memory_replacement_policy $memory_policy
+offline_mode $offline_mode
+
+EOD;
+
+ if (!empty($settings['cache_swap_low'])) $conf .= "cache_swap_low {$settings['cache_swap_low']}\n";
+ if (!empty($settings['cache_swap_high'])) $conf .= "cache_swap_high {$settings['cache_swap_high']}\n";
+
+ $donotcache = base64_decode($settings['donotcache']);
+ if (!empty($donotcache)) {
+ file_put_contents(SQUID_ACLDIR . '/donotcache.acl', $donotcache);
+ $conf .= 'acl donotcache dstdomain "' . SQUID_ACLDIR . "/donotcache.acl\"\n";
+ $conf .= 'cache deny donotcache';
+ }
+ elseif (file_exists(SQUID_ACLDIR . '/donotcache.acl')) {
+ unlink(SQUID_ACLDIR . '/donotcache.acl');
+ }
+
+ return $conf;
+}
+
+function squid_resync_upstream() {
+ global $config;
+ $settings = $config['installedpackages']['squidupstream']['config'][0];
+
+ $conf = '';
+ if ($settings['proxy_forwarding'] == 'on') {
+ $conf .= "cache_peer {$settings['proxy_addr']} parent {$settings['proxy_port']} {$settings['icp_port']} ";
+
+ if (!empty($settings['username']))
+ $conf .= " login={$settings['username']}";
+ if (!empty($settings['password']))
+ $conf .= ":{$settings['password']}";
+ }
+
+ return $conf;
+}
+
+function squid_resync_redirector() {
+ global $config;
+
+ $httpav_enabled = ($config['installedpackages']['clamav']['config'][0]['scan_http'] == 'on');
+ if ($httpav_enabled) {
+ $conf = "url_rewrite_program /usr/local/bin/squirm\n";
+ } else {
+ $conf = "# No redirector configured\n";
+ }
+ return $conf;
+}
+
+function squid_resync_nac() {
+ global $config, $valid_acls;
+
+ $port = ($settings['proxy_port'] ? $settings['proxy_port'] : 3128);
+ $settings = $config['installedpackages']['squidnac']['config'][0];
+ $webgui_port = $config['system']['webgui']['port'];
+
+ $conf = <<<EOD
+
+# Setup some default acls
+acl all src 0.0.0.0/0.0.0.0
+acl localhost src 127.0.0.1/255.255.255.255
+acl safeports port 21 70 80 210 280 443 488 563 591 631 777 901 $webgui_port $port 1025-65535
+acl sslports port 443 563 $webgui_port
+acl manager proto cache_object
+acl purge method PURGE
+acl connect method CONNECT
+acl dynamic urlpath_regex cgi-bin \?
+
+EOD;
+
+ $allowed_subnets = explode("\n", base64_decode($settings['allowed_subnets']));
+ $allowed = "";
+ foreach ($allowed_subnets as $subnet) {
+ if(!empty($subnet)) {
+ $subnet = trim($subnet);
+ $allowed .= "$subnet ";
+ }
+ }
+ if (!empty($allowed)) {
+ $conf .= "acl allowed_subnets src $allowed\n";
+ $valid_acls[] = 'allowed_subnets';
+ }
+
+ $options = array( 'unrestricted_hosts' => 'src',
+ 'banned_hosts' => 'src',
+ 'whitelist' => 'dstdom_regex -i',
+ 'blacklist' => 'dstdom_regex -i',
+ );
+ foreach ($options as $option => $directive) {
+ $contents = base64_decode($settings[$option]);
+ if (!empty($contents)) {
+ file_put_contents(SQUID_ACLDIR . "/$option.acl", $contents);
+ $conf .= "acl $option $directive \"" . SQUID_ACLDIR . "/$option.acl\"\n";
+ $valid_acls[] = $option;
+ }
+ elseif (file_exists(SQUID_ACLDIR . "/$option.acl")) {
+ unlink(SQUID_ACLDIR . "/$option.acl");
+ }
+ }
+
+ $conf .= <<<EOD
+cache deny dynamic
+http_access allow manager localhost
+
+EOD;
+
+ if(!empty($settings['ext_cachemanager'])) {
+ $extmgr = explode(";", ($settings['ext_cachemanager']));
+ $count = 1;
+ $conf .= "\n# Allow external cache managers\n";
+// $conf .= "acl ext_manager src ".$settings['ext_cachemanager']."\n";
+ foreach ($extmgr as $mgr) {
+ $conf .= "acl ext_manager_".$count." src ";
+ $conf .= $mgr." ";
+ $conf .= "\n";
+ $conf .= "http_access allow manager ext_manager_".$count."\n";
+ $count += 1;
+ }}
+
+ $conf .= <<<EOD
+
+http_access deny manager
+http_access allow purge localhost
+http_access deny purge
+http_access deny !safeports
+http_access deny CONNECT !sslports
+
+# Always allow localhost connections
+http_access allow localhost
+
+EOD;
+
+ return $conf;
+}
+
+function squid_resync_traffic() {
+ global $config, $valid_acls;
+ if(!is_array($valid_acls))
+ return;
+ $settings = $config['installedpackages']['squidtraffic']['config'][0];
+ $conf = '';
+
+ if (!empty($settings['quick_abort_min']) || ($settings['quick_abort_min']) == "0") $conf .= "quick_abort_min {$settings['quick_abort_min']} KB\n";
+ if (!empty($settings['quick_abort_max']) || ($settings['quick_abort_max']) == "0") $conf .= "quick_abort_max {$settings['quick_abort_max']} KB\n";
+ if (!empty($settings['quick_abort_pct'])) $conf .= "quick_abort_pct {$settings['quick_abort_pct']}\n";
+
+ $up_limit = ($settings['max_upload_size'] ? $settings['max_upload_size'] : 0);
+ $down_limit = ($settings['max_download_size'] ? $settings['max_download_size'] : 0);
+ $conf .= "request_body_max_size $up_limit KB\n";
+ $conf .= 'reply_body_max_size ' . ($down_limit * 1024) . " allow all\n";
+
+ // Only apply throttling past 10MB
+ // XXX: Should this really be hardcoded?
+ $threshold = 10 * 1024 * 1024;
+ $overall = $settings['overall_throttling'];
+ if (!isset($overall) || ($overall == 0))
+ $overall = -1;
+ else
+ $overall *= 1024;
+ $perhost = $settings['perhost_throttling'];
+ if (!isset($perhost) || ($perhost == 0))
+ $perhost = -1;
+ else
+ $perhost *= 1024;
+ $conf .= <<<EOD
+delay_pools 1
+delay_class 1 2
+delay_parameters 1 $overall/$overall $perhost/$perhost
+delay_initial_bucket_level 100
+
+EOD;
+
+ if(! empty($settings['unrestricted_hosts'])) {
+ foreach (array('unrestricted_hosts') as $item) {
+ if (in_array($item, $valid_acls))
+ $conf .= "# Do not throttle unrestricted hosts\n";
+ $conf .= "delay_access 1 deny $item\n";
+ }
+ }
+
+ if ($settings['throttle_specific'] == 'on') {
+ $exts = array();
+ $binaries = 'bin,cab,sea,ar,arj,tar,tgz,gz,tbz,bz2,zip,7z,exe,com';
+ $cdimages = 'iso,bin,mds,nrg,gho,bwt,b5t,pqi';
+ $multimedia = 'aiff?,asf,avi,divx,mov,mp3,mp4,wmv,mpe?g,qt,ra?m';
+ foreach (array( 'throttle_binaries' => $binaries,
+ 'throttle_cdimages' => $cdimages,
+ 'throttle_multimedia' => $multimedia) as $field => $set) {
+ if ($settings[$field] == 'on')
+ $exts = array_merge($exts, explode(",", $set));
+ }
+
+ foreach (explode(",", $settings['throttle_others']) as $ext) {
+ if (!empty($ext)) $exts[] = $ext;
+ }
+
+ $contents = '';
+ foreach ($exts as $ext)
+ $contents .= "\.$ext\$\n";
+ file_put_contents(SQUID_ACLDIR . '/throttle_exts.acl', $contents);
+
+ $conf .= "# Throttle extensions matched in the url\n";
+ $conf .= "acl throttle_exts urlpath_regex -i \"" . SQUID_ACLDIR . "/throttle_exts.acl\"\n";
+ $conf .= "delay_access 1 allow throttle_exts\n";
+ $conf .= "delay_access 1 deny all\n";
+ }
+ else
+ $conf .= "delay_access 1 allow all\n";
+
+ return $conf;
+}
+
+function squid_resync_auth() {
+ global $config, $valid_acls;
+
+ $settings = $config['installedpackages']['squidauth']['config'][0];
+ $settingsnac = $config['installedpackages']['squidnac']['config'][0];
+ $settingsconfig = $config['installedpackages']['squid']['config'][0];
+ $conf = '';
+
+ // Deny the banned guys before allowing the good guys
+ if(! empty($settingsnac['banned_hosts'])) {
+ if (squid_is_valid_acl('banned_hosts')) {
+ $conf .= "# These hosts are banned\n";
+ $conf .= "http_access deny banned_hosts\n";
+ }
+ }
+ if(! empty($settingsnac['banned_macs'])) {
+ if (squid_is_valid_acl('banned_macs')) {
+ $conf .= "# These macs are banned\n";
+ $conf .= "http_access deny banned_macs\n";
+ }
+ }
+
+ // Unrestricted hosts take precendence over blacklist
+ if(! empty($settingsnac['unrestricted_hosts'])) {
+ if (squid_is_valid_acl('unrestricted_hosts')) {
+ $conf .= "# These hosts do not have any restrictions\n";
+ $conf .= "http_access allow unrestricted_hosts\n";
+ }
+ }
+ if(! empty($settingsnac['unrestricted_macs'])) {
+ if (squid_is_valid_acl('unrestricted_macs')) {
+ $conf .= "# These hosts do not have any restrictions\n";
+ $conf .= "http_access allow unrestricted_macs\n";
+ }
+ }
+
+ // Whitelist and blacklist also take precendence over other allow rules
+ if(! empty($settingsnac['whitelist'])) {
+ if (squid_is_valid_acl('whitelist')) {
+ $conf .= "# Always allow access to whitelist domains\n";
+ $conf .= "http_access allow whitelist\n";
+ }
+ }
+ if(! empty($settingsnac['blacklist'])) {
+ if (squid_is_valid_acl('blacklist')) {
+ $conf .= "# Block access to blacklist domains\n";
+ $conf .= "http_access deny blacklist\n";
+ }
+ }
+
+ $transparent_proxy = ($settingsconfig['transparent_proxy'] == 'on');
+ $auth_method = (($settings['auth_method'] && !$transparent_proxy) ? $settings['auth_method'] : 'none');
+ // Allow the remaining ACLs if no authentication is set
+ if ($auth_method == 'none') {
+ if ($settingsconfig['allow_interface'] == 'on') {
+ $conf .= "# Allow local network(s) on interface(s)\n";
+ $allowed = array('localnet', 'allowed_subnets');
+ $allowed = array_filter($allowed, 'squid_is_valid_acl');
+ foreach ($allowed as $acl)
+ $conf .= "http_access allow $acl\n";
+ }
+ }
+ else {
+ $noauth = implode(' ', explode("\n", base64_decode($settings['no_auth_hosts'])));
+ if (!empty($noauth)) {
+ $conf .= "acl noauth src $noauth\n";
+ $valid_acls[] = 'noauth';
+ }
+
+ // Set up the external authentication programs
+ $auth_ttl = ($settings['auth_ttl'] ? $settings['auth_ttl'] : 60);
+ $processes = ($settings['auth_processes'] ? $settings['auth_processes'] : 5);
+ $prompt = ($settings['auth_prompt'] ? $settings['auth_prompt'] : 'Please enter your credentials to access the proxy');
+ switch ($auth_method) {
+ case 'local':
+ $conf .= 'auth_param basic program /usr/local/libexec/squid/ncsa_auth ' . SQUID_PASSWD . "\n";
+ break;
+ case 'ldap':
+ $port = (isset($settings['auth_port']) ? ":{$settings['auth_port']}" : '');
+ $password = (isset($settings['ldap_pass']) ? "-w {$settings['ldap_pass']}" : '');
+ $conf .= "auth_param basic program /usr/local/libexec/squid/squid_ldap_auth -v {$settings['ldap_version']} -b {$settings['ldap_basedomain']} -D {$settings['ldap_user']} $password -f \"{$settings['ldap_filter']}\" -u uid -P {$settings['auth_server']}$port\n";
+ break;
+ case 'radius':
+ $port = (isset($settings['auth_port']) ? "-p {$settings['auth_server_port']}" : '');
+ $conf .= "auth_param basic program /usr/local/libexec/squid/squid_radius_auth -w {$settings['radius_secret']} -h {$settings['auth_server']} $port\n";
+ break;
+ case 'msnt':
+ $conf .= "auth_param basic program /usr/local/libexec/squid/msnt_auth\n";
+ break;
+ }
+ $conf .= <<<EOD
+auth_param basic children $processes
+auth_param basic realm $prompt
+auth_param basic credentialsttl $auth_ttl minutes
+acl password proxy_auth REQUIRED
+
+EOD;
+
+ // Onto the ACLs
+ $password = array('localnet', 'allowed_subnets');
+ $passwordless = array('unrestricted_hosts');
+ if ($settings['unrestricted_auth'] == 'on') {
+ // Even the unrestricted hosts should authenticate
+ $password = array_merge($password, $passwordless);
+ $passwordless = array();
+ }
+ $passwordless[] = 'noauth';
+ $password = array_filter($password, 'squid_is_valid_acl');
+ $passwordless = array_filter($passwordless, 'squid_is_valid_acl');
+
+ // Allow the ACLs that don't need to authenticate
+ foreach ($passwordless as $acl)
+ $conf .= "http_access allow $acl\n";
+
+ // Allow the other ACLs as long as they authenticate
+ foreach ($password as $acl)
+ $conf .= "http_access allow password $acl\n";
+ }
+
+ if(!empty($config['installedpackages']['squid']['config'][0]['custom_options'])) {
+ $custopts = explode(";", ($config['installedpackages']['squid']['config'][0]['custom_options']));
+ $conf .= "# Custom options\n";
+ foreach ($custopts as $custopt) {
+ $conf .= $custopt."\n";
+ }
+ }
+
+ $conf .= "# Default block all to be sure\n";
+ $conf .= "http_access deny all\n";
+
+ return $conf;
+}
+
+function squid_resync_users() {
+ global $config;
+
+ $users = $config['installedpackages']['squidusers']['config'];
+ $contents = '';
+ if (is_array($users)) {
+ foreach ($users as $user)
+ $contents .= $user['username'] . ':' . crypt($user['password'], base64_encode($user['password'])) . "\n";
+ }
+ file_put_contents(SQUID_PASSWD, $contents);
+ chown(SQUID_PASSWD, 'proxy');
+ chmod(SQUID_PASSWD, 0600);
+}
+
+function squid_resync() {
+ global $config;
+ $conf = squid_resync_general() . "\n";
+ $conf .= squid_resync_cache() . "\n";
+ $conf .= squid_resync_redirector() . "\n";
+ $conf .= squid_resync_upstream() . "\n";
+ $conf .= squid_resync_nac() . "\n";
+ $conf .= squid_resync_traffic() . "\n";
+ $conf .= squid_resync_auth();
+ squid_resync_users();
+
+ /* make sure pinger is executable */
+ if(file_exists("/usr/local/libexec/squid/pinger"))
+ exec("chmod a+x /usr/local/libexec/squid/pinger");
+
+ file_put_contents(SQUID_CONFBASE . '/squid.conf', $conf);
+
+ $log_dir = $config['installedpackages']['squid']['config'][0]['log_dir'].'/';
+
+ if(!is_dir($log_dir)) {
+ log_error("Creating squid log dir $log_dir");
+ make_dirs($log_dir);
+ squid_chown_recursive($log_dir, 'proxy', 'proxy');
+ }
+
+ squid_dash_z();
+
+ if (!is_service_running('squid')) {
+ log_error("Starting Squid");
+ mwexec_bg("/usr/local/sbin/squid -D");
+ } else {
+ log_error("Reloading Squid for configuration sync");
+ mwexec("/usr/local/sbin/squid -k reconfigure");
+ }
+
+ filter_configure();
+}
+
+function squid_print_javascript_auth() {
+ global $config;
+ $transparent_proxy = ($config['installedpackages']['squid']['config'][0]['transparent_proxy'] == 'on');
+
+ // No authentication for transparent proxy
+ if ($transparent_proxy) {
+ $javascript = <<<EOD
+<script language="JavaScript">
+<!--
+function on_auth_method_changed() {
+ document.iform.auth_method.disabled = 1;
+ document.iform.auth_server.disabled = 1;
+ document.iform.auth_server_port.disabled = 1;
+ document.iform.ldap_user.disabled = 1;
+ document.iform.ldap_version.disabled = 1;
+ document.iform.ldap_filter.disabled = 1;
+ document.iform.ldap_password.disabled = 1;
+ document.iform.ldap_basedomain.disabled = 1;
+ document.iform.radius_secret.disabled = 1;
+ document.iform.msnt_secondary.disabled = 1;
+ document.iform.auth_prompt.disabled = 1;
+ document.iform.auth_processes.disabled = 1;
+ document.iform.auth_ttl.disabled = 1;
+ document.iform.unrestricted_auth.disabled = 1;
+ document.iform.no_auth_hosts.disabled = 1;
+}
+-->
+</script>
+
+EOD;
+ }
+ else {
+ $javascript = <<<EOD
+<script language="JavaScript">
+<!--
+function on_auth_method_changed() {
+ var field = document.iform.auth_method;
+ var auth_method = field.options[field.selectedIndex].value;
+
+ if (auth_method == 'none') {
+ document.iform.auth_server.disabled = 1;
+ document.iform.auth_server_port.disabled = 1;
+ document.iform.ldap_user.disabled = 1;
+ document.iform.ldap_version.disabled = 1;
+ document.iform.ldap_filter.disabled = 1;
+ document.iform.ldap_password.disabled = 1;
+ document.iform.ldap_basedomain.disabled = 1;
+ document.iform.radius_secret.disabled = 1;
+ document.iform.msnt_secondary.disabled = 1;
+ document.iform.auth_prompt.disabled = 1;
+ document.iform.auth_processes.disabled = 1;
+ document.iform.auth_ttl.disabled = 1;
+ document.iform.unrestricted_auth.disabled = 1;
+ document.iform.no_auth_hosts.disabled = 1;
+ }
+ else {
+ document.iform.auth_prompt.disabled = 0;
+ document.iform.auth_processes.disabled = 0;
+ document.iform.auth_ttl.disabled = 0;
+ document.iform.unrestricted_auth.disabled = 0;
+ document.iform.no_auth_hosts.disabled = 0;
+ }
+
+ switch (auth_method) {
+ case 'local':
+ document.iform.auth_server.disabled = 1;
+ document.iform.auth_server_port.disabled = 1;
+ document.iform.ldap_user.disabled = 1;
+ document.iform.ldap_password.disabled = 1;
+ document.iform.ldap_version.disabled = 1;
+ document.iform.ldap_filter.disabled = 1;
+ document.iform.ldap_basedomain.disabled = 1;
+ document.iform.radius_secret.disabled = 1;
+ document.iform.msnt_secondary.disabled = 1;
+ break;
+ case 'ldap':
+ document.iform.auth_server.disabled = 0;
+ document.iform.auth_server_port.disabled = 0;
+ document.iform.ldap_user.disabled = 0;
+ document.iform.ldap_password.disabled = 0;
+ document.iform.ldap_version.disabled = 0;
+ document.iform.ldap_filter.disabled = 0;
+ document.iform.ldap_basedomain.disabled = 0;
+ document.iform.radius_secret.disabled = 1;
+ document.iform.msnt_secondary.disabled = 1;
+ break;
+ case 'radius':
+ document.iform.auth_server.disabled = 0;
+ document.iform.auth_server_port.disabled = 0;
+ document.iform.ldap_user.disabled = 1;
+ document.iform.ldap_password.disabled = 1;
+ document.iform.ldap_version.disabled = 1;
+ document.iform.ldap_filter.disabled = 1;
+ document.iform.ldap_basedomain.disabled = 1;
+ document.iform.radius_secret.disabled = 0;
+ document.iform.msnt_secondary.disabled = 1;
+ break;
+ case 'msnt':
+ document.iform.auth_server.disabled = 0;
+ document.iform.auth_server_port.disabled = 1;
+ document.iform.ldap_user.disabled = 1;
+ document.iform.ldap_password.disabled = 1;
+ document.iform.ldap_version.disabled = 1;
+ document.iform.ldap_filter.disabled = 1;
+ document.iform.ldap_basedomain.disabled = 1;
+ document.iform.radius_secret.disabled = 1;
+ document.iform.msnt_secondary.disabled = 0;
+ break;
+ }
+}
+-->
+</script>
+
+EOD;
+ }
+
+ print($javascript);
+}
+
+function squid_print_javascript_auth2() {
+ print("<script language=\"JavaScript\">on_auth_method_changed()</script>\n");
+}
+
+function squid_generate_rules($type) {
+ global $config;
+
+ $squid_conf = $config['installedpackages']['squid']['config'][0];
+ if (!is_service_running('squid')) {
+ log_error("SQUID is installed but not started. Not installing redirect rules.");
+ return;
+ }
+
+ if (($squid_conf['transparent_proxy'] != 'on') || ($squid_conf['allow_interface'] != 'on')) {
+ return;
+ }
+
+ $ifaces = explode(",", $squid_conf['active_interface']);
+ $ifaces = array_map('convert_friendly_interface_to_real_interface_name', $ifaces);
+ $port = ($squid_conf['proxy_port'] ? $squid_conf['proxy_port'] : 3128);
+
+ switch($type) {
+ case 'nat':
+ $rules .= "\n# Setup Squid proxy redirect\n";
+ if ($squid_conf['private_subnet_proxy_off'] == 'on') {
+ foreach ($ifaces as $iface){
+ $rules .= "no rdr on $iface proto tcp from any to { 192.168.0.0/16, 172.16.0.0/12, 10.0.0.0/8 } port 80\n";
+ }
+ }
+
+ if (!empty($squid_conf['defined_ip_proxy_off'])) {
+ $defined_ip_proxy_off = explode(";", $squid_conf['defined_ip_proxy_off']);
+ $exempt_ip = "";
+ foreach ($defined_ip_proxy_off as $ip_proxy_off) {
+ if(!empty($ip_proxy_off)) {
+ $ip_proxy_off = trim($ip_proxy_off);
+ $exempt_ip .= ", $ip_proxy_off";
+ }
+ }
+ $exempt_ip = substr($exempt_ip,2);
+ foreach ($ifaces as $iface){
+ $rules .= "no rdr on $iface proto tcp from { $exempt_ip } to any port 80\n";
+ }
+ }
+
+ foreach ($ifaces as $iface){
+ $rules .= "rdr on $iface proto tcp from any to !($iface) port 80 -> 127.0.0.1 port 80\n";
+ };
+ $rules .= "\n";
+ break;
+ case 'filter':
+ foreach ($ifaces as $iface){
+ $rules .= "# Setup squid pass rules for proxy\n";
+ $rules .= "pass in quick on $iface proto tcp from any to !($iface) port 80 flags S/SA keep state\n";
+ $rules .= "pass in quick on $iface proto tcp from any to !($iface) port $port flags S/SA keep state\n";
+ $rules .= "\n";
+ };
+ break;
+ default:
+ break;
+ }
+
+ return $rules;
+}
+?>
diff --git a/config/squid/squid.xml b/config/squid/squid.xml
new file mode 100644
index 00000000..4c8bc4ab
--- /dev/null
+++ b/config/squid/squid.xml
@@ -0,0 +1,333 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>squid</name>
+ <version>2.6.STABLE18</version>
+ <title>Proxy server: General settings</title>
+ <include_file>/usr/local/pkg/squid.inc</include_file>
+ <menu>
+ <name>Proxy server</name>
+ <tooltiptext>Modify the proxy server's settings</tooltiptext>
+ <section>Services</section>
+ <url>/pkg_edit.php?xml=squid.xml&amp;id=0</url>
+ </menu>
+ <service>
+ <name>squid</name>
+ <rcfile>squid.sh</rcfile>
+ <executable>squid</executable>
+ <description>Proxy server Service</description>
+ </service>
+ <tabs>
+ <tab>
+ <text>General settings</text>
+ <url>/pkg_edit.php?xml=squid.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Upstream proxy</text>
+ <url>/pkg_edit.php?xml=squid_upstream.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Cache management</text>
+ <url>/pkg_edit.php?xml=squid_cache.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Access control</text>
+ <url>/pkg_edit.php?xml=squid_nac.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Traffic management</text>
+ <url>/pkg_edit.php?xml=squid_traffic.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Auth settings</text>
+ <url>/pkg_edit.php?xml=squid_auth.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Local users</text>
+ <url>/pkg.php?xml=squid_users.xml</url>
+ </tab>
+ </tabs>
+ <!-- Installation -->
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.org/packages/config/squid/squid.inc</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.org/packages/config/squid/squid_cache.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.org/packages/config/squid/squid_nac.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.org/packages/config/squid/squid_ng.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.org/packages/config/squid/squid_traffic.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.org/packages/config/squid/squid_upstream.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.org/packages/config/squid/squid_auth.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.org/packages/config/squid/squid_users.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/etc/rc.d/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.org/packages/config/squid/proxy_monitor.sh</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.org/packages/config/squid/squid_cache.xml</item>
+ </additional_files_needed>
+ <fields>
+ <field>
+ <fielddescr>Proxy interface</fielddescr>
+ <fieldname>active_interface</fieldname>
+ <description>The interface(s) the proxy server will bind to.</description>
+ <type>interfaces_selection</type>
+ <required/>
+ <default_value>lan</default_value>
+ <multiple/>
+ </field>
+ <field>
+ <fielddescr>Allow users on interface</fielddescr>
+ <fieldname>allow_interface</fieldname>
+ <description>If this field is checked, the users connected to the interface selected in the 'Proxy interface' field will be allowed to use the proxy, i.e., there will be no need to add the interface's subnet to the list of allowed subnets. This is just a shortcut.</description>
+ <type>checkbox</type>
+ <required/>
+ <default_value>on</default_value>
+ </field>
+ <field>
+ <fielddescr>Transparent proxy</fielddescr>
+ <fieldname>transparent_proxy</fieldname>
+ <description>If transparent mode is enabled, all requests for destination port 80 will be forwarded to the proxy server without any additional configuration necessary.</description>
+ <type>checkbox</type>
+ <required/>
+ </field>
+ <field>
+ <fielddescr>Do NOT proxy Private Address Space (RFC 1918)</fielddescr>
+ <fieldname>private_subnet_proxy_off</fieldname>
+ <description>Do not forward traffic to Private Address Space (RFC 1918) &lt;b&gt;destination&lt;/b&gt; through the proxy server.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Do NOT proxy these IPs</fielddescr>
+ <fieldname>defined_ip_proxy_off</fieldname>
+ <description>Do not forward traffic from these &lt;b&gt;source&lt;/b&gt; IPs through the proxy server. Separate by semi-colons (;).</description>
+ <type>input</type>
+ <size>80</size>
+ </field>
+ <field>
+ <fielddescr>Enabled logging</fielddescr>
+ <fieldname>log_enabled</fieldname>
+ <description>This will enable the access log. Don't switch this on if you don't have much disk space left.</description>
+ <type>checkbox</type>
+ <enablefields>log_query_terms,log_user_agents</enablefields>
+ </field>
+ <field>
+ <fielddescr>Log store directory</fielddescr>
+ <fieldname>log_dir</fieldname>
+ <description>The directory where the log will be stored (note: do not end with a / mark)</description>
+ <type>input</type>
+ <size>60</size>
+ <required/>
+ <default_value>/var/squid/log</default_value>
+ </field>
+ <field>
+ <fielddescr>Log rotate</fielddescr>
+ <fieldname>log_rotate</fieldname>
+ <description>Defines how many days of logfiles will be kept. Rotation is disabled if left empty.</description>
+ <type>input</type>
+ <size>5</size>
+ </field>
+ <field>
+ <fielddescr>Proxy port</fielddescr>
+ <fieldname>proxy_port</fieldname>
+ <description>This is the port the proxy server will listen on.</description>
+ <type>input</type>
+ <size>5</size>
+ <required/>
+ <default_value>3128</default_value>
+ </field>
+ <field>
+ <fielddescr>ICP port</fielddescr>
+ <fieldname>icp_port</fieldname>
+ <description>This is the port the Proxy Server will send and receive ICP queries to and from neighbor caches. Leave this blank if you don't want the proxy server to communicate with neighbor caches through ICP.</description>
+ <type>input</type>
+ <size>5</size>
+ </field>
+ <field>
+ <fielddescr>Visible hostname</fielddescr>
+ <fieldname>visible_hostname</fieldname>
+ <description>This is the URL to be displayed in proxy server error messages.</description>
+ <type>input</type>
+ <size>60</size>
+ <default_value>localhost</default_value>
+ </field>
+ <field>
+ <fielddescr>Administrator email</fielddescr>
+ <fieldname>admin_email</fieldname>
+ <description>This is the email address displayed in error messages to the users.</description>
+ <type>input</type>
+ <size>60</size>
+ <default_value>admin@localhost</default_value>
+ </field>
+ <field>
+ <fielddescr>Language</fielddescr>
+ <fieldname>error_language</fieldname>
+ <description>Select the language in which the proxy server will display error messages to users.</description>
+ <type>select</type>
+ <default_value>English</default_value>
+ </field>
+ <field>
+ <fielddescr>Disable X-Forward</fielddescr>
+ <fieldname>disable_xforward</fieldname>
+ <description>If not set, Squid will include your system's IP address or name in the HTTP requests it forwards.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Disable VIA</fielddescr>
+ <fieldname>disable_via</fieldname>
+ <description>If not set, Squid will include a Via header in requests and replies as required by RFC2616.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>What to do with requests that have whitespace characters in the URI</fielddescr>
+ <fieldname>uri_whitespace</fieldname>
+ <description>&lt;b&gt; strip:&lt;/b&gt; The whitespace characters are stripped out of the URL. This is the behavior recommended by RFC2396. &lt;p&gt; &lt;b&gt; deny:&lt;/b&gt; The request is denied. The user receives an "Invalid Request" message.&lt;p&gt; &lt;b&gt; allow:&lt;/b&gt; The request is allowed and the URI is not changed. The whitespace characters remain in the URI.&lt;p&gt; &lt;b&gt; encode:&lt;/b&gt; The request is allowed and the whitespace characters are encoded according to RFC1738.&lt;p&gt; &lt;b&gt; chop:&lt;/b&gt; The request is allowed and the URI is chopped at the first whitespace.</description>
+ <type>select</type>
+ <default_value>strip</default_value>
+ <options>
+ <option>
+ <name>strip</name>
+ <value>strip</value>
+ </option>
+ <option>
+ <name>deny</name>
+ <value>deny</value>
+ </option>
+ <option>
+ <name>allow</name>
+ <value>allow</value>
+ </option>
+ <option>
+ <name>encode</name>
+ <value>encode</value>
+ </option>
+ <option>
+ <name>chop</name>
+ <value>chop</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Use alternate DNS-servers for the proxy-server</fielddescr>
+ <fieldname>dns_nameservers</fieldname>
+ <description>If you want to use other DNS-servers than the DNS-forwarder, enter the IPs here, separated by semi-colons (;).</description>
+ <type>input</type>
+ <size>60</size>
+ </field>
+ <field>
+ <fielddescr>Suppress Squid Version</fielddescr>
+ <fieldname>disable_squidversion</fieldname>
+ <description>If set, suppress Squid version string info in HTTP headers and HTML error pages.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Custom Options</fielddescr>
+ <fieldname>custom_options</fieldname>
+ <description>You can put your own custom options here, separated by semi-colons (;). They'll be added to the configuration. They need to be squid.conf native options, otherwise squid will NOT work.</description>
+ <type>textarea</type>
+ <cols>65</cols>
+ <rows>5</rows>
+ </field>
+ </fields>
+ <custom_php_command_before_form>
+ squid_before_form_general(&amp;$pkg);
+ </custom_php_command_before_form>
+ <custom_add_php_command>
+ squid_resync();
+ </custom_add_php_command>
+ <custom_php_validation_command>
+ squid_validate_general($_POST, &amp;$input_errors);
+ </custom_php_validation_command>
+ <custom_php_resync_config_command>
+ squid_resync();
+ exec("/bin/rm -f /usr/local/etc/rc.d/squid");
+ </custom_php_resync_config_command>
+ <custom_php_install_command>
+ update_status("Checking Squid cache... One moment please...");
+ update_output_window("This operation may take quite some time, please be patient. Do not press stop or attempt to navigate away from this page during this process.");
+ squid_install_command();
+ squid_resync();
+ exec("/bin/rm -f /usr/local/etc/rc.d/squid");
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ squid_deinstall_command();
+ exec("/bin/rm -f /usr/local/etc/rc.d/squid*");
+ </custom_php_deinstall_command>
+</packagegui>
diff --git a/config/squid/squid_auth.inc b/config/squid/squid_auth.inc
new file mode 100644
index 00000000..7c99a01b
--- /dev/null
+++ b/config/squid/squid_auth.inc
@@ -0,0 +1,446 @@
+<?php
+/* $Id$ */
+
+/*
+ squid_auth.inc
+ part of pfSense (www.pfSense.com)
+
+ Copyright (C) 2005 Michael Capp <michael.capp@gmail.com>
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+function global_eval_auth_options()
+{
+ global $config;
+ conf_mount_rw();
+ config_lock();
+
+ switch ($config['installedpackages']['squidauth']['config'][0]['auth_method']) {
+ case "none":
+ dynamic_auth_content("pkg_edit");
+ dynamic_no_auth();
+ break;
+ case "local_auth":
+ dynamic_auth_content("pkg");
+ /* create empty passwd file to prevent stat error with squid reload */
+ touch ("/usr/local/etc/squid/advanced/ncsa/passwd");
+ dynamic_local_auth();
+ break;
+ case "ldap_bind":
+ dynamic_auth_content("pkg_edit");
+ dynamic_ldap_auth();
+ break;
+ case "domain_auth":
+ $filecontents = file("/usr/local/pkg/squid_auth.xml");
+ dynamic_auth_content("pkg_edit");
+ dynamic_domain_auth();
+ break;
+ case "radius_auth":
+ $filecontents = file("/usr/local/pkg/squid_auth.xml");
+ dynamic_auth_content("pkg_edit");
+ dynamic_radius_auth();
+ break;
+ default:
+ $filecontents = file("/usr/local/pkg/squid_auth.xml");
+ dynamic_auth_content("pkg_edit");
+ dynamic_no_auth();
+ break;
+ }
+
+ config_unlock();
+ conf_mount_ro();
+
+} /* end function global_eval_auth_options */
+
+function dynamic_no_auth() {
+ global $config;
+ conf_mount_rw();
+ $fout = fopen("/usr/local/pkg/squid_extauth.xml", "w");
+ fwrite($fout, "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n");
+ fwrite($fout, "<packagegui>\n");
+ fwrite($fout, " <name>squidextnoauth</name>\n");
+ fwrite($fout, " <title>Services: Proxy Server -> Extended Authentication Settings</title>\n");
+ fwrite($fout, " <configpath>installedpackages->package->squidextnoauth->configuration->settings</configpath>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <aftersaveredirect>/pkg_edit.php?xml=squid_extauth.xml&amp;id=0</aftersaveredirect>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tabs>\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>General Settings</text>\n");
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_ng.xml&amp;id=0</url>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>Upstream Proxy</text>\n");
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_upstream.xml&amp;id=0</url>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>Cache Mgmt</text>\n");
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_cache.xml&amp;id=0</url>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>Network Access Control</text>\n");
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_nac.xml&amp;id=0</url>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>Traffic Mgmt</text>\n");
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_traffic.xml&amp;id=0</url>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>Auth Settings</text>\n");
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_auth.xml&amp;id=0</url>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>Extended Auth Settings</text>\n");
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_extauth.xml&amp;id=0</url>\n");
+ fwrite($fout, " <active/>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " </tabs>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <fields>\n");
+ fwrite($fout, " <field>\n");
+ fwrite($fout, " <fielddescr>No Authentication Defined</fielddescr>\n");
+ fwrite($fout, " <fieldname>no_auth</fieldname>\n");
+ fwrite($fout, " </field>\n");
+ fwrite($fout, " </fields>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <custom_add_php_command_late>\n");
+ fwrite($fout, " require_once(\"/usr/local/pkg/squid_ng.inc\");");
+ fwrite($fout, "\n");
+ fwrite($fout, " global_write_squid_config();\n");
+ fwrite($fout, " mwexec(\"/usr/local/sbin/squid -k reconfigure\");\n");
+ fwrite($fout, " </custom_add_php_command_late>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, "</packagegui>\n");
+ fclose($fout);
+
+ /* mount filesystem read-only */
+ conf_mount_ro();
+}
+
+function dynamic_local_auth() {
+ global $config;
+ conf_mount_rw();
+
+ $fout = fopen("/usr/local/pkg/squid_extauth.xml", "w");
+
+ fwrite($fout, "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, "<packagegui>\n");
+ fwrite($fout, " <name>squidextlocalauth</name>\n");
+ fwrite($fout, " <title>Services: Proxy Server -> Extended Auth Settings</title>\n");
+ fwrite($fout, " <version>2.5.10_4</version>\n");
+ fwrite($fout, " <configpath>installedpackages->package->squidextlocalauth->configuration->settings</configpath>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <files></files>\n");
+ fwrite($fout, " <menu></menu>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <aftersaveredirect>/pkg.php?xml=squid_extauth.xml&amp;id=0</aftersaveredirect>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tabs>\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>General Settings</text>\n");
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_ng.xml&amp;id=0</url>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>Upstream Proxy</text>\n");
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_upstream.xml&amp;id=0</url>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>Cache Mgmt</text>\n");
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_cache.xml&amp;id=0</url>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>Network Access Control</text>\n");
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_nac.xml&amp;id=0</url>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>Traffic Mgmt</text>\n");
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_traffic.xml&amp;id=0</url>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>Auth Settings</text>\n");
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_auth.xml&amp;id=0</url>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>Extended Auth Settings</text>\n");
+ fwrite($fout, " <url>/pkg.php?xml=squid_extauth.xml&amp;id=0</url>\n");
+ fwrite($fout, " <active/>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " </tabs>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <adddeleteeditpagefields>\n");
+ fwrite($fout, " <columnitem>\n");
+ fwrite($fout, " <fielddescr>Username</fielddescr>\n");
+ fwrite($fout, " <fieldname>username</fieldname>\n");
+ fwrite($fout, " </columnitem>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <columnitem>\n");
+ fwrite($fout, " <fielddescr>Description</fielddescr>\n");
+ fwrite($fout, " <fieldname>description</fieldname>\n");
+ fwrite($fout, " </columnitem>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <columnitem>\n");
+ fwrite($fout, " <fielddescr>Restriction Group</fielddescr>\n");
+ fwrite($fout, " <fieldname>group</fieldname>\n");
+ fwrite($fout, " </columnitem>\n");
+ fwrite($fout, " </adddeleteeditpagefields>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <fields>\n");
+ fwrite($fout, " <field>\n");
+ fwrite($fout, " <fielddescr>Username</fielddescr>\n");
+ fwrite($fout, " <fieldname>username</fieldname>\n");
+ fwrite($fout, " <type>input</type>\n");
+ fwrite($fout, " <size>15</size>\n");
+ fwrite($fout, " </field>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <field>\n");
+ fwrite($fout, " <fielddescr>Password</fielddescr>\n");
+ fwrite($fout, " <fieldname>password</fieldname>\n");
+ fwrite($fout, " <type>password</type>\n");
+ fwrite($fout, " <size>8</size>\n");
+ fwrite($fout, " </field>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <field>\n");
+ fwrite($fout, " <fielddescr>Description (Optional)</fielddescr>\n");
+ fwrite($fout, " <fieldname>description</fieldname>\n");
+ fwrite($fout, " <type>input</type>\n");
+ fwrite($fout, " <size>30</size>\n");
+ fwrite($fout, " </field>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <field>\n");
+ fwrite($fout, " <fielddescr>Restriction Group</fielddescr>\n");
+ fwrite($fout, " <fieldname>group</fieldname>\n");
+ fwrite($fout, " <type>select</type>\n");
+ fwrite($fout, " <options>\n");
+ fwrite($fout, " <option><name>Standard</name><value>Standard</value></option>\n");
+ fwrite($fout, " <option><name>Extended</name><value>Extended</value></option>\n");
+ fwrite($fout, " </options>\n");
+ fwrite($fout, " </field>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " </fields>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <custom_add_php_command_late>\n");
+ fwrite($fout, " require_once(\"/usr/local/pkg/squid_ng.inc\");\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " mod_htpasswd();\n");
+ fwrite($fout, " global_write_squid_config();\n");
+ fwrite($fout, " mwexec(\"/usr/local/sbin/squid -k reconfigure\");\n");
+ fwrite($fout, " </custom_add_php_command_late>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, "</packagegui>\n");
+
+ fclose($fout);
+
+ /* mount filesystem read-only */
+ conf_mount_ro();
+}
+
+function dynamic_ldap_auth() {
+ global $config;
+ conf_mount_rw();
+
+ $fout = fopen("/usr/local/pkg/squid_extauth.xml", "w");
+
+ fwrite($fout, "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, "<packagegui>\n");
+ fwrite($fout, " <name>squidextldapauth</name>\n");
+ fwrite($fout, " <title>Services: Proxy Server -> Extended Auth Settings</title>\n");
+ fwrite($fout, " <version>2.5.11</version>\n");
+ fwrite($fout, " <configpath>installedpackages->package->squidextldapauth->configuration->settings</configpath>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <files></files>\n");
+ fwrite($fout, " <menu></menu>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <aftersaveredirect>/pkg_edit.php?xml=squid_extauth.xml&amp;id=0</aftersaveredirect>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tabs>\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>General Settings</text>\n");
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_ng.xml&amp;id=0</url>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>Upstream Proxy</text>\n");
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_upstream.xml&amp;id=0</url>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>Cache Mgmt</text>\n");
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_cache.xml&amp;id=0</url>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>Network Access Control</text>\n");
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_nac.xml&amp;id=0</url>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>Traffic Mgmt</text>\n");
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_traffic.xml&amp;id=0</url>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>Auth Settings</text>\n");
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_auth.xml&amp;id=0</url>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>Extended Auth Settings</text>\n");
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_extauth.xml&amp;id=0</url>\n");
+ fwrite($fout, " <active/>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " </tabs>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <fields>\n");
+ fwrite($fout, " <field>\n");
+ fwrite($fout, " <fielddescr>Base DN</fielddescr>\n");
+ fwrite($fout, " <fieldname>ldap_basedn</fieldname>\n");
+ fwrite($fout, " <description>This is the base where the LDAP search starts. All subsequent organizational units (OUs)will be included. Example: \"ou=users,o=company\" will search for users in and under the specified company.</description>\n");
+ fwrite($fout, " <type>input</type>\n");
+ fwrite($fout, " <size>50</size>\n");
+ fwrite($fout, " </field>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <field>\n");
+ fwrite($fout, " <fielddescr>LDAP Server</fielddescr>\n");
+ fwrite($fout, " <fieldname>ldap_server</fieldname>\n");
+ fwrite($fout, " <description>This is the LDAP server that the bind will be attempted against.</description>\n");
+ fwrite($fout, " <type>input</type>\n");
+ fwrite($fout, " <size>20</size>\n");
+ fwrite($fout, " </field>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <field>\n");
+ fwrite($fout, " <fielddescr>LDAP Type</fielddescr>\n");
+ fwrite($fout, " <fieldname>ldap_type</fieldname>\n");
+ fwrite($fout, " <description>This specifies the supported LDAP types.</description>\n");
+ fwrite($fout, " <type>select</type>\n");
+ fwrite($fout, " <options>\n");
+ fwrite($fout, " <option><name>Active Directory</name><value>active_directory</value></option>\n");
+ fwrite($fout, " <option><name>Novell eDirectory</name><value>novell_edirectory</value></option>\n");
+ fwrite($fout, " <option><name>LDAP v2</name><value>ldap_v2</value></option>\n");
+ fwrite($fout, " <option><name>LDAP v3</name><value>ldap_v3</value></option>\n");
+ fwrite($fout, " </options>\n");
+ fwrite($fout, " </field>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <field>\n");
+ fwrite($fout, " <fielddescr>LDAP Port</fielddescr>\n");
+ fwrite($fout, " <fieldname>ldap_port</fieldname>\n");
+ fwrite($fout, " <description>This is the port that LDAP bind will attempt on. The default is \"389\".</description>\n");
+ fwrite($fout, " <type>input</type>\n");
+ fwrite($fout, " <size>5</size>\n");
+ fwrite($fout, " </field>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <field>\n");
+ fwrite($fout, " <fielddescr>Bind DN Username</fielddescr>\n");
+ fwrite($fout, " <fieldname>bind_dn_username</fieldname>\n");
+ fwrite($fout, " <description>If \"anonymous bind\" is not supported, please specify the bind username that can access the Base DN hierarchy.</description>\n");
+ fwrite($fout, " <type>input</type>\n");
+ fwrite($fout, " <size>30</size>\n");
+ fwrite($fout, " </field>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <field>\n");
+ fwrite($fout, " <fielddescr>Bind DN Password</fielddescr>\n");
+ fwrite($fout, " <fieldname>bind_dn_password</fieldname>\n");
+ fwrite($fout, " <description>This is the associated password with the Bind DN Username previously specified.</description>\n");
+ fwrite($fout, " <type>password</type>\n");
+ fwrite($fout, " </field>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " </fields>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <custom_add_php_command_late>\n");
+ fwrite($fout, " require_once(\"/usr/local/pkg/squid_ng.inc\");\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " mod_htpasswd();\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " global_write_squid_config();\n");
+ fwrite($fout, " mwexec(\"/usr/local/sbin/squid -k reconfigure\");\n");
+ fwrite($fout, " </custom_add_php_command_late>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, "</packagegui>\n");
+
+ fclose($fout);
+
+ /* mount filesystem read-only */
+ conf_mount_ro();
+}
+
+/* dynamically re-writes all squid xml files to handle adddeletecolumnitems properly */
+function dynamic_auth_content($pkgvar) {
+
+ switch ($pkgvar) {
+ case "pkg":
+ if ($handle = opendir("/usr/local/pkg")) {
+ while (($file = readdir($handle)) != false) {
+ if (stristr($file, "squid_") && stristr($file, ".xml")) {
+ $filecontents = file("/usr/local/pkg/" . $file);
+ $fout = fopen("/usr/local/pkg/" . $file, "w");
+ foreach($filecontents as $line) {
+ if (stristr($line, "<url>/pkg_edit.php?xml=squid_extauth.xml&amp;id=0</url>")) {
+ fwrite($fout, " <url>/pkg.php?xml=squid_extauth.xml&amp;id=0</url>\n");
+ } else {
+ fwrite($fout, $line);
+ }
+ }
+ }
+ }
+ }
+ break;
+
+ case "pkg_edit":
+ if ($handle = opendir("/usr/local/pkg")) {
+ while (($file = readdir($handle)) != false) {
+ if (stristr($file, "squid_") && stristr($file, ".xml")) {
+ $filecontents = file("/usr/local/pkg/" . $file);
+ $fout = fopen("/usr/local/pkg/" . $file,"w");
+ foreach($filecontents as $line) {
+ if (stristr($line, "<url>/pkg.php?xml=squid_extauth.xml&amp;id=0</url>")) {
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_extauth.xml&amp;id=0</url>\n");
+ } else {
+ fwrite($fout, $line);
+ }
+ }
+ }
+ }
+ }
+ break;
+ }
+
+} /* end function dynamic_auth_content */
+?> \ No newline at end of file
diff --git a/config/squid/squid_auth.xml b/config/squid/squid_auth.xml
new file mode 100644
index 00000000..b3e7c5c1
--- /dev/null
+++ b/config/squid/squid_auth.xml
@@ -0,0 +1,225 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>squidauth</name>
+ <version>none</version>
+ <title>Proxy server: Authentication</title>
+ <include_file>squid.inc</include_file>
+ <tabs>
+ <tab>
+ <text>General settings</text>
+ <url>/pkg_edit.php?xml=squid.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Upstream proxy</text>
+ <url>/pkg_edit.php?xml=squid_upstream.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Cache management</text>
+ <url>/pkg_edit.php?xml=squid_cache.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Access control</text>
+ <url>/pkg_edit.php?xml=squid_nac.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Traffic management</text>
+ <url>/pkg_edit.php?xml=squid_traffic.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Auth settings</text>
+ <url>/pkg_edit.php?xml=squid_auth.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Local users</text>
+ <url>/pkg.php?xml=squid_users.xml</url>
+ </tab>
+ </tabs>
+ <fields>
+ <field>
+ <fielddescr>Authentication method</fielddescr>
+ <fieldname>auth_method</fieldname>
+ <description>Select an authentication method. This will allow users to be authenticated by local or external services.</description>
+ <type>select</type>
+ <required/>
+ <default_value>none</default_value>
+ <options>
+ <option><name>None</name><value>none</value></option>
+ <option><name>Local</name><value>local</value></option>
+ <option><name>LDAP</name><value>ldap</value></option>
+ <option><name>RADIUS</name><value>radius</value></option>
+ <option><name>NT domain</name><value>msnt</value></option>
+ </options>
+ <onchange>on_auth_method_changed()</onchange>
+ </field>
+ <field>
+ <fielddescr>LDAP version</fielddescr>
+ <fieldname>ldap_version</fieldname>
+ <description>Enter LDAP protocol version (2 or 3).</description>
+ <type>select</type>
+ <default_value>2</default_value>
+ <options>
+ <option><name>2</name><value>2</value></option>
+ <option><name>3</name><value>3</value></option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Authentication server</fielddescr>
+ <fieldname>auth_server</fieldname>
+ <description>Enter here the IP or hostname of the server that will perform the authentication.</description>
+ <type>input</type>
+ <size>60</size>
+ </field>
+ <field>
+ <fielddescr>Authentication server port</fielddescr>
+ <fieldname>auth_server_port</fieldname>
+ <description>Enter here the port to use to connect to the authentication server. Leave this field blank to use the authentication method's default port.</description>
+ <type>input</type>
+ <size>60</size>
+ </field>
+ <field>
+ <fielddescr>LDAP server user DN</fielddescr>
+ <fieldname>ldap_user</fieldname>
+ <description>Enter here the user DN to use to connect to the LDAP server.</description>
+ <type>input</type>
+ <size>60</size>
+ </field>
+ <field>
+ <fielddescr>LDAP password</fielddescr>
+ <fieldname>ldap_pass</fieldname>
+ <description>Enter here the password to use to connect to the LDAP server.</description>
+ <type>password</type>
+ <size>60</size>
+ </field>
+ <field>
+ <fielddescr>LDAP base domain</fielddescr>
+ <fieldname>ldap_basedomain</fieldname>
+ <description>For LDAP authentication, enter here the base domain in the LDAP server.</description>
+ <type>input</type>
+ <size>60</size>
+ </field>
+ <field>
+ <fielddescr>LDAP search filter</fielddescr>
+ <fieldname>ldap_filter</fieldname>
+ <description>Enter LDAP search filter.</description>
+ <type>input</type>
+ <size>60</size>
+ <default_value>(&amp;(objectClass=person)(uid=%s))</default_value>
+ </field>
+ <field>
+ <fielddescr>RADIUS secret</fielddescr>
+ <fieldname>radius_secret</fieldname>
+ <description>The RADIUS secret for RADIUS authentication.</description>
+ <type>password</type>
+ <size>60</size>
+ </field>
+ <field>
+ <fielddescr>Secondary NT servers</fielddescr>
+ <fieldname>msnt_secondary</fieldname>
+ <description>Comma-separated list of secondary servers to be used for NT domain authentication.</description>
+ <type>input</type>
+ <size>60</size>
+ </field>
+ <field>
+ <fielddescr>Authentication prompt</fielddescr>
+ <fieldname>auth_prompt</fieldname>
+ <description>This string will be displayed at the top of the authentication request window.</description>
+ <type>input</type>
+ <default_value>Please enter your credentials to access the proxy</default_value>
+ </field>
+ <field>
+ <fielddescr>Authentication processes</fielddescr>
+ <fieldname>auth_processes</fieldname>
+ <description>The number of authenticator processes to spawn. If many authentications are expected within a short timeframe, increase this number accordingly.</description>
+ <type>input</type>
+ <size>60</size>
+ <default_value>5</default_value>
+ </field>
+ <field>
+ <fielddescr>Authentication TTL</fielddescr>
+ <fieldname>auth_ttl</fieldname>
+ <description>This specifies for how long (in minutes) the proxy server assumes an externally validated username and password combination is valid (Time To Live). When the TTL expires, the user will be prompted for credentials again.</description>
+ <type>input</type>
+ <size>60</size>
+ <default_value>60</default_value>
+ </field>
+ <field>
+ <fielddescr>Requiere authentication for unrestricted hosts</fielddescr>
+ <fieldname>unrestricted_auth</fieldname>
+ <description>If this option is enabled, even users tagged as unrestricted through access control are required to authenticate to use the proxy.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Subnets that don't need authentication</fielddescr>
+ <fieldname>no_auth_hosts</fieldname>
+ <description>Enter each subnet or IP address on a new line (in CIDR format, e.g.: 10.5.0.0/16, 192.168.1.50/32) that should not be asked for authentication to access the proxy.</description>
+ <type>textarea</type>
+ <cols>50</cols>
+ <rows>5</rows>
+ <encoding>base64</encoding>
+ </field>
+ </fields>
+ <custom_php_validation_command>
+ squid_validate_auth($_POST, &amp;$input_errors);
+ </custom_php_validation_command>
+ <custom_php_after_form_command>
+ squid_print_javascript_auth2();
+ </custom_php_after_form_command>
+ <custom_php_resync_config_command>
+ squid_resync();
+ </custom_php_resync_config_command>
+ <custom_php_before_form_command>
+ squid_print_javascript_auth2();
+ </custom_php_before_form_command>
+ <custom_php_after_head_command>
+ $transparent_proxy = ($config['installedpackages']['squid']['config'][0]['transparent_proxy'] == 'on');
+ if($transparent_proxy)
+ $input_errors[] = "Authentication cannot be enabled while transparent proxy mode is enabled";
+ squid_print_javascript_auth();
+ </custom_php_after_head_command>
+</packagegui>
diff --git a/config/squid/squid_cache.xml b/config/squid/squid_cache.xml
new file mode 100644
index 00000000..9c96e67d
--- /dev/null
+++ b/config/squid/squid_cache.xml
@@ -0,0 +1,223 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>squidcache</name>
+ <version>none</version>
+ <title>Proxy server: Cache management</title>
+ <include_file>squid.inc</include_file>
+ <tabs>
+ <tab>
+ <text>General settings</text>
+ <url>/pkg_edit.php?xml=squid.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Upstream proxy</text>
+ <url>/pkg_edit.php?xml=squid_upstream.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Cache management</text>
+ <url>/pkg_edit.php?xml=squid_cache.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Access control</text>
+ <url>/pkg_edit.php?xml=squid_nac.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Traffic management</text>
+ <url>/pkg_edit.php?xml=squid_traffic.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Auth settings</text>
+ <url>/pkg_edit.php?xml=squid_auth.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Local users</text>
+ <url>/pkg.php?xml=squid_users.xml</url>
+ </tab>
+ </tabs>
+ <fields>
+ <field>
+ <fielddescr>Hard disk cache size</fielddescr>
+ <fieldname>harddisk_cache_size</fieldname>
+ <description>This is the amount of disk space (in megabytes) to use for cached objects.</description>
+ <type>input</type>
+ <required/>
+ <default_value>100</default_value>
+ </field>
+ <field>
+ <fielddescr>Hard disk cache system</fielddescr>
+ <fieldname>harddisk_cache_system</fieldname>
+ <description>This specifies the kind of storage system to use. &lt;p&gt; &lt;b&gt; ufs &lt;/b&gt; is the old well-known Squid storage format that has always been there. &lt;p&gt; &lt;b&gt; aufs &lt;/b&gt; uses POSIX-threads to avoid blocking the main Squid process on disk-I/O. (Formerly known as async-io.) &lt;p&gt; &lt;b&gt; diskd &lt;/b&gt; uses a separate process to avoid blocking the main Squid process on disk-I/O.</description>
+ <type>select</type>
+ <default_value>aufs</default_value>
+ <options>
+ <option><name>ufs</name><value>ufs</value></option>
+ <option><name>aufs</name><value>aufs</value></option>
+ <option><name>diskd</name><value>diskd</value></option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Hard disk cache location</fielddescr>
+ <fieldname>harddisk_cache_location</fieldname>
+ <description>This is the directory where the cache will be stored. (note: do not end with a /). If you change this location, squid needs to make a new cache, this could take a while</description>
+ <type>input</type>
+ <size>60</size>
+ <required/>
+ <default_value>/var/squid/cache</default_value>
+ </field>
+ <field>
+ <fielddescr>Memory cache size</fielddescr>
+ <fieldname>memory_cache_size</fieldname>
+ <description>This is the amount of physical RAM (in megabytes) to be used for negative cache and in-transit objects. This value should not exceed more than 50% of the installed RAM. The minimum value is 1MB.</description>
+ <type>input</type>
+ <required/>
+ <default_value>8</default_value>
+ </field>
+ <field>
+ <fielddescr>Minimum object size</fielddescr>
+ <fieldname>minimum_object_size</fieldname>
+ <description>Objects smaller than the size specified (in kilobytes) will not be saved on disk. The default value is 0, meaning there is no minimum.</description>
+ <type>input</type>
+ <required />
+ <default_value>0</default_value>
+ </field>
+ <field>
+ <fielddescr>Maximum object size</fielddescr>
+ <fieldname>maximum_object_size</fieldname>
+ <description>Objects larger than the size specified (in kilobytes) will not be saved on disk. If you wish to increase speed more than you want to save bandwidth, this should be set to a low value.</description>
+ <type>input</type>
+ <required/>
+ <default_value>4</default_value>
+ </field>
+ <field>
+ <fielddescr>Level 1 subdirectories</fielddescr>
+ <fieldname>level1_subdirs</fieldname>
+ <description>Each level-1 directory contains 256 subdirectories, so a value of 256 level-1 directories will use a total of 65536 directories for the hard disk cache. This will significantly slow down the startup process of the proxy service, but can speed up the caching under certain conditions.</description>
+ <type>select</type>
+ <default_value>16</default_value>
+ <options>
+ <option><name>4</name><value>4</value></option>
+ <option><name>8</name><value>8</value></option>
+ <option><name>16</name><value>16</value></option>
+ <option><name>32</name><value>32</value></option>
+ <option><name>64</name><value>64</value></option>
+ <option><name>128</name><value>128</value></option>
+ <option><name>256</name><value>256</value></option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Memory replacement policy</fielddescr>
+ <fieldname>memory_replacement_policy</fieldname>
+ <description>The memory replacement policy determines which objects are purged from memory when space is needed. The default policy for memory replacement is GDSF. &lt;p&gt; &lt;b&gt; LRU: Last Recently Used Policy &lt;/b&gt; - The LRU policies keep recently referenced objects. i.e., it replaces the object that has not been accessed for the longest time. &lt;p&gt; &lt;b&gt; Heap GDSF: Greedy-Dual Size Frequency &lt;/b&gt; - The Heap GDSF policy optimizes object-hit rate by keeping smaller, popular objects in cache. It achieves a lower byte hit rate than LFUDA though, since it evicts larger (possibly popular) objects. &lt;p&gt; &lt;b&gt; Heap LFUDA: Least Frequently Used with Dynamic Aging &lt;/b&gt; - The Heap LFUDA policy keeps popular objects in cache regardless of their size and thus optimizes byte hit rate at the expense of hit rate since one large, popular object will prevent many smaller, slightly less popular objects from being cached. &lt;p&gt; &lt;b&gt; Heap LRU: Last Recently Used &lt;/b&gt; - Works like LRU, but uses a heap instead. &lt;p&gt; Note: If using the LFUDA replacement policy, the value of Maximum Object Size should be increased above its default of 12KB to maximize the potential byte hit rate improvement of LFUDA.</description>
+ <type>select</type>
+ <default_value>heap GDSF</default_value>
+ <options>
+ <option><name>LRU</name><value>lru</value></option>
+ <option><name>Heap LFUDA</name><value>heap LFUDA</value></option>
+ <option><name>Heap GDSF</name><value>heap GDSF</value></option>
+ <option><name>Heap LRU</name><value>heap LRU</value></option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Cache replacement policy</fielddescr>
+ <fieldname>cache_replacement_policy</fieldname>
+ <description>The cache replacement policy decides which objects will remain in cache and which objects are replaced to create space for the new objects. The default policy for cache replacement is LFUDA. Please see the type descriptions specified in the memory replacement policy for additional detail.</description>
+ <type>select</type>
+ <default_value>heap LFUDA</default_value>
+ <options>
+ <option><name>LRU</name><value>lru</value></option>
+ <option><name>Heap LFUDA</name><value>heap LFUDA</value></option>
+ <option><name>Heap GDSF</name><value>heap GDSF</value></option>
+ <option><name>Heap LRU</name><value>heap LRU</value></option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Low-water-mark in %</fielddescr>
+ <fieldname>cache_swap_low</fieldname>
+ <description>Cache replacement begins when the swap usage is above the low-low-water mark and attempts to maintain utilisation near the low-water-mark.</description>
+ <type>input</type>
+ <default_value>90</default_value>
+ </field>
+ <field>
+ <fielddescr>High-water-mark in %</fielddescr>
+ <fieldname>cache_swap_high</fieldname>
+ <description>As swap utilisation gets close to the high-water-mark object eviction becomes more aggressive.</description>
+ <type>input</type>
+ <default_value>95</default_value>
+ </field>
+ <field>
+ <fielddescr>Do not cache</fielddescr>
+ <fieldname>donotcache</fieldname>
+ <description>Enter each domain or IP address on a new line that should never be cached.</description>
+ <type>textarea</type>
+ <cols>50</cols>
+ <rows>5</rows>
+ <encoding>base64</encoding>
+ </field>
+ <field>
+ <fielddescr>Enable offline mode</fielddescr>
+ <fieldname>enable_offline</fieldname>
+ <description>Enable this option and the proxy server will never try to validate cached objects. The offline mode gives access to more cached information than the proposed feature would allow (stale cached versions, where the origin server should have been contacted).</description>
+ <type>checkbox</type>
+ <required/>
+ </field>
+ </fields>
+ <custom_php_command_before_form>
+ if($_POST['harddisk_cache_size'] != $config['installedpackages']['squidcache']['config'][0]['harddisk_cache_size']) {
+ $needs_dash_z = true;
+ }
+ </custom_php_command_before_form>
+ <custom_php_validation_command>
+ squid_validate_cache($_POST, &amp;$input_errors);
+ </custom_php_validation_command>
+ <custom_php_resync_config_command>
+ squid_resync();
+ if($needs_dash_z)
+ squid_dash_z();
+ </custom_php_resync_config_command>
+</packagegui>
diff --git a/config/squid/squid_extauth.xml b/config/squid/squid_extauth.xml
new file mode 100644
index 00000000..745e85d5
--- /dev/null
+++ b/config/squid/squid_extauth.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>squidextnoauth</name>
+ <version>none</version>
+ <title>Services: Proxy Server -> Extended Authentication Settings</title>
+ <aftersaveredirect>/pkg_edit.php?xml=squid_extauth.xml&amp;id=0</aftersaveredirect>
+ <tabs>
+ <tab>
+ <text>General Settings</text>
+ <url>/pkg_edit.php?xml=squid_ng.xml&amp;id=0</url>
+ </tab>
+
+ <tab>
+ <text>Upstream Proxy</text>
+ <url>/pkg_edit.php?xml=squid_upstream.xml&amp;id=0</url>
+ </tab>
+
+ <tab>
+ <text>Cache Mgmt</text>
+ <url>/pkg_edit.php?xml=squid_cache.xml&amp;id=0</url>
+ </tab>
+
+ <tab>
+ <text>Network Access Control</text>
+ <url>/pkg_edit.php?xml=squid_nac.xml&amp;id=0</url>
+ </tab>
+
+ <tab>
+ <text>Traffic Mgmt</text>
+ <url>/pkg_edit.php?xml=squid_traffic.xml&amp;id=0</url>
+ </tab>
+
+ <tab>
+ <text>Auth Settings</text>
+ <url>/pkg_edit.php?xml=squid_auth.xml&amp;id=0</url>
+ </tab>
+
+ <tab>
+ <text>Extended Auth Settings</text>
+ <url>/pkg_edit.php?xml=squid_extauth.xml&amp;id=0</url>
+ <active/>
+ </tab>
+
+ </tabs>
+ <configpath>installedpackages->package->squidextnoauth->configuration->settings</configpath>
+ <fields>
+ <field>
+ <fielddescr>No Authentication Defined</fielddescr>
+ <fieldname>no_auth</fieldname>
+ <type>text</type>
+ </field>
+ </fields>
+
+ <custom_add_php_command_late>
+ require_once("/usr/local/pkg/squid_ng.inc");
+
+ global_write_squid_config();
+ mwexec("/usr/local/sbin/squid -k reconfigure");
+ </custom_add_php_command_late>
+
+</packagegui>
diff --git a/config/squid/squid_nac.xml b/config/squid/squid_nac.xml
new file mode 100644
index 00000000..e0489f8e
--- /dev/null
+++ b/config/squid/squid_nac.xml
@@ -0,0 +1,143 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>squidnac</name>
+ <version>none</version>
+ <title>Proxy server: Access control</title>
+ <include_file>squid.inc</include_file>
+ <tabs>
+ <tab>
+ <text>General settings</text>
+ <url>/pkg_edit.php?xml=squid.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Upstream proxy</text>
+ <url>/pkg_edit.php?xml=squid_upstream.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Cache management</text>
+ <url>/pkg_edit.php?xml=squid_cache.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Access control</text>
+ <url>/pkg_edit.php?xml=squid_nac.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Traffic management</text>
+ <url>/pkg_edit.php?xml=squid_traffic.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Auth settings</text>
+ <url>/pkg_edit.php?xml=squid_auth.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Local users</text>
+ <url>/pkg.php?xml=squid_users.xml</url>
+ </tab>
+ </tabs>
+ <fields>
+ <field>
+ <fielddescr>Allowed subnets</fielddescr>
+ <fieldname>allowed_subnets</fieldname>
+ <description>Enter each subnet on a new line that is allowed to use the proxy. The subnets must be expressed as CIDR ranges (e.g.: 192.168.1.0/24). Note that the proxy interface subnet is already an allowed subnet. All the other subnets won't be able to use the proxy.</description>
+ <type>textarea</type>
+ <cols>50</cols>
+ <rows>5</rows>
+ <encoding>base64</encoding>
+ </field>
+ <field>
+ <fielddescr>Unrestricted IPs</fielddescr>
+ <fieldname>unrestricted_hosts</fieldname>
+ <description>Enter each unrestricted IP address on a new line that is not to be filtered out by the other access control directives set in this page.</description>
+ <type>textarea</type>
+ <cols>50</cols>
+ <rows>5</rows>
+ <encoding>base64</encoding>
+ </field>
+ <field>
+ <fielddescr>Banned host addresses</fielddescr>
+ <fieldname>banned_hosts</fieldname>
+ <description>Enter each IP address on a new line that is not to be allowed to use the proxy.</description>
+ <type>textarea</type>
+ <cols>50</cols>
+ <rows>5</rows>
+ <encoding>base64</encoding>
+ </field>
+ <field>
+ <fielddescr>Whitelist</fielddescr>
+ <fieldname>whitelist</fieldname>
+ <description>Enter each destination domain on a new line that will be accessable to the users that are allowed to use the proxy.</description>
+ <type>textarea</type>
+ <cols>50</cols>
+ <rows>5</rows>
+ <encoding>base64</encoding>
+ </field>
+ <field>
+ <fielddescr>Blacklist</fielddescr>
+ <fieldname>blacklist</fieldname>
+ <description>Enter each destination domain on a new line that will be blocked to the users that are allowed to use the proxy.</description>
+ <type>textarea</type>
+ <cols>50</cols>
+ <rows>5</rows>
+ <encoding>base64</encoding>
+ </field>
+ <field>
+ <fielddescr>External Cache-Managers</fielddescr>
+ <fieldname>ext_cachemanager</fieldname>
+ <description>Enter the IPs for the external Cache Managers to be allowed here, separated by semi-colons (;).</description>
+ <type>input</type>
+ <size>60</size>
+ </field>
+ </fields>
+ <custom_php_validation_command>
+ squid_validate_nac($_POST, &amp;$input_errors);
+ </custom_php_validation_command>
+ <custom_php_resync_config_command>
+ squid_resync();
+ </custom_php_resync_config_command>
+</packagegui>
diff --git a/config/squid/squid_ng.inc b/config/squid/squid_ng.inc
new file mode 100644
index 00000000..dc18e349
--- /dev/null
+++ b/config/squid/squid_ng.inc
@@ -0,0 +1,1067 @@
+<?php
+/* $Id$ */
+
+/*
+ squid_ng.inc
+ part of pfSense (www.pfSense.com)
+
+ Copyright (C) 2005 Michael Capp <michael.capp@gmail.com>
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+function global_write_squid_config()
+{
+ global $config;
+ conf_mount_rw();
+ config_lock();
+
+ /* define squid configuration file in variable for replace function */
+ $squidconfig = "/usr/local/etc/squid/squid.conf";
+
+ /* squid.xml values */
+ $active_interface = $config['installedpackages']['squid']['config'][0]['active_interface'];
+ $transparent_proxy = $config['installedpackages']['squid']['config'][0]['transparent_proxy'];
+ $log_enabled = $config['installedpackages']['squid']['config'][0]['log_enabled'];
+ $urlfier_enable = $config['installedpackages']['squid']['config'][0]['urlfilter_enable'];
+ $accesslog_disabled = $config['installedpackages']['squid']['config'][0]['accesslog_disabled'];
+ $log_query_terms = $config['installedpackages']['squid']['config'][0]['log_query_terms'];
+ $log_user_agents = $config['installedpackages']['squid']['config'][0]['log_user_agents'];
+ $proxy_port = $config['installedpackages']['squid']['config'][0]['proxy_port'];
+ $visible_hostname = $config['installedpackages']['squid']['config'][0]['visible_hostname'];
+ $cache_admin_email = $config['installedpackages']['squid']['config'][0]['cache_admin_email'];
+ $error_language = $config['installedpackages']['squid']['config'][0]['error_language'];
+ $cachemgr_enabled = $config['installedpackages']['squid']['config'][0]['cachemgr_enabled'];
+
+ /* squid_upstream.xml values */
+ $proxy_forwarding = $config['installedpackages']['squidupstream']['config'][0]['proxy_forwarding'];
+ $client_ip_forwarding = $config['installedpackages']['squidupstream']['config'][0]['client_ip_forwarding'];
+ $user_forwarding = $config['installedpackages']['squidupstream']['config'][0]['user_forwarding'];
+ $upstream_proxy = $config['installedpackages']['squidupstream']['config'][0]['upstream_proxy'];
+ $upstream_proxy_port = $config['installedpackages']['squidupstream']['config'][0]['upstream_proxy_port'];
+ $upstream_username = $config['installedpackages']['squidupstream']['config'][0]['upstream_username'];
+ $upstream_password = $config['installedpackages']['squidupstream']['config'][0]['upstream_psasword'];
+
+ /* squid_cache.xml values */
+ $memory_cache_size = $config['installedpackages']['squidcache']['config'][0]['memory_cache_size'];
+ $harddisk_cache_size = $config['installedpackages']['squidcache']['config'][0]['harddisk_cache_size'];
+ $minimum_object_size = $config['installedpackages']['squidcache']['config'][0]['minimum_object_size'];
+ $maximum_object_size = $config['installedpackages']['squidcache']['config'][0]['maximum_object_size'];
+ $level_subdirs = $config['installedpackages']['squidcache']['config'][0]['level_subdirs'];
+ $memory_replacement = $config['installedpackages']['squidcache']['config'][0]['memory_replacement'];
+ $cache_replacement = $config['installedpackages']['squidcache']['config'][0]['cache_replacement'];
+ $domain = $config['installedpackages']['squidcache']['config'][0]['domain'];
+ $enable_offline = $config['installedpackages']['squidcache']['config'][0]['enable_offline'];
+
+ /* squid_nac.xml values */
+ $allowed_subnets = $config['installedpackages']['squidnac']['config'][0]['allowed_subnets'];
+ $unrestricted_ip_addr = $config['installedpackages']['squidnac']['config'][0]['unrestricted_ip_address'];
+ $unrestricted_mac_addr = $config['installedpackages']['squidnac']['config'][0]['unrestricted_mac_addresses'];
+ $banned_ip_addr = $config['installedpackages']['squidnac']['config'][0]['banned_ip_addresses'];
+ $banned_mac_addr = $config['installedpackages']['squidnac']['config'][0]['banned_mac_addresses'];
+ $override_hosts = $config['installedpackages']['squidnac']['config'][0]['override_hosts'];
+
+ /* squid_traffic.xml values */
+ $max_download_size = $config['installedpackages']['squidtraffic']['config'][0]['max_download_size'];
+ $max_upload_size = $config['installedpackages']['squidtraffic']['config'][0]['max_upload_size'];
+ $dl_overall = $config['installedpackages']['squidtraffic']['config'][0]['dl_overall'];
+ $dl_per_host = $config['installedpackages']['squidtraffic']['config'][0]['dl_per_host'];
+ $throttle_binary_files = $config['installedpackages']['squidtraffic']['config'][0]['throttle_binary_files'];
+ $throttle_cd_images = $config['installedpackages']['squidtraffic']['config'][0]['throttle_cd_images'];
+ $throttle_multimedia = $config['installedpackages']['squidtraffic']['config'][0]['throttle_multimedia'];
+
+ /* squid_auth.xml values */
+ $auth_method = $config['installedpackages']['squidauth']['config'][0]['auth_method'];
+ $auth_processes = $config['installedpackages']['squidauth']['config'][0]['auth_processes'];
+ $auth_cache_ttl = $config['installedpackages']['squidauth']['config'][0]['auth_cache_ttl'];
+ $limit_ip_addr = $config['installedpackages']['squidauth']['config'][0]['limit_ip_addr'];
+ $user_ip_cache_ttl = $config['installedpackages']['squidauth']['config'][0]['user_ip_cache_ttl'];
+ $req_unrestricted_auth = $config['installedpackages']['squidauth']['config'][0]['req_unrestricted_auth'];
+ $auth_realm_prompt = $config['installedpackages']['squidauth']['config'][0]['auth_realm_prompt'];
+ $no_domain_auth = $config['installedpackages']['squidauth']['config'][0]['no_domain_auth'];
+ $min_pass_length = $config['installedpackages']['squidauth']['config'][0]['min_pass_length'];
+ $bypass_extended = $config['installedpackages']['squidauth']['config'][0]['bypass_extended'];
+
+ /* squid_extauth.xml (ldap) values */
+ $ldap_basedn = $config['installedpackages']['squidextldapauth']['config'][0]['ldap_basedn'];
+ $ldap_server = $config['installedpackages']['squidextldapauth']['config'][0]['ldap_server'];
+ $ldap_type = $config['installedpackages']['squidextldapauth']['config'][0]['ldap_type'];
+ $ldap_port = $config['installedpackages']['squidextldapauth']['config'][0]['ldap_port'];
+ $bind_dn_username = $config['installedpackages']['squidextldapauth']['config'][0]['bind_dn_username'];
+ $bind_dn_password = $config['installedpackages']['squidextldapauth']['config'][0]['bind_dn_password'];
+
+ /* squid_extauth.xml (radius) values */
+ $radius_server = $config['installedpackages']['squidextradiusauth']['config'][0]['radius_server'];
+ $radius_port = $config['installedpackages']['squidextradiusauth']['config'][0]['radius_port'];
+ $radius_identifier = $config['installedpackages']['squidextradiusauth']['config'][0]['radius_identifier'];
+ $radius_secret = $config['installedpackages']['squidextradiusauth']['config'][0]['radius_secret'];
+
+ /* static variable assignments for directory mapping */
+ $acldir = "/usr/local/etc/squid/advanced/acls";
+ $ncsadir = "/usr/local/etc/squid/advanced/ncsa";
+ $ntlmdir = "/usr/local/etc/squid/advanced/ntlm";
+ $radiusdir = "/usr/local/etc/squid/advanced/radius";
+
+ $fout = fopen($squidconfig, "w");
+
+ $config_array = array('shutdown_lifetime 5 seconds' . "\n\n");
+
+ if (isset($cachemgr_enabled) && ($cachemgr_enabled == "on")) {
+ mwexec("cp /usr/local/libexec/squid/cachemgr.cgi /usr/local/www/cachemgr.cgi");
+ mwexec("chmod a+rx /usr/local/www/cachemgr.cgi");
+ } else {
+ mwexec("rm -f /usr/local/www/cachemgr.cgi");
+ }
+ unset($cachemgr_enabled);
+
+ if (!isset($icp_port) or ($icp_port == "")) {
+ $icp_port = "3130";
+ }
+ $config_array[] = 'icp_port ' . $icp_port . "\n";
+ unset($icp_port);
+
+ if(!isset($proxy_port) or ($proxy_port == "")) {
+ $proxy_port = "3128";
+ }
+
+ if (isset($transparent_proxy) && ($transparent_proxy != "on")) {
+ $int = convert_friendly_interface_to_real_interface_name($active_interface);
+ $listen_ip = find_interface_ip($int);
+
+ $config_array[] = 'http_port ' . $listen_ip . ':' . $proxy_port . "\n\n";
+ $config_array[] = 'acl QUERY urlpath_regex cgi-bin \?' . "\n";
+ $config_array[] = 'no_cache deny QUERY' . "\n\n";
+ }
+ $config_array[] = 'http_port 127.0.0.1:' . $proxy_port . "\n\n";
+ unset($proxy_port);
+
+ if (isset($domain) && ($domain !== "")) {
+ if (!file_exists($acldir)) {
+ mwexec("/bin/mkdir -p " . $acldir);
+ }
+
+ $aclout = fopen($acldir . "/dst_nocache.acl","w");
+
+ $domain_array = split("; ",$domain);
+ foreach ($domain_array as $no_cache_domain) {
+ fwrite($aclout, $no_cache_domain . "\n");
+ }
+
+ fclose($aclout);
+
+ $config_array[] = 'acl no_cache_domains dstdomain "' . $acldir . '/dst_nocache.acl"' . "\n";
+ $config_array[] = 'no_cache deny no_cache_domains' . "\n\n";
+ }
+ unset($no_cache_domain);
+ unset($domain_array);
+ unset($domain);
+
+ $config_array[] = 'cache_effective_user squid' . "\n";
+ $config_array[] = 'cache_effective_group squid' . "\n\n";
+ $config_array[] = 'pid_filename /var/run/squid.pid' . "\n\n";
+
+ if (!isset($memory_cache_size) or ($memory_cache_size == "")) {
+ $memory_cache_size = "8";
+ }
+ $config_array[] = 'cache_mem ' . $memory_cache_size . ' MB' . "\n";
+ unset($memory_cache_size);
+
+ if (!isset($harddisk_cache_size) or ($harddisk_cache_size == "")) {
+ $harddisk_cache_size = "500";
+ }
+
+ if (!isset($level_subdirs) or ($level_subdirs == "")) {
+ $level_subdirs = "16";
+ }
+
+ $config_array[] = 'cache_dir diskd /var/squid/cache ' . $harddisk_cache_size . ' ' . $level_subdirs . ' 256' . "\n\n";
+ unset($harddisk_cache_size);
+ unset($level_subdirs);
+
+ if (!isset($error_language) or ($error_language == "")) {
+ $error_language = "English";
+ }
+ $config_array[] = 'error_directory /usr/local/etc/squid/errors/' . $error_language . "\n\n";
+ unset($error_language);
+
+ if (isset($offline_mode) && ($offline_mode == "on")) {
+ $config_array[] = 'offline_mode on' . "\n\n";
+ } else {
+ $config_array[] = 'offline_mode off' . "\n\n";
+ }
+
+ if (!isset($memory_replacement) or ($memory_replacement == "")) {
+ $memory_replacement = "heap GDSF";
+ }
+ $config_array[] = 'memory_replacement_policy ' . $memory_replacement . "\n";
+ unset($memory_replacement);
+
+ if (!isset($cache_replacement) or ($cache_replacement == "")) {
+ $cache_replacement="heap GDSF";
+ }
+ $config_array[] = 'cache_replacement_policy ' . $cache_replacement . "\n\n";
+ unset($cache_replacement);
+
+ if (isset($accesslog_disabled) && ($accesslog_disabled == "on")) {
+ $config_array[] = 'cache_access_log none' . "\n";
+ } else {
+ $config_array[] = 'cache_access_log /var/log/access.log' . "\n";
+ }
+ $config_array[] = 'cache_log /var/log/cache.log' . "\n";
+ $config_array[] = 'cache_store_log none' . "\n";
+ unset($accesslog_disabled);
+ unset($log_enabled);
+
+ if (isset($log_query_terms) && ($log_query_terms == "on")) {
+ $config_array[] = 'strip_query_terms off' . "\n";
+ } else {
+ $config_array[] = 'strip_query_terms on' . "\n";
+ }
+ unset($log_query_terms);
+
+ $config_array[] = 'useragent_log /var/log/useragent.log' . "\n\n";
+ unset($log_user_agents);
+
+ $config_array[] = 'log_mime_hdrs off' . "\n";
+ $config_array[] = 'emulate_httpd_log on' . "\n";
+
+ switch ($user_forwarding) {
+ case "on":
+ $config_array[] = 'forwarded_for on' . "\n\n";
+ break;
+ case "off":
+ $config_array[] = 'forwarded_for off' . "\n\n";
+ break;
+ default:
+ $config_array[] = 'forwarded_for off' . "\n\n";
+ break;
+ }
+ unset($user_forwarding);
+
+ switch ($auth_method) {
+ case "none":
+ break;
+ case "local_auth":
+ $config_array[] = 'auth_param basic program /usr/local/libexec/squid/ncsa_auth /usr/local/etc/squid/advanced/ncsa/passwd' . "\n";
+ if (!isset($auth_processes) or ($auth_processes == "")) {
+ $auth_processes = "5";
+ }
+ $config_array[] = 'auth_param basic children ' . $auth_processes . "\n";
+
+ if (!isset($auth_realm_prompt) or ($auth_realm_prompt == "")) {
+ $auth_realm_prompt = "pfSense Advanced Proxy";
+ }
+ $config_array[] = 'auth_param basic realm ' . $auth_realm_prompt . "\n";
+
+ if (!isset($auth_cache_ttl) or ($auth_cache_ttl == "")) {
+ $auth_cache_ttl = "60";
+ }
+ $config_array[] = 'auth_param basic credentialsttl ' . $auth_cache_ttl . ' minutes' . "\n\n";
+ $config_array[] = 'acl for_inetusers proxy_auth REQUIRED' . "\n\n";
+
+ unset($auth_realm_prompt);
+ unset($auth_processes);
+ unset($auth_cache_ttl);
+
+ break;
+ case "radius_auth";
+ $config_array[] = 'auth_param basic program /usr/local/libexec/squid/squid_rad_auth -h ' . $radius_server . ' -p ' . $radius_port . ' -i ' . $radius_identifier . ' -w ' . $radius_secret . "\n";
+ if (!isset($auth_processes) or ($auth_processes == "")) {
+ $auth_processes = "5";
+ }
+ $config_array[] = 'auth_param basic children ' . $auth_processes . "\n";
+
+ if (!isset($auth_realm_prompt) or ($auth_realm_prompt == "")) {
+ $auth_realm_prompt = "pfSense Advanced Proxy";
+ }
+ $config_array[] = 'auth_param basic realm ' . $auth_realm_prompt . "\n";
+
+ if (!isset($auth_cache_ttl) or ($auth_cache_ttl == "")) {
+ $auth_cache_ttl = "60";
+ }
+ $config_array[] = 'auth_param basic credentialsttl ' . $auth_cache_ttl . ' minutes' . "\n\n";
+ $config_array[] = 'acl for_inetusers proxy_auth REQUIRED' . "\n\n";
+
+ unset($auth_realm_prompt);
+ unset($auth_processes);
+ unset($auth_cache_ttl);
+
+ break;
+ case "ldap_bind";
+ $config_array[] = 'auth_param basic program /usr/local/libexec/squid_ldap_auth -b "' . $ldap_basedn . '" -D "' . $bind_dn_username . '" -w "' . $bind_dn_password . '" -f "(&(objectClass=person)(cn=%s))" -u -cn -P "' . $ldap_server . ":" . $ldap_port . "\n";
+ $config_array[] = 'auth_param basic program /usr/local/libexec/squid/squid_ldap_auth';
+ $config_array[] = ' -b "' . $ldap_basedn . '"';
+ $config_array[] = ' -D "' . $bind_dn_username . '"';
+ $config_array[] = " -w " . $bind_dn_password;
+ $config_array[] = ' -f "(&(objectClass=person)(cn=%s))"';
+ $config_array[] = " -u cn -P " . $ldap_server . ":" . $ldap_port . "\n";
+
+ if (!isset($auth_processes) or ($auth_processes == "")) {
+ $auth_processes = "5";
+ }
+ $config_array[] = 'auth_param basic children ' . $auth_processes . "\n";
+
+ if (!isset($auth_realm_prompt) or ($auth_realm_prompt == "")) {
+ $auth_realm_prompt = "pfSense Advanced Proxy";
+ }
+ $config_array[] = 'auth_param basic realm ' . $auth_realm_prompt . "\n";
+
+ if (!isset($auth_cache_ttl) or ($auth_cache_ttl == "")) {
+ $auth_cache_ttl = "60";
+ }
+ $config_array[] = 'auth_param basic credentialsttl ' . $auth_cache_ttl . ' minutes' . "\n\n";
+ $config_array[] = 'acl for_inetusers proxy_auth REQUIRED' . "\n\n";
+
+ unset($auth_realm_prompt);
+ unset($auth_processes);
+ unset($auth_cache_ttl);
+
+ break;
+ case "windows_auth";
+ break;
+ }
+
+ if (isset($throttle_binary_files) && ($throttle_binary_files == "on")) {
+ if (!file_exists($acldir)) {
+ mwexec("/bin/mkdir -p " . $acldir);
+ }
+
+ $binary_out = "\.bin$\n\.cab$\n\.gz$\n\.rar$\n\.sea$\n\.tar$\n\.tgz$\n\.zip$\n";
+
+ $throttle_out = fopen($acldir . "/dst_throttle_binary.acl", "w");
+ fwrite($throttle_out, $binary_out);
+ fclose($throttle_out);
+ $config_array[] = 'acl for_throttled_binary url_regex -i "' . $acldir . '/dst_throttle_binary.acl"' . "\n";
+ } else {
+ if (file_exists($acldir . "/dst_throttle_binary.acl")) unlink($acldir . "/dst_throttle_binary.acl");
+ }
+ unset($throttle_binary_files);
+ unset($throttle_out);
+ unset($binary_out);
+
+ if (isset($throttle_cd_images) && ($throttle_cd_images == "on")) {
+ if (!file_exists($acldir)) {
+ mwexec("/bin/mkdir -p " . $acldir);
+ }
+
+ $cd_out = "\.b5t$\n\.bin$\n\.bwt$\n\.cdi$\n\.cue$\n\.gho$\n\.img$\n\.iso$\n\.mds$\n\.nrg$\n\.pqi$\n";
+
+ $throttle_out = fopen($acldir . "/dst_throttle_cd.acl","w");
+ fwrite($throttle_out, $cd_out);
+ fclose($throttle_out);
+ $config_array[] = 'acl for_throttled_cd url_regex -i "' . $acldir . '/dst_throttle_cd.acl"' . "\n";
+ } else {
+ if (file_exists($acldir . "/dst_throttle_cd.acl")) {
+ unlink($acldir . "/dst_throttle_cd.acl");
+ }
+ }
+ unset($throttle_cd_images);
+ unset($throttle_out);
+ unset($cd_out);
+
+ if (isset($throttle_multimedia) && ($throttle_multimedia == "on")) {
+ if (!file_exists($acldir)) {
+ mwexec("/bin/mkdir -p " . $acldir);
+ }
+
+ $multimedia_out = "\.aiff?$\n\.asf$\n\.avi$\n\.divx$\n\.mov$\n\.mp3$\n\.mpe?g$\n\.qt$\n\.ra?m$\n";
+
+ $throttle_out = fopen($acldir . "/dst_throttle_multimedia.acl","w");
+ fwrite($throttle_out, $multimedia_out);
+ fclose($throttle_out);
+ $config_array[] = 'acl for_throttled_multimedia url_regex -i "' . $acldir . '/dst_throttle_multimedia.acl"' . "\n";
+ } else {
+ if (file_exists($acldir . "/dst_throttle_multimedia.acl")) {
+ unlink($acldir . "/dst_throttle_multimedia.acl");
+ }
+ }
+ unset($throttle_multimedia);
+ unset($multimedia_out);
+ unset($throttle_out);
+
+ $config_array[] = 'acl within_timeframe time MTWHFAS 00:00-24:00' . "\n\n";
+
+ /* obtain interface subnet and address for Squid rules */
+ $lactive_interface = strtolower($active_interface);
+
+ $lancfg = $config['interfaces'][$lactive_interface];
+ $lanif = $lancfg['if'];
+ $lanip = $lancfg['ipaddr'];
+ $lansa = gen_subnet($lancfg['ipaddr'], $lancfg['subnet']);
+ $lansn = $lancfg['subnet'];
+
+ $config_array[] = 'acl all src 0.0.0.0/0.0.0.0' . "\n";
+ $config_array[] = 'acl localnet src ' . $lansa . '/' . $lansn . "\n";
+ $config_array[] = 'acl localhost src 127.0.0.1/255.255.255.255' . "\n";
+ $config_array[] = 'acl SSL_ports port 443 563 873 # https, snews, rsync' . "\n";
+ $config_array[] = 'acl Safe_ports port 80 # http' . "\n";
+ $config_array[] = 'acl Safe_ports port 21 # ftp' . "\n";
+ $config_array[] = 'acl Safe_ports port 443 563 873 # https, snews, rsync' . "\n";
+ $config_array[] = 'acl Safe_ports port 70 # gopher' . "\n";
+ $config_array[] = 'acl Safe_ports port 210 # wais' . "\n";
+ $config_array[] = 'acl Safe_ports port 1025-65535 # unregistered ports' . "\n";
+ $config_array[] = 'acl Safe_ports port 280 # http-mgmt' . "\n";
+ $config_array[] = 'acl Safe_ports port 488 # gss-http' . "\n";
+ $config_array[] = 'acl Safe_ports port 591 # filemaker' . "\n";
+ $config_array[] = 'acl Safe_ports port 777 # multiling http' . "\n";
+ $config_array[] = 'acl Safe_ports port 800 # Squids port (for icons)' . "\n\n";
+
+ /* allow access through proxy for custom admin port */
+ $custom_port = $config['system']['webgui']['port'];
+ if (isset($custom_port) && ($custom_port !== "")) {
+ $config_array[] = 'acl pf_admin_port port ' . $custom_port . "\n";
+ unset($custom_port);
+ } else {
+ $admin_protocol = $config['system']['webgui']['protocol'];
+ switch ($admin_protocol) {
+ case "http";
+ $config_array[] = 'acl pf_admin_port port 80' ."\n";
+ break;
+ case "https";
+ $config_array[] = 'acl pf_admin_port port 443' . "\n";
+ break;
+ default;
+ $config_array[] = 'acl pf_admin_port port 80' . "\n";
+ break;
+ }
+ unset($admin_protocol);
+ }
+
+ /* define override hosts as specified in squid_nac.xml */
+ if (isset($override_hosts) && ($override_hosts !== "")) {
+ if (!file_exists($acldir)) {
+ mwexec("/bin/mkdir -p " . $acldir);
+ }
+
+ $aclout = fopen($acldir . "/src_override_hosts.acl", "w");
+
+ $override_hosts_array = split("; ", $override_hosts);
+ foreach ($override_hosts_array as $ind_override_host) {
+ fwrite($aclout, $ind_override_host . "\n");
+ }
+
+ fclose($aclout);
+
+ $config_array[] = 'acl override_hosts src "/usr/local/etc/squid/advanced/acls/src_override_hosts.acl"' . "\n";
+ }
+ /* clear variables */
+ unset($override_hosts_array);
+ unset($ind_override_host);
+ unset($override_hosts);
+
+ /* define subnets allowed to utilize proxy service */
+ if (isset($allowed_subnets) && ($allowed_subnets !== "")) {
+ if (!file_exists($acldir)) {
+ mwexec("/bin/mkdir -p " . $acldir);
+ mwexec("touch {$acldir}/src_subnets.acl");
+ }
+
+ $aclout = fopen($acldir . "/src_subnets.acl","w");
+
+ $allowed_subnets_array = split("; ",$allowed_subnets);
+ foreach ($allowed_subnets_array as $ind_allowed_subnets) {
+ fwrite($aclout, $ind_allowed_subnets . "\n");
+ }
+
+ fclose($aclout);
+ } else {
+
+ $aclout = fopen($acldir . "/src_subnets.acl","w");
+ fwrite($aclout, $lansa . "/" . $lansn . "\n");
+ fclose($aclout);
+ }
+
+ $config_array[] = 'acl pf_networks src "/usr/local/etc/squid/advanced/acls/src_subnets.acl"' . "\n";
+
+ unset($allowed_subnets_array);
+ unset($ind_allowed_subnets);
+ unset($allowed_subnets);
+
+ /* define ip addresses that have 'unrestricted' access */
+ if (isset($unrestricted_ip_addr) && ($unrestricted_ip_addr !== "")) {
+ if (!file_exists($acldir)) {
+ mwexec("/bin/mkdir -p " . $acldir);
+ }
+
+ $aclout = fopen($acldir . "/src_unrestricted_ip.acl","w");
+
+ $unrestricted_ip_array = split("; ",$unrestricted_ip_addr);
+ foreach ($unrestricted_ip_array as $ind_unrestricted_ip) {
+ fwrite($aclout, $ind_unrestricted_ip . "\n");
+ }
+
+ fclose($aclout);
+
+ $config_array[] = 'acl pf_unrestricted_ip src "/usr/local/etc/squid/advanced/acls/src_unrestricted_ip.acl"' . "\n";
+ }
+ unset($unrestricted_ip_array);
+ unset($unrestricted_ip_addr);
+ unset($ind_unrestricted_ip);
+
+ /* define mac addresses that have 'unrestricted' access */
+ if (isset($unrestricted_mac_addr) && ($unrestricted_mac_addr !== "")) {
+ if (!file_exists($acldir)) {
+ mwexec("/bin/mkdir -p " . $acldir);
+ }
+
+ $aclout = fopen($acldir . "/src_unrestricted_mac.acl","w");
+
+ $unrestricted_mac_array = split("; ",$unrestricted_mac_addr);
+ foreach ($unrestricted_mac_array as $ind_unrestricted_mac) {
+ fwrite($aclout, $ind_unrestricted_mac . "\n");
+ }
+
+ fclose($aclout);
+
+ $config_array[] = 'acl pf_unrestricted_mac src "/usr/local/etc/squid/advanced/acls/src_unrestricted_mac.acl"' . "\n";
+ }
+ unset($unrestricted_mac_array);
+ unset($unrestricted_mac_addr);
+ unset($ind_unrestricted_mac);
+
+ /* define ip addresses that are banned from using the proxy service */
+ if (isset($banned_ip_addr) && ($banned_ip_addr !== "")) {
+ if (!file_exists($acldir)) {
+ mwexec("/bin/mkdir -p " . $acldir);
+ }
+
+ $aclout = fopen($acldir . "/src_banned_ip.acl","w");
+
+ $banned_ip_array = split("; ",$banned_ip_addr);
+ foreach ($banned_ip_array as $ind_banned_ip) {
+ fwrite($aclout, $ind_banned_ip . "\n");
+ }
+
+ fclose($aclout);
+
+ $config_array[] = 'acl pf_banned_ip src "/usr/local/etc/squid/advanced/acls/src_banned_ip.acl"' . "\n";
+ }
+ unset($banned_ip_addr);
+ unset($banned_ip_addr);
+ unset($ind_banned_ip);
+
+ /* define mac addresses that are banned from using the proxy service */
+ if (isset($banned_mac_addr) && ($banned_mac_addr !== "")) {
+ if (!file_exists($acldir)) {
+ mwexec("/bin/mkdir -p " . $acldir);
+ }
+
+ $aclout = fopen($acldir . "/src_banned_mac.acl","w");
+
+ $banned_mac_array = split("; ",$banned_mac_addr);
+ foreach ($banned_mac_array as $ind_banned_mac) {
+ fwrite($aclout, $ind_banned_mac . "\n");
+ }
+
+ fclose($aclout);
+
+ $config_array[] = 'acl pf_banned_mac src "/usr/local/etc/squid/advanced/acls/src_banned_mac.acl"' . "\n";
+ }
+ unset($banned_mac_array);
+ unset($banned_mac_addr);
+ unset($ind_banned_mac);
+
+ $config_array[] = 'acl pf_ips dst ' . $lanip . "\n";
+ $config_array[] = 'acl CONNECT method CONNECT' . "\n\n";
+
+ if (isset($auth_method) && ($auth_method == "none")) {
+ $config_array[] = 'http_access allow localnet' . "\n";
+ }
+ $config_array[] = 'http_access allow localhost' . "\n";
+
+ if (isset($override_hosts) && ($override_hosts !== "")) {
+ $config_array[] = 'http_access allow override_hosts' . "\n";
+ }
+ $config_array[] = "\n";
+
+ switch ($config['system']['webgui']['protocol']) {
+ case "http":
+ $config_array[] = 'http_access allow pf_ips' . "\n";
+ $config_array[] = 'http_access allow pf_admin_port' . "\n";
+ $config_array[] = 'http_access deny !pf_networks' . "\n\n";
+ break;
+ case "https":
+ $config_array[] = 'http_access allow CONNECT pf_ips' . "\n";
+ $config_array[] = 'http_access allow CONNECT pf_admin_port' . "\n";
+ $config_array[] = 'http_access deny CONNECT !pf_networks' . "\n\n";
+ break;
+ }
+
+ $config_array[] = 'http_access deny !Safe_ports' . "\n";
+ $config_array[] = 'http_access deny CONNECT !SSL_ports' . "\n\n";
+
+ if (isset($auth_method) && ($auth_method != "none")) {
+ $config_array[] = 'http_access allow pf_networks for_inetusers within_timeframe' . "\n";
+ }
+
+ $config_array[] = 'http_access deny all' . "\n\n";
+
+ if (isset($dl_overall) && ($dl_overall !== "") and isset($dl_per_host) && ($dl_per_host == "")) {
+ $config_array[] = 'delay_pools 1' . "\n";
+ $config_array[] = 'delay_class 1 3' . "\n";
+
+ if ($dl_overall == "unlimited") {
+ $config_array[] = 'delay_parameters 1 -1/-1 -1/-1 ' . ($dl_overall * 125) . '/' . ($dl_overall * 250) . "\n";
+ } else {
+ $config_array[] = 'delay_parameters 1 ' . ($dl_overall * 125) . '/' . ($dl_overall * 250) . ' -1/-1 -1/-1' . "\n";
+ }
+
+ /* if no unrestricted ip addresses are defined; this line is ignored */
+ if (isset($unrestricted_ip_addr) && ($unrestricted_ip_addr == "")) $config_array[] = 'delay_access 1 deny pf_unrestricted_ip' . "\n";
+
+ /* this will define bandwidth delay restrictions for specified throttles */
+ if (isset($throttle_binary_files) && ($throttle_binary_files == "on")) {
+ $config_array[] = 'delay_access 1 allow all for_throttled_binary' . "\n";
+ }
+ if (isset($throttle_cd_images) && ($throttle_cd_images == "on")) {
+ $config_array[] = 'delay_access 1 allow all for_throttled_cd' . "\n";
+ }
+ if (isset($throttle_multimedia) && ($throttle_multimedia == "on")) {
+ $config_array[] = 'delay_access 1 allow all for_throttled_multimedia' . "\n";
+ } else {
+ $config_array[] = 'delay_access 1 allow all' . "\n";
+ }
+ $config_array[] = 'delay_initial_bucket_level 100%' . "\n\n";
+ }
+
+ if (isset($dl_per_host) && ($dl_per_host !== "") and isset($dl_overall) && ($dl_overall == "")) {
+ $config_array[] = 'delay_pools 1' . "\n";
+ $config_array[] = 'delay_class 1 3' . "\n";
+
+ if ($dl_per_host == "unlimited") {
+ $config_array[] = 'delay_parameters 1 ' . ($dl_per_host * 125) . '/' . ($dl_per_host * 250) . '-1/-1 -1/-1' . "\n";
+ } else {
+ $config_array[] = 'delay_parameters 1 -1/-1 -1/-1 ' . ($dl_per_host * 125) . '/' . ($dl_per_host * 250) . "\n";
+ }
+
+ /* if no unrestricted ip addresses are defined; this line is ignored */
+ if (isset($unrestricted_ip_addr) && ($unrestricted_ip_addr !== "")) $config_array[] = 'delay_access 1 deny pf_unrestricted_ip' . "\n";
+
+ /* this will define bandwidth delay restrictions for specified throttles */
+ if ($throttle_binary_files == "on") {
+ $config_array[] = 'delay_access 1 allow all for_throttled_binary' . "\n";
+ }
+ if ($throttle_cd_images == "on") {
+ $config_array[] = 'delay_access 1 allow all for_throttled_cd' . "\n";
+ }
+ if ($throttle_multimedia == "on") {
+ $config_array[] = 'delay_access 1 allow all for_throttled_multimedia' ."\n";
+ } else {
+ $config_array[] = 'delay_access 1 allow all' . "\n";
+ }
+ $config_array[] = 'delay_initial_bucket_level 100%' . "\n\n\n";
+ }
+
+ if (isset($dl_overall) && ($dl_overall !== "") and isset($dl_per_host) && ($dl_per_host !== "")) {
+ /* if no bandwidth restrictions are specified, then these parameters are not necessary */
+ if ($dl_overall !== "unlimited" and $dl_per_host !== "unlimited") {
+
+ if ((isset($dl_overall) && ($dl_overall == "unlimited")) and (isset($dl_per_host) && ($dl_per_host !== ""))) {
+ $config_array[] = 'delay_pools 1' . "\n";
+ $config_array[] = 'delay_class 1 3' . "\n";
+ $config_array[] = 'delay_parameters 1 -1/-1 -1/-1 ' . ($dl_per_host * 125) . '/' . ($dl_overall * 250) . "\n";
+ } elseif (isset($dl_overall) && ($dl_overall !== "") and isset($dl_per_host) && ($dl_per_host == "unlimited")) {
+ $config_array[] = 'delay_pools 1' . "\n";
+ $config_array[] = 'delay_class 1 3' . "\n";
+ $config_array[] = 'delay_parameters 1 ' . ($dl_overall * 125) . '/' . ($dl_overall * 250) . ' -1/-1 -1/-1' . "\n";
+ }
+ }
+
+ if ($dl_overall !== "unlimited" and $dl_per_host !== "unlimited") {
+
+ /* if no unrestricted ip addresses are defined; this line is ignored */
+ if (isset($unrestricted_ip_addr) && ($unrestricted_ip_addr !== "")) $config_array[] = 'delay_access 1 deny pf_unrestricted_ip' . "\n";
+
+ /* this will define bandwidth delay restrictions for specified throttles */
+ if ($throttle_binary_files == "on") {
+ $config_array[] = 'delay_access 1 allow all for_throttled_binary' . "\n";
+ }
+ if ($throttle_cd_images == "on") {
+ $config_array[] = 'delay_access 1 allow all for_throttled_cd' . "\n";
+ }
+ if ($throttle_multimedia == "on") {
+ $config_array[] = 'delay_access 1 allow all for_throttled_multimedia' . "\n";
+ } else {
+ $config_array[] = 'delay_access 1 allow all' . "\n";
+ }
+ $config_array[] = 'delay_initial_bucket_level 100%' . "\n\n";
+ }
+ }
+
+ $config_array[] = 'header_access X-Forwarded-For deny all' . "\n";
+ $config_array[] = 'header_access Via deny all' . "\n\n";
+
+ /* TODO: acl customization for snmp support */
+ /* fwrite($fout, "\n"); */
+
+ if (isset($urlfilter_enable) && ($urlfilter_enable == "on")) {
+ $config_array[] = 'redirect_program /usr/sbin/squidGuard' . "\n";
+ $config_array[] = 'redirect_children 5' . "\n\n";
+ }
+
+ if (isset($max_upload_size) && ($max_upload_size != "")) {
+ $config_array[] = 'request_body_max_size ' . $max_download_size . 'KB' . "\n";
+ }
+
+ if (isset($max_download_size) && ($max_download_size != "")) {
+ if (isset($unrestricted_ip_addr) && ($unrestricted_ip_addr !== "")) $config_array[] = 'reply_body_max_size 0 allow pf_unrestricted_ip' . "\n";
+ /* fwrite($fout, "#reply_body_max_size 0 allow for_extended_users\n"); */
+ $config_array[] = 'reply_body_max_size ' . $max_download_size * 1024 . ' allow all' . "\n\n";
+ }
+
+ /* set default value for maximum_object_size */
+ if (!isset($maximum_object_size) or ($maximum_object_size == "")) {
+ $maximum_object_size = "4096";
+ }
+
+ /* set default value for minimum_object_size */
+ if (!isset($minimum_object_size) or ($minimum_object_size == "")) {
+ $minimum_object_size = "0";
+ }
+ $config_array[] = 'maximum_object_size ' . $maximum_object_size . ' KB' . "\n";
+ $config_array[] = 'minimum_object_size ' . $minimum_object_size . ' KB' . "\n\n";
+
+ if (isset($proxy_forwarding) && ($proxy_forwarding == "on")) {
+ $config_array[] = 'cache_peer ' . $upstream_proxy . ' parent ' . $upstream_proxy_port . ' 3130 login=' . upstream_username . ':' . upstream_password . ' default no-query' . "\n";
+ $config_array[] = 'never_direct allow all' . "\n";
+ }
+ unset($proxy_forwarding);
+
+
+ /* define default ruleset for transparent proxy operation */
+ if (isset($transparent_proxy) && ($transparent_proxy == "on")) {
+ $config_array[] = 'httpd_accel_host virtual' . "\n";
+ $config_array[] = 'httpd_accel_port 80' . "\n";
+ $config_array[] = 'httpd_accel_with_proxy on' . "\n";
+ $config_array[] = 'httpd_accel_uses_host_header on' . "\n\n";
+ }
+ unset($transparent_proxy);
+
+
+ /* define visible hostname */
+ if (isset($visible_hostname) && ($visible_hostname !== "")) {
+ $config_array[] = 'visible_hostname ' . $visible_hostname . "\n";
+ }
+ unset($visible_hostname);
+
+ /* define cache administrators email address within error messages */
+ if (isset($cache_admin_email) && ($cache_admin_email !== "")) {
+ $config_array[] = 'cache_mgr ' . $cache_admin_email . "\n\n";
+ }
+ unset($cache_admin_email);
+
+ /* write configuration file */
+ foreach ($config_array as $config_item)
+ {
+ fwrite($fout, trim($config_item));
+
+ if (stristr($config_item, "\n"))
+ {
+ for ($i = 1; $i < count(explode("\n", $config_item)); $i++)
+ {
+ fwrite($fout, "\n");
+ }
+ }
+
+ }
+ fclose($fout);
+
+ conf_mount_ro();
+ config_unlock();
+
+ touch($squidconfig);
+} /* end function write_squid_config */
+
+function custom_php_install_command() {
+ /* write initial static config for transparent proxy */
+ write_static_squid_config();
+
+ touch("/tmp/custom_php_install_command");
+
+ /* make sure this all exists, see:
+ * http://forum.pfsense.org/index.php?topic=23.msg2391#msg2391
+ */
+ update_output_window("Setting up Squid environment...");
+ mwexec("mkdir -p /var/squid");
+ mwexec("chown squid:squid /var/squid");
+ mwexec("mkdir -p /var/squid/logs");
+ mwexec("chown squid:squid /var/squid/logs");
+ mwexec("mkdir -p /var/squid/cache");
+ mwexec("chown squid:squid /var/squid/cache");
+ mwexec("mkdir -p /usr/local/etc/squid/advanced");
+ mwexec("chown squid:squid /usr/local/etc/squid/advanced");
+ mwexec("mkdir -p /usr/local/etc/squid/advanced/acls");
+ mwexec("chown squid:squid /usr/local/etc/squid/advanced/acls");
+ mwexec("touch /usr/local/etc/squid/advanced/acls/src_subnets.acl");
+ mwexec("chown squid:squid /usr/local/etc/squid/advanced/acls/src_subnets.acl");
+ mwexec("touch /usr/local/etc/squid/advanced/acls/src_unrestricted_ip.acl");
+ mwexec("chown squid:squid /usr/local/etc/squid/advanced/acls/src_unrestricted_ip.acl");
+ mwexec("cp /usr/local/etc/squid/mime.conf.default /usr/local/etc/squid/mime.conf");
+
+
+ /* set a few extra items noted by regan */
+ update_output_window("Creating logs and setting user information...");
+ $fdsquid = fopen("/usr/local/etc/rc.d/aSquid.sh", "w");
+ fwrite($fdsquid, "#/bin/sh\n");
+ fwrite($fdsquid, "# \n");
+ fwrite($fdsquid, "# This file was created by the pfSense package system\n");
+ fwrite($fdsquid, "# Sets up squid option on each bootup that are not persistent\n");
+ fwrite($fdsquid, "# \n\n");
+ fwrite($fdsquid, "chown squid:wheel /dev/pf\n");
+ fwrite($fdsquid, "chmod ug+rw /dev/pf\n");
+ fwrite($fdsquid, "touch /var/log/useragent.log\n");
+ fwrite($fdsquid, "touch /var/log/access.log\n");
+ fwrite($fdsquid, "touch /var/log/cache.log\n");
+ fwrite($fdsquid, "chown squid:wheel /var/log/cache.log\n");
+ fwrite($fdsquid, "chown squid:wheel /var/log/access.log\n");
+ fwrite($fdsquid, "chown squid:wheel /var/log/useragent.log\n");
+ fwrite($fdsquid, "\n");
+ fclose($fdsquid);
+ mwexec("chmod a+rx /usr/local/etc/rc.d/aSquid.sh");
+ mwexec("/usr/local/etc/rc.d/aSquid.sh");
+
+ update_output_window("Creating Proxy Server initialization scripts...");
+ $start = "touch /tmp/ro_root_mount; /usr/local/sbin/squid -D; touch /tmp/filter_dirty";
+ $stop = "/usr/local/sbin/squid -k shutdown";
+ write_rcfile(array(
+ "file" => "squid.sh",
+ "start" => $start,
+ "stop" => $stop
+ )
+ );
+
+ mwexec("chmod 755 /usr/local/etc/rc.d/squid.sh");
+
+ /* create log directory hierarchies if they don't exist */
+ update_output_window("Creating required directory hierarchies...");
+
+ if (!file_exists("/var/squid/logs")) {
+ mwexec("mkdir -p /var/squid/logs");
+ }
+ mwexec("/usr/sbin/chown squid:squid /var/squid/logs");
+
+
+ if (!file_exists("/var/squid/cache")) {
+ mwexec("mkdir -p /var/squid/cache");
+ }
+ mwexec("/usr/sbin/chown squid:squid /var/squid/cache");
+
+ if (!file_exists("/usr/local/etc/squid/advanced/acls")) {
+ mwexec("mkdir -p /usr/local/etc/squid/advanced/acls");
+ }
+ mwexec("/usr/sbin/chown squid:squid /usr/local/etc/squid/advanced/acls");
+
+ if (!file_exists("/usr/local/etc/squid/advanced/ncsa")) {
+ mwexec("mkdir -p /usr/local/etc/squid/advanced/ncsa");
+ }
+ mwexec("/usr/sbin/chown squid:squid /usr/local/etc/squid/advanced/ncsa");
+
+ if (!file_exists("/usr/local/etc/squid/advanced/ntlm")) {
+ mwexec("mkdir -p /usr/local/etc/squid/advanced/ntlm");
+ }
+ mwexec("/usr/sbin/chown squid:squid /usr/local/etc/squid/advanced/ntlm");
+
+ if (!file_exists("/usr/local/etc/squid/advanced/radius")) {
+ mwexec("mkdir -p /usr/local/etc/squid/advanced/radius");
+ }
+ mwexec("/usr/sbin/chown squid:squid /usr/local/etc/squid/advanced/radius");
+
+ $devfs_file = fopen("/etc/devfs.conf", "a");
+ fwrite($devfs_file, "\n# Allow squid to query the packet filter bymaking is group-accessable. ");
+ fwrite($devfs_file, "own pf root:squid");
+ fwrite($devfs_file, "perm pf 0640");
+ fclose($devfs_file);
+
+ update_output_window("Initializing Cache... This may take a moment...");
+ mwexec("/usr/local/sbin/squid -z");
+
+ update_output_window("Starting Proxy Server...");
+ start_service("squid");
+}
+
+function custom_php_deinstall_command() {
+ update_output_window("Stopping proxy service...");
+ stop_service("squid");
+ sleep(1);
+ /* brute force any remaining squid processes out */
+ mwexec("/usr/bin/killall squid");
+ mwexec("/usr/bin/killall pinger");
+ update_output_window("Recursively removing directories hierarchies. If existant, log files in /var/squid/logs will remain...");
+ mwexec("rm -rf /var/squid/cache");
+ update_output_window("Removing configuration files...");
+ unlink_if_exists("/usr/local/etc/rc.d/squid.sh");
+ unlink_if_exists("/usr/local/libexec/squid");
+ unlink_if_exists("/usr/local/etc/rc.d/aSquid.sh");
+ mwexec("rm -f /usr/local/etc/rc.d/squid*");
+ mwexec("rm -f /usr/local/www/cachemgr.cgi");
+ filter_configure();
+}
+
+function write_static_squid_config() {
+ touch("/tmp/write_static_squid_config");
+ global $config;
+ $lancfg = $config['interfaces']['lan'];
+ $lanif = $lancfg['if'];
+ $lanip = $lancfg['ipaddr'];
+ $lansa = gen_subnet($lancfg['ipaddr'], $lancfg['subnet']);
+ $lansn = $lancfg['subnet'];
+
+ $fout = fopen("/usr/local/etc/squid/squid.conf","w");
+ fwrite($fout, "#\n");
+ fwrite($fout, "# This file was automatically generated by the pfSense package manager.\n");
+ fwrite($fout, "# This default policy enables transparent proxy with no local disk logging.\n");
+ fwrite($fout, "#\n");
+
+ /* set # of dns children */
+ fwrite($fout, "dns_children 15\n");
+
+ fwrite($fout, "shutdown_lifetime 5 seconds\n");
+ fwrite($fout, "icp_port 0\n");
+ fwrite($fout, "\n");
+
+ fwrite($fout, "acl QUERY urlpath_regex cgi-bin \?\n");
+ fwrite($fout, "no_cache deny QUERY\n");
+ fwrite($fout, "\n");
+
+ fwrite($fout, "pid_filename /var/run/squid.pid\n");
+ fwrite($fout, "\n");
+
+ fwrite($fout, "cache_mem 24 MB\n");
+ fwrite($fout, "cache_dir diskd /var/squid/cache 500 16 256\n");
+ fwrite($fout, "\n");
+
+ fwrite($fout, "error_directory /usr/local/etc/squid/errors/English\n");
+ fwrite($fout, "\n");
+
+ fwrite($fout, "memory_replacement_policy heap GDSF\n");
+ fwrite($fout, "cache_replacement_policy heap GDSF\n");
+ fwrite($fout, "\n");
+
+ fwrite($fout, "cache_access_log none\n");
+ fwrite($fout, "cache_log none\n");
+ fwrite($fout, "cache_store_log none\n");
+ fwrite($fout, "\n");
+
+ fwrite($fout, "log_mime_hdrs off\n");
+ fwrite($fout, "emulate_httpd_log on\n");
+ fwrite($fout, "forwarded_for off\n");
+ fwrite($fout, "\n");
+
+ fwrite($fout, "acl within_timeframe time MTWHFAS 00:00-24:00\n");
+ fwrite($fout, "\n");
+
+ fwrite($fout, "acl all src 0.0.0.0/0.0.0.0\n");
+ fwrite($fout, "acl localnet src " . $lansa . "/" . $lansn . "\n");
+ fwrite($fout, "acl localhost src 127.0.0.1/255.255.255.255\n");
+ fwrite($fout, "acl SSL_ports port 443 563 873 # https, snews, rsync\n");
+ fwrite($fout, "acl Safe_ports port 80 # http\n");
+ fwrite($fout, "acl Safe_ports port 21 # ftp\n");
+ fwrite($fout, "acl Safe_ports port 443 563 873 # https, snews, rsync\n");
+ fwrite($fout, "acl Safe_ports port 70 # gopher\n");
+ fwrite($fout, "acl Safe_ports port 210 # wais\n");
+ fwrite($fout, "acl Safe_ports port 1025-65535 # unregistered ports\n");
+ fwrite($fout, "acl Safe_ports port 280 # http-mgmt\n");
+ fwrite($fout, "acl Safe_ports port 488 # gss-http\n");
+ fwrite($fout, "acl Safe_ports port 591 # filemaker\n");
+ fwrite($fout, "acl Safe_ports port 777 # multiling http\n");
+ fwrite($fout, "acl Safe_ports port 800 # Squids port (for icons)\n");
+ fwrite($fout, "\n");
+
+ fwrite($fout, "acl CONNECT method CONNECT\n");
+ fwrite($fout, "\n");
+
+ fwrite($fout, "#access to squid; local machine; no restrictions\n");
+ fwrite($fout, "http_access allow localnet\n");
+ fwrite($fout, "http_access allow localhost\n");
+ fwrite($fout, "\n");
+
+ fwrite($fout, "#Deny non web services\n");
+ fwrite($fout, "http_access deny !Safe_ports\n");
+ fwrite($fout, "http_access deny CONNECT !SSL_ports\n");
+ fwrite($fout, "\n");
+
+ fwrite($fout, "#Set custom configured ACLs\n");
+ fwrite($fout, "http_access deny all\n");
+ fwrite($fout, "visible_hostname pfSense\n");
+ fwrite($fout, "\n");
+
+ fwrite($fout, "cache_effective_user squid\n");
+ fwrite($fout, "cache_effective_group squid\n");
+ fwrite($fout, "\n");
+
+ fwrite($fout, "maximum_object_size 4096 KB\n");
+ fwrite($fout, "minimum_object_size 0 KB\n");
+ fwrite($fout, "\n");
+
+ fwrite($fout, "request_body_max_size 0 KB\n");
+ fwrite($fout, "reply_body_max_size 0 allow all\n");
+ fwrite($fout, "\n");
+
+ fwrite($fout, "httpd_accel_host virtual\n");
+ fwrite($fout, "httpd_accel_port 80\n");
+ fwrite($fout, "httpd_accel_with_proxy on\n");
+ fwrite($fout, "httpd_accel_uses_host_header on\n");
+
+ fclose($fout);
+}
+
+function mod_htpasswd() {
+ global $config;
+ conf_mount_rw();
+ config_lock();
+
+ if (!file_exists("/usr/local/etc/squid/advanced/ncsa")) mwexec("mkdir -p /usr/local/etc/squid/advanced/ncsa");
+
+ $passfile = fopen("/usr/local/etc/squid/advanced/ncsa/passwd", "w+");
+
+ if (isset($config['installedpackages']['squidextlocalauth']['config']) && $config['installedpackages']['squidextlocalauth']['config'] != "") {
+ foreach($config['installedpackages']['squidextlocalauth']['config'] as $rowhelper) {
+ $encpass = generate_htpasswd($rowhelper['username'], $rowhelper['password']);
+ fwrite($passfile, $rowhelper['username'] . ":" . $encpass . "\n");
+ }
+ }
+
+ fclose($passfile);
+
+ conf_mount_ro();
+ config_unlock();
+}
+
+function generate_htpasswd($username, $password) {
+ $all = explode( " ",
+ "a b c d e f g h i j k l m n o p q r s t u v w x y z "
+ . "A B C D E F G H I J K L M N O P Q R S T U V W X Y Z "
+ . "0 1 2 3 4 5 6 7 8 9");
+
+ for ($i = 0; $i < 9; $i++) {
+ srand((double)microtime()*1000000);
+ $randy = rand(0,61);
+ $seed .= $all[$randy];
+ }
+
+ $crypt = crypt($password, "$1$$seed");
+ return $crypt;
+}
+
+?>
diff --git a/config/squid/squid_ng.xml b/config/squid/squid_ng.xml
new file mode 100644
index 00000000..5949606e
--- /dev/null
+++ b/config/squid/squid_ng.xml
@@ -0,0 +1,267 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>squid</name>
+ <version>2.5.12_4</version>
+ <title>Services: Proxy Server</title>
+ <category>Security</category>
+ <aftersaveredirect>/pkg_edit.php?xml=squid_ng.xml&amp;id=0</aftersaveredirect>
+ <include_file>/usr/local/pkg/squid_ng.inc</include_file>
+ <menu>
+ <name>Squid</name>
+ <tooltiptext>Modify settings for Proxy Server</tooltiptext>
+ <section>Services</section>
+ <url>/pkg_edit.php?xml=squid_ng.xml&amp;id=0</url>
+ </menu>
+ <menu>
+ <name>Squid stats</name>
+ <tooltiptext>Show Squid statistics</tooltiptext>
+ <section>Services</section>
+ <url>/cachemgr.cgi</url>
+ </menu>
+ <service>
+ <name>squid</name>
+ <rcfile>squid.sh</rcfile>
+ </service>
+ <tabs>
+ <tab>
+ <text>General Settings</text>
+ <url>/pkg_edit.php?xml=squid.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Upstream Proxy</text>
+ <url>/pkg_edit.php?xml=squid_upstream.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Cache Mgmt</text>
+ <url>/pkg_edit.php?xml=squid_cache.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Network Access Control</text>
+ <url>/pkg_edit.php?xml=squid_nac.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Traffic Mgmt</text>
+ <url>/pkg_edit.php?xml=squid_traffic.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Auth Settings</text>
+ <url>/pkg_edit.php?xml=squid_auth.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Extended Auth Settings</text>
+ <url>/pkg_edit.php?xml=squid_extauth.xml&amp;id=0</url>
+ </tab>
+ </tabs>
+ <configpath>installedpackages->package->squidng->configuration->settings</configpath>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/squid/squid_cache.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/squid/squid_nac.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/squid/squid_ng.inc</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/squid/squid_traffic.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/squid/squid_upstream.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/squid/squid_auth.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/squid/squid_auth.inc</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/squid/squid_extauth.xml</item>
+ </additional_files_needed>
+ <fields>
+ <field>
+ <fielddescr>Proxy Listening Interface</fielddescr>
+ <fieldname>active_interface</fieldname>
+ <description>This defines the active listening interface to which the proxy server will listen for its requests.</description>
+ <type>interfaces_selection</type>
+ </field>
+ <field>
+ <fielddescr>Transparent Proxy</fielddescr>
+ <fieldname>transparent_proxy</fieldname>
+ <description>If transparent mode is enabled; all requests for destination port 80 will be forwarded to the proxy server without any additional configuration necessary.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>URL Filtering Enabled</fielddescr>
+ <fieldname>urlfilter_enable</fieldname>
+ <description>This enables the advanced functionality in conjunction with squidGuard to provide an array of URL filtering options. This squidGuard functionality can be additionally configured from Services -> Advanced Proxy Filtering</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Disable Access Log</fielddescr>
+ <fieldname>accesslog_disabled</fieldname>
+ <description>Disable the access log entirely. By default, Squid keeps a log of all requests it processes in /var/log/access.log. This can grow to be fairly large. If you do not require this logging, check this box to disable.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Log Query Terms</fielddescr>
+ <fieldname>log_query_terms</fieldname>
+ <description>This will log the complete URL rather than the part of the URL containing dynamic queries.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Log User Agents</fielddescr>
+ <fieldname>log_user_agents</fieldname>
+ <description>This will enable the useragent string to be written to a separate log. The results are not shown in the GUI and should only be used for debugging purposes.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Proxy Port</fielddescr>
+ <fieldname>proxy_port</fieldname>
+ <description>This is the port the Proxy Server will listen for client requests on. The default is 3128.</description>
+ <type>input</type>
+ <size>4</size>
+ <combinefieldsend>true</combinefieldsend>
+ </field>
+ <field>
+ <fielddescr>ICP Port</fielddescr>
+ <fieldname>icp_port</fieldname>
+ <description>This is the port the Proxy Server will send and receive ICP queries to and from neighbor caches. The default value is 0, which means this function is disabled.</description>
+ <type>input</type>
+ <size>4</size>
+ </field>
+ <field>
+ <fielddescr>Visible Hostname</fielddescr>
+ <fieldname>visible_hostname</fieldname>
+ <description>This URL is displayed on the Proxy Server error messages.</description>
+ <type>input</type>
+ <size>35</size>
+ </field>
+ <field>
+ <fielddescr>Cache Administrator E-Mail</fielddescr>
+ <fieldname>cache_admin_email</fieldname>
+ <description>This E-Mail address is displayed on the Proxy Server error messages.</description>
+ <type>input</type>
+ <size>35</size>
+ </field>
+ <field>
+ <fielddescr>Error Messages Language</fielddescr>
+ <fieldname>error_language</fieldname>
+ <description>Select the language in which the Proxy Server shall display error messages to users.</description>
+ <type>select</type>
+ <options>
+ <option><name>Bulgarian</name><value>Bulgarian</value></option>
+ <option><name>Catalan</name><value>Catalan</value></option>
+ <option><name>Czech</name><value>Czech</value></option>
+ <option><name>Danish</name><value>Danish</value></option>
+ <option><name>Dutch</name><value>Dutch</value></option>
+ <option><name>English</name><value>English</value></option>
+ <option><name>Estonian</name><value>Estonian</value></option>
+ <option><name>Finnish</name><value>Finnish</value></option>
+ <option><name>French</name><value>French</value></option>
+ <option><name>German</name><value>German</value></option>
+ <option><name>Hebrew</name><value>Hebrew</value></option>
+ <option><name>Hungarian</name><value>Hungarian</value></option>
+ <option><name>Italian</name><value>Italian</value></option>
+ <option><name>Japanese</name><value>Japanese</value></option>
+ <option><name>Korean</name><value>Korean</value></option>
+ <option><name>Lithuanian</name><value>Lithuanian</value></option>
+ <option><name>Polish</name><value>Polish</value></option>
+ <option><name>Portuguese</name><value>Portuguese</value></option>
+ <option><name>Romanian</name><value>Romanian</value></option>
+ <option><name>Russian-1251</name><value>Russian-1251</value></option>
+ <option><name>Russian-koi8-r</name><value>Russian-koi8-r</value></option>
+ <option><name>Serbian</name><value>Serbian</value></option>
+ <option><name>Simplify Chinese</name><value>Simplify Chinese</value></option>
+ <option><name>Slovak</name><value>Slovak</value></option>
+ <option><name>Spanish</name><value>Spanish</value></option>
+ <option><name>Swedish</name><value>Swedish</value></option>
+ <option><name>Traditional Chinese</name><value>Traditional Chinese</value></option>
+ <option><name>Turkish</name><value>Turkish</value></option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Enable cachemgr</fielddescr>
+ <fieldname>cachemgr_enabled</fieldname>
+ <description>Enable Squid's cachemgr.cgi to provide stats. Once enabled you can access this from the pfSense menus. &lt;b&gt;Note:&lt;/b&gt; This page is not secured by pfSense, any user with access to the pfSense admin port can view the stats. The page prompts for a password but it only required for shutting down Squid.</description>
+ <type>checkbox</type>
+ </field>
+
+ </fields>
+ <custom_add_php_command_late>
+ global_write_squid_config();
+ mwexec("/usr/local/sbin/squid -k reconfigure");
+ start_service("squid");
+ </custom_add_php_command_late>
+ <custom_php_install_command>
+ custom_php_install_command();
+ write_static_squid_config();
+ mwexec("/usr/local/sbin/squid -k reconfigure");
+ start_service("squid");
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ custom_php_deinstall_command();
+ stop_service("squid");
+ </custom_php_deinstall_command>
+</packagegui>
diff --git a/config/squid/squid_traffic.xml b/config/squid/squid_traffic.xml
new file mode 100644
index 00000000..1330cac9
--- /dev/null
+++ b/config/squid/squid_traffic.xml
@@ -0,0 +1,177 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>squidtraffic</name>
+ <version>none</version>
+ <title>Proxy server: Traffic management</title>
+ <include_file>squid.inc</include_file>
+ <tabs>
+ <tab>
+ <text>General settings</text>
+ <url>/pkg_edit.php?xml=squid.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Upstream proxy</text>
+ <url>/pkg_edit.php?xml=squid_upstream.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Cache management</text>
+ <url>/pkg_edit.php?xml=squid_cache.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Access control</text>
+ <url>/pkg_edit.php?xml=squid_nac.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Traffic management</text>
+ <url>/pkg_edit.php?xml=squid_traffic.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Auth settings</text>
+ <url>/pkg_edit.php?xml=squid_auth.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Local users</text>
+ <url>/pkg.php?xml=squid_users.xml</url>
+ </tab>
+ </tabs>
+ <fields>
+ <field>
+ <fielddescr>Maximum download size</fielddescr>
+ <fieldname>max_download_size</fieldname>
+ <description>Limit the maximum total download size to the size specified here (in kilobytes). Set to 0 to disable.</description>
+ <type>input</type>
+ <required/>
+ <default_value>0</default_value>
+ </field>
+ <field>
+ <fielddescr>Maximum upload size</fielddescr>
+ <fieldname>max_upload_size</fieldname>
+ <description>Limit the maximum total upload size to the size specified here (in kilobytes). Set to 0 to disable.</description>
+ <type>input</type>
+ <required/>
+ <default_value>0</default_value>
+ </field>
+ <field>
+ <fielddescr>Overall bandwidth throttling</fielddescr>
+ <fieldname>overall_throttling</fieldname>
+ <description>This value specifies (in kilobytes per second) the bandwidth throttle for downloads. Users will gradually have their download speed increased according to this value. Set to 0 to disable bandwidth throttling.</description>
+ <type>input</type>
+ <required/>
+ <default_value>0</default_value>
+ </field>
+ <field>
+ <fielddescr>Per-host throttling</fielddescr>
+ <fieldname>perhost_throttling</fieldname>
+ <description>This value specifies the download throttling per host. Set to 0 to disable this.</description>
+ <type>input</type>
+ <required/>
+ <default_value>0</default_value>
+ </field>
+ <field>
+ <fielddescr>Throttle only specific extensions</fielddescr>
+ <fieldname>throttle_specific</fieldname>
+ <description>Leave this checked to be able to choose the extensions that throttling will be applied to. Otherwise, all files will be throttled.</description>
+ <type>checkbox</type>
+ <enablefields>throttle_binaries,throttle_cdimages,throttle_multimedia,throttle_others</enablefields>
+ <default_value>on</default_value>
+ </field>
+ <field>
+ <fielddescr>Throttle binary files</fielddescr>
+ <fieldname>throttle_binaries</fieldname>
+ <description>Check this to apply bandwidth throttle to binary files. This includes compressed archives and executables.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Throttle CD images</fielddescr>
+ <fieldname>throttle_cdimages</fieldname>
+ <description>Check this to apply bandwidth throttle to CD image files.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Throttle multimedia files</fielddescr>
+ <fieldname>throttle_multimedia</fieldname>
+ <description>Check this to apply bandwidth throttle to multimedia files, such as movies or songs.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Throttle other extensions</fielddescr>
+ <fieldname>throttle_others</fieldname>
+ <description>Comma-separated list of extensions to apply bandwidth throttle to.</description>
+ <type>input</type>
+ <size>60</size>
+ </field>
+ <field>
+ <fielddescr>Finish transfer if less than x KB remaining</fielddescr>
+ <fieldname>quick_abort_min</fieldname>
+ <description>If the transfer has less than x KB remaining, it will finish the retrieval. Set to 0 to abort the transfer immediately.</description>
+ <type>input</type>
+ <default_value>0</default_value>
+ </field>
+ <field>
+ <fielddescr>Abort transfer if more than x KB remaining</fielddescr>
+ <fieldname>quick_abort_max</fieldname>
+ <description>If the transfer has more than x KB remaining, it will abort the retrieval. Set to 0 to abort the transfer immediately.</description>
+ <type>input</type>
+ <default_value>0</default_value>
+ </field>
+ <field>
+ <fielddescr>Finish transfer if more than x % finished</fielddescr>
+ <fieldname>quick_abort_pct</fieldname>
+ <description>If more than x % of the transfer has completed, it will finish the retrieval.</description>
+ <type>input</type>
+ <default_value>0</default_value>
+ </field>
+ </fields>
+ <custom_php_validation_command>
+ squid_validate_traffic($_POST, &amp;$input_errors);
+ </custom_php_validation_command>
+ <custom_php_resync_config_command>
+ squid_resync();
+ </custom_php_resync_config_command>
+</packagegui>
diff --git a/config/squid/squid_upstream.xml b/config/squid/squid_upstream.xml
new file mode 100644
index 00000000..1102c672
--- /dev/null
+++ b/config/squid/squid_upstream.xml
@@ -0,0 +1,133 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>squidupstream</name>
+ <version>none</version>
+ <title>Proxy server: Upstream proxy settings</title>
+ <include_file>squid.inc</include_file>
+ <tabs>
+ <tab>
+ <text>General settings</text>
+ <url>/pkg_edit.php?xml=squid.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Upstream proxy</text>
+ <url>/pkg_edit.php?xml=squid_upstream.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Cache management</text>
+ <url>/pkg_edit.php?xml=squid_cache.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Access control</text>
+ <url>/pkg_edit.php?xml=squid_nac.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Traffic management</text>
+ <url>/pkg_edit.php?xml=squid_traffic.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Auth settings</text>
+ <url>/pkg_edit.php?xml=squid_auth.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Local users</text>
+ <url>/pkg.php?xml=squid_users.in</url>
+ </tab>
+ </tabs>
+ <fields>
+ <field>
+ <fielddescr>Enable forwarding</fielddescr>
+ <fieldname>proxy_forwarding</fieldname>
+ <description>This option enables the proxy server to forward requests to an upstream server.</description>
+ <type>checkbox</type>
+ <enablefields>proxy_addr,proxy_port,icp_port,username,password</enablefields>
+ <required/>
+ </field>
+ <field>
+ <fielddescr>Hostname</fielddescr>
+ <fieldname>proxy_addr</fieldname>
+ <description>Enter here the IP address or host name of the upstream proxy.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>TCP port</fielddescr>
+ <fieldname>proxy_port</fieldname>
+ <description>Enter the port to use to connect to the upstream proxy.</description>
+ <type>input</type>
+ <size>5</size>
+ <default_value>3128</default_value>
+ </field>
+ <field>
+ <fielddescr>ICP port</fielddescr>
+ <fieldname>icp_port</fieldname>
+ <description>Enter the port to connect to the upstream proxy for the ICP protocol. Use port number 7 to disable ICP communication between the proxies.</description>
+ <type>input</type>
+ <size>5</size>
+ <default_value>7</default_value>
+ </field>
+ <field>
+ <fielddescr>Username</fielddescr>
+ <fieldname>username</fieldname>
+ <description>If the upstream proxy requires a username, specify it here.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Password</fielddescr>
+ <fieldname>password</fieldname>
+ <description>If the upstream proxy requires a password, specify it here.</description>
+ <type>password</type>
+ </field>
+ </fields>
+ <custom_php_validation_command>
+ squid_validate_upstream($_POST, &amp;$input_errors);
+ </custom_php_validation_command>
+ <custom_php_resync_config_command>
+ squid_resync();
+ </custom_php_resync_config_command>
+</packagegui>
diff --git a/config/squid/squid_users.xml b/config/squid/squid_users.xml
new file mode 100644
index 00000000..34260817
--- /dev/null
+++ b/config/squid/squid_users.xml
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>squidusers</name>
+ <version>none</version>
+ <title>Proxy server: Local users</title>
+ <include_file>squid.inc</include_file>
+ <delete_string>A proxy server user has been deleted.</delete_string>
+ <addedit_string>A proxy server user has been created/modified.</addedit_string>
+ <tabs>
+ <tab>
+ <text>General settings</text>
+ <url>/pkg_edit.php?xml=squid.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Upstream proxy</text>
+ <url>/pkg_edit.php?xml=squid_upstream.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Cache management</text>
+ <url>/pkg_edit.php?xml=squid_cache.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Access control</text>
+ <url>/pkg_edit.php?xml=squid_nac.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Traffic management</text>
+ <url>/pkg_edit.php?xml=squid_traffic.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Auth settings</text>
+ <url>/pkg_edit.php?xml=squid_auth.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Local users</text>
+ <url>/pkg.php?xml=squid_users.xml</url>
+ <active/>
+ </tab>
+ </tabs>
+ <adddeleteeditpagefields>
+ <columnitem>
+ <fielddescr>Username</fielddescr>
+ <fieldname>username</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Description</fielddescr>
+ <fieldname>description</fieldname>
+ </columnitem>
+ </adddeleteeditpagefields>
+ <fields>
+ <field>
+ <fielddescr>Username</fielddescr>
+ <fieldname>username</fieldname>
+ <description>Enter the username here.</description>
+ <type>input</type>
+ <required/>
+ </field>
+ <field>
+ <fielddescr>Password</fielddescr>
+ <fieldname>password</fieldname>
+ <description>Enter the password here.</description>
+ <type>password</type>
+ <required/>
+ </field>
+ <field>
+ <fielddescr>Description</fielddescr>
+ <fieldname>description</fieldname>
+ <description>You may enter a description here for your reference (not parsed).</description>
+ <type>input</type>
+ </field>
+ </fields>
+ <custom_php_resync_config_command>
+ squid_resync_users();
+ </custom_php_resync_config_command>
+</packagegui>
diff --git a/config/squid3/proxy_monitor.sh b/config/squid3/proxy_monitor.sh
new file mode 100644
index 00000000..fab2ee54
--- /dev/null
+++ b/config/squid3/proxy_monitor.sh
@@ -0,0 +1,72 @@
+#!/bin/sh
+# $Id$ */
+#
+# proxy_monitor.sh
+# Copyright (C) 2006 Scott Ullrich
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+set -e
+
+LOOP_SLEEP=55
+
+if [ -f /var/run/squid_alarm ]; then
+ rm /var/run/squid_alarm
+fi
+
+# Sleep 5 seconds on startup not to mangle with existing boot scripts.
+sleep 5
+
+# Squid monitor 1.2
+while [ /bin/true ]; do
+ if [ ! -f /var/run/squid_alarm ]; then
+ NUM_PROCS=`ps auxw | grep "[s]quid -D"|awk '{print $2}'| wc -l | awk '{ print $1 }'`
+ if [ $NUM_PROCS -lt 1 ]; then
+ # squid is down
+ echo "Squid has exited. Reconfiguring filter." | \
+ logger -p daemon.info -i -t Squid_Alarm
+ echo "Attempting restart..." | logger -p daemon.info -i -t Squid_Alarm
+ /usr/local/etc/rc.d/squid.sh start
+ sleep 3
+ echo "Reconfiguring filter..." | logger -p daemon.info -i -t Squid_Alarm
+ /etc/rc.filter_configure_sync
+ touch /var/run/squid_alarm
+ fi
+ fi
+ NUM_PROCS=`ps auxw | grep "[s]quid -D"|awk '{print $2}'| wc -l | awk '{ print $1 }'`
+ if [ $NUM_PROCS -gt 0 ]; then
+ if [ -f /var/run/squid_alarm ]; then
+ echo "Squid has resumed. Reconfiguring filter." | \
+ logger -p daemon.info -i -t Squid_Alarm
+ /etc/rc.filter_configure_sync
+ rm /var/run/squid_alarm
+ fi
+ fi
+ sleep $LOOP_SLEEP
+done
+
+if [ -f /var/run/squid_alarm ]; then
+ rm /var/run/squid_alarm
+fi
+
diff --git a/config/squid3/squid.inc b/config/squid3/squid.inc
new file mode 100644
index 00000000..827ce903
--- /dev/null
+++ b/config/squid3/squid.inc
@@ -0,0 +1,1264 @@
+<?php
+/* $Id$ */
+/*
+ squid.inc
+ Copyright (C) 2006 Scott Ullrich
+ Copyright (C) 2006 Fernando Lemos
+ Copyright (C) 2008 Martin Fuchs
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require_once('globals.inc');
+require_once('config.inc');
+require_once('util.inc');
+require_once('pfsense-utils.inc');
+require_once('pkg-utils.inc');
+require_once('filter.inc');
+require_once('service-utils.inc');
+
+define('SQUID_CONFBASE', '/usr/local/etc/squid');
+define('SQUID_ACLDIR', '/var/squid/acl');
+define('SQUID_PASSWD', '/var/etc/squid.passwd');
+
+$valid_acls = array();
+
+function squid_get_real_interface_address($iface) {
+ global $config;
+
+ $iface = convert_friendly_interface_to_real_interface_name($iface);
+ $line = trim(shell_exec("ifconfig $iface | grep inet | grep -v inet6"));
+ list($dummy, $ip, $dummy2, $netmask) = explode(" ", $line);
+
+ return array($ip, long2ip(hexdec($netmask)));
+}
+
+function squid_chown_recursive($dir, $user, $group) {
+ chown($dir, $user);
+ chgrp($dir, $group);
+ $handle = opendir($dir) ;
+ while (($item = readdir($handle)) !== false) {
+ if (($item != ".") && ($item != "..")) {
+ $path = "$dir/$item";
+ if (is_dir($path))
+ squid_chown_recursive($path, $user, $group);
+ else {
+ chown($path, $user);
+ chgrp($path, $group);
+ }
+ }
+ }
+}
+
+/* setup cache */
+function squid_dash_z() {
+ global $config;
+ $settings = $config['installedpackages']['squidcache']['config'][0];
+ $cachedir =($settings['harddisk_cache_location'] ? $settings['harddisk_cache_location'] : '/var/squid/cache');
+
+ if(!is_dir($cachedir.'/')) {
+ log_error("Creating Squid cache dir $cachedir");
+ make_dirs($cachedir);
+ squid_chown_recursive($cachedir, 'proxy', 'proxy');
+ }
+
+ if(!is_dir($cachedir.'/00/')) {
+ log_error("Creating squid cache subdirs in $cachedir");
+ mwexec("/usr/local/sbin/squid -k shutdown");
+ sleep(5);
+ mwexec("/usr/local/sbin/squid -k kill");
+ mwexec("/usr/local/sbin/squid -z");
+ }
+
+ exec("chmod a+rw /var/squid/cache/swap.state");
+
+}
+
+function squid_is_valid_acl($acl) {
+ global $valid_acls;
+ if(!is_array($valid_acls))
+ return;
+ return in_array($acl, $valid_acls);
+}
+
+function squid_install_command() {
+ global $config;
+ /* migrate existing csv config fields */
+ $settingsauth = $config['installedpackages']['squidauth']['config'][0];
+ $settingscache = $config['installedpackages']['squidcache']['config'][0];
+ $settingsnac = $config['installedpackages']['squidnac']['config'][0];
+
+ /* migrate auth settings */
+ if (!empty($settingsauth['no_auth_hosts'])) {
+ if(strstr($settingsauth['no_auth_hosts'], ",")) {
+ $settingsauth['no_auth_hosts'] = base64_encode(implode("\n", explode(",", $settingsauth['no_auth_hosts'])));
+ $config['installedpackages']['squidauth']['config'][0]['no_auth_hosts'] = $settingsauth['no_auth_hosts'];
+ }
+ }
+
+ /* migrate cache settings */
+ if (!empty($settingscache['donotcache'])) {
+ if(strstr($settingscache['donotcache'], ",")) {
+ $settingscache['donotcache'] = base64_encode(implode("\n", explode(",", $settingscache['donotcache'])));
+ $config['installedpackages']['squidcache']['config'][0]['donotcache'] = $settingscache['donotcache'];
+ }
+ }
+
+ /* migrate nac settings */
+ if(! empty($settingsnac['allowed_subnets'])) {
+ if(strstr($settingsnac['allowed_subnets'], ",")) {
+ $settingsnac['allowed_subnets'] = base64_encode(implode("\n", explode(",", $settingsnac['allowed_subnets'])));
+ $config['installedpackages']['squidnac']['config'][0]['allowed_subnets'] = $settingsnac['allowed_subnets'];
+ }
+ }
+ if(! empty($settingsnac['banned_hosts'])) {
+ if(strstr($settingsnac['banned_hosts'], ",")) {
+ $settingsnac['banned_hosts'] = base64_encode(implode("\n", explode(",", $settingsnac['banned_hosts'])));
+ $config['installedpackages']['squidnac']['config'][0]['banned_hosts'] = $settingsnac['banned_hosts'];
+ }
+ }
+ if(! empty($settingsnac['banned_macs'])) {
+ if(strstr($settingsnac['banned_macs'], ",")) {
+ $settingsnac['banned_macs'] = base64_encode(implode("\n", explode(",", $settingsnac['banned_macs'])));
+ $config['installedpackages']['squidnac']['config'][0]['banned_macs'] = $settingsnac['banned_macs'];
+ }
+ }
+ if(! empty($settingsnac['unrestricted_hosts'])) {
+ if(strstr($settingsnac['unrestricted_hosts'], ",")) {
+ $settingsnac['unrestricted_hosts'] = base64_encode(implode("\n", explode(",", $settingsnac['unrestricted_hosts'])));
+ $config['installedpackages']['squidnac']['config'][0]['unrestricted_hosts'] = $settingsnac['unrestricted_hosts'];
+ }
+ }
+ if(! empty($settingsnac['unrestricted_macs'])) {
+ if(strstr($settingsnac['unrestricted_macs'], ",")) {
+ $settingsnac['unrestricted_macs'] = base64_encode(implode("\n", explode(",", $settingsnac['unrestricted_macs'])));
+ $config['installedpackages']['squidnac']['config'][0]['unrestricted_macs'] = $settingsnac['unrestricted_macs'];
+ }
+ }
+ if(! empty($settingsnac['whitelist'])) {
+ if(strstr($settingsnac['whitelist'], ",")) {
+ $settingsnac['whitelist'] = base64_encode(implode("\n", explode(",", $settingsnac['whitelist'])));
+ $config['installedpackages']['squidnac']['config'][0]['whitelist'] = $settingsnac['whitelist'];
+ }
+ }
+ if(! empty($settingsnac['blacklist'])) {
+ if(strstr($settingsnac['blacklist'], ",")) {
+ $settingsnac['blacklist'] = base64_encode(implode("\n", explode(",", $settingsnac['blacklist'])));
+ $config['installedpackages']['squidnac']['config'][0]['blacklist'] = $settingsnac['blacklist'];
+ }
+ }
+
+ update_status("Writing configuration... One moment please...");
+
+ write_config();
+
+ /* create cache */
+ update_status("Creating squid cache pools... One moment please...");
+ squid_dash_z();
+ /* make sure pinger is executable */
+ if(file_exists("/usr/local/libexec/squid/pinger"))
+ exec("/bin/chmod a+x /usr/local/libexec/squid/pinger");
+ if(file_exists("/usr/local/etc/rc.d/squid"))
+ exec("/bin/rm /usr/local/etc/rc.d/squid");
+ $rc = array();
+ $rc['file'] = 'squid.sh';
+ $rc['start'] = <<<EOD
+if [ -z "`ps auxw | grep "[s]quid -D"|awk '{print $2}'`" ];then
+ /usr/local/sbin/squid -D
+fi
+
+EOD;
+ $rc['stop'] = <<<EOD
+/usr/local/sbin/squid -k shutdown
+# Just to be sure...
+sleep 5
+killall -9 squid 2>/dev/null
+killall pinger 2>/dev/null
+
+EOD;
+ $rc['restart'] = <<<EOD
+if [ -z "`ps auxw | grep "[s]quid -D"|awk '{print $2}'`" ];then
+ /usr/local/sbin/squid -D
+ else
+ /usr/local/sbin/squid -k reconfigure
+ fi
+
+EOD;
+ update_status("Writing rc files... One moment please...");
+ write_rcfile($rc);
+
+ exec("chmod a+rx /usr/local/libexec/squid/dnsserver");
+
+ foreach (array( SQUID_CONFBASE,
+ SQUID_ACLDIR,
+ ) as $dir) {
+ make_dirs($dir);
+ squid_chown_recursive($dir, 'proxy', 'proxy');
+ }
+
+ /* kill any running proxy alarm scripts */
+ update_status("Checking for running processes... One moment please...");
+ log_error("Stopping any running proxy monitors");
+ mwexec("ps awux | grep \"proxy_monitor\" | grep -v \"grep\" | grep -v \"php\" | awk '{ print $2 }' | xargs kill");
+ sleep(1);
+
+ if (!file_exists(SQUID_CONFBASE . '/mime.conf') && file_exists(SQUID_CONFBASE . '/mime.conf.default'))
+ copy(SQUID_CONFBASE . '/mime.conf.default', SQUID_CONFBASE . '/mime.conf');
+
+ update_status("Checking cache... One moment please...");
+ squid_dash_z();
+
+ if (!is_service_running('squid')) {
+ update_status("Starting... One moment please...");
+ log_error("Starting Squid");
+ mwexec_bg("/usr/local/sbin/squid -D");
+ } else {
+ update_status("Reloading Squid for configuration sync... One moment please...");
+ log_error("Reloading Squid for configuration sync");
+ mwexec("/usr/local/sbin/squid -k reconfigure");
+ }
+
+ /* restart proxy alarm scripts */
+ log_error("Starting a proxy monitor script");
+ mwexec_bg("/usr/local/etc/rc.d/proxy_monitor.sh");
+
+ update_status("Reconfiguring filter... One moment please...");
+ filter_configure();
+}
+
+function squid_deinstall_command() {
+ global $config;
+ squid_install_cron(false);
+ $settings = $config['installedpackages']['squidcache']['config'][0];
+ $cachedir =($settings['harddisk_cache_location'] ? $settings['harddisk_cache_location'] : '/var/squid/cache');
+ $logdir = ($settings['log_dir'] ? $settings['log_dir'] : '/var/squid/log');
+
+ mwexec('rm -rf $cachedir');
+ mwexec('rm -rf $logdir');
+ mwexec('rm -f /usr/local/etc/rc.d/proxy_monitor.sh');
+ mwexec("ps awux | grep \"proxy_monitor\" | grep -v \"grep\" | grep -v \"php\" | awk '{ print $2 }' | xargs kill");
+ mwexec("ps awux | grep \"squid\" | grep -v \"grep\" | awk '{ print $2 }' | xargs kill");
+ mwexec("ps awux | grep \"dnsserver\" | grep -v \"grep\" | awk '{ print $2 }' | xargs kill");
+ mwexec("ps awux | grep \"unlinkd\" | grep -v \"grep\" | awk '{ print $2 }' | xargs kill");
+ filter_configure();
+}
+
+function squid_before_form_general($pkg) {
+ $values = get_dir(SQUID_CONFBASE . '/errors/');
+ // Get rid of '..' and '.'
+ array_shift($values);
+ array_shift($values);
+ $name = array();
+ foreach ($values as $value)
+ $names[] = implode(" ", explode("_", $value));
+
+ $i = 0;
+ foreach ($pkg['fields']['field'] as $field) {
+ if ($field['fieldname'] == 'error_language')
+ break;
+ $i++;
+ }
+ $field = &$pkg['fields']['field'][$i];
+
+ for ($i = 0; $i < count($values) - 1; $i++)
+ $field['options']['option'][] = array('name' => $names[$i], 'value' => $values[$i]);
+}
+
+function squid_validate_general($post, $input_errors) {
+ global $config;
+ $icp_port = trim($post['icp_port']);
+ if (!empty($icp_port) && !is_port($icp_port))
+ $input_errors[] = 'You must enter a valid port number in the \'ICP port\' field';
+
+ if (substr($post['log_dir'], -1, 1) == '/')
+ $input_errors[] = 'You may not end log location with an / mark';
+
+ if ($post['log_dir']{0} != '/')
+ $input_errors[] = 'You must start log location with a / mark';
+ if (strlen($post['log_dir']) <= 3)
+ $input_errors[] = "That is not a valid log location dir";
+
+ $log_rotate = trim($post['log_rotate']);
+ if (!empty($log_rotate) && (!is_numeric($log_rotate) or ($log_rotate < 1)))
+ $input_errors[] = 'You must enter a valid number of days \'Log rotate\' field';
+
+ $webgui_port = $config['system']['webgui']['port'];
+ if(($config['system']['webgui']['port'] == "") && ($config['system']['webgui']['protocol'] == "http")) {
+ $webgui_port = 80;
+ }
+ if(($config['system']['webgui']['port'] == "") && ($config['system']['webgui']['protocol'] == "https")) {
+ $webgui_port = 443;
+ }
+
+ if (($post['transparent_proxy'] != 'on') && ($port == $webgui_port)) {
+ $input_errors[] = "You can not run squid on the same port as the webgui";
+ }
+
+ if (($post['transparent_proxy'] != 'on') && ($post['private_subnet_proxy_off'] == 'on')) {
+ $input_errors[] = "You can not bypass traffic to private subnets without using the transparent proxy.";
+ }
+
+ if (($post['transparent_proxy'] != 'on') && !empty($post['defined_ip_proxy_off'])) {
+ $input_errors[] = "You can not bypass traffic from specific IPs without using the transparent proxy.";
+ }
+
+ foreach (array('defined_ip_proxy_off') as $hosts) {
+ foreach (explode(";", $post[$hosts]) as $host) {
+ $host = trim($host);
+ if (!empty($host) && !is_ipaddr($host))
+ $input_errors[] = "The entry '$host' is not a valid IP address";
+ }
+ }
+
+ if(!empty($post['dns_nameservers'])) {
+ $altdns = explode(";", ($post['dns_nameservers']));
+ foreach ($altdns as $dnssrv) {
+ if (!is_ipaddr($dnssrv))
+ $input_errors[] = 'You must enter a valid IP address in the \'Alternate DNS servers\' field';
+ }}
+}
+
+function squid_validate_upstream($post, $input_errors) {
+ if ($post['proxy_forwarding'] == 'on') {
+ $addr = trim($post['proxy_addr']);
+ if (empty($addr))
+ $input_errors[] = 'The field \'Hostname\' is required';
+ else {
+ if (!is_ipaddr($addr) && !is_domain($addr))
+ $input_errors[] = 'You must enter a valid IP address or host name in the \'Proxy hostname\' field';
+ }
+
+ foreach (array('proxy_port' => 'TCP port', 'icp_port' => 'ICP port') as $field => $name) {
+ $port = trim($post[$field]);
+ if (empty($port))
+ $input_errors[] = "The field '$name' is required";
+ else {
+ if (!is_port($port))
+ $input_errors[] = "The field '$name' must contain a valid port number, between 0 and 65535";
+ }
+ }
+ }
+}
+
+function squid_validate_cache($post, $input_errors) {
+ $num_fields = array( 'harddisk_cache_size' => 'Hard disk cache size',
+ 'memory_cache_size' => 'Memory cache size',
+ 'maximum_object_size' => 'Maximum object size',
+ );
+ foreach ($num_fields as $field => $name) {
+ $value = trim($post[$field]);
+ if (!is_numeric($value) || ($value < 0))
+ $input_errors[] = "You must enter a valid value for '$field'";
+ }
+
+ $value = trim($post['minimum_object_size']);
+ if (!is_numeric($value) || ($value < 0))
+ $input_errors[] = 'You must enter a valid value for \'Minimum object size\'';
+
+ if (!empty($post['cache_swap_low'])) {
+ $value = trim($post['cache_swap_low']);
+ if (!is_numeric($value) || ($value > 100))
+ $input_errors[] = 'You must enter a valid value for \'Low-water-mark\'';
+ }
+
+ if (!empty($post['cache_swap_high'])) {
+ $value = trim($post['cache_swap_high']);
+ if (!is_numeric($value) || ($value > 100))
+ $input_errors[] = 'You must enter a valid value for \'High-water-mark\'';
+ }
+
+ if ($post['donotcache'] != "") {
+ foreach (split("\n", $post['donotcache']) as $host) {
+ $host = trim($host);
+ if (!is_ipaddr($host) && !is_domain($host))
+ $input_errors[] = "The host '$host' is not a valid IP or host name";
+ }
+ }
+
+ squid_dash_z();
+
+}
+
+function squid_validate_nac($post, $input_errors) {
+ $allowed_subnets = explode("\n", $post['allowed_subnets']);
+ foreach ($allowed_subnets as $subnet) {
+ $subnet = trim($subnet);
+ if (!empty($subnet) && !is_subnet($subnet))
+ $input_errors[] = "The subnet '$subnet' is not a valid CIDR range";
+ }
+
+ foreach (array( 'unrestricted_hosts', 'banned_hosts') as $hosts) {
+ foreach (explode("\n", $post[$hosts]) as $host) {
+ $host = trim($host);
+ if (!empty($host) && !is_ipaddr($host))
+ $input_errors[] = "The host '$host' is not a valid IP address";
+ }
+ }
+
+ foreach (array('unrestricted_macs', 'banned_macs') as $macs) {
+ foreach (explode("\n", $post[$macs]) as $mac) {
+ $mac = trim($mac);
+ if (!empty($mac) && !is_macaddr($mac))
+ $input_errors[] = "The mac '$mac' is not a valid MAC address";
+ }
+ }
+
+ foreach (explode(",", $post['timelist']) as $time) {
+ $time = trim($time);
+ if (!empty($time) && !squid_is_timerange($time))
+ $input_errors[] = "The time range '$time' is not a valid time range";
+ }
+
+ if(!empty($post['ext_cachemanager'])) {
+ $extmgr = explode(";", ($post['ext_cachemanager']));
+ foreach ($extmgr as $mgr) {
+ if (!is_ipaddr($mgr))
+ $input_errors[] = 'You must enter a valid IP address in the \'External Cache Manager\' field';
+ }}
+}
+
+function squid_validate_traffic($post, $input_errors) {
+ $num_fields = array( 'max_download_size' => 'Maximum download size',
+ 'max_upload_size' => 'Maximum upload size',
+ 'perhost_throttling' => 'Per-host bandwidth throttling',
+ 'overall_throttling' => 'Overall bandwidth throttling',
+ );
+ foreach ($num_fields as $field => $name) {
+ $value = trim($post[$field]);
+ if (!is_numeric($value) || ($value < 0))
+ $input_errors[] = "The field '$name' must contain a positive number";
+ }
+
+ if (!empty($post['quick_abort_min'])) {
+ $value = trim($post['quick_abort_min']);
+ if (!is_numeric($value))
+ $input_errors[] = "The field 'Finish when remaining KB' must contain a positive number";
+ }
+
+ if (!empty($post['quick_abort_max'])) {
+ $value = trim($post['quick_abort_max']);
+ if (!is_numeric($value))
+ $input_errors[] = "The field 'Abort when remaining KB' must contain a positive number";
+ }
+
+ if (!empty($post['quick_abort_pct'])) {
+ $value = trim($post['quick_abort_pct']);
+ if (!is_numeric($value) || ($value > 100))
+ $input_errors[] = "The field 'Finish when remaining %' must contain a percentaged value";
+ }
+
+}
+
+function squid_validate_auth($post, $input_errors) {
+ $num_fields = array( array('auth_processes', 'Authentication processes', 1),
+ array('auth_ttl', 'Authentication TTL', 0),
+ );
+ foreach ($num_fields as $field) {
+ $value = trim($post[$field[0]]);
+ if (!empty($value) && (!is_numeric($value) || ($value < $field[2])))
+ $input_errors[] = "The field '{$field[1]}' must contain a valid number greater than {$field[2]}";
+ }
+
+ $auth_method = $post['auth_method'];
+ if (($auth_method != 'none') && ($auth_method != 'local')) {
+ $server = trim($post['auth_server']);
+ if (empty($server))
+ $input_errors[] = 'The field \'Authentication server\' is required';
+ else if (!is_ipaddr($server) && !is_domain($server))
+ $input_errors[] = 'The field \'Authentication server\' must contain a valid IP address or domain name';
+
+ $port = trim($post['auth_server_port']);
+ if (!empty($port) && !is_port($port))
+ $input_errors[] = 'The field \'Authentication server port\' must contain a valid port number';
+
+ switch ($auth_method) {
+ case 'ldap':
+ $user = trim($post['ldap_user']);
+ if (empty($user))
+ $input_errors[] = 'The field \'LDAP server user DN\' is required';
+ else if (!$user)
+ $input_errors[] = 'The field \'LDAP server user DN\' must be a valid domain name';
+ break;
+ case 'radius':
+ $secret = trim($post['radius_secret']);
+ if (empty($secret))
+ $input_errors[] = 'The field \'RADIUS secret\' is required';
+ break;
+ case 'msnt':
+ foreach (explode(",", trim($post['msnt_secondary'])) as $server) {
+ if (!empty($server) && !is_ipaddr($server) && !is_domain($server))
+ $input_errors[] = "The host '$server' is not a valid IP address or domain name";
+ }
+ break;
+ }
+
+ $no_auth = explode("\n", $post['no_auth_hosts']);
+ foreach ($no_auth as $host) {
+ $host = trim($host);
+ if (!empty($host) && !is_subnet($host))
+ $input_errors[] = "The host '$host' is not a valid CIDR range";
+ }
+ }
+}
+
+function squid_install_cron($should_install) {
+ global $config, $g;
+ if($g['booting']==true)
+ return;
+ $is_installed = false;
+ if(!$config['cron']['item'])
+ return;
+ $x=0;
+ foreach($config['cron']['item'] as $item) {
+ if(strstr($item['command'], "/usr/local/sbin/squid")) {
+ $is_installed = true;
+ break;
+ }
+ $x++;
+ }
+ switch($should_install) {
+ case true:
+ if(!$is_installed) {
+ $cron_item = array();
+ $cron_item['minute'] = "0";
+ $cron_item['hour'] = "0";
+ $cron_item['mday'] = "*";
+ $cron_item['month'] = "*";
+ $cron_item['wday'] = "*";
+ $cron_item['who'] = "root";
+ $cron_item['command'] = "/usr/local/sbin/squid -k rotate";
+ $config['cron']['item'][] = $cron_item;
+ parse_config(true);
+ write_config("Squid Log Rotation");
+ configure_cron();
+ }
+ break;
+ case false:
+ if($is_installed == true) {
+ if($x > 0) {
+ unset($config['cron']['item'][$x]);
+ parse_config(true);
+ write_config();
+ }
+ configure_cron();
+ }
+ break;
+ }
+}
+
+function squid_resync_general() {
+ global $g, $config, $valid_acls;
+
+ $settings = $config['installedpackages']['squid']['config'][0];
+ $conf = "# This file is automatically generated by pfSense\n";
+ $conf = "# Do not edit manually !\n";
+
+ $port = ($settings['proxy_port'] ? $settings['proxy_port'] : 3128);
+ $ifaces = ($settings['active_interface'] ? $settings['active_interface'] : 'lan');
+ $real_ifaces = array();
+ foreach (explode(",", $ifaces) as $i => $iface) {
+ $real_ifaces[] = squid_get_real_interface_address($iface);
+ if($real_ifaces[$i][0]) {
+ $conf .= "http_port {$real_ifaces[$i][0]}:$port\n";
+ }
+ }
+ if (($settings['transparent_proxy'] == 'on')) {
+ $conf .= "http_port 127.0.0.1:80 transparent\n"; // for squid < v.3.1 (for pf)
+// $conf .= "http_port 127.0.0.1:80 intercept\n"; // new from squid >= 3.1 (for pf)
+ }
+ $icp_port = ($settings['icp_port'] ? $settings['icp_port'] : 0);
+
+ $pidfile = "{$g['varrun_path']}/squid.pid";
+ $language = ($settings['error_language'] ? $settings['error_language'] : 'English');
+ $errordir = SQUID_CONFBASE . '/errors/' . $language;
+ $icondir = SQUID_CONFBASE . '/icons';
+ $hostname = ($settings['visible_hostname'] ? $settings['visible_hostname'] : 'localhost');
+ $email = ($settings['admin_email'] ? $settings['admin_email'] : 'admin@localhost');
+
+ $logdir = ($settings['log_dir'] ? $settings['log_dir'] : '/var/squid/log');
+
+ $logdir_cache = $logdir . '/cache.log';
+ $logdir_access = ($settings['log_enabled'] == 'on' ? $logdir . '/access.log' : '/dev/null');
+
+ $conf .= <<<EOD
+icp_port $icp_port
+
+pid_filename $pidfile
+cache_effective_user proxy
+cache_effective_group proxy
+error_directory $errordir
+icon_directory $icondir
+visible_hostname $hostname
+cache_mgr $email
+access_log $logdir_access
+cache_log $logdir_cache
+cache_store_log none
+
+EOD;
+
+ if (!empty($settings['log_rotate'])) {
+ $conf .= "logfile_rotate {$settings['log_rotate']}\n";
+ squid_install_cron(true);
+ }
+ else {
+ squid_install_cron(false);
+ }
+
+ $conf .= <<<EOD
+shutdown_lifetime 3 seconds
+
+EOD;
+
+ if ($settings['allow_interface'] == 'on') {
+ $src = '';
+ foreach ($real_ifaces as $iface) {
+ list($ip, $mask) = $iface;
+ $ip = long2ip(ip2long($ip) & ip2long($mask));
+ $src .= " $ip/$mask";
+ }
+ $conf .= "# Allow local network(s) on interface(s)\n";
+ $conf .= "acl localnet src $src\n";
+ $valid_acls[] = 'localnet';
+ }
+ if ($settings['disable_xforward']) $conf .= "forwarded_for off\n";
+ if ($settings['disable_via']) $conf .= "via off\n";
+ if ($settings['disable_squidversion']) $conf .= "httpd_suppress_version_string on\n";
+ if (!empty($settings['uri_whitespace'])) $conf .= "uri_whitespace {$settings['uri_whitespace']}\n";
+ else $conf .= "uri_whitespace strip\n"; //only used for first run
+
+ if(!empty($settings['dns_nameservers'])) {
+ $altdns = explode(";", ($settings['dns_nameservers']));
+ $conf .= "dns_nameservers ";
+ foreach ($altdns as $dnssrv) {
+ $conf .= $dnssrv." ";
+ }
+// $conf .= "\n"; //Kill blank line after DNS-Servers
+ }
+
+ return $conf;
+}
+
+
+function squid_resync_cache() {
+ global $config;
+
+ $settings = $config['installedpackages']['squidcache']['config'][0];
+
+ $cachedir =($settings['harddisk_cache_location'] ? $settings['harddisk_cache_location'] : '/var/squid/cache');
+ $disk_cache_size = ($settings['harddisk_cache_size'] ? $settings['harddisk_cache_size'] : 100);
+ $disk_cache_system = ($settings['harddisk_cache_system'] ? $settings['harddisk_cache_system'] : 'aufs');
+ $level1 = ($settings['level1_subdirs'] ? $settings['level1_subdirs'] : 16);
+ $memory_cache_size = ($settings['memory_cache_size'] ? $settings['memory_cache_size'] : 8);
+ $max_objsize = ($settings['maximum_object_size'] ? $settings['maximum_object_size'] : 10);
+ $min_objsize = ($settings['minimum_object_size'] ? $settings['minimum_object_size'] : 0);
+ $cache_policy = ($settings['cache_replacement_policy'] ? $settings['cache_replacement_policy'] : 'heap LFUDA');
+ $memory_policy = ($settings['memory_replacement_policy'] ? $settings['memory_replacement_policy'] : 'heap GDSF');
+ $offline_mode = ($settings['enable_offline'] == 'on' ? 'on' : 'off');
+
+ $conf = <<<EOD
+cache_dir $disk_cache_system $cachedir $disk_cache_size $level1 256
+cache_mem $memory_cache_size MB
+maximum_object_size $max_objsize KB
+minimum_object_size $min_objsize KB
+cache_replacement_policy $cache_policy
+memory_replacement_policy $memory_policy
+offline_mode $offline_mode
+
+EOD;
+
+ if (!empty($settings['cache_swap_low'])) $conf .= "cache_swap_low {$settings['cache_swap_low']}\n";
+ if (!empty($settings['cache_swap_high'])) $conf .= "cache_swap_high {$settings['cache_swap_high']}\n";
+
+ $donotcache = base64_decode($settings['donotcache']);
+ if (!empty($donotcache)) {
+ file_put_contents(SQUID_ACLDIR . '/donotcache.acl', $donotcache);
+ $conf .= 'acl donotcache dstdomain "' . SQUID_ACLDIR . "/donotcache.acl\"\n";
+ $conf .= 'cache deny donotcache';
+ }
+ elseif (file_exists(SQUID_ACLDIR . '/donotcache.acl')) {
+ unlink(SQUID_ACLDIR . '/donotcache.acl');
+ }
+
+ return $conf;
+}
+
+function squid_resync_upstream() {
+ global $config;
+ $settings = $config['installedpackages']['squidupstream']['config'][0];
+
+ $conf = '';
+ if ($settings['proxy_forwarding'] == 'on') {
+ $conf .= "cache_peer {$settings['proxy_addr']} parent {$settings['proxy_port']} {$settings['icp_port']} ";
+
+ if (!empty($settings['username']))
+ $conf .= " login={$settings['username']}";
+ if (!empty($settings['password']))
+ $conf .= ":{$settings['password']}";
+ }
+
+ return $conf;
+}
+
+function squid_resync_redirector() {
+ global $config;
+
+ $httpav_enabled = ($config['installedpackages']['clamav']['config'][0]['scan_http'] == 'on');
+ if ($httpav_enabled) {
+ $conf = "url_rewrite_program /usr/local/bin/squirm\n";
+ } else {
+ $conf = "# No redirector configured\n";
+ }
+ return $conf;
+}
+
+function squid_resync_nac() {
+ global $config, $valid_acls;
+
+ $port = ($settings['proxy_port'] ? $settings['proxy_port'] : 3128);
+ $settings = $config['installedpackages']['squidnac']['config'][0];
+ $webgui_port = $config['system']['webgui']['port'];
+
+ $conf = <<<EOD
+
+# Setup some default acls
+acl localhost src 127.0.0.1/255.255.255.255
+acl safeports port 21 70 80 210 280 443 488 563 591 631 777 901 $webgui_port $port 1025-65535
+acl sslports port 443 563 $webgui_port
+acl manager proto cache_object
+acl purge method PURGE
+acl connect method CONNECT
+acl dynamic urlpath_regex cgi-bin \?
+
+EOD;
+
+ $allowed_subnets = explode("\n", base64_decode($settings['allowed_subnets']));
+ $allowed = "";
+ foreach ($allowed_subnets as $subnet) {
+ if(!empty($subnet)) {
+ $subnet = trim($subnet);
+ $allowed .= "$subnet ";
+ }
+ }
+ if (!empty($allowed)) {
+ $conf .= "acl allowed_subnets src $allowed\n";
+ $valid_acls[] = 'allowed_subnets';
+ }
+
+ $options = array( 'unrestricted_hosts' => 'src',
+ 'banned_hosts' => 'src',
+ 'whitelist' => 'dstdom_regex -i',
+ 'blacklist' => 'dstdom_regex -i',
+ );
+ foreach ($options as $option => $directive) {
+ $contents = base64_decode($settings[$option]);
+ if (!empty($contents)) {
+ file_put_contents(SQUID_ACLDIR . "/$option.acl", $contents);
+ $conf .= "acl $option $directive \"" . SQUID_ACLDIR . "/$option.acl\"\n";
+ $valid_acls[] = $option;
+ }
+ elseif (file_exists(SQUID_ACLDIR . "/$option.acl")) {
+ unlink(SQUID_ACLDIR . "/$option.acl");
+ }
+ }
+
+ $conf .= <<<EOD
+cache deny dynamic
+http_access allow manager localhost
+
+EOD;
+
+ if(!empty($settings['ext_cachemanager'])) {
+ $extmgr = explode(";", ($settings['ext_cachemanager']));
+ $count = 1;
+ $conf .= "\n# Allow external cache managers\n";
+// $conf .= "acl ext_manager src ".$settings['ext_cachemanager']."\n";
+ foreach ($extmgr as $mgr) {
+ $conf .= "acl ext_manager_".$count." src ";
+ $conf .= $mgr." ";
+ $conf .= "\n";
+ $conf .= "http_access allow manager ext_manager_".$count."\n";
+ $count += 1;
+ }}
+
+ $conf .= <<<EOD
+
+http_access deny manager
+http_access allow purge localhost
+http_access deny purge
+http_access deny !safeports
+http_access deny CONNECT !sslports
+
+# Always allow localhost connections
+http_access allow localhost
+
+EOD;
+
+ return $conf;
+}
+
+function squid_resync_traffic() {
+ global $config, $valid_acls;
+ if(!is_array($valid_acls))
+ return;
+ $settings = $config['installedpackages']['squidtraffic']['config'][0];
+ $conf = '';
+
+ if (!empty($settings['quick_abort_min']) || ($settings['quick_abort_min']) == "0") $conf .= "quick_abort_min {$settings['quick_abort_min']} KB\n";
+ if (!empty($settings['quick_abort_max']) || ($settings['quick_abort_max']) == "0") $conf .= "quick_abort_max {$settings['quick_abort_max']} KB\n";
+ if (!empty($settings['quick_abort_pct'])) $conf .= "quick_abort_pct {$settings['quick_abort_pct']}\n";
+
+ $up_limit = ($settings['max_upload_size'] ? $settings['max_upload_size'] : 0);
+ $down_limit = ($settings['max_download_size'] ? $settings['max_download_size'] : 0);
+ $conf .= "request_body_max_size $up_limit KB\n";
+ $conf .= 'reply_body_max_size ' . ($down_limit * 1024) . "\n";
+
+ // Only apply throttling past 10MB
+ // XXX: Should this really be hardcoded?
+ $threshold = 10 * 1024 * 1024;
+ $overall = $settings['overall_throttling'];
+ if (!isset($overall) || ($overall == 0))
+ $overall = -1;
+ else
+ $overall *= 1024;
+ $perhost = $settings['perhost_throttling'];
+ if (!isset($perhost) || ($perhost == 0))
+ $perhost = -1;
+ else
+ $perhost *= 1024;
+ $conf .= <<<EOD
+delay_pools 1
+delay_class 1 2
+delay_parameters 1 $overall/$overall $perhost/$perhost
+delay_initial_bucket_level 100
+
+EOD;
+
+ if(! empty($settings['unrestricted_hosts'])) {
+ foreach (array('unrestricted_hosts') as $item) {
+ if (in_array($item, $valid_acls))
+ $conf .= "# Do not throttle unrestricted hosts\n";
+ $conf .= "delay_access 1 deny $item\n";
+ }
+ }
+
+ if ($settings['throttle_specific'] == 'on') {
+ $exts = array();
+ $binaries = 'bin,cab,sea,ar,arj,tar,tgz,gz,tbz,bz2,zip,7z,exe,com';
+ $cdimages = 'iso,bin,mds,nrg,gho,bwt,b5t,pqi';
+ $multimedia = 'aiff?,asf,avi,divx,mov,mp3,mp4,wmv,mpe?g,qt,ra?m';
+ foreach (array( 'throttle_binaries' => $binaries,
+ 'throttle_cdimages' => $cdimages,
+ 'throttle_multimedia' => $multimedia) as $field => $set) {
+ if ($settings[$field] == 'on')
+ $exts = array_merge($exts, explode(",", $set));
+ }
+
+ foreach (explode(",", $settings['throttle_others']) as $ext) {
+ if (!empty($ext)) $exts[] = $ext;
+ }
+
+ $contents = '';
+ foreach ($exts as $ext)
+ $contents .= "\.$ext\$\n";
+ file_put_contents(SQUID_ACLDIR . '/throttle_exts.acl', $contents);
+
+ $conf .= "# Throttle extensions matched in the url\n";
+ $conf .= "acl throttle_exts urlpath_regex -i \"" . SQUID_ACLDIR . "/throttle_exts.acl\"\n";
+ $conf .= "delay_access 1 allow throttle_exts\n";
+ $conf .= "delay_access 1 deny all\n";
+ }
+ else
+ $conf .= "delay_access 1 allow all\n";
+
+ return $conf;
+}
+
+function squid_resync_auth() {
+ global $config, $valid_acls;
+
+ $settings = $config['installedpackages']['squidauth']['config'][0];
+ $settingsnac = $config['installedpackages']['squidnac']['config'][0];
+ $settingsconfig = $config['installedpackages']['squid']['config'][0];
+ $conf = '';
+
+ // Deny the banned guys before allowing the good guys
+ if(! empty($settingsnac['banned_hosts'])) {
+ if (squid_is_valid_acl('banned_hosts')) {
+ $conf .= "# These hosts are banned\n";
+ $conf .= "http_access deny banned_hosts\n";
+ }
+ }
+ if(! empty($settingsnac['banned_macs'])) {
+ if (squid_is_valid_acl('banned_macs')) {
+ $conf .= "# These macs are banned\n";
+ $conf .= "http_access deny banned_macs\n";
+ }
+ }
+
+ // Unrestricted hosts take precendence over blacklist
+ if(! empty($settingsnac['unrestricted_hosts'])) {
+ if (squid_is_valid_acl('unrestricted_hosts')) {
+ $conf .= "# These hosts do not have any restrictions\n";
+ $conf .= "http_access allow unrestricted_hosts\n";
+ }
+ }
+ if(! empty($settingsnac['unrestricted_macs'])) {
+ if (squid_is_valid_acl('unrestricted_macs')) {
+ $conf .= "# These hosts do not have any restrictions\n";
+ $conf .= "http_access allow unrestricted_macs\n";
+ }
+ }
+
+ // Whitelist and blacklist also take precendence over other allow rules
+ if(! empty($settingsnac['whitelist'])) {
+ if (squid_is_valid_acl('whitelist')) {
+ $conf .= "# Always allow access to whitelist domains\n";
+ $conf .= "http_access allow whitelist\n";
+ }
+ }
+ if(! empty($settingsnac['blacklist'])) {
+ if (squid_is_valid_acl('blacklist')) {
+ $conf .= "# Block access to blacklist domains\n";
+ $conf .= "http_access deny blacklist\n";
+ }
+ }
+
+ $transparent_proxy = ($settingsconfig['transparent_proxy'] == 'on');
+ $auth_method = (($settings['auth_method'] && !$transparent_proxy) ? $settings['auth_method'] : 'none');
+ // Allow the remaining ACLs if no authentication is set
+ if ($auth_method == 'none') {
+ if ($settingsconfig['allow_interface'] == 'on') {
+ $conf .= "# Allow local network(s) on interface(s)\n";
+ $allowed = array('localnet', 'allowed_subnets');
+ $allowed = array_filter($allowed, 'squid_is_valid_acl');
+ foreach ($allowed as $acl)
+ $conf .= "http_access allow $acl\n";
+ }
+ }
+ else {
+ $noauth = implode(' ', explode("\n", base64_decode($settings['no_auth_hosts'])));
+ if (!empty($noauth)) {
+ $conf .= "acl noauth src $noauth\n";
+ $valid_acls[] = 'noauth';
+ }
+
+ // Set up the external authentication programs
+ $auth_ttl = ($settings['auth_ttl'] ? $settings['auth_ttl'] : 60);
+ $processes = ($settings['auth_processes'] ? $settings['auth_processes'] : 5);
+ $prompt = ($settings['auth_prompt'] ? $settings['auth_prompt'] : 'Please enter your credentials to access the proxy');
+ switch ($auth_method) {
+ case 'local':
+ $conf .= 'auth_param basic program /usr/local/libexec/squid/ncsa_auth ' . SQUID_PASSWD . "\n";
+ break;
+ case 'ldap':
+ $port = (isset($settings['auth_port']) ? ":{$settings['auth_port']}" : '');
+ $password = (isset($settings['ldap_pass']) ? "-w {$settings['ldap_pass']}" : '');
+ $conf .= "auth_param basic program /usr/local/libexec/squid/squid_ldap_auth -v {$settings['ldap_version']} -b {$settings['ldap_basedomain']} -D {$settings['ldap_user']} $password -f \"{$settings['ldap_filter']}\" -u uid -P {$settings['auth_server']}$port\n";
+ break;
+ case 'radius':
+ $port = (isset($settings['auth_port']) ? "-p {$settings['auth_server_port']}" : '');
+ $conf .= "auth_param basic program /usr/local/libexec/squid/squid_radius_auth -w {$settings['radius_secret']} -h {$settings['auth_server']} $port\n";
+ break;
+ case 'msnt':
+ $conf .= "auth_param basic program /usr/local/libexec/squid/msnt_auth\n";
+ break;
+ }
+ $conf .= <<<EOD
+auth_param basic children $processes
+auth_param basic realm $prompt
+auth_param basic credentialsttl $auth_ttl minutes
+acl password proxy_auth REQUIRED
+
+EOD;
+
+ // Onto the ACLs
+ $password = array('localnet', 'allowed_subnets');
+ $passwordless = array('unrestricted_hosts');
+ if ($settings['unrestricted_auth'] == 'on') {
+ // Even the unrestricted hosts should authenticate
+ $password = array_merge($password, $passwordless);
+ $passwordless = array();
+ }
+ $passwordless[] = 'noauth';
+ $password = array_filter($password, 'squid_is_valid_acl');
+ $passwordless = array_filter($passwordless, 'squid_is_valid_acl');
+
+ // Allow the ACLs that don't need to authenticate
+ foreach ($passwordless as $acl)
+ $conf .= "http_access allow $acl\n";
+
+ // Allow the other ACLs as long as they authenticate
+ foreach ($password as $acl)
+ $conf .= "http_access allow password $acl\n";
+ }
+
+ if(!empty($config['installedpackages']['squid']['config'][0]['custom_options'])) {
+ $custopts = explode(";", ($config['installedpackages']['squid']['config'][0]['custom_options']));
+ $conf .= "# Custom options\n";
+ foreach ($custopts as $custopt) {
+ $conf .= $custopt."\n";
+ }
+ }
+
+ $conf .= "# Default block all to be sure\n";
+ $conf .= "http_access deny all\n";
+
+ return $conf;
+}
+
+function squid_resync_users() {
+ global $config;
+
+ $users = $config['installedpackages']['squidusers']['config'];
+ $contents = '';
+ if (is_array($users)) {
+ foreach ($users as $user)
+ $contents .= $user['username'] . ':' . crypt($user['password'], base64_encode($user['password'])) . "\n";
+ }
+ file_put_contents(SQUID_PASSWD, $contents);
+ chown(SQUID_PASSWD, 'proxy');
+ chmod(SQUID_PASSWD, 0600);
+}
+
+function squid_resync() {
+ global $config;
+ $conf = squid_resync_general() . "\n";
+ $conf .= squid_resync_cache() . "\n";
+ $conf .= squid_resync_redirector() . "\n";
+ $conf .= squid_resync_upstream() . "\n";
+ $conf .= squid_resync_nac() . "\n";
+ $conf .= squid_resync_traffic() . "\n";
+ $conf .= squid_resync_auth();
+ squid_resync_users();
+
+ /* make sure pinger is executable */
+ if(file_exists("/usr/local/libexec/squid/pinger"))
+ exec("chmod a+x /usr/local/libexec/squid/pinger");
+
+ file_put_contents(SQUID_CONFBASE . '/squid.conf', $conf);
+
+ $log_dir = $config['installedpackages']['squid']['config'][0]['log_dir'].'/';
+
+ if(!is_dir($log_dir)) {
+ log_error("Creating squid log dir $log_dir");
+ make_dirs($log_dir);
+ squid_chown_recursive($log_dir, 'proxy', 'proxy');
+ }
+
+ squid_dash_z();
+
+ if (!is_service_running('squid')) {
+ log_error("Starting Squid");
+ mwexec_bg("/usr/local/sbin/squid -D");
+ } else {
+ log_error("Reloading Squid for configuration sync");
+ mwexec("/usr/local/sbin/squid -k reconfigure");
+ }
+
+ filter_configure();
+}
+
+function squid_print_javascript_auth() {
+ global $config;
+ $transparent_proxy = ($config['installedpackages']['squid']['config'][0]['transparent_proxy'] == 'on');
+
+ // No authentication for transparent proxy
+ if ($transparent_proxy) {
+ $javascript = <<<EOD
+<script language="JavaScript">
+<!--
+function on_auth_method_changed() {
+ document.iform.auth_method.disabled = 1;
+ document.iform.auth_server.disabled = 1;
+ document.iform.auth_server_port.disabled = 1;
+ document.iform.ldap_user.disabled = 1;
+ document.iform.ldap_version.disabled = 1;
+ document.iform.ldap_filter.disabled = 1;
+ document.iform.ldap_password.disabled = 1;
+ document.iform.ldap_basedomain.disabled = 1;
+ document.iform.radius_secret.disabled = 1;
+ document.iform.msnt_secondary.disabled = 1;
+ document.iform.auth_prompt.disabled = 1;
+ document.iform.auth_processes.disabled = 1;
+ document.iform.auth_ttl.disabled = 1;
+ document.iform.unrestricted_auth.disabled = 1;
+ document.iform.no_auth_hosts.disabled = 1;
+}
+-->
+</script>
+
+EOD;
+ }
+ else {
+ $javascript = <<<EOD
+<script language="JavaScript">
+<!--
+function on_auth_method_changed() {
+ var field = document.iform.auth_method;
+ var auth_method = field.options[field.selectedIndex].value;
+
+ if (auth_method == 'none') {
+ document.iform.auth_server.disabled = 1;
+ document.iform.auth_server_port.disabled = 1;
+ document.iform.ldap_user.disabled = 1;
+ document.iform.ldap_version.disabled = 1;
+ document.iform.ldap_filter.disabled = 1;
+ document.iform.ldap_password.disabled = 1;
+ document.iform.ldap_basedomain.disabled = 1;
+ document.iform.radius_secret.disabled = 1;
+ document.iform.msnt_secondary.disabled = 1;
+ document.iform.auth_prompt.disabled = 1;
+ document.iform.auth_processes.disabled = 1;
+ document.iform.auth_ttl.disabled = 1;
+ document.iform.unrestricted_auth.disabled = 1;
+ document.iform.no_auth_hosts.disabled = 1;
+ }
+ else {
+ document.iform.auth_prompt.disabled = 0;
+ document.iform.auth_processes.disabled = 0;
+ document.iform.auth_ttl.disabled = 0;
+ document.iform.unrestricted_auth.disabled = 0;
+ document.iform.no_auth_hosts.disabled = 0;
+ }
+
+ switch (auth_method) {
+ case 'local':
+ document.iform.auth_server.disabled = 1;
+ document.iform.auth_server_port.disabled = 1;
+ document.iform.ldap_user.disabled = 1;
+ document.iform.ldap_password.disabled = 1;
+ document.iform.ldap_version.disabled = 1;
+ document.iform.ldap_filter.disabled = 1;
+ document.iform.ldap_basedomain.disabled = 1;
+ document.iform.radius_secret.disabled = 1;
+ document.iform.msnt_secondary.disabled = 1;
+ break;
+ case 'ldap':
+ document.iform.auth_server.disabled = 0;
+ document.iform.auth_server_port.disabled = 0;
+ document.iform.ldap_user.disabled = 0;
+ document.iform.ldap_password.disabled = 0;
+ document.iform.ldap_version.disabled = 0;
+ document.iform.ldap_filter.disabled = 0;
+ document.iform.ldap_basedomain.disabled = 0;
+ document.iform.radius_secret.disabled = 1;
+ document.iform.msnt_secondary.disabled = 1;
+ break;
+ case 'radius':
+ document.iform.auth_server.disabled = 0;
+ document.iform.auth_server_port.disabled = 0;
+ document.iform.ldap_user.disabled = 1;
+ document.iform.ldap_password.disabled = 1;
+ document.iform.ldap_version.disabled = 1;
+ document.iform.ldap_filter.disabled = 1;
+ document.iform.ldap_basedomain.disabled = 1;
+ document.iform.radius_secret.disabled = 0;
+ document.iform.msnt_secondary.disabled = 1;
+ break;
+ case 'msnt':
+ document.iform.auth_server.disabled = 0;
+ document.iform.auth_server_port.disabled = 1;
+ document.iform.ldap_user.disabled = 1;
+ document.iform.ldap_password.disabled = 1;
+ document.iform.ldap_version.disabled = 1;
+ document.iform.ldap_filter.disabled = 1;
+ document.iform.ldap_basedomain.disabled = 1;
+ document.iform.radius_secret.disabled = 1;
+ document.iform.msnt_secondary.disabled = 0;
+ break;
+ }
+}
+-->
+</script>
+
+EOD;
+ }
+
+ print($javascript);
+}
+
+function squid_print_javascript_auth2() {
+ print("<script language=\"JavaScript\">on_auth_method_changed()</script>\n");
+}
+
+function squid_generate_rules($type) {
+ global $config;
+
+ $squid_conf = $config['installedpackages']['squid']['config'][0];
+ if (!is_service_running('squid')) {
+ log_error("SQUID is installed but not started. Not installing redirect rules.");
+ return;
+ }
+
+ if (($squid_conf['transparent_proxy'] != 'on') || ($squid_conf['allow_interface'] != 'on')) {
+ return;
+ }
+
+ $ifaces = explode(",", $squid_conf['active_interface']);
+ $ifaces = array_map('convert_friendly_interface_to_real_interface_name', $ifaces);
+ $port = ($squid_conf['proxy_port'] ? $squid_conf['proxy_port'] : 3128);
+
+ switch($type) {
+ case 'nat':
+ $rules .= "\n# Setup Squid proxy redirect\n";
+ if ($squid_conf['private_subnet_proxy_off'] == 'on') {
+ foreach ($ifaces as $iface){
+ $rules .= "no rdr on $iface proto tcp from any to { 192.168.0.0/16, 172.16.0.0/12, 10.0.0.0/8 } port 80\n";
+ }
+ }
+
+ if (!empty($squid_conf['defined_ip_proxy_off'])) {
+ $defined_ip_proxy_off = explode(";", $squid_conf['defined_ip_proxy_off']);
+ $exempt_ip = "";
+ foreach ($defined_ip_proxy_off as $ip_proxy_off) {
+ if(!empty($ip_proxy_off)) {
+ $ip_proxy_off = trim($ip_proxy_off);
+ $exempt_ip .= ", $ip_proxy_off";
+ }
+ }
+ $exempt_ip = substr($exempt_ip,2);
+ foreach ($ifaces as $iface){
+ $rules .= "no rdr on $iface proto tcp from { $exempt_ip } to any port 80\n";
+ }
+ }
+
+ foreach ($ifaces as $iface){
+ $rules .= "rdr on $iface proto tcp from any to !($iface) port 80 -> 127.0.0.1 port 80\n";
+ };
+ $rules .= "\n";
+ break;
+ case 'filter':
+ foreach ($ifaces as $iface){
+ $rules .= "# Setup squid pass rules for proxy\n";
+ $rules .= "pass in quick on $iface proto tcp from any to !($iface) port 80 flags S/SA keep state\n";
+ $rules .= "pass in quick on $iface proto tcp from any to !($iface) port $port flags S/SA keep state\n";
+ $rules .= "\n";
+ };
+ break;
+ default:
+ break;
+ }
+
+ return $rules;
+}
+?>
diff --git a/config/squid3/squid.xml b/config/squid3/squid.xml
new file mode 100644
index 00000000..8529526e
--- /dev/null
+++ b/config/squid3/squid.xml
@@ -0,0 +1,333 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>squid</name>
+ <version>3.0.8</version>
+ <title>Proxy server: General settings</title>
+ <include_file>/usr/local/pkg/squid.inc</include_file>
+ <menu>
+ <name>Proxy server</name>
+ <tooltiptext>Modify the proxy server's settings</tooltiptext>
+ <section>Services</section>
+ <url>/pkg_edit.php?xml=squid.xml&amp;id=0</url>
+ </menu>
+ <service>
+ <name>squid</name>
+ <rcfile>squid.sh</rcfile>
+ <executable>squid</executable>
+ <description>Proxy server Service</description>
+ </service>
+ <tabs>
+ <tab>
+ <text>General settings</text>
+ <url>/pkg_edit.php?xml=squid.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Upstream proxy</text>
+ <url>/pkg_edit.php?xml=squid_upstream.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Cache management</text>
+ <url>/pkg_edit.php?xml=squid_cache.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Access control</text>
+ <url>/pkg_edit.php?xml=squid_nac.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Traffic management</text>
+ <url>/pkg_edit.php?xml=squid_traffic.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Auth settings</text>
+ <url>/pkg_edit.php?xml=squid_auth.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Local users</text>
+ <url>/pkg.php?xml=squid_users.xml</url>
+ </tab>
+ </tabs>
+ <!-- Installation -->
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.org/packages/config/squid3/squid.inc</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.org/packages/config/squid3/squid_cache.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.org/packages/config/squid3/squid_nac.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.org/packages/config/squid3/squid_ng.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.org/packages/config/squid3/squid_traffic.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.org/packages/config/squid3/squid_upstream.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.org/packages/config/squid3/squid_auth.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.org/packages/config/squid3/squid_users.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/etc/rc.d/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.org/packages/config/squid3/proxy_monitor.sh</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.org/packages/config/squid3/squid_cache.xml</item>
+ </additional_files_needed>
+ <fields>
+ <field>
+ <fielddescr>Proxy interface</fielddescr>
+ <fieldname>active_interface</fieldname>
+ <description>The interface(s) the proxy server will bind to.</description>
+ <type>interfaces_selection</type>
+ <required/>
+ <default_value>lan</default_value>
+ <multiple/>
+ </field>
+ <field>
+ <fielddescr>Allow users on interface</fielddescr>
+ <fieldname>allow_interface</fieldname>
+ <description>If this field is checked, the users connected to the interface selected in the 'Proxy interface' field will be allowed to use the proxy, i.e., there will be no need to add the interface's subnet to the list of allowed subnets. This is just a shortcut.</description>
+ <type>checkbox</type>
+ <required/>
+ <default_value>on</default_value>
+ </field>
+ <field>
+ <fielddescr>Transparent proxy</fielddescr>
+ <fieldname>transparent_proxy</fieldname>
+ <description>If transparent mode is enabled, all requests for destination port 80 will be forwarded to the proxy server without any additional configuration necessary.</description>
+ <type>checkbox</type>
+ <required/>
+ </field>
+ <field>
+ <fielddescr>Do NOT proxy Private Address Space (RFC 1918)</fielddescr>
+ <fieldname>private_subnet_proxy_off</fieldname>
+ <description>Do not forward traffic to Private Address Space (RFC 1918) &lt;b&gt;destination&lt;/b&gt; through the proxy server.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Do NOT proxy these IPs</fielddescr>
+ <fieldname>defined_ip_proxy_off</fieldname>
+ <description>Do not forward traffic from these &lt;b&gt;source&lt;/b&gt; IPs through the proxy server. Separate by semi-colons (;).</description>
+ <type>input</type>
+ <size>80</size>
+ </field>
+ <field>
+ <fielddescr>Enabled logging</fielddescr>
+ <fieldname>log_enabled</fieldname>
+ <description>This will enable the access log. Don't switch this on if you don't have much disk space left.</description>
+ <type>checkbox</type>
+ <enablefields>log_query_terms,log_user_agents</enablefields>
+ </field>
+ <field>
+ <fielddescr>Log store directory</fielddescr>
+ <fieldname>log_dir</fieldname>
+ <description>The directory where the log will be stored (note: do not end with a / mark)</description>
+ <type>input</type>
+ <size>60</size>
+ <required/>
+ <default_value>/var/squid/log</default_value>
+ </field>
+ <field>
+ <fielddescr>Log rotate</fielddescr>
+ <fieldname>log_rotate</fieldname>
+ <description>Defines how many days of logfiles will be kept. Rotation is disabled if left empty.</description>
+ <type>input</type>
+ <size>5</size>
+ </field>
+ <field>
+ <fielddescr>Proxy port</fielddescr>
+ <fieldname>proxy_port</fieldname>
+ <description>This is the port the proxy server will listen on.</description>
+ <type>input</type>
+ <size>5</size>
+ <required/>
+ <default_value>3128</default_value>
+ </field>
+ <field>
+ <fielddescr>ICP port</fielddescr>
+ <fieldname>icp_port</fieldname>
+ <description>This is the port the Proxy Server will send and receive ICP queries to and from neighbor caches. Leave this blank if you don't want the proxy server to communicate with neighbor caches through ICP.</description>
+ <type>input</type>
+ <size>5</size>
+ </field>
+ <field>
+ <fielddescr>Visible hostname</fielddescr>
+ <fieldname>visible_hostname</fieldname>
+ <description>This is the URL to be displayed in proxy server error messages.</description>
+ <type>input</type>
+ <size>60</size>
+ <default_value>localhost</default_value>
+ </field>
+ <field>
+ <fielddescr>Administrator email</fielddescr>
+ <fieldname>admin_email</fieldname>
+ <description>This is the email address displayed in error messages to the users.</description>
+ <type>input</type>
+ <size>60</size>
+ <default_value>admin@localhost</default_value>
+ </field>
+ <field>
+ <fielddescr>Language</fielddescr>
+ <fieldname>error_language</fieldname>
+ <description>Select the language in which the proxy server will display error messages to users.</description>
+ <type>select</type>
+ <default_value>English</default_value>
+ </field>
+ <field>
+ <fielddescr>Disable X-Forward</fielddescr>
+ <fieldname>disable_xforward</fieldname>
+ <description>If not set, Squid will include your system's IP address or name in the HTTP requests it forwards.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Disable VIA</fielddescr>
+ <fieldname>disable_via</fieldname>
+ <description>If not set, Squid will include a Via header in requests and replies as required by RFC2616.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>What to do with requests that have whitespace characters in the URI</fielddescr>
+ <fieldname>uri_whitespace</fieldname>
+ <description>&lt;b&gt; strip:&lt;/b&gt; The whitespace characters are stripped out of the URL. This is the behavior recommended by RFC2396. &lt;p&gt; &lt;b&gt; deny:&lt;/b&gt; The request is denied. The user receives an "Invalid Request" message.&lt;p&gt; &lt;b&gt; allow:&lt;/b&gt; The request is allowed and the URI is not changed. The whitespace characters remain in the URI.&lt;p&gt; &lt;b&gt; encode:&lt;/b&gt; The request is allowed and the whitespace characters are encoded according to RFC1738.&lt;p&gt; &lt;b&gt; chop:&lt;/b&gt; The request is allowed and the URI is chopped at the first whitespace.</description>
+ <type>select</type>
+ <default_value>strip</default_value>
+ <options>
+ <option>
+ <name>strip</name>
+ <value>strip</value>
+ </option>
+ <option>
+ <name>deny</name>
+ <value>deny</value>
+ </option>
+ <option>
+ <name>allow</name>
+ <value>allow</value>
+ </option>
+ <option>
+ <name>encode</name>
+ <value>encode</value>
+ </option>
+ <option>
+ <name>chop</name>
+ <value>chop</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Use alternate DNS-servers for the proxy-server</fielddescr>
+ <fieldname>dns_nameservers</fieldname>
+ <description>If you want to use other DNS-servers than the DNS-forwarder, enter the IPs here, separated by semi-colons (;).</description>
+ <type>input</type>
+ <size>60</size>
+ </field>
+ <field>
+ <fielddescr>Suppress Squid Version</fielddescr>
+ <fieldname>disable_squidversion</fieldname>
+ <description>If set, suppress Squid version string info in HTTP headers and HTML error pages.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Custom Options</fielddescr>
+ <fieldname>custom_options</fieldname>
+ <description>You can put your own custom options here, separated by semi-colons (;). They'll be added to the configuration. They need to be squid.conf native options, otherwise squid will NOT work.</description>
+ <type>textarea</type>
+ <cols>65</cols>
+ <rows>5</rows>
+ </field>
+ </fields>
+ <custom_php_command_before_form>
+ squid_before_form_general(&amp;$pkg);
+ </custom_php_command_before_form>
+ <custom_add_php_command>
+ squid_resync();
+ </custom_add_php_command>
+ <custom_php_validation_command>
+ squid_validate_general($_POST, &amp;$input_errors);
+ </custom_php_validation_command>
+ <custom_php_resync_config_command>
+ squid_resync();
+ exec("/bin/rm -f /usr/local/etc/rc.d/squid");
+ </custom_php_resync_config_command>
+ <custom_php_install_command>
+ update_status("Checking Squid cache... One moment please...");
+ update_output_window("This operation may take quite some time, please be patient. Do not press stop or attempt to navigate away from this page during this process.");
+ squid_install_command();
+ squid_resync();
+ exec("/bin/rm -f /usr/local/etc/rc.d/squid");
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ squid_deinstall_command();
+ exec("/bin/rm -f /usr/local/etc/rc.d/squid*");
+ </custom_php_deinstall_command>
+</packagegui>
diff --git a/config/squid3/squid_auth.inc b/config/squid3/squid_auth.inc
new file mode 100644
index 00000000..7c99a01b
--- /dev/null
+++ b/config/squid3/squid_auth.inc
@@ -0,0 +1,446 @@
+<?php
+/* $Id$ */
+
+/*
+ squid_auth.inc
+ part of pfSense (www.pfSense.com)
+
+ Copyright (C) 2005 Michael Capp <michael.capp@gmail.com>
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+function global_eval_auth_options()
+{
+ global $config;
+ conf_mount_rw();
+ config_lock();
+
+ switch ($config['installedpackages']['squidauth']['config'][0]['auth_method']) {
+ case "none":
+ dynamic_auth_content("pkg_edit");
+ dynamic_no_auth();
+ break;
+ case "local_auth":
+ dynamic_auth_content("pkg");
+ /* create empty passwd file to prevent stat error with squid reload */
+ touch ("/usr/local/etc/squid/advanced/ncsa/passwd");
+ dynamic_local_auth();
+ break;
+ case "ldap_bind":
+ dynamic_auth_content("pkg_edit");
+ dynamic_ldap_auth();
+ break;
+ case "domain_auth":
+ $filecontents = file("/usr/local/pkg/squid_auth.xml");
+ dynamic_auth_content("pkg_edit");
+ dynamic_domain_auth();
+ break;
+ case "radius_auth":
+ $filecontents = file("/usr/local/pkg/squid_auth.xml");
+ dynamic_auth_content("pkg_edit");
+ dynamic_radius_auth();
+ break;
+ default:
+ $filecontents = file("/usr/local/pkg/squid_auth.xml");
+ dynamic_auth_content("pkg_edit");
+ dynamic_no_auth();
+ break;
+ }
+
+ config_unlock();
+ conf_mount_ro();
+
+} /* end function global_eval_auth_options */
+
+function dynamic_no_auth() {
+ global $config;
+ conf_mount_rw();
+ $fout = fopen("/usr/local/pkg/squid_extauth.xml", "w");
+ fwrite($fout, "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n");
+ fwrite($fout, "<packagegui>\n");
+ fwrite($fout, " <name>squidextnoauth</name>\n");
+ fwrite($fout, " <title>Services: Proxy Server -> Extended Authentication Settings</title>\n");
+ fwrite($fout, " <configpath>installedpackages->package->squidextnoauth->configuration->settings</configpath>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <aftersaveredirect>/pkg_edit.php?xml=squid_extauth.xml&amp;id=0</aftersaveredirect>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tabs>\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>General Settings</text>\n");
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_ng.xml&amp;id=0</url>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>Upstream Proxy</text>\n");
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_upstream.xml&amp;id=0</url>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>Cache Mgmt</text>\n");
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_cache.xml&amp;id=0</url>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>Network Access Control</text>\n");
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_nac.xml&amp;id=0</url>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>Traffic Mgmt</text>\n");
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_traffic.xml&amp;id=0</url>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>Auth Settings</text>\n");
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_auth.xml&amp;id=0</url>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>Extended Auth Settings</text>\n");
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_extauth.xml&amp;id=0</url>\n");
+ fwrite($fout, " <active/>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " </tabs>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <fields>\n");
+ fwrite($fout, " <field>\n");
+ fwrite($fout, " <fielddescr>No Authentication Defined</fielddescr>\n");
+ fwrite($fout, " <fieldname>no_auth</fieldname>\n");
+ fwrite($fout, " </field>\n");
+ fwrite($fout, " </fields>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <custom_add_php_command_late>\n");
+ fwrite($fout, " require_once(\"/usr/local/pkg/squid_ng.inc\");");
+ fwrite($fout, "\n");
+ fwrite($fout, " global_write_squid_config();\n");
+ fwrite($fout, " mwexec(\"/usr/local/sbin/squid -k reconfigure\");\n");
+ fwrite($fout, " </custom_add_php_command_late>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, "</packagegui>\n");
+ fclose($fout);
+
+ /* mount filesystem read-only */
+ conf_mount_ro();
+}
+
+function dynamic_local_auth() {
+ global $config;
+ conf_mount_rw();
+
+ $fout = fopen("/usr/local/pkg/squid_extauth.xml", "w");
+
+ fwrite($fout, "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, "<packagegui>\n");
+ fwrite($fout, " <name>squidextlocalauth</name>\n");
+ fwrite($fout, " <title>Services: Proxy Server -> Extended Auth Settings</title>\n");
+ fwrite($fout, " <version>2.5.10_4</version>\n");
+ fwrite($fout, " <configpath>installedpackages->package->squidextlocalauth->configuration->settings</configpath>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <files></files>\n");
+ fwrite($fout, " <menu></menu>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <aftersaveredirect>/pkg.php?xml=squid_extauth.xml&amp;id=0</aftersaveredirect>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tabs>\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>General Settings</text>\n");
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_ng.xml&amp;id=0</url>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>Upstream Proxy</text>\n");
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_upstream.xml&amp;id=0</url>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>Cache Mgmt</text>\n");
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_cache.xml&amp;id=0</url>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>Network Access Control</text>\n");
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_nac.xml&amp;id=0</url>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>Traffic Mgmt</text>\n");
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_traffic.xml&amp;id=0</url>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>Auth Settings</text>\n");
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_auth.xml&amp;id=0</url>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>Extended Auth Settings</text>\n");
+ fwrite($fout, " <url>/pkg.php?xml=squid_extauth.xml&amp;id=0</url>\n");
+ fwrite($fout, " <active/>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " </tabs>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <adddeleteeditpagefields>\n");
+ fwrite($fout, " <columnitem>\n");
+ fwrite($fout, " <fielddescr>Username</fielddescr>\n");
+ fwrite($fout, " <fieldname>username</fieldname>\n");
+ fwrite($fout, " </columnitem>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <columnitem>\n");
+ fwrite($fout, " <fielddescr>Description</fielddescr>\n");
+ fwrite($fout, " <fieldname>description</fieldname>\n");
+ fwrite($fout, " </columnitem>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <columnitem>\n");
+ fwrite($fout, " <fielddescr>Restriction Group</fielddescr>\n");
+ fwrite($fout, " <fieldname>group</fieldname>\n");
+ fwrite($fout, " </columnitem>\n");
+ fwrite($fout, " </adddeleteeditpagefields>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <fields>\n");
+ fwrite($fout, " <field>\n");
+ fwrite($fout, " <fielddescr>Username</fielddescr>\n");
+ fwrite($fout, " <fieldname>username</fieldname>\n");
+ fwrite($fout, " <type>input</type>\n");
+ fwrite($fout, " <size>15</size>\n");
+ fwrite($fout, " </field>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <field>\n");
+ fwrite($fout, " <fielddescr>Password</fielddescr>\n");
+ fwrite($fout, " <fieldname>password</fieldname>\n");
+ fwrite($fout, " <type>password</type>\n");
+ fwrite($fout, " <size>8</size>\n");
+ fwrite($fout, " </field>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <field>\n");
+ fwrite($fout, " <fielddescr>Description (Optional)</fielddescr>\n");
+ fwrite($fout, " <fieldname>description</fieldname>\n");
+ fwrite($fout, " <type>input</type>\n");
+ fwrite($fout, " <size>30</size>\n");
+ fwrite($fout, " </field>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <field>\n");
+ fwrite($fout, " <fielddescr>Restriction Group</fielddescr>\n");
+ fwrite($fout, " <fieldname>group</fieldname>\n");
+ fwrite($fout, " <type>select</type>\n");
+ fwrite($fout, " <options>\n");
+ fwrite($fout, " <option><name>Standard</name><value>Standard</value></option>\n");
+ fwrite($fout, " <option><name>Extended</name><value>Extended</value></option>\n");
+ fwrite($fout, " </options>\n");
+ fwrite($fout, " </field>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " </fields>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <custom_add_php_command_late>\n");
+ fwrite($fout, " require_once(\"/usr/local/pkg/squid_ng.inc\");\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " mod_htpasswd();\n");
+ fwrite($fout, " global_write_squid_config();\n");
+ fwrite($fout, " mwexec(\"/usr/local/sbin/squid -k reconfigure\");\n");
+ fwrite($fout, " </custom_add_php_command_late>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, "</packagegui>\n");
+
+ fclose($fout);
+
+ /* mount filesystem read-only */
+ conf_mount_ro();
+}
+
+function dynamic_ldap_auth() {
+ global $config;
+ conf_mount_rw();
+
+ $fout = fopen("/usr/local/pkg/squid_extauth.xml", "w");
+
+ fwrite($fout, "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, "<packagegui>\n");
+ fwrite($fout, " <name>squidextldapauth</name>\n");
+ fwrite($fout, " <title>Services: Proxy Server -> Extended Auth Settings</title>\n");
+ fwrite($fout, " <version>2.5.11</version>\n");
+ fwrite($fout, " <configpath>installedpackages->package->squidextldapauth->configuration->settings</configpath>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <files></files>\n");
+ fwrite($fout, " <menu></menu>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <aftersaveredirect>/pkg_edit.php?xml=squid_extauth.xml&amp;id=0</aftersaveredirect>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tabs>\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>General Settings</text>\n");
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_ng.xml&amp;id=0</url>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>Upstream Proxy</text>\n");
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_upstream.xml&amp;id=0</url>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>Cache Mgmt</text>\n");
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_cache.xml&amp;id=0</url>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>Network Access Control</text>\n");
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_nac.xml&amp;id=0</url>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>Traffic Mgmt</text>\n");
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_traffic.xml&amp;id=0</url>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>Auth Settings</text>\n");
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_auth.xml&amp;id=0</url>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <tab>\n");
+ fwrite($fout, " <text>Extended Auth Settings</text>\n");
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_extauth.xml&amp;id=0</url>\n");
+ fwrite($fout, " <active/>\n");
+ fwrite($fout, " </tab>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " </tabs>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <fields>\n");
+ fwrite($fout, " <field>\n");
+ fwrite($fout, " <fielddescr>Base DN</fielddescr>\n");
+ fwrite($fout, " <fieldname>ldap_basedn</fieldname>\n");
+ fwrite($fout, " <description>This is the base where the LDAP search starts. All subsequent organizational units (OUs)will be included. Example: \"ou=users,o=company\" will search for users in and under the specified company.</description>\n");
+ fwrite($fout, " <type>input</type>\n");
+ fwrite($fout, " <size>50</size>\n");
+ fwrite($fout, " </field>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <field>\n");
+ fwrite($fout, " <fielddescr>LDAP Server</fielddescr>\n");
+ fwrite($fout, " <fieldname>ldap_server</fieldname>\n");
+ fwrite($fout, " <description>This is the LDAP server that the bind will be attempted against.</description>\n");
+ fwrite($fout, " <type>input</type>\n");
+ fwrite($fout, " <size>20</size>\n");
+ fwrite($fout, " </field>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <field>\n");
+ fwrite($fout, " <fielddescr>LDAP Type</fielddescr>\n");
+ fwrite($fout, " <fieldname>ldap_type</fieldname>\n");
+ fwrite($fout, " <description>This specifies the supported LDAP types.</description>\n");
+ fwrite($fout, " <type>select</type>\n");
+ fwrite($fout, " <options>\n");
+ fwrite($fout, " <option><name>Active Directory</name><value>active_directory</value></option>\n");
+ fwrite($fout, " <option><name>Novell eDirectory</name><value>novell_edirectory</value></option>\n");
+ fwrite($fout, " <option><name>LDAP v2</name><value>ldap_v2</value></option>\n");
+ fwrite($fout, " <option><name>LDAP v3</name><value>ldap_v3</value></option>\n");
+ fwrite($fout, " </options>\n");
+ fwrite($fout, " </field>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <field>\n");
+ fwrite($fout, " <fielddescr>LDAP Port</fielddescr>\n");
+ fwrite($fout, " <fieldname>ldap_port</fieldname>\n");
+ fwrite($fout, " <description>This is the port that LDAP bind will attempt on. The default is \"389\".</description>\n");
+ fwrite($fout, " <type>input</type>\n");
+ fwrite($fout, " <size>5</size>\n");
+ fwrite($fout, " </field>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <field>\n");
+ fwrite($fout, " <fielddescr>Bind DN Username</fielddescr>\n");
+ fwrite($fout, " <fieldname>bind_dn_username</fieldname>\n");
+ fwrite($fout, " <description>If \"anonymous bind\" is not supported, please specify the bind username that can access the Base DN hierarchy.</description>\n");
+ fwrite($fout, " <type>input</type>\n");
+ fwrite($fout, " <size>30</size>\n");
+ fwrite($fout, " </field>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <field>\n");
+ fwrite($fout, " <fielddescr>Bind DN Password</fielddescr>\n");
+ fwrite($fout, " <fieldname>bind_dn_password</fieldname>\n");
+ fwrite($fout, " <description>This is the associated password with the Bind DN Username previously specified.</description>\n");
+ fwrite($fout, " <type>password</type>\n");
+ fwrite($fout, " </field>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " </fields>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " <custom_add_php_command_late>\n");
+ fwrite($fout, " require_once(\"/usr/local/pkg/squid_ng.inc\");\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " mod_htpasswd();\n");
+ fwrite($fout, "\n");
+ fwrite($fout, " global_write_squid_config();\n");
+ fwrite($fout, " mwexec(\"/usr/local/sbin/squid -k reconfigure\");\n");
+ fwrite($fout, " </custom_add_php_command_late>\n");
+ fwrite($fout, "\n");
+ fwrite($fout, "</packagegui>\n");
+
+ fclose($fout);
+
+ /* mount filesystem read-only */
+ conf_mount_ro();
+}
+
+/* dynamically re-writes all squid xml files to handle adddeletecolumnitems properly */
+function dynamic_auth_content($pkgvar) {
+
+ switch ($pkgvar) {
+ case "pkg":
+ if ($handle = opendir("/usr/local/pkg")) {
+ while (($file = readdir($handle)) != false) {
+ if (stristr($file, "squid_") && stristr($file, ".xml")) {
+ $filecontents = file("/usr/local/pkg/" . $file);
+ $fout = fopen("/usr/local/pkg/" . $file, "w");
+ foreach($filecontents as $line) {
+ if (stristr($line, "<url>/pkg_edit.php?xml=squid_extauth.xml&amp;id=0</url>")) {
+ fwrite($fout, " <url>/pkg.php?xml=squid_extauth.xml&amp;id=0</url>\n");
+ } else {
+ fwrite($fout, $line);
+ }
+ }
+ }
+ }
+ }
+ break;
+
+ case "pkg_edit":
+ if ($handle = opendir("/usr/local/pkg")) {
+ while (($file = readdir($handle)) != false) {
+ if (stristr($file, "squid_") && stristr($file, ".xml")) {
+ $filecontents = file("/usr/local/pkg/" . $file);
+ $fout = fopen("/usr/local/pkg/" . $file,"w");
+ foreach($filecontents as $line) {
+ if (stristr($line, "<url>/pkg.php?xml=squid_extauth.xml&amp;id=0</url>")) {
+ fwrite($fout, " <url>/pkg_edit.php?xml=squid_extauth.xml&amp;id=0</url>\n");
+ } else {
+ fwrite($fout, $line);
+ }
+ }
+ }
+ }
+ }
+ break;
+ }
+
+} /* end function dynamic_auth_content */
+?> \ No newline at end of file
diff --git a/config/squid3/squid_auth.xml b/config/squid3/squid_auth.xml
new file mode 100644
index 00000000..b3e7c5c1
--- /dev/null
+++ b/config/squid3/squid_auth.xml
@@ -0,0 +1,225 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>squidauth</name>
+ <version>none</version>
+ <title>Proxy server: Authentication</title>
+ <include_file>squid.inc</include_file>
+ <tabs>
+ <tab>
+ <text>General settings</text>
+ <url>/pkg_edit.php?xml=squid.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Upstream proxy</text>
+ <url>/pkg_edit.php?xml=squid_upstream.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Cache management</text>
+ <url>/pkg_edit.php?xml=squid_cache.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Access control</text>
+ <url>/pkg_edit.php?xml=squid_nac.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Traffic management</text>
+ <url>/pkg_edit.php?xml=squid_traffic.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Auth settings</text>
+ <url>/pkg_edit.php?xml=squid_auth.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Local users</text>
+ <url>/pkg.php?xml=squid_users.xml</url>
+ </tab>
+ </tabs>
+ <fields>
+ <field>
+ <fielddescr>Authentication method</fielddescr>
+ <fieldname>auth_method</fieldname>
+ <description>Select an authentication method. This will allow users to be authenticated by local or external services.</description>
+ <type>select</type>
+ <required/>
+ <default_value>none</default_value>
+ <options>
+ <option><name>None</name><value>none</value></option>
+ <option><name>Local</name><value>local</value></option>
+ <option><name>LDAP</name><value>ldap</value></option>
+ <option><name>RADIUS</name><value>radius</value></option>
+ <option><name>NT domain</name><value>msnt</value></option>
+ </options>
+ <onchange>on_auth_method_changed()</onchange>
+ </field>
+ <field>
+ <fielddescr>LDAP version</fielddescr>
+ <fieldname>ldap_version</fieldname>
+ <description>Enter LDAP protocol version (2 or 3).</description>
+ <type>select</type>
+ <default_value>2</default_value>
+ <options>
+ <option><name>2</name><value>2</value></option>
+ <option><name>3</name><value>3</value></option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Authentication server</fielddescr>
+ <fieldname>auth_server</fieldname>
+ <description>Enter here the IP or hostname of the server that will perform the authentication.</description>
+ <type>input</type>
+ <size>60</size>
+ </field>
+ <field>
+ <fielddescr>Authentication server port</fielddescr>
+ <fieldname>auth_server_port</fieldname>
+ <description>Enter here the port to use to connect to the authentication server. Leave this field blank to use the authentication method's default port.</description>
+ <type>input</type>
+ <size>60</size>
+ </field>
+ <field>
+ <fielddescr>LDAP server user DN</fielddescr>
+ <fieldname>ldap_user</fieldname>
+ <description>Enter here the user DN to use to connect to the LDAP server.</description>
+ <type>input</type>
+ <size>60</size>
+ </field>
+ <field>
+ <fielddescr>LDAP password</fielddescr>
+ <fieldname>ldap_pass</fieldname>
+ <description>Enter here the password to use to connect to the LDAP server.</description>
+ <type>password</type>
+ <size>60</size>
+ </field>
+ <field>
+ <fielddescr>LDAP base domain</fielddescr>
+ <fieldname>ldap_basedomain</fieldname>
+ <description>For LDAP authentication, enter here the base domain in the LDAP server.</description>
+ <type>input</type>
+ <size>60</size>
+ </field>
+ <field>
+ <fielddescr>LDAP search filter</fielddescr>
+ <fieldname>ldap_filter</fieldname>
+ <description>Enter LDAP search filter.</description>
+ <type>input</type>
+ <size>60</size>
+ <default_value>(&amp;(objectClass=person)(uid=%s))</default_value>
+ </field>
+ <field>
+ <fielddescr>RADIUS secret</fielddescr>
+ <fieldname>radius_secret</fieldname>
+ <description>The RADIUS secret for RADIUS authentication.</description>
+ <type>password</type>
+ <size>60</size>
+ </field>
+ <field>
+ <fielddescr>Secondary NT servers</fielddescr>
+ <fieldname>msnt_secondary</fieldname>
+ <description>Comma-separated list of secondary servers to be used for NT domain authentication.</description>
+ <type>input</type>
+ <size>60</size>
+ </field>
+ <field>
+ <fielddescr>Authentication prompt</fielddescr>
+ <fieldname>auth_prompt</fieldname>
+ <description>This string will be displayed at the top of the authentication request window.</description>
+ <type>input</type>
+ <default_value>Please enter your credentials to access the proxy</default_value>
+ </field>
+ <field>
+ <fielddescr>Authentication processes</fielddescr>
+ <fieldname>auth_processes</fieldname>
+ <description>The number of authenticator processes to spawn. If many authentications are expected within a short timeframe, increase this number accordingly.</description>
+ <type>input</type>
+ <size>60</size>
+ <default_value>5</default_value>
+ </field>
+ <field>
+ <fielddescr>Authentication TTL</fielddescr>
+ <fieldname>auth_ttl</fieldname>
+ <description>This specifies for how long (in minutes) the proxy server assumes an externally validated username and password combination is valid (Time To Live). When the TTL expires, the user will be prompted for credentials again.</description>
+ <type>input</type>
+ <size>60</size>
+ <default_value>60</default_value>
+ </field>
+ <field>
+ <fielddescr>Requiere authentication for unrestricted hosts</fielddescr>
+ <fieldname>unrestricted_auth</fieldname>
+ <description>If this option is enabled, even users tagged as unrestricted through access control are required to authenticate to use the proxy.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Subnets that don't need authentication</fielddescr>
+ <fieldname>no_auth_hosts</fieldname>
+ <description>Enter each subnet or IP address on a new line (in CIDR format, e.g.: 10.5.0.0/16, 192.168.1.50/32) that should not be asked for authentication to access the proxy.</description>
+ <type>textarea</type>
+ <cols>50</cols>
+ <rows>5</rows>
+ <encoding>base64</encoding>
+ </field>
+ </fields>
+ <custom_php_validation_command>
+ squid_validate_auth($_POST, &amp;$input_errors);
+ </custom_php_validation_command>
+ <custom_php_after_form_command>
+ squid_print_javascript_auth2();
+ </custom_php_after_form_command>
+ <custom_php_resync_config_command>
+ squid_resync();
+ </custom_php_resync_config_command>
+ <custom_php_before_form_command>
+ squid_print_javascript_auth2();
+ </custom_php_before_form_command>
+ <custom_php_after_head_command>
+ $transparent_proxy = ($config['installedpackages']['squid']['config'][0]['transparent_proxy'] == 'on');
+ if($transparent_proxy)
+ $input_errors[] = "Authentication cannot be enabled while transparent proxy mode is enabled";
+ squid_print_javascript_auth();
+ </custom_php_after_head_command>
+</packagegui>
diff --git a/config/squid3/squid_cache.xml b/config/squid3/squid_cache.xml
new file mode 100644
index 00000000..9c96e67d
--- /dev/null
+++ b/config/squid3/squid_cache.xml
@@ -0,0 +1,223 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>squidcache</name>
+ <version>none</version>
+ <title>Proxy server: Cache management</title>
+ <include_file>squid.inc</include_file>
+ <tabs>
+ <tab>
+ <text>General settings</text>
+ <url>/pkg_edit.php?xml=squid.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Upstream proxy</text>
+ <url>/pkg_edit.php?xml=squid_upstream.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Cache management</text>
+ <url>/pkg_edit.php?xml=squid_cache.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Access control</text>
+ <url>/pkg_edit.php?xml=squid_nac.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Traffic management</text>
+ <url>/pkg_edit.php?xml=squid_traffic.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Auth settings</text>
+ <url>/pkg_edit.php?xml=squid_auth.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Local users</text>
+ <url>/pkg.php?xml=squid_users.xml</url>
+ </tab>
+ </tabs>
+ <fields>
+ <field>
+ <fielddescr>Hard disk cache size</fielddescr>
+ <fieldname>harddisk_cache_size</fieldname>
+ <description>This is the amount of disk space (in megabytes) to use for cached objects.</description>
+ <type>input</type>
+ <required/>
+ <default_value>100</default_value>
+ </field>
+ <field>
+ <fielddescr>Hard disk cache system</fielddescr>
+ <fieldname>harddisk_cache_system</fieldname>
+ <description>This specifies the kind of storage system to use. &lt;p&gt; &lt;b&gt; ufs &lt;/b&gt; is the old well-known Squid storage format that has always been there. &lt;p&gt; &lt;b&gt; aufs &lt;/b&gt; uses POSIX-threads to avoid blocking the main Squid process on disk-I/O. (Formerly known as async-io.) &lt;p&gt; &lt;b&gt; diskd &lt;/b&gt; uses a separate process to avoid blocking the main Squid process on disk-I/O.</description>
+ <type>select</type>
+ <default_value>aufs</default_value>
+ <options>
+ <option><name>ufs</name><value>ufs</value></option>
+ <option><name>aufs</name><value>aufs</value></option>
+ <option><name>diskd</name><value>diskd</value></option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Hard disk cache location</fielddescr>
+ <fieldname>harddisk_cache_location</fieldname>
+ <description>This is the directory where the cache will be stored. (note: do not end with a /). If you change this location, squid needs to make a new cache, this could take a while</description>
+ <type>input</type>
+ <size>60</size>
+ <required/>
+ <default_value>/var/squid/cache</default_value>
+ </field>
+ <field>
+ <fielddescr>Memory cache size</fielddescr>
+ <fieldname>memory_cache_size</fieldname>
+ <description>This is the amount of physical RAM (in megabytes) to be used for negative cache and in-transit objects. This value should not exceed more than 50% of the installed RAM. The minimum value is 1MB.</description>
+ <type>input</type>
+ <required/>
+ <default_value>8</default_value>
+ </field>
+ <field>
+ <fielddescr>Minimum object size</fielddescr>
+ <fieldname>minimum_object_size</fieldname>
+ <description>Objects smaller than the size specified (in kilobytes) will not be saved on disk. The default value is 0, meaning there is no minimum.</description>
+ <type>input</type>
+ <required />
+ <default_value>0</default_value>
+ </field>
+ <field>
+ <fielddescr>Maximum object size</fielddescr>
+ <fieldname>maximum_object_size</fieldname>
+ <description>Objects larger than the size specified (in kilobytes) will not be saved on disk. If you wish to increase speed more than you want to save bandwidth, this should be set to a low value.</description>
+ <type>input</type>
+ <required/>
+ <default_value>4</default_value>
+ </field>
+ <field>
+ <fielddescr>Level 1 subdirectories</fielddescr>
+ <fieldname>level1_subdirs</fieldname>
+ <description>Each level-1 directory contains 256 subdirectories, so a value of 256 level-1 directories will use a total of 65536 directories for the hard disk cache. This will significantly slow down the startup process of the proxy service, but can speed up the caching under certain conditions.</description>
+ <type>select</type>
+ <default_value>16</default_value>
+ <options>
+ <option><name>4</name><value>4</value></option>
+ <option><name>8</name><value>8</value></option>
+ <option><name>16</name><value>16</value></option>
+ <option><name>32</name><value>32</value></option>
+ <option><name>64</name><value>64</value></option>
+ <option><name>128</name><value>128</value></option>
+ <option><name>256</name><value>256</value></option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Memory replacement policy</fielddescr>
+ <fieldname>memory_replacement_policy</fieldname>
+ <description>The memory replacement policy determines which objects are purged from memory when space is needed. The default policy for memory replacement is GDSF. &lt;p&gt; &lt;b&gt; LRU: Last Recently Used Policy &lt;/b&gt; - The LRU policies keep recently referenced objects. i.e., it replaces the object that has not been accessed for the longest time. &lt;p&gt; &lt;b&gt; Heap GDSF: Greedy-Dual Size Frequency &lt;/b&gt; - The Heap GDSF policy optimizes object-hit rate by keeping smaller, popular objects in cache. It achieves a lower byte hit rate than LFUDA though, since it evicts larger (possibly popular) objects. &lt;p&gt; &lt;b&gt; Heap LFUDA: Least Frequently Used with Dynamic Aging &lt;/b&gt; - The Heap LFUDA policy keeps popular objects in cache regardless of their size and thus optimizes byte hit rate at the expense of hit rate since one large, popular object will prevent many smaller, slightly less popular objects from being cached. &lt;p&gt; &lt;b&gt; Heap LRU: Last Recently Used &lt;/b&gt; - Works like LRU, but uses a heap instead. &lt;p&gt; Note: If using the LFUDA replacement policy, the value of Maximum Object Size should be increased above its default of 12KB to maximize the potential byte hit rate improvement of LFUDA.</description>
+ <type>select</type>
+ <default_value>heap GDSF</default_value>
+ <options>
+ <option><name>LRU</name><value>lru</value></option>
+ <option><name>Heap LFUDA</name><value>heap LFUDA</value></option>
+ <option><name>Heap GDSF</name><value>heap GDSF</value></option>
+ <option><name>Heap LRU</name><value>heap LRU</value></option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Cache replacement policy</fielddescr>
+ <fieldname>cache_replacement_policy</fieldname>
+ <description>The cache replacement policy decides which objects will remain in cache and which objects are replaced to create space for the new objects. The default policy for cache replacement is LFUDA. Please see the type descriptions specified in the memory replacement policy for additional detail.</description>
+ <type>select</type>
+ <default_value>heap LFUDA</default_value>
+ <options>
+ <option><name>LRU</name><value>lru</value></option>
+ <option><name>Heap LFUDA</name><value>heap LFUDA</value></option>
+ <option><name>Heap GDSF</name><value>heap GDSF</value></option>
+ <option><name>Heap LRU</name><value>heap LRU</value></option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Low-water-mark in %</fielddescr>
+ <fieldname>cache_swap_low</fieldname>
+ <description>Cache replacement begins when the swap usage is above the low-low-water mark and attempts to maintain utilisation near the low-water-mark.</description>
+ <type>input</type>
+ <default_value>90</default_value>
+ </field>
+ <field>
+ <fielddescr>High-water-mark in %</fielddescr>
+ <fieldname>cache_swap_high</fieldname>
+ <description>As swap utilisation gets close to the high-water-mark object eviction becomes more aggressive.</description>
+ <type>input</type>
+ <default_value>95</default_value>
+ </field>
+ <field>
+ <fielddescr>Do not cache</fielddescr>
+ <fieldname>donotcache</fieldname>
+ <description>Enter each domain or IP address on a new line that should never be cached.</description>
+ <type>textarea</type>
+ <cols>50</cols>
+ <rows>5</rows>
+ <encoding>base64</encoding>
+ </field>
+ <field>
+ <fielddescr>Enable offline mode</fielddescr>
+ <fieldname>enable_offline</fieldname>
+ <description>Enable this option and the proxy server will never try to validate cached objects. The offline mode gives access to more cached information than the proposed feature would allow (stale cached versions, where the origin server should have been contacted).</description>
+ <type>checkbox</type>
+ <required/>
+ </field>
+ </fields>
+ <custom_php_command_before_form>
+ if($_POST['harddisk_cache_size'] != $config['installedpackages']['squidcache']['config'][0]['harddisk_cache_size']) {
+ $needs_dash_z = true;
+ }
+ </custom_php_command_before_form>
+ <custom_php_validation_command>
+ squid_validate_cache($_POST, &amp;$input_errors);
+ </custom_php_validation_command>
+ <custom_php_resync_config_command>
+ squid_resync();
+ if($needs_dash_z)
+ squid_dash_z();
+ </custom_php_resync_config_command>
+</packagegui>
diff --git a/config/squid3/squid_extauth.xml b/config/squid3/squid_extauth.xml
new file mode 100644
index 00000000..745e85d5
--- /dev/null
+++ b/config/squid3/squid_extauth.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>squidextnoauth</name>
+ <version>none</version>
+ <title>Services: Proxy Server -> Extended Authentication Settings</title>
+ <aftersaveredirect>/pkg_edit.php?xml=squid_extauth.xml&amp;id=0</aftersaveredirect>
+ <tabs>
+ <tab>
+ <text>General Settings</text>
+ <url>/pkg_edit.php?xml=squid_ng.xml&amp;id=0</url>
+ </tab>
+
+ <tab>
+ <text>Upstream Proxy</text>
+ <url>/pkg_edit.php?xml=squid_upstream.xml&amp;id=0</url>
+ </tab>
+
+ <tab>
+ <text>Cache Mgmt</text>
+ <url>/pkg_edit.php?xml=squid_cache.xml&amp;id=0</url>
+ </tab>
+
+ <tab>
+ <text>Network Access Control</text>
+ <url>/pkg_edit.php?xml=squid_nac.xml&amp;id=0</url>
+ </tab>
+
+ <tab>
+ <text>Traffic Mgmt</text>
+ <url>/pkg_edit.php?xml=squid_traffic.xml&amp;id=0</url>
+ </tab>
+
+ <tab>
+ <text>Auth Settings</text>
+ <url>/pkg_edit.php?xml=squid_auth.xml&amp;id=0</url>
+ </tab>
+
+ <tab>
+ <text>Extended Auth Settings</text>
+ <url>/pkg_edit.php?xml=squid_extauth.xml&amp;id=0</url>
+ <active/>
+ </tab>
+
+ </tabs>
+ <configpath>installedpackages->package->squidextnoauth->configuration->settings</configpath>
+ <fields>
+ <field>
+ <fielddescr>No Authentication Defined</fielddescr>
+ <fieldname>no_auth</fieldname>
+ <type>text</type>
+ </field>
+ </fields>
+
+ <custom_add_php_command_late>
+ require_once("/usr/local/pkg/squid_ng.inc");
+
+ global_write_squid_config();
+ mwexec("/usr/local/sbin/squid -k reconfigure");
+ </custom_add_php_command_late>
+
+</packagegui>
diff --git a/config/squid3/squid_nac.xml b/config/squid3/squid_nac.xml
new file mode 100644
index 00000000..73c4cae5
--- /dev/null
+++ b/config/squid3/squid_nac.xml
@@ -0,0 +1,143 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>squidnac</name>
+ <version>none</version>
+ <title>Proxy server: Access control</title>
+ <include_file>squid.inc</include_file>
+ <tabs>
+ <tab>
+ <text>General settings</text>
+ <url>/pkg_edit.php?xml=squid.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Upstream proxy</text>
+ <url>/pkg_edit.php?xml=squid_upstream.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Cache management</text>
+ <url>/pkg_edit.php?xml=squid_cache.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Access control</text>
+ <url>/pkg_edit.php?xml=squid_nac.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Traffic management</text>
+ <url>/pkg_edit.php?xml=squid_traffic.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Auth settings</text>
+ <url>/pkg_edit.php?xml=squid_auth.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Local users</text>
+ <url>/pkg.php?xml=squid_users.xml</url>
+ </tab>
+ </tabs>
+ <fields>
+ <field>
+ <fielddescr>Allowed subnets</fielddescr>
+ <fieldname>allowed_subnets</fieldname>
+ <description>Enter each subnet on a new line that is allowed to use the proxy. The subnets must be expressed as CIDR ranges (e.g.: 192.168.1.0/24). Note that the proxy interface subnet is already an allowed subnet. All the other subnets won't be able to use the proxy.</description>
+ <type>textarea</type>
+ <cols>50</cols>
+ <rows>5</rows>
+ <encoding>base64</encoding>
+ </field>
+ <field>
+ <fielddescr>Unrestricted IPs</fielddescr>
+ <fieldname>unrestricted_hosts</fieldname>
+ <description>Enter each unrestricted IP address on a new line that is not to be filtered out by the other access control directives set in this page.</description>
+ <type>textarea</type>
+ <cols>50</cols>
+ <rows>5</rows>
+ <encoding>base64</encoding>
+ </field>
+ <field>
+ <fielddescr>Banned host addresses</fielddescr>
+ <fieldname>banned_hosts</fieldname>
+ <description>Enter each IP address on a new line that is not to be allowed to use the proxy.</description>
+ <type>textarea</type>
+ <cols>50</cols>
+ <rows>5</rows>
+ <encoding>base64</encoding>
+ </field>
+ <field>
+ <fielddescr>Whitelist</fielddescr>
+ <fieldname>whitelist</fieldname>
+ <description>Enter each destination domain on a new line that will be accessable to the users that are allowed to use the proxy.</description>
+ <type>textarea</type>
+ <cols>50</cols>
+ <rows>5</rows>
+ <encoding>base64</encoding>
+ </field>
+ <field>
+ <fielddescr>Blacklist</fielddescr>
+ <fieldname>blacklist</fieldname>
+ <description>Enter each destination domain on a new line that will be blocked to the users that are allowed to use the proxy.</description>
+ <type>textarea</type>
+ <cols>50</cols>
+ <rows>5</rows>
+ <encoding>base64</encoding>
+ </field>
+ <field>
+ <fielddescr>External Cache-Managers</fielddescr>
+ <fieldname>ext_cachemanager</fieldname>
+ <description>Enter the IPs for the external Cache Managers to be allowed here, separated by semi-colons (;).</description>
+ <type>input</type>
+ <size>60</size>
+ </field>
+ </fields>
+ <custom_php_validation_command>
+ squid_validate_nac($_POST, &amp;$input_errors);
+ </custom_php_validation_command>
+ <custom_php_resync_config_command>
+ squid_resync();
+ </custom_php_resync_config_command>
+</packagegui>
diff --git a/config/squid3/squid_ng.inc b/config/squid3/squid_ng.inc
new file mode 100644
index 00000000..dc18e349
--- /dev/null
+++ b/config/squid3/squid_ng.inc
@@ -0,0 +1,1067 @@
+<?php
+/* $Id$ */
+
+/*
+ squid_ng.inc
+ part of pfSense (www.pfSense.com)
+
+ Copyright (C) 2005 Michael Capp <michael.capp@gmail.com>
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+function global_write_squid_config()
+{
+ global $config;
+ conf_mount_rw();
+ config_lock();
+
+ /* define squid configuration file in variable for replace function */
+ $squidconfig = "/usr/local/etc/squid/squid.conf";
+
+ /* squid.xml values */
+ $active_interface = $config['installedpackages']['squid']['config'][0]['active_interface'];
+ $transparent_proxy = $config['installedpackages']['squid']['config'][0]['transparent_proxy'];
+ $log_enabled = $config['installedpackages']['squid']['config'][0]['log_enabled'];
+ $urlfier_enable = $config['installedpackages']['squid']['config'][0]['urlfilter_enable'];
+ $accesslog_disabled = $config['installedpackages']['squid']['config'][0]['accesslog_disabled'];
+ $log_query_terms = $config['installedpackages']['squid']['config'][0]['log_query_terms'];
+ $log_user_agents = $config['installedpackages']['squid']['config'][0]['log_user_agents'];
+ $proxy_port = $config['installedpackages']['squid']['config'][0]['proxy_port'];
+ $visible_hostname = $config['installedpackages']['squid']['config'][0]['visible_hostname'];
+ $cache_admin_email = $config['installedpackages']['squid']['config'][0]['cache_admin_email'];
+ $error_language = $config['installedpackages']['squid']['config'][0]['error_language'];
+ $cachemgr_enabled = $config['installedpackages']['squid']['config'][0]['cachemgr_enabled'];
+
+ /* squid_upstream.xml values */
+ $proxy_forwarding = $config['installedpackages']['squidupstream']['config'][0]['proxy_forwarding'];
+ $client_ip_forwarding = $config['installedpackages']['squidupstream']['config'][0]['client_ip_forwarding'];
+ $user_forwarding = $config['installedpackages']['squidupstream']['config'][0]['user_forwarding'];
+ $upstream_proxy = $config['installedpackages']['squidupstream']['config'][0]['upstream_proxy'];
+ $upstream_proxy_port = $config['installedpackages']['squidupstream']['config'][0]['upstream_proxy_port'];
+ $upstream_username = $config['installedpackages']['squidupstream']['config'][0]['upstream_username'];
+ $upstream_password = $config['installedpackages']['squidupstream']['config'][0]['upstream_psasword'];
+
+ /* squid_cache.xml values */
+ $memory_cache_size = $config['installedpackages']['squidcache']['config'][0]['memory_cache_size'];
+ $harddisk_cache_size = $config['installedpackages']['squidcache']['config'][0]['harddisk_cache_size'];
+ $minimum_object_size = $config['installedpackages']['squidcache']['config'][0]['minimum_object_size'];
+ $maximum_object_size = $config['installedpackages']['squidcache']['config'][0]['maximum_object_size'];
+ $level_subdirs = $config['installedpackages']['squidcache']['config'][0]['level_subdirs'];
+ $memory_replacement = $config['installedpackages']['squidcache']['config'][0]['memory_replacement'];
+ $cache_replacement = $config['installedpackages']['squidcache']['config'][0]['cache_replacement'];
+ $domain = $config['installedpackages']['squidcache']['config'][0]['domain'];
+ $enable_offline = $config['installedpackages']['squidcache']['config'][0]['enable_offline'];
+
+ /* squid_nac.xml values */
+ $allowed_subnets = $config['installedpackages']['squidnac']['config'][0]['allowed_subnets'];
+ $unrestricted_ip_addr = $config['installedpackages']['squidnac']['config'][0]['unrestricted_ip_address'];
+ $unrestricted_mac_addr = $config['installedpackages']['squidnac']['config'][0]['unrestricted_mac_addresses'];
+ $banned_ip_addr = $config['installedpackages']['squidnac']['config'][0]['banned_ip_addresses'];
+ $banned_mac_addr = $config['installedpackages']['squidnac']['config'][0]['banned_mac_addresses'];
+ $override_hosts = $config['installedpackages']['squidnac']['config'][0]['override_hosts'];
+
+ /* squid_traffic.xml values */
+ $max_download_size = $config['installedpackages']['squidtraffic']['config'][0]['max_download_size'];
+ $max_upload_size = $config['installedpackages']['squidtraffic']['config'][0]['max_upload_size'];
+ $dl_overall = $config['installedpackages']['squidtraffic']['config'][0]['dl_overall'];
+ $dl_per_host = $config['installedpackages']['squidtraffic']['config'][0]['dl_per_host'];
+ $throttle_binary_files = $config['installedpackages']['squidtraffic']['config'][0]['throttle_binary_files'];
+ $throttle_cd_images = $config['installedpackages']['squidtraffic']['config'][0]['throttle_cd_images'];
+ $throttle_multimedia = $config['installedpackages']['squidtraffic']['config'][0]['throttle_multimedia'];
+
+ /* squid_auth.xml values */
+ $auth_method = $config['installedpackages']['squidauth']['config'][0]['auth_method'];
+ $auth_processes = $config['installedpackages']['squidauth']['config'][0]['auth_processes'];
+ $auth_cache_ttl = $config['installedpackages']['squidauth']['config'][0]['auth_cache_ttl'];
+ $limit_ip_addr = $config['installedpackages']['squidauth']['config'][0]['limit_ip_addr'];
+ $user_ip_cache_ttl = $config['installedpackages']['squidauth']['config'][0]['user_ip_cache_ttl'];
+ $req_unrestricted_auth = $config['installedpackages']['squidauth']['config'][0]['req_unrestricted_auth'];
+ $auth_realm_prompt = $config['installedpackages']['squidauth']['config'][0]['auth_realm_prompt'];
+ $no_domain_auth = $config['installedpackages']['squidauth']['config'][0]['no_domain_auth'];
+ $min_pass_length = $config['installedpackages']['squidauth']['config'][0]['min_pass_length'];
+ $bypass_extended = $config['installedpackages']['squidauth']['config'][0]['bypass_extended'];
+
+ /* squid_extauth.xml (ldap) values */
+ $ldap_basedn = $config['installedpackages']['squidextldapauth']['config'][0]['ldap_basedn'];
+ $ldap_server = $config['installedpackages']['squidextldapauth']['config'][0]['ldap_server'];
+ $ldap_type = $config['installedpackages']['squidextldapauth']['config'][0]['ldap_type'];
+ $ldap_port = $config['installedpackages']['squidextldapauth']['config'][0]['ldap_port'];
+ $bind_dn_username = $config['installedpackages']['squidextldapauth']['config'][0]['bind_dn_username'];
+ $bind_dn_password = $config['installedpackages']['squidextldapauth']['config'][0]['bind_dn_password'];
+
+ /* squid_extauth.xml (radius) values */
+ $radius_server = $config['installedpackages']['squidextradiusauth']['config'][0]['radius_server'];
+ $radius_port = $config['installedpackages']['squidextradiusauth']['config'][0]['radius_port'];
+ $radius_identifier = $config['installedpackages']['squidextradiusauth']['config'][0]['radius_identifier'];
+ $radius_secret = $config['installedpackages']['squidextradiusauth']['config'][0]['radius_secret'];
+
+ /* static variable assignments for directory mapping */
+ $acldir = "/usr/local/etc/squid/advanced/acls";
+ $ncsadir = "/usr/local/etc/squid/advanced/ncsa";
+ $ntlmdir = "/usr/local/etc/squid/advanced/ntlm";
+ $radiusdir = "/usr/local/etc/squid/advanced/radius";
+
+ $fout = fopen($squidconfig, "w");
+
+ $config_array = array('shutdown_lifetime 5 seconds' . "\n\n");
+
+ if (isset($cachemgr_enabled) && ($cachemgr_enabled == "on")) {
+ mwexec("cp /usr/local/libexec/squid/cachemgr.cgi /usr/local/www/cachemgr.cgi");
+ mwexec("chmod a+rx /usr/local/www/cachemgr.cgi");
+ } else {
+ mwexec("rm -f /usr/local/www/cachemgr.cgi");
+ }
+ unset($cachemgr_enabled);
+
+ if (!isset($icp_port) or ($icp_port == "")) {
+ $icp_port = "3130";
+ }
+ $config_array[] = 'icp_port ' . $icp_port . "\n";
+ unset($icp_port);
+
+ if(!isset($proxy_port) or ($proxy_port == "")) {
+ $proxy_port = "3128";
+ }
+
+ if (isset($transparent_proxy) && ($transparent_proxy != "on")) {
+ $int = convert_friendly_interface_to_real_interface_name($active_interface);
+ $listen_ip = find_interface_ip($int);
+
+ $config_array[] = 'http_port ' . $listen_ip . ':' . $proxy_port . "\n\n";
+ $config_array[] = 'acl QUERY urlpath_regex cgi-bin \?' . "\n";
+ $config_array[] = 'no_cache deny QUERY' . "\n\n";
+ }
+ $config_array[] = 'http_port 127.0.0.1:' . $proxy_port . "\n\n";
+ unset($proxy_port);
+
+ if (isset($domain) && ($domain !== "")) {
+ if (!file_exists($acldir)) {
+ mwexec("/bin/mkdir -p " . $acldir);
+ }
+
+ $aclout = fopen($acldir . "/dst_nocache.acl","w");
+
+ $domain_array = split("; ",$domain);
+ foreach ($domain_array as $no_cache_domain) {
+ fwrite($aclout, $no_cache_domain . "\n");
+ }
+
+ fclose($aclout);
+
+ $config_array[] = 'acl no_cache_domains dstdomain "' . $acldir . '/dst_nocache.acl"' . "\n";
+ $config_array[] = 'no_cache deny no_cache_domains' . "\n\n";
+ }
+ unset($no_cache_domain);
+ unset($domain_array);
+ unset($domain);
+
+ $config_array[] = 'cache_effective_user squid' . "\n";
+ $config_array[] = 'cache_effective_group squid' . "\n\n";
+ $config_array[] = 'pid_filename /var/run/squid.pid' . "\n\n";
+
+ if (!isset($memory_cache_size) or ($memory_cache_size == "")) {
+ $memory_cache_size = "8";
+ }
+ $config_array[] = 'cache_mem ' . $memory_cache_size . ' MB' . "\n";
+ unset($memory_cache_size);
+
+ if (!isset($harddisk_cache_size) or ($harddisk_cache_size == "")) {
+ $harddisk_cache_size = "500";
+ }
+
+ if (!isset($level_subdirs) or ($level_subdirs == "")) {
+ $level_subdirs = "16";
+ }
+
+ $config_array[] = 'cache_dir diskd /var/squid/cache ' . $harddisk_cache_size . ' ' . $level_subdirs . ' 256' . "\n\n";
+ unset($harddisk_cache_size);
+ unset($level_subdirs);
+
+ if (!isset($error_language) or ($error_language == "")) {
+ $error_language = "English";
+ }
+ $config_array[] = 'error_directory /usr/local/etc/squid/errors/' . $error_language . "\n\n";
+ unset($error_language);
+
+ if (isset($offline_mode) && ($offline_mode == "on")) {
+ $config_array[] = 'offline_mode on' . "\n\n";
+ } else {
+ $config_array[] = 'offline_mode off' . "\n\n";
+ }
+
+ if (!isset($memory_replacement) or ($memory_replacement == "")) {
+ $memory_replacement = "heap GDSF";
+ }
+ $config_array[] = 'memory_replacement_policy ' . $memory_replacement . "\n";
+ unset($memory_replacement);
+
+ if (!isset($cache_replacement) or ($cache_replacement == "")) {
+ $cache_replacement="heap GDSF";
+ }
+ $config_array[] = 'cache_replacement_policy ' . $cache_replacement . "\n\n";
+ unset($cache_replacement);
+
+ if (isset($accesslog_disabled) && ($accesslog_disabled == "on")) {
+ $config_array[] = 'cache_access_log none' . "\n";
+ } else {
+ $config_array[] = 'cache_access_log /var/log/access.log' . "\n";
+ }
+ $config_array[] = 'cache_log /var/log/cache.log' . "\n";
+ $config_array[] = 'cache_store_log none' . "\n";
+ unset($accesslog_disabled);
+ unset($log_enabled);
+
+ if (isset($log_query_terms) && ($log_query_terms == "on")) {
+ $config_array[] = 'strip_query_terms off' . "\n";
+ } else {
+ $config_array[] = 'strip_query_terms on' . "\n";
+ }
+ unset($log_query_terms);
+
+ $config_array[] = 'useragent_log /var/log/useragent.log' . "\n\n";
+ unset($log_user_agents);
+
+ $config_array[] = 'log_mime_hdrs off' . "\n";
+ $config_array[] = 'emulate_httpd_log on' . "\n";
+
+ switch ($user_forwarding) {
+ case "on":
+ $config_array[] = 'forwarded_for on' . "\n\n";
+ break;
+ case "off":
+ $config_array[] = 'forwarded_for off' . "\n\n";
+ break;
+ default:
+ $config_array[] = 'forwarded_for off' . "\n\n";
+ break;
+ }
+ unset($user_forwarding);
+
+ switch ($auth_method) {
+ case "none":
+ break;
+ case "local_auth":
+ $config_array[] = 'auth_param basic program /usr/local/libexec/squid/ncsa_auth /usr/local/etc/squid/advanced/ncsa/passwd' . "\n";
+ if (!isset($auth_processes) or ($auth_processes == "")) {
+ $auth_processes = "5";
+ }
+ $config_array[] = 'auth_param basic children ' . $auth_processes . "\n";
+
+ if (!isset($auth_realm_prompt) or ($auth_realm_prompt == "")) {
+ $auth_realm_prompt = "pfSense Advanced Proxy";
+ }
+ $config_array[] = 'auth_param basic realm ' . $auth_realm_prompt . "\n";
+
+ if (!isset($auth_cache_ttl) or ($auth_cache_ttl == "")) {
+ $auth_cache_ttl = "60";
+ }
+ $config_array[] = 'auth_param basic credentialsttl ' . $auth_cache_ttl . ' minutes' . "\n\n";
+ $config_array[] = 'acl for_inetusers proxy_auth REQUIRED' . "\n\n";
+
+ unset($auth_realm_prompt);
+ unset($auth_processes);
+ unset($auth_cache_ttl);
+
+ break;
+ case "radius_auth";
+ $config_array[] = 'auth_param basic program /usr/local/libexec/squid/squid_rad_auth -h ' . $radius_server . ' -p ' . $radius_port . ' -i ' . $radius_identifier . ' -w ' . $radius_secret . "\n";
+ if (!isset($auth_processes) or ($auth_processes == "")) {
+ $auth_processes = "5";
+ }
+ $config_array[] = 'auth_param basic children ' . $auth_processes . "\n";
+
+ if (!isset($auth_realm_prompt) or ($auth_realm_prompt == "")) {
+ $auth_realm_prompt = "pfSense Advanced Proxy";
+ }
+ $config_array[] = 'auth_param basic realm ' . $auth_realm_prompt . "\n";
+
+ if (!isset($auth_cache_ttl) or ($auth_cache_ttl == "")) {
+ $auth_cache_ttl = "60";
+ }
+ $config_array[] = 'auth_param basic credentialsttl ' . $auth_cache_ttl . ' minutes' . "\n\n";
+ $config_array[] = 'acl for_inetusers proxy_auth REQUIRED' . "\n\n";
+
+ unset($auth_realm_prompt);
+ unset($auth_processes);
+ unset($auth_cache_ttl);
+
+ break;
+ case "ldap_bind";
+ $config_array[] = 'auth_param basic program /usr/local/libexec/squid_ldap_auth -b "' . $ldap_basedn . '" -D "' . $bind_dn_username . '" -w "' . $bind_dn_password . '" -f "(&(objectClass=person)(cn=%s))" -u -cn -P "' . $ldap_server . ":" . $ldap_port . "\n";
+ $config_array[] = 'auth_param basic program /usr/local/libexec/squid/squid_ldap_auth';
+ $config_array[] = ' -b "' . $ldap_basedn . '"';
+ $config_array[] = ' -D "' . $bind_dn_username . '"';
+ $config_array[] = " -w " . $bind_dn_password;
+ $config_array[] = ' -f "(&(objectClass=person)(cn=%s))"';
+ $config_array[] = " -u cn -P " . $ldap_server . ":" . $ldap_port . "\n";
+
+ if (!isset($auth_processes) or ($auth_processes == "")) {
+ $auth_processes = "5";
+ }
+ $config_array[] = 'auth_param basic children ' . $auth_processes . "\n";
+
+ if (!isset($auth_realm_prompt) or ($auth_realm_prompt == "")) {
+ $auth_realm_prompt = "pfSense Advanced Proxy";
+ }
+ $config_array[] = 'auth_param basic realm ' . $auth_realm_prompt . "\n";
+
+ if (!isset($auth_cache_ttl) or ($auth_cache_ttl == "")) {
+ $auth_cache_ttl = "60";
+ }
+ $config_array[] = 'auth_param basic credentialsttl ' . $auth_cache_ttl . ' minutes' . "\n\n";
+ $config_array[] = 'acl for_inetusers proxy_auth REQUIRED' . "\n\n";
+
+ unset($auth_realm_prompt);
+ unset($auth_processes);
+ unset($auth_cache_ttl);
+
+ break;
+ case "windows_auth";
+ break;
+ }
+
+ if (isset($throttle_binary_files) && ($throttle_binary_files == "on")) {
+ if (!file_exists($acldir)) {
+ mwexec("/bin/mkdir -p " . $acldir);
+ }
+
+ $binary_out = "\.bin$\n\.cab$\n\.gz$\n\.rar$\n\.sea$\n\.tar$\n\.tgz$\n\.zip$\n";
+
+ $throttle_out = fopen($acldir . "/dst_throttle_binary.acl", "w");
+ fwrite($throttle_out, $binary_out);
+ fclose($throttle_out);
+ $config_array[] = 'acl for_throttled_binary url_regex -i "' . $acldir . '/dst_throttle_binary.acl"' . "\n";
+ } else {
+ if (file_exists($acldir . "/dst_throttle_binary.acl")) unlink($acldir . "/dst_throttle_binary.acl");
+ }
+ unset($throttle_binary_files);
+ unset($throttle_out);
+ unset($binary_out);
+
+ if (isset($throttle_cd_images) && ($throttle_cd_images == "on")) {
+ if (!file_exists($acldir)) {
+ mwexec("/bin/mkdir -p " . $acldir);
+ }
+
+ $cd_out = "\.b5t$\n\.bin$\n\.bwt$\n\.cdi$\n\.cue$\n\.gho$\n\.img$\n\.iso$\n\.mds$\n\.nrg$\n\.pqi$\n";
+
+ $throttle_out = fopen($acldir . "/dst_throttle_cd.acl","w");
+ fwrite($throttle_out, $cd_out);
+ fclose($throttle_out);
+ $config_array[] = 'acl for_throttled_cd url_regex -i "' . $acldir . '/dst_throttle_cd.acl"' . "\n";
+ } else {
+ if (file_exists($acldir . "/dst_throttle_cd.acl")) {
+ unlink($acldir . "/dst_throttle_cd.acl");
+ }
+ }
+ unset($throttle_cd_images);
+ unset($throttle_out);
+ unset($cd_out);
+
+ if (isset($throttle_multimedia) && ($throttle_multimedia == "on")) {
+ if (!file_exists($acldir)) {
+ mwexec("/bin/mkdir -p " . $acldir);
+ }
+
+ $multimedia_out = "\.aiff?$\n\.asf$\n\.avi$\n\.divx$\n\.mov$\n\.mp3$\n\.mpe?g$\n\.qt$\n\.ra?m$\n";
+
+ $throttle_out = fopen($acldir . "/dst_throttle_multimedia.acl","w");
+ fwrite($throttle_out, $multimedia_out);
+ fclose($throttle_out);
+ $config_array[] = 'acl for_throttled_multimedia url_regex -i "' . $acldir . '/dst_throttle_multimedia.acl"' . "\n";
+ } else {
+ if (file_exists($acldir . "/dst_throttle_multimedia.acl")) {
+ unlink($acldir . "/dst_throttle_multimedia.acl");
+ }
+ }
+ unset($throttle_multimedia);
+ unset($multimedia_out);
+ unset($throttle_out);
+
+ $config_array[] = 'acl within_timeframe time MTWHFAS 00:00-24:00' . "\n\n";
+
+ /* obtain interface subnet and address for Squid rules */
+ $lactive_interface = strtolower($active_interface);
+
+ $lancfg = $config['interfaces'][$lactive_interface];
+ $lanif = $lancfg['if'];
+ $lanip = $lancfg['ipaddr'];
+ $lansa = gen_subnet($lancfg['ipaddr'], $lancfg['subnet']);
+ $lansn = $lancfg['subnet'];
+
+ $config_array[] = 'acl all src 0.0.0.0/0.0.0.0' . "\n";
+ $config_array[] = 'acl localnet src ' . $lansa . '/' . $lansn . "\n";
+ $config_array[] = 'acl localhost src 127.0.0.1/255.255.255.255' . "\n";
+ $config_array[] = 'acl SSL_ports port 443 563 873 # https, snews, rsync' . "\n";
+ $config_array[] = 'acl Safe_ports port 80 # http' . "\n";
+ $config_array[] = 'acl Safe_ports port 21 # ftp' . "\n";
+ $config_array[] = 'acl Safe_ports port 443 563 873 # https, snews, rsync' . "\n";
+ $config_array[] = 'acl Safe_ports port 70 # gopher' . "\n";
+ $config_array[] = 'acl Safe_ports port 210 # wais' . "\n";
+ $config_array[] = 'acl Safe_ports port 1025-65535 # unregistered ports' . "\n";
+ $config_array[] = 'acl Safe_ports port 280 # http-mgmt' . "\n";
+ $config_array[] = 'acl Safe_ports port 488 # gss-http' . "\n";
+ $config_array[] = 'acl Safe_ports port 591 # filemaker' . "\n";
+ $config_array[] = 'acl Safe_ports port 777 # multiling http' . "\n";
+ $config_array[] = 'acl Safe_ports port 800 # Squids port (for icons)' . "\n\n";
+
+ /* allow access through proxy for custom admin port */
+ $custom_port = $config['system']['webgui']['port'];
+ if (isset($custom_port) && ($custom_port !== "")) {
+ $config_array[] = 'acl pf_admin_port port ' . $custom_port . "\n";
+ unset($custom_port);
+ } else {
+ $admin_protocol = $config['system']['webgui']['protocol'];
+ switch ($admin_protocol) {
+ case "http";
+ $config_array[] = 'acl pf_admin_port port 80' ."\n";
+ break;
+ case "https";
+ $config_array[] = 'acl pf_admin_port port 443' . "\n";
+ break;
+ default;
+ $config_array[] = 'acl pf_admin_port port 80' . "\n";
+ break;
+ }
+ unset($admin_protocol);
+ }
+
+ /* define override hosts as specified in squid_nac.xml */
+ if (isset($override_hosts) && ($override_hosts !== "")) {
+ if (!file_exists($acldir)) {
+ mwexec("/bin/mkdir -p " . $acldir);
+ }
+
+ $aclout = fopen($acldir . "/src_override_hosts.acl", "w");
+
+ $override_hosts_array = split("; ", $override_hosts);
+ foreach ($override_hosts_array as $ind_override_host) {
+ fwrite($aclout, $ind_override_host . "\n");
+ }
+
+ fclose($aclout);
+
+ $config_array[] = 'acl override_hosts src "/usr/local/etc/squid/advanced/acls/src_override_hosts.acl"' . "\n";
+ }
+ /* clear variables */
+ unset($override_hosts_array);
+ unset($ind_override_host);
+ unset($override_hosts);
+
+ /* define subnets allowed to utilize proxy service */
+ if (isset($allowed_subnets) && ($allowed_subnets !== "")) {
+ if (!file_exists($acldir)) {
+ mwexec("/bin/mkdir -p " . $acldir);
+ mwexec("touch {$acldir}/src_subnets.acl");
+ }
+
+ $aclout = fopen($acldir . "/src_subnets.acl","w");
+
+ $allowed_subnets_array = split("; ",$allowed_subnets);
+ foreach ($allowed_subnets_array as $ind_allowed_subnets) {
+ fwrite($aclout, $ind_allowed_subnets . "\n");
+ }
+
+ fclose($aclout);
+ } else {
+
+ $aclout = fopen($acldir . "/src_subnets.acl","w");
+ fwrite($aclout, $lansa . "/" . $lansn . "\n");
+ fclose($aclout);
+ }
+
+ $config_array[] = 'acl pf_networks src "/usr/local/etc/squid/advanced/acls/src_subnets.acl"' . "\n";
+
+ unset($allowed_subnets_array);
+ unset($ind_allowed_subnets);
+ unset($allowed_subnets);
+
+ /* define ip addresses that have 'unrestricted' access */
+ if (isset($unrestricted_ip_addr) && ($unrestricted_ip_addr !== "")) {
+ if (!file_exists($acldir)) {
+ mwexec("/bin/mkdir -p " . $acldir);
+ }
+
+ $aclout = fopen($acldir . "/src_unrestricted_ip.acl","w");
+
+ $unrestricted_ip_array = split("; ",$unrestricted_ip_addr);
+ foreach ($unrestricted_ip_array as $ind_unrestricted_ip) {
+ fwrite($aclout, $ind_unrestricted_ip . "\n");
+ }
+
+ fclose($aclout);
+
+ $config_array[] = 'acl pf_unrestricted_ip src "/usr/local/etc/squid/advanced/acls/src_unrestricted_ip.acl"' . "\n";
+ }
+ unset($unrestricted_ip_array);
+ unset($unrestricted_ip_addr);
+ unset($ind_unrestricted_ip);
+
+ /* define mac addresses that have 'unrestricted' access */
+ if (isset($unrestricted_mac_addr) && ($unrestricted_mac_addr !== "")) {
+ if (!file_exists($acldir)) {
+ mwexec("/bin/mkdir -p " . $acldir);
+ }
+
+ $aclout = fopen($acldir . "/src_unrestricted_mac.acl","w");
+
+ $unrestricted_mac_array = split("; ",$unrestricted_mac_addr);
+ foreach ($unrestricted_mac_array as $ind_unrestricted_mac) {
+ fwrite($aclout, $ind_unrestricted_mac . "\n");
+ }
+
+ fclose($aclout);
+
+ $config_array[] = 'acl pf_unrestricted_mac src "/usr/local/etc/squid/advanced/acls/src_unrestricted_mac.acl"' . "\n";
+ }
+ unset($unrestricted_mac_array);
+ unset($unrestricted_mac_addr);
+ unset($ind_unrestricted_mac);
+
+ /* define ip addresses that are banned from using the proxy service */
+ if (isset($banned_ip_addr) && ($banned_ip_addr !== "")) {
+ if (!file_exists($acldir)) {
+ mwexec("/bin/mkdir -p " . $acldir);
+ }
+
+ $aclout = fopen($acldir . "/src_banned_ip.acl","w");
+
+ $banned_ip_array = split("; ",$banned_ip_addr);
+ foreach ($banned_ip_array as $ind_banned_ip) {
+ fwrite($aclout, $ind_banned_ip . "\n");
+ }
+
+ fclose($aclout);
+
+ $config_array[] = 'acl pf_banned_ip src "/usr/local/etc/squid/advanced/acls/src_banned_ip.acl"' . "\n";
+ }
+ unset($banned_ip_addr);
+ unset($banned_ip_addr);
+ unset($ind_banned_ip);
+
+ /* define mac addresses that are banned from using the proxy service */
+ if (isset($banned_mac_addr) && ($banned_mac_addr !== "")) {
+ if (!file_exists($acldir)) {
+ mwexec("/bin/mkdir -p " . $acldir);
+ }
+
+ $aclout = fopen($acldir . "/src_banned_mac.acl","w");
+
+ $banned_mac_array = split("; ",$banned_mac_addr);
+ foreach ($banned_mac_array as $ind_banned_mac) {
+ fwrite($aclout, $ind_banned_mac . "\n");
+ }
+
+ fclose($aclout);
+
+ $config_array[] = 'acl pf_banned_mac src "/usr/local/etc/squid/advanced/acls/src_banned_mac.acl"' . "\n";
+ }
+ unset($banned_mac_array);
+ unset($banned_mac_addr);
+ unset($ind_banned_mac);
+
+ $config_array[] = 'acl pf_ips dst ' . $lanip . "\n";
+ $config_array[] = 'acl CONNECT method CONNECT' . "\n\n";
+
+ if (isset($auth_method) && ($auth_method == "none")) {
+ $config_array[] = 'http_access allow localnet' . "\n";
+ }
+ $config_array[] = 'http_access allow localhost' . "\n";
+
+ if (isset($override_hosts) && ($override_hosts !== "")) {
+ $config_array[] = 'http_access allow override_hosts' . "\n";
+ }
+ $config_array[] = "\n";
+
+ switch ($config['system']['webgui']['protocol']) {
+ case "http":
+ $config_array[] = 'http_access allow pf_ips' . "\n";
+ $config_array[] = 'http_access allow pf_admin_port' . "\n";
+ $config_array[] = 'http_access deny !pf_networks' . "\n\n";
+ break;
+ case "https":
+ $config_array[] = 'http_access allow CONNECT pf_ips' . "\n";
+ $config_array[] = 'http_access allow CONNECT pf_admin_port' . "\n";
+ $config_array[] = 'http_access deny CONNECT !pf_networks' . "\n\n";
+ break;
+ }
+
+ $config_array[] = 'http_access deny !Safe_ports' . "\n";
+ $config_array[] = 'http_access deny CONNECT !SSL_ports' . "\n\n";
+
+ if (isset($auth_method) && ($auth_method != "none")) {
+ $config_array[] = 'http_access allow pf_networks for_inetusers within_timeframe' . "\n";
+ }
+
+ $config_array[] = 'http_access deny all' . "\n\n";
+
+ if (isset($dl_overall) && ($dl_overall !== "") and isset($dl_per_host) && ($dl_per_host == "")) {
+ $config_array[] = 'delay_pools 1' . "\n";
+ $config_array[] = 'delay_class 1 3' . "\n";
+
+ if ($dl_overall == "unlimited") {
+ $config_array[] = 'delay_parameters 1 -1/-1 -1/-1 ' . ($dl_overall * 125) . '/' . ($dl_overall * 250) . "\n";
+ } else {
+ $config_array[] = 'delay_parameters 1 ' . ($dl_overall * 125) . '/' . ($dl_overall * 250) . ' -1/-1 -1/-1' . "\n";
+ }
+
+ /* if no unrestricted ip addresses are defined; this line is ignored */
+ if (isset($unrestricted_ip_addr) && ($unrestricted_ip_addr == "")) $config_array[] = 'delay_access 1 deny pf_unrestricted_ip' . "\n";
+
+ /* this will define bandwidth delay restrictions for specified throttles */
+ if (isset($throttle_binary_files) && ($throttle_binary_files == "on")) {
+ $config_array[] = 'delay_access 1 allow all for_throttled_binary' . "\n";
+ }
+ if (isset($throttle_cd_images) && ($throttle_cd_images == "on")) {
+ $config_array[] = 'delay_access 1 allow all for_throttled_cd' . "\n";
+ }
+ if (isset($throttle_multimedia) && ($throttle_multimedia == "on")) {
+ $config_array[] = 'delay_access 1 allow all for_throttled_multimedia' . "\n";
+ } else {
+ $config_array[] = 'delay_access 1 allow all' . "\n";
+ }
+ $config_array[] = 'delay_initial_bucket_level 100%' . "\n\n";
+ }
+
+ if (isset($dl_per_host) && ($dl_per_host !== "") and isset($dl_overall) && ($dl_overall == "")) {
+ $config_array[] = 'delay_pools 1' . "\n";
+ $config_array[] = 'delay_class 1 3' . "\n";
+
+ if ($dl_per_host == "unlimited") {
+ $config_array[] = 'delay_parameters 1 ' . ($dl_per_host * 125) . '/' . ($dl_per_host * 250) . '-1/-1 -1/-1' . "\n";
+ } else {
+ $config_array[] = 'delay_parameters 1 -1/-1 -1/-1 ' . ($dl_per_host * 125) . '/' . ($dl_per_host * 250) . "\n";
+ }
+
+ /* if no unrestricted ip addresses are defined; this line is ignored */
+ if (isset($unrestricted_ip_addr) && ($unrestricted_ip_addr !== "")) $config_array[] = 'delay_access 1 deny pf_unrestricted_ip' . "\n";
+
+ /* this will define bandwidth delay restrictions for specified throttles */
+ if ($throttle_binary_files == "on") {
+ $config_array[] = 'delay_access 1 allow all for_throttled_binary' . "\n";
+ }
+ if ($throttle_cd_images == "on") {
+ $config_array[] = 'delay_access 1 allow all for_throttled_cd' . "\n";
+ }
+ if ($throttle_multimedia == "on") {
+ $config_array[] = 'delay_access 1 allow all for_throttled_multimedia' ."\n";
+ } else {
+ $config_array[] = 'delay_access 1 allow all' . "\n";
+ }
+ $config_array[] = 'delay_initial_bucket_level 100%' . "\n\n\n";
+ }
+
+ if (isset($dl_overall) && ($dl_overall !== "") and isset($dl_per_host) && ($dl_per_host !== "")) {
+ /* if no bandwidth restrictions are specified, then these parameters are not necessary */
+ if ($dl_overall !== "unlimited" and $dl_per_host !== "unlimited") {
+
+ if ((isset($dl_overall) && ($dl_overall == "unlimited")) and (isset($dl_per_host) && ($dl_per_host !== ""))) {
+ $config_array[] = 'delay_pools 1' . "\n";
+ $config_array[] = 'delay_class 1 3' . "\n";
+ $config_array[] = 'delay_parameters 1 -1/-1 -1/-1 ' . ($dl_per_host * 125) . '/' . ($dl_overall * 250) . "\n";
+ } elseif (isset($dl_overall) && ($dl_overall !== "") and isset($dl_per_host) && ($dl_per_host == "unlimited")) {
+ $config_array[] = 'delay_pools 1' . "\n";
+ $config_array[] = 'delay_class 1 3' . "\n";
+ $config_array[] = 'delay_parameters 1 ' . ($dl_overall * 125) . '/' . ($dl_overall * 250) . ' -1/-1 -1/-1' . "\n";
+ }
+ }
+
+ if ($dl_overall !== "unlimited" and $dl_per_host !== "unlimited") {
+
+ /* if no unrestricted ip addresses are defined; this line is ignored */
+ if (isset($unrestricted_ip_addr) && ($unrestricted_ip_addr !== "")) $config_array[] = 'delay_access 1 deny pf_unrestricted_ip' . "\n";
+
+ /* this will define bandwidth delay restrictions for specified throttles */
+ if ($throttle_binary_files == "on") {
+ $config_array[] = 'delay_access 1 allow all for_throttled_binary' . "\n";
+ }
+ if ($throttle_cd_images == "on") {
+ $config_array[] = 'delay_access 1 allow all for_throttled_cd' . "\n";
+ }
+ if ($throttle_multimedia == "on") {
+ $config_array[] = 'delay_access 1 allow all for_throttled_multimedia' . "\n";
+ } else {
+ $config_array[] = 'delay_access 1 allow all' . "\n";
+ }
+ $config_array[] = 'delay_initial_bucket_level 100%' . "\n\n";
+ }
+ }
+
+ $config_array[] = 'header_access X-Forwarded-For deny all' . "\n";
+ $config_array[] = 'header_access Via deny all' . "\n\n";
+
+ /* TODO: acl customization for snmp support */
+ /* fwrite($fout, "\n"); */
+
+ if (isset($urlfilter_enable) && ($urlfilter_enable == "on")) {
+ $config_array[] = 'redirect_program /usr/sbin/squidGuard' . "\n";
+ $config_array[] = 'redirect_children 5' . "\n\n";
+ }
+
+ if (isset($max_upload_size) && ($max_upload_size != "")) {
+ $config_array[] = 'request_body_max_size ' . $max_download_size . 'KB' . "\n";
+ }
+
+ if (isset($max_download_size) && ($max_download_size != "")) {
+ if (isset($unrestricted_ip_addr) && ($unrestricted_ip_addr !== "")) $config_array[] = 'reply_body_max_size 0 allow pf_unrestricted_ip' . "\n";
+ /* fwrite($fout, "#reply_body_max_size 0 allow for_extended_users\n"); */
+ $config_array[] = 'reply_body_max_size ' . $max_download_size * 1024 . ' allow all' . "\n\n";
+ }
+
+ /* set default value for maximum_object_size */
+ if (!isset($maximum_object_size) or ($maximum_object_size == "")) {
+ $maximum_object_size = "4096";
+ }
+
+ /* set default value for minimum_object_size */
+ if (!isset($minimum_object_size) or ($minimum_object_size == "")) {
+ $minimum_object_size = "0";
+ }
+ $config_array[] = 'maximum_object_size ' . $maximum_object_size . ' KB' . "\n";
+ $config_array[] = 'minimum_object_size ' . $minimum_object_size . ' KB' . "\n\n";
+
+ if (isset($proxy_forwarding) && ($proxy_forwarding == "on")) {
+ $config_array[] = 'cache_peer ' . $upstream_proxy . ' parent ' . $upstream_proxy_port . ' 3130 login=' . upstream_username . ':' . upstream_password . ' default no-query' . "\n";
+ $config_array[] = 'never_direct allow all' . "\n";
+ }
+ unset($proxy_forwarding);
+
+
+ /* define default ruleset for transparent proxy operation */
+ if (isset($transparent_proxy) && ($transparent_proxy == "on")) {
+ $config_array[] = 'httpd_accel_host virtual' . "\n";
+ $config_array[] = 'httpd_accel_port 80' . "\n";
+ $config_array[] = 'httpd_accel_with_proxy on' . "\n";
+ $config_array[] = 'httpd_accel_uses_host_header on' . "\n\n";
+ }
+ unset($transparent_proxy);
+
+
+ /* define visible hostname */
+ if (isset($visible_hostname) && ($visible_hostname !== "")) {
+ $config_array[] = 'visible_hostname ' . $visible_hostname . "\n";
+ }
+ unset($visible_hostname);
+
+ /* define cache administrators email address within error messages */
+ if (isset($cache_admin_email) && ($cache_admin_email !== "")) {
+ $config_array[] = 'cache_mgr ' . $cache_admin_email . "\n\n";
+ }
+ unset($cache_admin_email);
+
+ /* write configuration file */
+ foreach ($config_array as $config_item)
+ {
+ fwrite($fout, trim($config_item));
+
+ if (stristr($config_item, "\n"))
+ {
+ for ($i = 1; $i < count(explode("\n", $config_item)); $i++)
+ {
+ fwrite($fout, "\n");
+ }
+ }
+
+ }
+ fclose($fout);
+
+ conf_mount_ro();
+ config_unlock();
+
+ touch($squidconfig);
+} /* end function write_squid_config */
+
+function custom_php_install_command() {
+ /* write initial static config for transparent proxy */
+ write_static_squid_config();
+
+ touch("/tmp/custom_php_install_command");
+
+ /* make sure this all exists, see:
+ * http://forum.pfsense.org/index.php?topic=23.msg2391#msg2391
+ */
+ update_output_window("Setting up Squid environment...");
+ mwexec("mkdir -p /var/squid");
+ mwexec("chown squid:squid /var/squid");
+ mwexec("mkdir -p /var/squid/logs");
+ mwexec("chown squid:squid /var/squid/logs");
+ mwexec("mkdir -p /var/squid/cache");
+ mwexec("chown squid:squid /var/squid/cache");
+ mwexec("mkdir -p /usr/local/etc/squid/advanced");
+ mwexec("chown squid:squid /usr/local/etc/squid/advanced");
+ mwexec("mkdir -p /usr/local/etc/squid/advanced/acls");
+ mwexec("chown squid:squid /usr/local/etc/squid/advanced/acls");
+ mwexec("touch /usr/local/etc/squid/advanced/acls/src_subnets.acl");
+ mwexec("chown squid:squid /usr/local/etc/squid/advanced/acls/src_subnets.acl");
+ mwexec("touch /usr/local/etc/squid/advanced/acls/src_unrestricted_ip.acl");
+ mwexec("chown squid:squid /usr/local/etc/squid/advanced/acls/src_unrestricted_ip.acl");
+ mwexec("cp /usr/local/etc/squid/mime.conf.default /usr/local/etc/squid/mime.conf");
+
+
+ /* set a few extra items noted by regan */
+ update_output_window("Creating logs and setting user information...");
+ $fdsquid = fopen("/usr/local/etc/rc.d/aSquid.sh", "w");
+ fwrite($fdsquid, "#/bin/sh\n");
+ fwrite($fdsquid, "# \n");
+ fwrite($fdsquid, "# This file was created by the pfSense package system\n");
+ fwrite($fdsquid, "# Sets up squid option on each bootup that are not persistent\n");
+ fwrite($fdsquid, "# \n\n");
+ fwrite($fdsquid, "chown squid:wheel /dev/pf\n");
+ fwrite($fdsquid, "chmod ug+rw /dev/pf\n");
+ fwrite($fdsquid, "touch /var/log/useragent.log\n");
+ fwrite($fdsquid, "touch /var/log/access.log\n");
+ fwrite($fdsquid, "touch /var/log/cache.log\n");
+ fwrite($fdsquid, "chown squid:wheel /var/log/cache.log\n");
+ fwrite($fdsquid, "chown squid:wheel /var/log/access.log\n");
+ fwrite($fdsquid, "chown squid:wheel /var/log/useragent.log\n");
+ fwrite($fdsquid, "\n");
+ fclose($fdsquid);
+ mwexec("chmod a+rx /usr/local/etc/rc.d/aSquid.sh");
+ mwexec("/usr/local/etc/rc.d/aSquid.sh");
+
+ update_output_window("Creating Proxy Server initialization scripts...");
+ $start = "touch /tmp/ro_root_mount; /usr/local/sbin/squid -D; touch /tmp/filter_dirty";
+ $stop = "/usr/local/sbin/squid -k shutdown";
+ write_rcfile(array(
+ "file" => "squid.sh",
+ "start" => $start,
+ "stop" => $stop
+ )
+ );
+
+ mwexec("chmod 755 /usr/local/etc/rc.d/squid.sh");
+
+ /* create log directory hierarchies if they don't exist */
+ update_output_window("Creating required directory hierarchies...");
+
+ if (!file_exists("/var/squid/logs")) {
+ mwexec("mkdir -p /var/squid/logs");
+ }
+ mwexec("/usr/sbin/chown squid:squid /var/squid/logs");
+
+
+ if (!file_exists("/var/squid/cache")) {
+ mwexec("mkdir -p /var/squid/cache");
+ }
+ mwexec("/usr/sbin/chown squid:squid /var/squid/cache");
+
+ if (!file_exists("/usr/local/etc/squid/advanced/acls")) {
+ mwexec("mkdir -p /usr/local/etc/squid/advanced/acls");
+ }
+ mwexec("/usr/sbin/chown squid:squid /usr/local/etc/squid/advanced/acls");
+
+ if (!file_exists("/usr/local/etc/squid/advanced/ncsa")) {
+ mwexec("mkdir -p /usr/local/etc/squid/advanced/ncsa");
+ }
+ mwexec("/usr/sbin/chown squid:squid /usr/local/etc/squid/advanced/ncsa");
+
+ if (!file_exists("/usr/local/etc/squid/advanced/ntlm")) {
+ mwexec("mkdir -p /usr/local/etc/squid/advanced/ntlm");
+ }
+ mwexec("/usr/sbin/chown squid:squid /usr/local/etc/squid/advanced/ntlm");
+
+ if (!file_exists("/usr/local/etc/squid/advanced/radius")) {
+ mwexec("mkdir -p /usr/local/etc/squid/advanced/radius");
+ }
+ mwexec("/usr/sbin/chown squid:squid /usr/local/etc/squid/advanced/radius");
+
+ $devfs_file = fopen("/etc/devfs.conf", "a");
+ fwrite($devfs_file, "\n# Allow squid to query the packet filter bymaking is group-accessable. ");
+ fwrite($devfs_file, "own pf root:squid");
+ fwrite($devfs_file, "perm pf 0640");
+ fclose($devfs_file);
+
+ update_output_window("Initializing Cache... This may take a moment...");
+ mwexec("/usr/local/sbin/squid -z");
+
+ update_output_window("Starting Proxy Server...");
+ start_service("squid");
+}
+
+function custom_php_deinstall_command() {
+ update_output_window("Stopping proxy service...");
+ stop_service("squid");
+ sleep(1);
+ /* brute force any remaining squid processes out */
+ mwexec("/usr/bin/killall squid");
+ mwexec("/usr/bin/killall pinger");
+ update_output_window("Recursively removing directories hierarchies. If existant, log files in /var/squid/logs will remain...");
+ mwexec("rm -rf /var/squid/cache");
+ update_output_window("Removing configuration files...");
+ unlink_if_exists("/usr/local/etc/rc.d/squid.sh");
+ unlink_if_exists("/usr/local/libexec/squid");
+ unlink_if_exists("/usr/local/etc/rc.d/aSquid.sh");
+ mwexec("rm -f /usr/local/etc/rc.d/squid*");
+ mwexec("rm -f /usr/local/www/cachemgr.cgi");
+ filter_configure();
+}
+
+function write_static_squid_config() {
+ touch("/tmp/write_static_squid_config");
+ global $config;
+ $lancfg = $config['interfaces']['lan'];
+ $lanif = $lancfg['if'];
+ $lanip = $lancfg['ipaddr'];
+ $lansa = gen_subnet($lancfg['ipaddr'], $lancfg['subnet']);
+ $lansn = $lancfg['subnet'];
+
+ $fout = fopen("/usr/local/etc/squid/squid.conf","w");
+ fwrite($fout, "#\n");
+ fwrite($fout, "# This file was automatically generated by the pfSense package manager.\n");
+ fwrite($fout, "# This default policy enables transparent proxy with no local disk logging.\n");
+ fwrite($fout, "#\n");
+
+ /* set # of dns children */
+ fwrite($fout, "dns_children 15\n");
+
+ fwrite($fout, "shutdown_lifetime 5 seconds\n");
+ fwrite($fout, "icp_port 0\n");
+ fwrite($fout, "\n");
+
+ fwrite($fout, "acl QUERY urlpath_regex cgi-bin \?\n");
+ fwrite($fout, "no_cache deny QUERY\n");
+ fwrite($fout, "\n");
+
+ fwrite($fout, "pid_filename /var/run/squid.pid\n");
+ fwrite($fout, "\n");
+
+ fwrite($fout, "cache_mem 24 MB\n");
+ fwrite($fout, "cache_dir diskd /var/squid/cache 500 16 256\n");
+ fwrite($fout, "\n");
+
+ fwrite($fout, "error_directory /usr/local/etc/squid/errors/English\n");
+ fwrite($fout, "\n");
+
+ fwrite($fout, "memory_replacement_policy heap GDSF\n");
+ fwrite($fout, "cache_replacement_policy heap GDSF\n");
+ fwrite($fout, "\n");
+
+ fwrite($fout, "cache_access_log none\n");
+ fwrite($fout, "cache_log none\n");
+ fwrite($fout, "cache_store_log none\n");
+ fwrite($fout, "\n");
+
+ fwrite($fout, "log_mime_hdrs off\n");
+ fwrite($fout, "emulate_httpd_log on\n");
+ fwrite($fout, "forwarded_for off\n");
+ fwrite($fout, "\n");
+
+ fwrite($fout, "acl within_timeframe time MTWHFAS 00:00-24:00\n");
+ fwrite($fout, "\n");
+
+ fwrite($fout, "acl all src 0.0.0.0/0.0.0.0\n");
+ fwrite($fout, "acl localnet src " . $lansa . "/" . $lansn . "\n");
+ fwrite($fout, "acl localhost src 127.0.0.1/255.255.255.255\n");
+ fwrite($fout, "acl SSL_ports port 443 563 873 # https, snews, rsync\n");
+ fwrite($fout, "acl Safe_ports port 80 # http\n");
+ fwrite($fout, "acl Safe_ports port 21 # ftp\n");
+ fwrite($fout, "acl Safe_ports port 443 563 873 # https, snews, rsync\n");
+ fwrite($fout, "acl Safe_ports port 70 # gopher\n");
+ fwrite($fout, "acl Safe_ports port 210 # wais\n");
+ fwrite($fout, "acl Safe_ports port 1025-65535 # unregistered ports\n");
+ fwrite($fout, "acl Safe_ports port 280 # http-mgmt\n");
+ fwrite($fout, "acl Safe_ports port 488 # gss-http\n");
+ fwrite($fout, "acl Safe_ports port 591 # filemaker\n");
+ fwrite($fout, "acl Safe_ports port 777 # multiling http\n");
+ fwrite($fout, "acl Safe_ports port 800 # Squids port (for icons)\n");
+ fwrite($fout, "\n");
+
+ fwrite($fout, "acl CONNECT method CONNECT\n");
+ fwrite($fout, "\n");
+
+ fwrite($fout, "#access to squid; local machine; no restrictions\n");
+ fwrite($fout, "http_access allow localnet\n");
+ fwrite($fout, "http_access allow localhost\n");
+ fwrite($fout, "\n");
+
+ fwrite($fout, "#Deny non web services\n");
+ fwrite($fout, "http_access deny !Safe_ports\n");
+ fwrite($fout, "http_access deny CONNECT !SSL_ports\n");
+ fwrite($fout, "\n");
+
+ fwrite($fout, "#Set custom configured ACLs\n");
+ fwrite($fout, "http_access deny all\n");
+ fwrite($fout, "visible_hostname pfSense\n");
+ fwrite($fout, "\n");
+
+ fwrite($fout, "cache_effective_user squid\n");
+ fwrite($fout, "cache_effective_group squid\n");
+ fwrite($fout, "\n");
+
+ fwrite($fout, "maximum_object_size 4096 KB\n");
+ fwrite($fout, "minimum_object_size 0 KB\n");
+ fwrite($fout, "\n");
+
+ fwrite($fout, "request_body_max_size 0 KB\n");
+ fwrite($fout, "reply_body_max_size 0 allow all\n");
+ fwrite($fout, "\n");
+
+ fwrite($fout, "httpd_accel_host virtual\n");
+ fwrite($fout, "httpd_accel_port 80\n");
+ fwrite($fout, "httpd_accel_with_proxy on\n");
+ fwrite($fout, "httpd_accel_uses_host_header on\n");
+
+ fclose($fout);
+}
+
+function mod_htpasswd() {
+ global $config;
+ conf_mount_rw();
+ config_lock();
+
+ if (!file_exists("/usr/local/etc/squid/advanced/ncsa")) mwexec("mkdir -p /usr/local/etc/squid/advanced/ncsa");
+
+ $passfile = fopen("/usr/local/etc/squid/advanced/ncsa/passwd", "w+");
+
+ if (isset($config['installedpackages']['squidextlocalauth']['config']) && $config['installedpackages']['squidextlocalauth']['config'] != "") {
+ foreach($config['installedpackages']['squidextlocalauth']['config'] as $rowhelper) {
+ $encpass = generate_htpasswd($rowhelper['username'], $rowhelper['password']);
+ fwrite($passfile, $rowhelper['username'] . ":" . $encpass . "\n");
+ }
+ }
+
+ fclose($passfile);
+
+ conf_mount_ro();
+ config_unlock();
+}
+
+function generate_htpasswd($username, $password) {
+ $all = explode( " ",
+ "a b c d e f g h i j k l m n o p q r s t u v w x y z "
+ . "A B C D E F G H I J K L M N O P Q R S T U V W X Y Z "
+ . "0 1 2 3 4 5 6 7 8 9");
+
+ for ($i = 0; $i < 9; $i++) {
+ srand((double)microtime()*1000000);
+ $randy = rand(0,61);
+ $seed .= $all[$randy];
+ }
+
+ $crypt = crypt($password, "$1$$seed");
+ return $crypt;
+}
+
+?>
diff --git a/config/squid3/squid_ng.xml b/config/squid3/squid_ng.xml
new file mode 100644
index 00000000..5949606e
--- /dev/null
+++ b/config/squid3/squid_ng.xml
@@ -0,0 +1,267 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>squid</name>
+ <version>2.5.12_4</version>
+ <title>Services: Proxy Server</title>
+ <category>Security</category>
+ <aftersaveredirect>/pkg_edit.php?xml=squid_ng.xml&amp;id=0</aftersaveredirect>
+ <include_file>/usr/local/pkg/squid_ng.inc</include_file>
+ <menu>
+ <name>Squid</name>
+ <tooltiptext>Modify settings for Proxy Server</tooltiptext>
+ <section>Services</section>
+ <url>/pkg_edit.php?xml=squid_ng.xml&amp;id=0</url>
+ </menu>
+ <menu>
+ <name>Squid stats</name>
+ <tooltiptext>Show Squid statistics</tooltiptext>
+ <section>Services</section>
+ <url>/cachemgr.cgi</url>
+ </menu>
+ <service>
+ <name>squid</name>
+ <rcfile>squid.sh</rcfile>
+ </service>
+ <tabs>
+ <tab>
+ <text>General Settings</text>
+ <url>/pkg_edit.php?xml=squid.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Upstream Proxy</text>
+ <url>/pkg_edit.php?xml=squid_upstream.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Cache Mgmt</text>
+ <url>/pkg_edit.php?xml=squid_cache.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Network Access Control</text>
+ <url>/pkg_edit.php?xml=squid_nac.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Traffic Mgmt</text>
+ <url>/pkg_edit.php?xml=squid_traffic.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Auth Settings</text>
+ <url>/pkg_edit.php?xml=squid_auth.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Extended Auth Settings</text>
+ <url>/pkg_edit.php?xml=squid_extauth.xml&amp;id=0</url>
+ </tab>
+ </tabs>
+ <configpath>installedpackages->package->squidng->configuration->settings</configpath>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/squid/squid_cache.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/squid/squid_nac.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/squid/squid_ng.inc</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/squid/squid_traffic.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/squid/squid_upstream.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/squid/squid_auth.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/squid/squid_auth.inc</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/squid/squid_extauth.xml</item>
+ </additional_files_needed>
+ <fields>
+ <field>
+ <fielddescr>Proxy Listening Interface</fielddescr>
+ <fieldname>active_interface</fieldname>
+ <description>This defines the active listening interface to which the proxy server will listen for its requests.</description>
+ <type>interfaces_selection</type>
+ </field>
+ <field>
+ <fielddescr>Transparent Proxy</fielddescr>
+ <fieldname>transparent_proxy</fieldname>
+ <description>If transparent mode is enabled; all requests for destination port 80 will be forwarded to the proxy server without any additional configuration necessary.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>URL Filtering Enabled</fielddescr>
+ <fieldname>urlfilter_enable</fieldname>
+ <description>This enables the advanced functionality in conjunction with squidGuard to provide an array of URL filtering options. This squidGuard functionality can be additionally configured from Services -> Advanced Proxy Filtering</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Disable Access Log</fielddescr>
+ <fieldname>accesslog_disabled</fieldname>
+ <description>Disable the access log entirely. By default, Squid keeps a log of all requests it processes in /var/log/access.log. This can grow to be fairly large. If you do not require this logging, check this box to disable.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Log Query Terms</fielddescr>
+ <fieldname>log_query_terms</fieldname>
+ <description>This will log the complete URL rather than the part of the URL containing dynamic queries.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Log User Agents</fielddescr>
+ <fieldname>log_user_agents</fieldname>
+ <description>This will enable the useragent string to be written to a separate log. The results are not shown in the GUI and should only be used for debugging purposes.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Proxy Port</fielddescr>
+ <fieldname>proxy_port</fieldname>
+ <description>This is the port the Proxy Server will listen for client requests on. The default is 3128.</description>
+ <type>input</type>
+ <size>4</size>
+ <combinefieldsend>true</combinefieldsend>
+ </field>
+ <field>
+ <fielddescr>ICP Port</fielddescr>
+ <fieldname>icp_port</fieldname>
+ <description>This is the port the Proxy Server will send and receive ICP queries to and from neighbor caches. The default value is 0, which means this function is disabled.</description>
+ <type>input</type>
+ <size>4</size>
+ </field>
+ <field>
+ <fielddescr>Visible Hostname</fielddescr>
+ <fieldname>visible_hostname</fieldname>
+ <description>This URL is displayed on the Proxy Server error messages.</description>
+ <type>input</type>
+ <size>35</size>
+ </field>
+ <field>
+ <fielddescr>Cache Administrator E-Mail</fielddescr>
+ <fieldname>cache_admin_email</fieldname>
+ <description>This E-Mail address is displayed on the Proxy Server error messages.</description>
+ <type>input</type>
+ <size>35</size>
+ </field>
+ <field>
+ <fielddescr>Error Messages Language</fielddescr>
+ <fieldname>error_language</fieldname>
+ <description>Select the language in which the Proxy Server shall display error messages to users.</description>
+ <type>select</type>
+ <options>
+ <option><name>Bulgarian</name><value>Bulgarian</value></option>
+ <option><name>Catalan</name><value>Catalan</value></option>
+ <option><name>Czech</name><value>Czech</value></option>
+ <option><name>Danish</name><value>Danish</value></option>
+ <option><name>Dutch</name><value>Dutch</value></option>
+ <option><name>English</name><value>English</value></option>
+ <option><name>Estonian</name><value>Estonian</value></option>
+ <option><name>Finnish</name><value>Finnish</value></option>
+ <option><name>French</name><value>French</value></option>
+ <option><name>German</name><value>German</value></option>
+ <option><name>Hebrew</name><value>Hebrew</value></option>
+ <option><name>Hungarian</name><value>Hungarian</value></option>
+ <option><name>Italian</name><value>Italian</value></option>
+ <option><name>Japanese</name><value>Japanese</value></option>
+ <option><name>Korean</name><value>Korean</value></option>
+ <option><name>Lithuanian</name><value>Lithuanian</value></option>
+ <option><name>Polish</name><value>Polish</value></option>
+ <option><name>Portuguese</name><value>Portuguese</value></option>
+ <option><name>Romanian</name><value>Romanian</value></option>
+ <option><name>Russian-1251</name><value>Russian-1251</value></option>
+ <option><name>Russian-koi8-r</name><value>Russian-koi8-r</value></option>
+ <option><name>Serbian</name><value>Serbian</value></option>
+ <option><name>Simplify Chinese</name><value>Simplify Chinese</value></option>
+ <option><name>Slovak</name><value>Slovak</value></option>
+ <option><name>Spanish</name><value>Spanish</value></option>
+ <option><name>Swedish</name><value>Swedish</value></option>
+ <option><name>Traditional Chinese</name><value>Traditional Chinese</value></option>
+ <option><name>Turkish</name><value>Turkish</value></option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Enable cachemgr</fielddescr>
+ <fieldname>cachemgr_enabled</fieldname>
+ <description>Enable Squid's cachemgr.cgi to provide stats. Once enabled you can access this from the pfSense menus. &lt;b&gt;Note:&lt;/b&gt; This page is not secured by pfSense, any user with access to the pfSense admin port can view the stats. The page prompts for a password but it only required for shutting down Squid.</description>
+ <type>checkbox</type>
+ </field>
+
+ </fields>
+ <custom_add_php_command_late>
+ global_write_squid_config();
+ mwexec("/usr/local/sbin/squid -k reconfigure");
+ start_service("squid");
+ </custom_add_php_command_late>
+ <custom_php_install_command>
+ custom_php_install_command();
+ write_static_squid_config();
+ mwexec("/usr/local/sbin/squid -k reconfigure");
+ start_service("squid");
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ custom_php_deinstall_command();
+ stop_service("squid");
+ </custom_php_deinstall_command>
+</packagegui>
diff --git a/config/squid3/squid_traffic.xml b/config/squid3/squid_traffic.xml
new file mode 100644
index 00000000..1330cac9
--- /dev/null
+++ b/config/squid3/squid_traffic.xml
@@ -0,0 +1,177 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>squidtraffic</name>
+ <version>none</version>
+ <title>Proxy server: Traffic management</title>
+ <include_file>squid.inc</include_file>
+ <tabs>
+ <tab>
+ <text>General settings</text>
+ <url>/pkg_edit.php?xml=squid.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Upstream proxy</text>
+ <url>/pkg_edit.php?xml=squid_upstream.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Cache management</text>
+ <url>/pkg_edit.php?xml=squid_cache.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Access control</text>
+ <url>/pkg_edit.php?xml=squid_nac.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Traffic management</text>
+ <url>/pkg_edit.php?xml=squid_traffic.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Auth settings</text>
+ <url>/pkg_edit.php?xml=squid_auth.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Local users</text>
+ <url>/pkg.php?xml=squid_users.xml</url>
+ </tab>
+ </tabs>
+ <fields>
+ <field>
+ <fielddescr>Maximum download size</fielddescr>
+ <fieldname>max_download_size</fieldname>
+ <description>Limit the maximum total download size to the size specified here (in kilobytes). Set to 0 to disable.</description>
+ <type>input</type>
+ <required/>
+ <default_value>0</default_value>
+ </field>
+ <field>
+ <fielddescr>Maximum upload size</fielddescr>
+ <fieldname>max_upload_size</fieldname>
+ <description>Limit the maximum total upload size to the size specified here (in kilobytes). Set to 0 to disable.</description>
+ <type>input</type>
+ <required/>
+ <default_value>0</default_value>
+ </field>
+ <field>
+ <fielddescr>Overall bandwidth throttling</fielddescr>
+ <fieldname>overall_throttling</fieldname>
+ <description>This value specifies (in kilobytes per second) the bandwidth throttle for downloads. Users will gradually have their download speed increased according to this value. Set to 0 to disable bandwidth throttling.</description>
+ <type>input</type>
+ <required/>
+ <default_value>0</default_value>
+ </field>
+ <field>
+ <fielddescr>Per-host throttling</fielddescr>
+ <fieldname>perhost_throttling</fieldname>
+ <description>This value specifies the download throttling per host. Set to 0 to disable this.</description>
+ <type>input</type>
+ <required/>
+ <default_value>0</default_value>
+ </field>
+ <field>
+ <fielddescr>Throttle only specific extensions</fielddescr>
+ <fieldname>throttle_specific</fieldname>
+ <description>Leave this checked to be able to choose the extensions that throttling will be applied to. Otherwise, all files will be throttled.</description>
+ <type>checkbox</type>
+ <enablefields>throttle_binaries,throttle_cdimages,throttle_multimedia,throttle_others</enablefields>
+ <default_value>on</default_value>
+ </field>
+ <field>
+ <fielddescr>Throttle binary files</fielddescr>
+ <fieldname>throttle_binaries</fieldname>
+ <description>Check this to apply bandwidth throttle to binary files. This includes compressed archives and executables.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Throttle CD images</fielddescr>
+ <fieldname>throttle_cdimages</fieldname>
+ <description>Check this to apply bandwidth throttle to CD image files.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Throttle multimedia files</fielddescr>
+ <fieldname>throttle_multimedia</fieldname>
+ <description>Check this to apply bandwidth throttle to multimedia files, such as movies or songs.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Throttle other extensions</fielddescr>
+ <fieldname>throttle_others</fieldname>
+ <description>Comma-separated list of extensions to apply bandwidth throttle to.</description>
+ <type>input</type>
+ <size>60</size>
+ </field>
+ <field>
+ <fielddescr>Finish transfer if less than x KB remaining</fielddescr>
+ <fieldname>quick_abort_min</fieldname>
+ <description>If the transfer has less than x KB remaining, it will finish the retrieval. Set to 0 to abort the transfer immediately.</description>
+ <type>input</type>
+ <default_value>0</default_value>
+ </field>
+ <field>
+ <fielddescr>Abort transfer if more than x KB remaining</fielddescr>
+ <fieldname>quick_abort_max</fieldname>
+ <description>If the transfer has more than x KB remaining, it will abort the retrieval. Set to 0 to abort the transfer immediately.</description>
+ <type>input</type>
+ <default_value>0</default_value>
+ </field>
+ <field>
+ <fielddescr>Finish transfer if more than x % finished</fielddescr>
+ <fieldname>quick_abort_pct</fieldname>
+ <description>If more than x % of the transfer has completed, it will finish the retrieval.</description>
+ <type>input</type>
+ <default_value>0</default_value>
+ </field>
+ </fields>
+ <custom_php_validation_command>
+ squid_validate_traffic($_POST, &amp;$input_errors);
+ </custom_php_validation_command>
+ <custom_php_resync_config_command>
+ squid_resync();
+ </custom_php_resync_config_command>
+</packagegui>
diff --git a/config/squid3/squid_upstream.xml b/config/squid3/squid_upstream.xml
new file mode 100644
index 00000000..1102c672
--- /dev/null
+++ b/config/squid3/squid_upstream.xml
@@ -0,0 +1,133 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>squidupstream</name>
+ <version>none</version>
+ <title>Proxy server: Upstream proxy settings</title>
+ <include_file>squid.inc</include_file>
+ <tabs>
+ <tab>
+ <text>General settings</text>
+ <url>/pkg_edit.php?xml=squid.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Upstream proxy</text>
+ <url>/pkg_edit.php?xml=squid_upstream.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Cache management</text>
+ <url>/pkg_edit.php?xml=squid_cache.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Access control</text>
+ <url>/pkg_edit.php?xml=squid_nac.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Traffic management</text>
+ <url>/pkg_edit.php?xml=squid_traffic.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Auth settings</text>
+ <url>/pkg_edit.php?xml=squid_auth.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Local users</text>
+ <url>/pkg.php?xml=squid_users.in</url>
+ </tab>
+ </tabs>
+ <fields>
+ <field>
+ <fielddescr>Enable forwarding</fielddescr>
+ <fieldname>proxy_forwarding</fieldname>
+ <description>This option enables the proxy server to forward requests to an upstream server.</description>
+ <type>checkbox</type>
+ <enablefields>proxy_addr,proxy_port,icp_port,username,password</enablefields>
+ <required/>
+ </field>
+ <field>
+ <fielddescr>Hostname</fielddescr>
+ <fieldname>proxy_addr</fieldname>
+ <description>Enter here the IP address or host name of the upstream proxy.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>TCP port</fielddescr>
+ <fieldname>proxy_port</fieldname>
+ <description>Enter the port to use to connect to the upstream proxy.</description>
+ <type>input</type>
+ <size>5</size>
+ <default_value>3128</default_value>
+ </field>
+ <field>
+ <fielddescr>ICP port</fielddescr>
+ <fieldname>icp_port</fieldname>
+ <description>Enter the port to connect to the upstream proxy for the ICP protocol. Use port number 7 to disable ICP communication between the proxies.</description>
+ <type>input</type>
+ <size>5</size>
+ <default_value>7</default_value>
+ </field>
+ <field>
+ <fielddescr>Username</fielddescr>
+ <fieldname>username</fieldname>
+ <description>If the upstream proxy requires a username, specify it here.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Password</fielddescr>
+ <fieldname>password</fieldname>
+ <description>If the upstream proxy requires a password, specify it here.</description>
+ <type>password</type>
+ </field>
+ </fields>
+ <custom_php_validation_command>
+ squid_validate_upstream($_POST, &amp;$input_errors);
+ </custom_php_validation_command>
+ <custom_php_resync_config_command>
+ squid_resync();
+ </custom_php_resync_config_command>
+</packagegui>
diff --git a/config/squid3/squid_users.xml b/config/squid3/squid_users.xml
new file mode 100644
index 00000000..34260817
--- /dev/null
+++ b/config/squid3/squid_users.xml
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>squidusers</name>
+ <version>none</version>
+ <title>Proxy server: Local users</title>
+ <include_file>squid.inc</include_file>
+ <delete_string>A proxy server user has been deleted.</delete_string>
+ <addedit_string>A proxy server user has been created/modified.</addedit_string>
+ <tabs>
+ <tab>
+ <text>General settings</text>
+ <url>/pkg_edit.php?xml=squid.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Upstream proxy</text>
+ <url>/pkg_edit.php?xml=squid_upstream.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Cache management</text>
+ <url>/pkg_edit.php?xml=squid_cache.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Access control</text>
+ <url>/pkg_edit.php?xml=squid_nac.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Traffic management</text>
+ <url>/pkg_edit.php?xml=squid_traffic.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Auth settings</text>
+ <url>/pkg_edit.php?xml=squid_auth.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Local users</text>
+ <url>/pkg.php?xml=squid_users.xml</url>
+ <active/>
+ </tab>
+ </tabs>
+ <adddeleteeditpagefields>
+ <columnitem>
+ <fielddescr>Username</fielddescr>
+ <fieldname>username</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Description</fielddescr>
+ <fieldname>description</fieldname>
+ </columnitem>
+ </adddeleteeditpagefields>
+ <fields>
+ <field>
+ <fielddescr>Username</fielddescr>
+ <fieldname>username</fieldname>
+ <description>Enter the username here.</description>
+ <type>input</type>
+ <required/>
+ </field>
+ <field>
+ <fielddescr>Password</fielddescr>
+ <fieldname>password</fieldname>
+ <description>Enter the password here.</description>
+ <type>password</type>
+ <required/>
+ </field>
+ <field>
+ <fielddescr>Description</fielddescr>
+ <fieldname>description</fieldname>
+ <description>You may enter a description here for your reference (not parsed).</description>
+ <type>input</type>
+ </field>
+ </fields>
+ <custom_php_resync_config_command>
+ squid_resync_users();
+ </custom_php_resync_config_command>
+</packagegui>
diff --git a/config/squidGuard.xml b/config/squidGuard.xml
new file mode 100644
index 00000000..dd837e50
--- /dev/null
+++ b/config/squidGuard.xml
@@ -0,0 +1,125 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>squidGuard</name>
+ <version>none</version>
+ <title>none</title>
+ <process_kill_command>squid</process_kill_command>
+ <custom_php_install_command>
+ $fout = fopen("/usr/local/etc/squid/squidGuard.conf","w");
+ fwrite($fout, "# This configuration was generated by the pfSense package manager.\n");
+ fwrite($fout, "logdir /usr/local/squid/logs\n");
+ fwrite($fout, "dbhome /var/db/squidGuard\n");
+ fwrite($fout, "dest ads {\n");
+ fwrite($fout, "\t domainlist\t ads/domains\n");
+ fwrite($fout, "\t urllist\t ads/urls\n");
+ fwrite($fout, "}\n");
+ fwrite($fout, "dest aggressive {\n");
+ fwrite($fout, "\t domainlist\t aggressive/domains\n");
+ fwrite($fout, "\t urllist\t aggressive/urls\n");
+ fwrite($fout, "}\n");
+ fwrite($fout, "dest audio-video {\n");
+ fwrite($fout, "\t domainlist\t audio-video/domains\n");
+ fwrite($fout, "\t urllist\t audio-video/urls\n");
+ fwrite($fout, "}\n");
+ fwrite($fout, "dest drugs {\n");
+ fwrite($fout, "\t domainlist\t drugs/domains\n");
+ fwrite($fout, "\t urllist\t drugs/urls\n");
+ fwrite($fout, "}\n");
+ fwrite($fout, "dest gambling {\n");
+ fwrite($fout, "\t domainlist\t gambling/domains\n");
+ fwrite($fout, "\t urllist\t gambling/urls\n");
+ fwrite($fout, "}\n");
+ fwrite($fout, "dest hacking {\n");
+ fwrite($fout, "\t domainlist\t hacking/domains\n");
+ fwrite($fout, "\t urllist\t hacking/urls\n");
+ fwrite($fout, "}\n");
+ fwrite($fout, "dest mail {\n");
+ fwrite($fout, "\t domainlist\t mail/domains\n");
+ fwrite($fout, "}\n");
+ fwrite($fout, "dest porn {\n");
+ fwrite($fout, "\t domainlist\t porn/domains\n");
+ fwrite($fout, "\t urllist\t porn/urls\n");
+ fwrite($fout, "}\n");
+ fwrite($fout, "dest proxy {\n");
+ fwrite($fout, "\t domainlist\t proxy/domains\n");
+ fwrite($fout, "\t urllist\t proxy/urls\n");
+ fwrite($fout, "}\n");
+ fwrite($fout, "dest violence {\n");
+ fwrite($fout, "\t domainlist\t violence/domains\n");
+ fwrite($fout, "\t urllist\t violence/urls\n");
+ fwrite($fout, "}\n");
+ fwrite($fout, "dest warez {\n");
+ fwrite($fout, "\t domainlist\t warez/domains\n");
+ fwrite($fout, "\t urllist\t warez/urls\n");
+ fwrite($fout, "}\n");
+ fwrite($fout, "acl {\n");
+ fwrite($fout, "\t default {\n");
+ fwrite($fout, "\t pass !ads !aggressive !audio-video !drugs !gambling !hacking !mail !porn !proxy !violence !warez all\n");
+ fwrite($fout, "\t redirect http://bkw.lindesign.se/tmp/denied.html");
+ fwrite($fout, "\t }\n");
+ fwrite($fout, "}\n");
+ fclose($fout);
+ add_text_to_file("/usr/local/etc/squid/squid.conf", "redirect_program /usr/local/bin/squidGuard -c /usr/local/etc/squid/squidGuard.conf");
+ /* $fout = fopen("/usr/local/etc/squid/squid.conf","a");
+ fwrite($fout, "redirect_program /usr/local/bin/squidGuard -c /usr/local/etc/squid/squidGuard.conf\n");
+ fclose($fout); */
+ mwexec("/usr/bin/touch /usr/local/squid/logs/squidGuard.log");
+ mwexec("/usr/sbin/chown squid /usr/local/squid/logs/squidGuard.log");
+ mwexec("/usr/bin/chgrp squid /usr/local/squid/logs/squidGuard.log");
+ mwexec("/bin/chmod 744 /usr/local/squid/logs/squidGuard.log");
+ mwexec("/usr/sbin/chown -R squid /var/db/squidGuard");
+ mwexec("/usr/bin/chgrp -R squid /var/db/squidGuard");
+ mwexec("/usr/local/sbin/squid -k reconfigure");
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ unlink_if_exists("/var/log/squidGuard.log");
+ rmdir_recursive("/var/db/squidGuard");
+ remove_text_from_file("/usr/local/etc/squid/squid.conf", "redirect_program /usr/local/bin/squidGuard -c /usr/local/etc/squid/squidGuard.conf");
+ mwexec("/usr/local/sbin/squid -k reconfigure");
+ </custom_php_deinstall_command>
+</packagegui>
diff --git a/config/squidGuard/.project b/config/squidGuard/.project
new file mode 100644
index 00000000..49cdc3c9
--- /dev/null
+++ b/config/squidGuard/.project
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>squidGuard</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ </buildSpec>
+ <natures>
+ </natures>
+</projectDescription>
diff --git a/config/squidGuard/sgerror.php b/config/squidGuard/sgerror.php
new file mode 100644
index 00000000..8084c5c3
--- /dev/null
+++ b/config/squidGuard/sgerror.php
@@ -0,0 +1,284 @@
+<?php
+$page_info = <<<EOD
+# ----------------------------------------------------------------------------------------------------------------------
+# SquidGuard error page generator
+# (C)2006-2007 Serg Dvoriancev
+# ----------------------------------------------------------------------------------------------------------------------
+# This programm processed redirection to specified URL or generated error page for standart HTTP error code.
+# Redirection supported http and https protocols.
+# ----------------------------------------------------------------------------------------------------------------------
+# Format:
+# sgerror.php?url=[http://myurl]or[https://myurl]or[error_code[space_code]output-message][incoming SquidGuard variables]
+# Incoming SquidGuard variables:
+# a=client_address
+# n=client_name
+# i=client_user
+# s=client_group
+# t=target_group
+# u=client_url
+# Example:
+# sgerror.php?url=http://myurl.com&a=..&n=..&i=..&s=..&t=..&u=..
+# sgerror.php?url=https://myurl.com&a=..&n=..&i=..&s=..&t=..&u=..
+# sgerror.php?url=404%20output-message&a=..&n=..&i=..&s=..&t=..&u=..
+# ----------------------------------------------------------------------------------------------------------------------
+# Tags:
+# myurl and output messages can include Tags
+# [a] - client address
+# [n] - client name
+# [i] - client user
+# [s] - client group
+# [t] - target group
+# [u] - client url
+# Example:
+# sgerror.php?url=401 Unauthorized access to URL [u] for client [n]
+# sgerror.php?url=http://my_error_page.php?cladr=%5Ba%5D&clname=%5Bn%5D // %5b=[ %d=]
+# ----------------------------------------------------------------------------------------------------------------------
+# Special Tags:
+# blank - get blank page
+# blank_img - get one-pixel transparent image (for replace banners and etc.)
+# Example:
+# sgerror.php?url=blank
+# sgerror.php?url=blank_img
+# ----------------------------------------------------------------------------------------------------------------------
+EOD;
+
+define('ACTION_URL', 'url');
+define('ACTION_RES', 'res');
+define('ACTION_MSG', 'msg');
+
+define('TAG_BLANK', 'blank');
+define('TAG_BLANK_IMG', 'blank_img');
+
+# ----------------------------------------------------------------------------------------------------------------------
+# ?url=EMPTY_IMG
+# Use this options for replace baners/ads to transparent picture. Thisbetter for viewing.
+# ----------------------------------------------------------------------------------------------------------------------
+# NULL GIF file
+# HEX: 47 49 46 38 39 61 - - -
+# SYM: G I F 8 9 a 01 00 | 01 00 80 00 00 FF FF FF | 00 00 00 2C 00 00 00 00 | 01 00 01 00 00 02 02 44 | 01 00 3B
+# ----------------------------------------------------------------------------------------------------------------------
+define(GIF_BODY, "GIF89a\x01\x00\x01\x00\x80\x00\x00\xFF\xFF\xFF\x00\x00\x00\x2C\x00\x00\x00\x00\x01\x00\x01\x00\x00\x02\x02\x44\x01\x00\x3B");
+
+$url = '';
+$msg = '';
+$cl = Array(); // squidGuard variables: %a %n %i %s %t %u
+$err_code = array();
+
+$err_code[301] = "301 Moved Permanently";
+$err_code[302] = "302 Found";
+$err_code[303] = "303 See Other";
+$err_code[305] = "305 Use Proxy";
+
+$err_code[400] = "400 Bad Request";
+$err_code[401] = "401 Unauthorized";
+$err_code[402] = "402 Payment Required";
+$err_code[403] = "403 Forbidden";
+$err_code[404] = "404 Not Found";
+$err_code[405] = "405 Method Not Allowed";
+$err_code[406] = "406 Not Acceptable";
+$err_code[407] = "407 Proxy Authentication Required";
+$err_code[408] = "408 Request Time-out";
+$err_code[409] = "409 Conflict";
+$err_code[410] = "410 Gone";
+$err_code[411] = "411 Length Required";
+$err_code[412] = "412 Precondition Failed";
+$err_code[413] = "413 Request Entity Too Large";
+$err_code[414] = "414 Request-URI Too Large";
+$err_code[415] = "415 Unsupported Media Type";
+$err_code[416] = "416 Requested range not satisfiable";
+$err_code[417] = "417 Expectation Failed";
+
+$err_code[500] = "500 Internal Server Error";
+$err_code[501] = "501 Not Implemented";
+$err_code[502] = "502 Bad Gateway";
+$err_code[503] = "503 Service Unavailable";
+$err_code[504] = "504 Gateway Time-out";
+$err_code[505] = "505 HTTP Version not supported";
+
+# ----------------------------------------------------------------------------------------------------------------------
+# check arg's
+# ----------------------------------------------------------------------------------------------------------------------
+
+if (count($_POST)) {
+ $url = trim($_POST['url']);
+ $msg = $_POST['msg'];
+ $cl['a'] = $_POST['a'];
+ $cl['n'] = $_POST['n'];
+ $cl['i'] = $_POST['i'];
+ $cl['s'] = $_POST['s'];
+ $cl['t'] = $_POST['t'];
+ $cl['u'] = $_POST['u'];
+}
+elseif (count($_GET)) {
+ $url = trim($_GET['url']);
+ $msg = $_GET['msg'];
+ $cl['a'] = $_GET['a'];
+ $cl['n'] = $_GET['n'];
+ $cl['i'] = $_GET['i'];
+ $cl['s'] = $_GET['s'];
+ $cl['t'] = $_GET['t'];
+ $cl['u'] = $_GET['u'];
+}
+else {
+ # Show 'About page'
+ echo get_page(get_about());
+ exit();
+}
+
+# ----------------------------------------------------------------------------------------------------------------------
+# url's
+# ----------------------------------------------------------------------------------------------------------------------
+if ($url) {
+ $err_id = 0;
+
+ // check error code
+ foreach ($err_code as $key => $val) {
+ if (strpos(strtolower($url), strval($key)) === 0) {
+ $err_id = $key;
+ break;
+ }
+ }
+
+ # blank page
+ if ($url === TAG_BLANK) {
+ echo get_page('');
+ }
+ # blank image
+ elseif ($url === TAG_BLANK_IMG) {
+ $msg = trim($msg);
+ if(strpos($msg, "maxlen_") !== false) {
+ $maxlen = intval(trim(str_replace("maxlen_", "", $url)));
+ filter_by_image_size($cl['u'], $maxlen);
+ exit();
+ }
+ else {
+ # --------------------------------------------------------------
+ # return blank image
+ # --------------------------------------------------------------
+ header("Content-Type: image/gif;"); // charset=windows-1251");
+ echo GIF_BODY;
+ }
+ }
+ # error code
+ elseif ($err_id !== 0) {
+ $er_msg = strstr($_GET['url'], ' ');
+ echo get_error_page($err_id, $er_msg);
+ }
+ # redirect url
+ elseif ((strpos(strtolower($url), "http://") === 0) or (strpos(strtolower($url), "https://") === 0)) {
+ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ # redirect to specified url
+ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ header("HTTP/1.0");
+ header("Location: $url", '', 302);
+ }
+ // error arguments
+ else {
+ echo get_page("sgerror: error arguments $url");
+ }
+}
+else {
+ echo get_page($_SERVER['QUERY_STRING']); //$url . implode(" ", $_GET));
+# echo get_error_page(500);
+}
+
+# ~~~~~~~~~~
+# Exit
+# ~~~~~~~~~~
+exit();
+
+# ----------------------------------------------------------------------------------------------------------------------
+# functions
+# ----------------------------------------------------------------------------------------------------------------------
+function get_page($body) {
+ $str = Array();
+ $str[] = '<html>';
+ $str[] = "<body>\n$body\n</body>";
+ $str[] = '</html>';
+ return implode("\n", $str);
+}
+
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# IE displayed self-page, if them size > 1024
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+function get_error_page($er_code_id, $err_msg='') {
+ global $err_code;
+ global $cl;
+ $str = Array();
+
+ header("HTTP/1.1 " . $err_code[$er_code_id]);
+
+ $str[] = '<html>';
+ $str[] = '<body>';
+ $str[] = '<h3>Request denied by pfSense proxy: ' . $err_code[$er_code_id] . '</h3>';
+ if ($err_msg) $str[] = "<b> Reason: </b> $err_msg";
+ $str[] = '<hr size="1" noshade>';
+ if ($cl['a']) $str[] = "<b> Client address: </b> {$cl['a']} <br>";
+ if ($cl['n']) $str[] = "<b> Client name: </b> {$cl['n']} <br>";
+ if ($cl['i']) $str[] = "<b> Client user: </b> {$cl['i']} <br>";
+ if ($cl['s']) $str[] = "<b> Client group: </b> {$cl['s']} <br>";
+ if ($cl['t']) $str[] = "<b> Target group: </b> {$cl['t']} <br>";
+ if ($cl['u']) $str[] = "<b> URL: </b> {$cl['u']} <br>";
+ $str[] = '<hr size="1" noshade>';
+ $str[] = "</body>";
+ $str[] = "</html>";
+
+ return implode("\n", $str);
+}
+
+function get_about() {
+ global $err_code;
+ global $page_info;
+ $str = Array();
+
+ // about info
+ $s = str_replace("\n", "<br>", $page_info);
+ $str[] = $s;
+ $str[] = "<br>";
+
+ $str[] = '<table>';
+ $str[] = ' <b>HTTP error codes (ERROR_CODE):</th></tr>';
+ foreach($err_code as $val) {
+ $str []= "<tr><td>$val";
+ }
+ $str[] = '</table>';
+
+ return implode("\n", $str);
+}
+
+function filter_by_image_size($url, $val_size) {
+
+ # load url header
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, $url);
+ curl_setopt($ch, CURLOPT_HEADER, 1);
+ curl_setopt($ch, CURLOPT_NOBODY, 1);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ $hd = curl_exec($ch);
+ curl_close($ch);
+
+ $size = 0;
+ $SKEY = "content-length:";
+ $s_tmp = strtolower($hd);
+ $s_tmp = str_replace("\n", " ", $s_tmp); # replace all "\n"
+ if (strpos($s_tmp, $SKEY) !== false) {
+ $s_tmp = trim(substr($s_tmp, strpos($s_tmp, $SKEY) + strlen($SKEY)));
+ $s_tmp = trim(substr($s_tmp, 0, strpos($s_tmp, " ")));
+ if (is_numeric($s_tmp))
+ $size = intval($s_tmp);
+ else $size = 0;
+ }
+
+ # === check url type and content size ===
+ # redirect to specified url
+ if (($size !== 0) && ($size < $val_size)) {
+ header("HTTP/1.0");
+ header("Location: $url", '', 302);
+ }
+ # return blank image
+ else {
+ header("Content-Type: image/gif;");
+ echo GIF_BODY;
+ }
+}
+?> \ No newline at end of file
diff --git a/config/squidGuard/squidguard.inc b/config/squidGuard/squidguard.inc
new file mode 100644
index 00000000..38ab4b7c
--- /dev/null
+++ b/config/squidGuard/squidguard.inc
@@ -0,0 +1,1394 @@
+<?php
+# ------------------------------------------------------------------------------
+/* squidguard.inc
+ (C)2006-2008 Serg Dvoriancev
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+# ------------------------------------------------------------------------------
+
+require_once('globals.inc');
+require_once('config.inc');
+require_once('util.inc');
+require_once('pfsense-utils.inc');
+require_once('pkg-utils.inc');
+require_once('filter.inc');
+require_once('service-utils.inc');
+require_once('squidguard_configurator.inc');
+# ------------------------------------------------------------------------------
+define('SQUIDGUARD_CONFBASE', '/usr/local/etc/squid');
+define('SQUIDGUARD_CONFFILE', '/squidguard.conf');
+define('SQUIDGUARD_CONFXML', '/squidguard_conf.xml');
+define('SQUIDGUARD_BINPATH', '/usr/local/bin');
+define('SQUIDGUARD_WORKDIR', '/usr/local/etc/squidGuard');
+define('SQUIDGUARD_LOGDIR', '/var/squidGuard/log');
+define('SQUIDGUARD_DBHOME', '/var/db/squidGuard');
+
+define('SQUIDGUARD_WEBGUI_LOG', '/squidguard_gui.log');
+define('SQUIDGUARD_WEBGUI_HISTORY_LOG', '/squidguard_gui_history.log');
+
+# ------------------------------------------------------------------------------
+
+define('F_NAME', 'name');
+define('F_DEST', 'dest');
+define('F_SOURCE', 'source');
+define('F_DESTINATION', 'dest');
+define('F_REWRITE', 'rewrite');
+define('F_REDIRECT', 'redirect');
+define('F_TIME', 'time');
+define('F_OVERDESTINATION', 'overdestination');
+define('F_OVERREWRITE', 'overrewrite');
+define('F_OVERREDIRECT', 'overredirect');
+define('F_TARGETURL', 'targeturl');
+define('F_REPLACETO', 'replaceto');
+define('F_TIMETYPE', 'timetype');
+define('F_TIMEDAYS', 'timedays');
+define('F_DATERANGE', 'daterange');
+define('F_TIMERANGE', 'sg_timerange');
+define('F_IPLIST', 'iplist');
+define('F_DESCRIPTION', 'description');
+define('F_EXPRESSIONS', 'expressions');
+define('F_DOMAINS', 'domains');
+define('F_URLS', 'urls');
+define('F_DISABLED', 'disabled');
+define('F_ENABLELOG', 'enablelog');
+define('F_SQUIDGUARDENABLE','squidguard_enable');
+define('F_BLACKLIST', 'blacklist');
+
+define('PREF_UPTIME', 'uptime_');
+define('PREF_UPTIME_DENY', 'uptimedeny_');
+define('PREF_OVERTIME', 'overtime_');
+define('PREF_OVERTIME_DENY', 'overtimedeny_');
+
+define('MODULE_GENERAL', 'squidguardgeneral');
+define('MODULE_DEFAULT', 'squidguarddefault');
+define('MODULE_ACL', 'squidguardacl');
+define('MODULE_DESTINATION', 'squidguarddest');
+define('MODULE_REWRITE', 'squidguardrewrite');
+define('MODULE_SOURCE', 'squidguardsrc');
+define('MODULE_TIME', 'squidguardtime');
+define('MODULE_LOG', 'squidguardlog');
+
+define('BLACKLIST_DEFAULT_URL', 'http://ftp.teledanmark.no/pub/www/proxy/squidGuard/contrib/blacklists.tar.gz'); # 360Kb
+define('BLACKLIST_DEFAULT_URL1', 'http://www.shallalist.de/Downloads/shallalist.tar.gz'); # ~7Mb
+define('BLACKLIST_TMP_FILE', '/var/tmp/blacklists.tar.gz');
+define('BLACKLIST_BTN_URL', 'Upload Url');
+define('BLACKLIST_BTN_LAST', 'Restore last');
+
+define('BLACKLIST_LOGFILE', 'blacklist.log');
+define('APPLY_BTN', 'Apply');
+define('WEBGUI_HISTORY_LOG', 'on');
+define('TEST_LOG', '/var/tmp/sqtest.test');
+define('SAFESEARCH', 'safesearch');
+
+# ==============================================================================
+# Initialization
+# ==============================================================================
+# use global variable $squidguard_config, defined in squidguard_configurator.inc
+sg_init(convert_pfxml_to_sgxml());
+
+# ==============================================================================
+# Validations
+# ==============================================================================
+function squidguard_validate($post, $input_errors)
+{
+ $submit = isset($_GET['submit']) ? $_GET['submit'] : $_POST['submit'];
+
+ # check config if 'Apply'
+ if ($submit === APPLY_BTN) sg_check_config_data(&$input_errors);
+}
+
+# ------------------------------------------------------------------------------
+# validate default
+# ------------------------------------------------------------------------------
+function squidguard_validate_default($post, $input_errors)
+{
+ squidguard_validate_acl($post, &$input_errors);
+}
+
+# ------------------------------------------------------------------------------
+# validate acl
+# ------------------------------------------------------------------------------
+function squidguard_validate_acl($post, $input_errors)
+{
+ $pass_up = array();
+ $deny_up = array();
+ $pass_up_val = '';
+ $pass_over = array();
+ $deny_over = array();
+ $pass_over_val = '';
+ $id = get_item_id();
+
+ # check name ('source')
+ $name = trim($post[F_NAME]);
+ if(!empty($name)) {
+ # validate name format
+ check_name_format($name, &$input_errors);
+
+ # check unique name
+ if (!sg_check_unique_name(F_ACLS, $name))
+ $input_errors[] = "Name '$name' already exists.";
+
+ # check source
+ $sgx = array();
+ $sgx[F_NAME] = $post[F_NAME];
+ $sgx[F_SOURCE] = $post[F_SOURCE];
+ sg_check_src($sgx, &$input_errors);
+ }
+
+ # store destinations to 'dest' value
+ foreach ($post as $key => $val) {
+ if (substr_count($key, PREF_UPTIME) != 0) {
+ $name = str_replace(PREF_UPTIME, '', $key);
+ if ($name) {
+ switch($val) {
+ case "allow": $pass_up_val .= " $name"; break;
+ case "white": $pass_up_val .= " ^$name"; break;
+ case "deny" : $pass_up_val .= " !$name"; break;
+ }
+ }
+ }
+ elseif (substr_count($key, PREF_OVERTIME) != 0) {
+ $name = str_replace(PREF_OVERTIME, '', $key);
+ if ($name) {
+ switch($val) {
+ case "allow": $pass_over_val .= " $name"; break;
+ case "white": $pass_over_val .= " ^$name"; break;
+ case "deny" : $pass_over_val .= " !$name"; break;
+ }
+ }
+ }
+ }
+
+ # !ATTENTION! on pfSense XML config must be must(shell) be '!all' instead of 'none' - it is a must for correct work GUI
+
+ # if not exists key 'all', then add 'none' - default 'deny all'
+ if ((substr_count($pass_up_val, 'all') == 0)) {
+ $pass_up_val .= ' !all';
+ }
+
+ if (!empty($pass_over_val) && (substr_count($pass_over_val, 'all') == 0)) {
+ $pass_over_val .= ' !all';
+ }
+
+ if (empty($pass_over_val))
+ $post[F_DEST] = "$pass_up_val";
+ else $post[F_DEST] = "$pass_up_val [$pass_over_val]";
+
+ # check redirect
+ $errmsg = '';
+ if (!sg_check_redirect($post[F_RMOD], $post[F_REDIRECT], &$errmsg)) {
+ $input_errors[] = "Redirect info error. $errmsg";
+ }
+}
+
+# ------------------------------------------------------------------------------
+# validate times
+# Format:
+# date: <date(or range)><time (or range)> -- days not parsed (reset to *)
+# weekly: <day or *><time or range> -- dates not parsed (reset to '')
+# ------------------------------------------------------------------------------
+function squidguard_validate_times($post, $input_errors)
+{
+ $id = get_item_id();
+
+ # check name
+ $name = trim($post[F_NAME]);
+ if(!empty($name)) {
+ check_name_format($name, &$input_errors);
+
+ # check unique name
+ if (!sg_check_unique_name(F_TIMES, $name))
+ $input_errors[] = "Name '$name' already exists";
+ }
+
+ # --- check format ---
+ $sgx = array();
+ $sgx[F_NAME] = $post[F_NAME];
+ $sgx[F_DESCRIPTION] = $post[F_DESCRIPTION];
+ # fields of $post have 'fnameX' format
+ for ($i=0; isset($post[F_TIMETYPE."$i"]); $i++) {
+ # correct and update
+ if (strtolower($post[F_TIMETYPE."$i"]) === "date") {
+ $post[F_TIMEDAYS."$i"] = '*';
+ # date cant be empty
+ if (trim($post[F_DATERANGE."$i"]) == '') $post[F_DATERANGE."$i"] = "*.*.*";
+ }
+ else $post[F_DATERANGE."$i"] = '';
+
+ if (trim($post[F_TIMERANGE."$i"]) == '') $post[F_TIMERANGE."$i"] = "00:00-23:59";
+
+ # $post->xml
+ $sgx_row = array();
+ $sgx_row[F_TIMETYPE] = $post[F_TIMETYPE."$i"];
+ $sgx_row[F_TIMEDAYS] = $post[F_TIMEDAYS."$i"];
+ $sgx_row[F_DATERANGE] = $post[F_DATERANGE."$i"];
+ $sgx_row[F_TIMERANGE] = $post[F_TIMERANGE."$i"];
+ $sgx[F_ITEM][] = $sgx_row;
+ }
+ #
+ sg_check_time($sgx, &$input_errors);
+
+}
+
+# ------------------------------------------------------------------------------
+# validate destinations
+# ------------------------------------------------------------------------------
+function squidguard_validate_destination($post, $input_errors) {
+ # check name
+ $name = trim($post[F_NAME]);
+ if(!empty($name)) {
+ check_name_format($name, &$input_errors);
+
+ # check unique name
+ if (!sg_check_unique_name(F_DESTINATIONS, $name))
+ $input_errors[] = "Name '$name' already exists";
+ }
+
+ # --- check format ---
+ $sgx = array();
+ $sgx[F_NAME] = $post[F_NAME];
+ $sgx[F_URLS] = $post[F_URLS];
+ $sgx[F_DOMAINS] = $post[F_DOMAINS];
+ $sgx[F_EXPRESSIONS] = $post[F_EXPRESSIONS];
+ $sgx[F_RMOD] = $post[F_RMOD];
+ $sgx[F_REDIRECT] = $post[F_REDIRECT];
+ #
+ sg_check_dest($sgx, &$input_errors);
+}
+
+# ------------------------------------------------------------------------------
+# validate rewrites
+# ------------------------------------------------------------------------------
+function squidguard_validate_rewrite($post, $input_errors) {
+ # check name
+ $name = trim($post[F_NAME]);
+ if(!empty($name)) {
+ # check name format <char><symbols without space> - Ab123
+ check_name_format($name, &$input_errors);
+
+ # check unique name
+ if (!sg_check_unique_name(F_REWRITES, $name))
+ $input_errors[] = "Name '$name' already exists";
+ }
+}
+
+# -----------------------------------------------------------------------------
+# squidguard_resync
+# -----------------------------------------------------------------------------
+function squidguard_resync() {
+ $upload_file = '';
+ $submit = '';
+ $url = '';
+ $proxy = '';
+
+ $submit = isset($_POST['submit']) ? $_POST['submit'] : $_GET['submit'];
+ $url = isset($_POST['blacklist_url']) ? $_POST['blacklist_url'] : $_GET['blacklist_url'];
+ $proxy = isset($_POST['blacklist_proxy']) ? $_POST['blacklist_proxy'] : $_GET['blacklist_proxy'];
+
+ # blacklist upload
+ if ($submit == BLACKLIST_BTN_URL) {
+ if ($url)
+ sg_reconfigure_blacklist($url, $proxy);
+ }
+
+ # blacklist restore last (if exists)
+ if ($submit == BLACKLIST_BTN_LAST) {
+ restore_arc_blacklist();
+ }
+
+ # apply changes
+ if ($submit == APPLY_BTN) {
+# write_config('Update squidGuard options.'); # store, if not 'Save' button
+# ïåðåíåñòè â validate äëÿ äåòåêòèðîâàíèÿ îøèáîê?
+ sg_reconfigure();
+ }
+}
+
+# -----------------------------------------------------------------------------
+# squidguard_resync_acl
+# -----------------------------------------------------------------------------
+
+function squidguard_resync_acl() {
+ global $config; # !!! ORDER !!!
+
+ $conf = $config['installedpackages'][MODULE_ACL]['config'];
+ $id = isset($_POST['id']) ? $_POST['id'] : $_GET['id'];
+
+ # --- sources part ---
+ # move current id by order
+ if (($id !== '') and is_array($conf)) {
+ $src_new = array();
+
+ foreach ($conf as $key => $src) {
+ $order = $src[F_ORDER];
+ # n_key: no_move=$key+$order or move=$order+$key
+ $n_key = is_numeric($order) ? sprintf("%04d%04d", $order, $key) : sprintf("%04d%04d", $key, 9999);
+ unset($src[F_ORDER]); # ! must be unset for display correct default position in 'select'!
+ $src_new[$n_key] = $src;
+ }
+ # sort by key
+ ksort($src_new);
+ reset($src_new);
+
+ $src_new = array_values($src_new); # make keys '0, 1, 2, ...'
+
+ # renew config
+ unset ($config['installedpackages'][MODULE_ACL]['config']);
+ $config['installedpackages'][MODULE_ACL]['config'] = $src_new;
+ write_config('Update squidguardacl config');
+
+ # renew global $squidguard_config
+ sg_init(convert_pfxml_to_sgxml());
+ }
+}
+
+# =============================================================================
+# common functions
+# =============================================================================
+
+# -----------------------------------------------------------------------------
+# get_pkgconf/sgconf_items_list
+# -----------------------------------------------------------------------------
+function get_pkgconf_items_list($pkg_gui_name, $fieldname) {
+ global $config;
+ $res = '';
+
+ $conf = $config['installedpackages'][$pkg_gui_name]['config'];
+ if (is_array($conf))
+ foreach($conf as $cf) $res[] = $cf[$fieldname];
+
+ return $res;
+}
+
+function get_sgconf_items_list($data_group, $fieldname) {
+ global $squidguard_config;
+ $res = '';
+
+ $conf = $squidguard_config[$data_group]['item'];
+ if (is_array($conf))
+ foreach($conf as $cf) $res[] = $cf[$fieldname];
+
+ return $res;
+}
+
+# ==============================================================================
+# Before form
+# ==============================================================================
+# squidguard_before_form
+# ------------------------------------------------------------------------------
+function squidguard_before_form($pkg) {
+ $i=0;
+
+ foreach($pkg['fields']['field'] as $field) {
+ # blacklist controls
+ switch ($field['fieldname']) {
+ case 'blacklist_url':
+ $fld = &$pkg['fields']['field'][$i];
+ $fld['description'] .= make_grid_blacklist(); # insert to description custom controls
+ break;
+ # Apply button
+ case 'squidguard_enable':
+ $fld = &$pkg['fields']['field'][$i];
+ $fld['description'] .= make_grid_general_items(); # insert to description custom controls
+ break;
+ # GUI log
+ case 'view_gui_log':
+ $fld = &$pkg['fields']['field'][$i];
+ $fld['description'] .= make_grid_general_items('gui_log'); # insert to description custom controls
+ break;
+ }
+ $i++;
+ }
+}
+
+# -----------------------------------------------------------------------------
+# squidguard_before_form_acl
+# -----------------------------------------------------------------------------
+function squidguard_before_form_acl($pkg, $is_acl=true) {
+ global $g;
+ global $squidguard_config;
+
+ $current_id = '';
+ $sources = '';
+ $source_items = '';
+ $destinations = '';
+ $dest_items = '';
+ $rewrites = '';
+ $rewr_names = '';
+ $times = '';
+ $time_names = '';
+ $acls_up = '';
+ $acls_over = '';
+
+ $current_id = isset($_POST['id']) ? $_POST['id'] : $_GET['id'];
+ $current_id = ($current_id) ? $current_id : 0;
+
+ # sources
+ $source_items = get_sgconf_items_list(F_SOURCES, 'name');
+ # generate sources list TODO: exclude used names from list, source name used in ACL unique
+ $i=0;
+ foreach($pkg['fields']['field'] as $field) {
+ if ($field['fieldname'] == 'source') {
+ $fld = &$pkg['fields']['field'][$i];
+ if (is_array($source_items)) {
+ foreach($source_items as $nm)
+ $fld['options']['option'][] = array('name'=>$nm, 'value'=>$nm);
+ }
+ }
+ # order
+ if (is_array($source_items) && $field['fieldname'] == 'order') {
+ $fld = &$pkg['fields']['field'][$i];
+ foreach($source_items as $nmkey => $nm)
+ $fld['options']['option'][] = array('name'=>$nm, 'value'=>$nmkey);
+ $fld['options']['option'][] = array('name'=>'--- Last ---', 'value'=>'9999');
+ $fld['options']['option'][] = array('name'=>'-----', 'value'=>''); # ! this is must be last !
+ }
+ $i++;
+ }
+
+ # destinations
+ # acls pass ---> prepare data for destinations; dest format 'uptime_dests_list [overtime_dests_list]'
+ $acl_dest = '';
+ $acl_overdest = '';
+
+ # acl & default
+ if ($pkg['name'] !== MODULE_DEFAULT) {
+ $acl_dest = $squidguard_config[F_ACLS]['item'][$current_id][F_DESTINATIONNAME];
+ $acl_overdest = $squidguard_config[F_ACLS]['item'][$current_id][F_OVERDESTINATIONNAME];
+ }
+ else $acl_dest = $squidguard_config[F_DEFAULT][F_DESTINATIONNAME];
+
+ # acl dest ontime
+ if ($acl_dest) {
+ # 'none' > to '!all'
+ $acl_dest = str_replace('none', '!all', $acl_dest);
+
+ $pss = explode(' ', $acl_dest);
+ foreach($pss as $val) {
+ $name = $val;
+ $name = str_replace('!', '', $name);
+ $name = str_replace('^', '', $name);
+ if (!empty($val)) {
+ switch($val[0]) {
+ case '!': $acls_up[$name] = 'deny'; break;
+ case '^': $acls_up[$name] = 'white'; break;
+ default : $acls_up[$name] = 'allow'; break;
+ }
+ }
+ }
+ }
+
+ # acl dest overtime
+ if ($acl_overdest) {
+ # 'none' > to '!all'
+ $acl_overdest = str_replace('none', '!all', $acl_overdest);
+
+ $pss = explode(' ', $acl_overdest);
+ foreach($pss as $val) {
+ $name = $val;
+ $name = str_replace('!', '', $name);
+ $name = str_replace('^', '', $name);
+ if (!empty($val)) {
+ switch($val[0]) {
+ case '!': $acls_over[$name] = 'deny'; break;
+ case '^': $acls_over[$name] = 'white'; break;
+ default : $acls_over[$name] = 'allow'; break;
+ }
+ }
+ }
+ }
+
+ # --- Destinations ---
+ # Blacklist
+ if ($squidguard_config[F_BLACKLISTENABLED] === 'on') {
+ $blk_entries = sg_entries_blacklist();
+ if (!empty($blk_entries)) {
+ foreach($blk_entries as $dst)
+ $dest_items[] = array ('name'=>$dst,
+ 'upt_value'=>$acls_up[$dst],
+ 'ovt_value'=>$acls_over[$dst],
+ 'description'=>'');
+ }
+ }
+
+ # User destinations
+ if ($squidguard_config[F_DESTINATIONS]) {
+ foreach($squidguard_config[F_DESTINATIONS]['item'] as $dst)
+ $dest_items[] = array ('name'=>$dst[F_NAME],
+ 'upt_value'=>$acls_up[$dst[F_NAME]],
+ 'ovt_value'=>$acls_over[$dst[F_NAME]],
+ 'description'=>$dst[F_DESCRIPTION]);
+ }
+
+ # Default all
+ $dest_items[] = array('name'=>FLT_DEFAULT_ALL,
+ 'upt_value'=>$acls_up[FLT_DEFAULT_ALL],
+ 'ovt_value'=>$acls_over[FLT_DEFAULT_ALL],
+ 'description'=>'Default access');
+
+ $i=0;
+ foreach($pkg['fields']['field'] as $field) {
+ if (($field['fieldname'] === 'dest')/* || ($field['fieldname'] == 'overdest')*/) {
+ $fld = &$pkg['fields']['field'][$i];
+ $fld['description'] .= make_grid_controls('', $dest_items, $is_acl); # insert to description custom controls
+ }
+ $i++;
+ }
+
+ # rewrites
+ $rewr_names = get_sgconf_items_list(F_REWRITES, 'name');
+ $i=0;
+ foreach($pkg['fields']['field'] as $field) {
+ if (($field['fieldname'] == 'rewrite') || ($field['fieldname'] == 'overrewrite')) {
+ $fld = &$pkg['fields']['field'][$i];
+ $fld['options']['option'][] = array('name'=>'none (rewrite not defined)', 'value'=>'');
+ if (is_array($rewr_names)) {
+ foreach($rewr_names as $nm)
+ $fld['options']['option'][] = array('name'=>$nm, 'value'=>$nm);
+ }
+ }
+ $i++;
+ }
+
+ # - set times field -
+ $time_names = get_sgconf_items_list(F_TIMES, 'name');
+ $i=0;
+ foreach($pkg['fields']['field'] as $field) {
+ if ($field['fieldname'] === 'time') {
+ $fld = &$pkg['fields']['field'][$i];
+ $fld['options']['option'][] = array('name'=>'none (time not defined)', 'value'=>'');
+ if (is_array($time_names)) {
+ foreach($time_names as $nm)
+ $fld['options']['option'][] = array('name'=>$nm, 'value'=>$nm);
+ }
+ break;
+ }
+ $i++;
+ }
+}
+
+# -----------------------------------------------------------------------------
+# squidguard_before_form_log
+# -----------------------------------------------------------------------------
+define('LOGSHOW_BUFSIZE', 16384);
+
+function squidguard_before_form_log($pkg) {
+ # ! nothing for config - only report. Possible use global $config !
+ global $config;
+ $i=0;
+ $move_pos = 0;
+ $move_step = 50;
+
+ foreach($pkg['fields']['field'] as $field) {
+ if ($field['fieldname'] == 'logtype') {
+ $slog = '';
+ $mlog = $config['installedpackages'][MODULE_LOG]['config'][0];
+
+ $filename = '';
+ $fld = &$pkg['fields']['field'][$i];
+ $move_pos = ($move_pos) ? $move_pos : 0;
+
+ switch ($mlog['logtype']) {
+ case 'block_log':
+ {
+ $filename = SQUIDGUARD_LOGDIR . "/" . SQUIDGUARD_ACCESSBLOCK_FILE;
+ $fh = '';
+ if (file_exists($filename)) {
+ $fh = fopen($filename, "r");
+ if ($fh) {
+ $fsize = filesize($filename);
+ # take LOGSHOW_BUFSIZE bytes from end
+ if ($fsize > LOGSHOW_BUFSIZE)
+ fseek($fh, -LOGSHOW_BUFSIZE, SEEK_END);
+ $s = fread($fh, LOGSHOW_BUFSIZE);
+ fclose($fh);
+
+ $slog .= "<tr><td colspan='7'>Block log '$filename'. Last 100:<td><tr>";
+
+ $s = explode("\n", $s);
+ unset($s[0]); # unset us'nt complete string
+
+ $slog .= "<tr><th>Num</th><th>DateTime</th><th>IP</th><th>URL</th><th>Filter</th><th>ID</th><th>Mtd</th></tr>";
+ foreach($s as $key => $vs) {
+ $nkey = $move_pos + intval($key);
+ $slog .= "<tr>";
+ $sx = $vs;
+ $sx = str_replace(array("/- -", "/-", "Request", "request","(", ")", "[", "]"), "", $sx);
+ $sx = explode(" ", $sx);
+
+ # formatting url
+ $spos =0;
+ $stmp = '';
+ while($spos + 81 < strlen($sx[4])) {
+ $stmp .= substr($sx[4], $spos, 81) . "<br>";
+ $spos += 81;
+ }
+ $stmp .= substr($sx[4], $spos, strlen($sx[4]) - $spos);
+ $sx[4] = $stmp;
+
+ if (!empty($vs))
+ $slog .= "<tr>
+ <td style='vertical-align: top; white-space: nowrap;'>" . strval($nkey) . "</td>
+ <td style='vertical-align: top; white-space: nowrap;'>$sx[0] $sx[1]</td>
+ <td style='vertical-align: top;'>$sx[5]</td>
+ <td style='vertical-align: top;'>$sx[4]</td>
+ <td style='vertical-align: top;'>$sx[3]</td>
+ <td style='vertical-align: top;'>$sx[2]</td>
+ <td style='vertical-align: top;'>$sx[6]</td></tr>";
+ }
+ }
+ }
+
+ }
+ break;
+ case 'configurator_log':
+ {
+ $filename = SQUIDGUARD_LOGDIR . SQUIDGUARDCONF_LOGFILE;
+ $slog .= "<b>$filename</b><br>";
+ if (file_exists($filename)) {
+ $slog .= file_get_contents($filename);
+ $slog = str_replace("\n", "<br>", $slog);
+ $slog = "<tr><td>$slog</td></tr>";
+ }
+ }
+ break;
+ case 'squidguard_log':
+ {
+ $slog .= 'squidguard_log report disabled';
+/*
+ $filename = SQUIDGUARD_LOGDIR . '/squidGuard.log';
+ $slog .= "<b>$filename</b><br>";
+ if (file_exists($filename)) {
+ $slog .= file_get_contents($filename);
+ $slog = explode("\n", $slog);
+ while (count($slog) > 500) array_shift($slog);
+ $slog = implode("\n", $slog);
+ $slog = str_replace("\n", "<br>", $slog);
+ $slog = "<tr><td>$slog</td></tr>";
+ }
+*/
+ }
+ break;
+ case 'squid_config':
+ {
+ $filename = SQUID_CONFIGFILE;
+ $slog .= "<b>$filename</b><br>";
+ if (file_exists($filename)) {
+ $slog .= file_get_contents($filename);
+ $slog = str_replace("\n", "<br>", $slog);
+ $slog = str_replace("\t", " ", $slog);
+ $slog = "<tr><td>$slog</td></tr>";
+ }
+ }
+ break;
+ case 'squidguard_config':
+ {
+ $filename = SQUIDGUARD_WORKDIR . "/squidGuard.conf";
+ $slog .= "<b>$filename</b><br>";
+ if (file_exists($filename)) {
+ $slog .= file_get_contents($filename);
+ $slog = str_replace("\n", "<br>", $slog);
+ $slog = str_replace("\t", " ", $slog);
+ $slog = "<tr><td>$slog</td></tr>";
+ }
+ }
+ break;
+ } # switch
+
+ $fld['description'] .=
+ "<INPUT class=formbtn type=submit value='Get log' name=Submit>
+ </tr><tr>
+ <td colspan='2'><table width='100%' class=tabcont cellSpacing=0 cellPadding=1 border=1>$slog</table>";
+ }
+ $i++;
+ }
+}
+
+# -----------------------------------------------------------------------------
+# make_grid_general_items
+# -----------------------------------------------------------------------------
+function make_grid_general_items($id = '')
+{
+ global $squidguard_config;
+
+ $bg_color = "bgcolor='#dddddd'";
+ $res = '';
+ $res .= "<table width='100%'>";
+
+ if ($id === '') {
+ # Apply
+ $res .= "<tr $bg_color><td><big>For saving configuration YOU need click button 'Save' on bottom of page</big></td></tr>
+ <tr><td><big>After changing configuration squidGuard you must <b><span style='color: #800000;'>apply all changes</span></b></big></td></tr>
+ <tr><td><input name='submit' type='submit' value='Apply'></td></tr>";
+
+ # service state
+ $sgstate = "<span style='color: #800000;'>STOPPED</span>";
+ if (is_service_running("squidGuard"))
+ $sgstate = "<span style='color: #008000;'>STARTED</span>";
+
+ if (is_blacklist_update_started())
+ $sgstate .= "<br><span style='color: #800000;'>Wait: began updating the blacklist.<br>New data will be available after some time.<br>After the upgrade, it is necessary to check the configuration.</span>";
+ $res .= "<tr $bg_color><td><big>SquidGuard service state: <b>$sgstate</b></big></td></tr>";
+ }
+ elseif ($id === 'gui_log') {
+ if ($squidguard_config['view_gui_log'] == 'on') {
+ $log_content = sg_getlog(50);
+ $log_content = str_replace("\n","<br>", $log_content);
+ $res .= "<tr $bg_color><td><font size='-1'><b>Web GUI log (Latest 50)</b></font></td></tr>";
+ $res .= "<tr $bg_color><td vAlign=top width='100%'><font size='-2'>$log_content</font></td></tr>";
+ }
+ }
+
+ $res .= "</table>";
+ return $res;
+}
+
+# -----------------------------------------------------------------------------
+# make_grid_blacklist
+# -----------------------------------------------------------------------------
+function make_grid_blacklist() {
+ $res = '';
+ # button 'Upload URL' and button 'Restore last blacklist'
+ $res = "<hr><input name='submit' value='" . BLACKLIST_BTN_URL . "' type='submit'>";
+ $res .= "&nbsp;<input name='submit' value='" . BLACKLIST_BTN_LAST . "' type='submit'>";
+ return $res;
+}
+
+# -----------------------------------------------------------------------------
+# make_grid_controls
+# -----------------------------------------------------------------------------
+function make_grid_controls($type, $items, $enable_overtime = true) {
+ global $g;
+
+ $res = '';
+ $tbl = '';
+ $color = '';
+ $color2 = '';
+ $x = 0;
+
+ foreach($items as $item) {
+ if ($x === 0) {
+ $color = '';
+ $color2 = 'style="background-color: #dddddd;"';
+ $x = 1;
+ }
+ else {
+ $color = 'style="background-color: #dddddd;"';
+ $color2 = '';
+ $x = 0;
+ }
+
+ $name = $item['name'];
+ $upt_val = $item['upt_value'];
+ $ovt_val = $item['ovt_value'];
+ $description = $item['description'];
+
+ $sel = "selected=\"selected\"";
+ $upt_A = $upt_B = $upt_C = $upt_D = '';
+ switch($upt_val) {
+ case "allow": $upt_B = $sel; break;
+ case "white": $upt_C = $sel; break;
+ case "deny" : $upt_D = $sel; break;
+ default: $upt_A = $sel; break;
+ }
+
+ $ovt_A = $ovt_B = $ovt_C= $ovt_D = '';
+ switch($ovt_val) {
+ case "allow": $ovt_B = $sel; break;
+ case "white": $ovt_C = $sel; break;
+ case "deny" : $ovt_D = $sel; break;
+ default: $ovt_A = $sel; break;
+ }
+ unset($sel);
+
+ $tbl .= "<tr>";
+ # uptime table
+ $tnm = PREF_UPTIME . $name;
+ $tbl .= "<td $color></td>";
+ $tbl .= "<td $color>$description [$name]</td>";
+ $tbl .= "<td $color>access</td>";
+ $tbl .= "<td $color><select id=$tnm name=\"$tnm\">";
+ if (substr_count($name, "all") === 0) {
+ $tbl .= "<option value=none name=\"----\" $upt_A>----</option>";
+ $tbl .= "<option value=white name=\"white\" $upt_C>white</option>";
+ $tbl .= "<option value=deny name=\"deny\" $upt_D>deny </option>";
+ $tbl .= "<option value=allow name=\"allow\" $upt_B>allow</option>";
+ }
+ else {
+ $tbl .= "<option value=allow name=\"allow\" $upt_B>allow</option>";
+ $tbl .= "<option value=deny name=\"deny\" $upt_D>deny </option>";
+ }
+ $tbl .= "</td>";
+
+ # overtime table
+ if ($enable_overtime) {
+ $tnm = PREF_OVERTIME . $name;
+ $tbl .= "<td $color></td>";
+ $tbl .= "<td $color>$description [$name]</td>";
+ $tbl .= "<td $color>access</td>";
+ $tbl .= "<td $color><select id=$tnm name=\"$tnm\">";
+ if (substr_count($name, "all") === 0) {
+ $tbl .= "<option value=none name=\"----\" $ovt_A>----</option>";
+ $tbl .= "<option value=white name=\"white\" $ovt_C>white</option>";
+ $tbl .= "<option value=deny name=\"deny\" $ovt_D>deny </option>";
+ $tbl .= "<option value=allow name=\"allow\" $ovt_B>allow</option>";
+ }
+ else {
+ $tbl .= "<option value=allow name=\"allow\" $ovt_B>allow</option>";
+ $tbl .= "<option value=deny name=\"deny\" $ovt_D>deny </option>";
+ }
+ $tbl .= "</td>";
+ }
+ $tbl .= "</tr>";
+ }
+
+ # header
+ if (!empty($tbl)) {
+ $color = 'style="background-color: #dddddd;"';
+ $thdr = '';
+ $hdr1up = "<big>Destination rules</big>";
+ $hdr1ov = "<big>Destination rules in overtime</big>";
+ $hds3 = "ACCESS: 'white' - always pass; 'deny' - block; 'allow' - pass, if not blocked.";
+ if ($enable_overtime) {
+ $thdr .= "<tr><td colspan='8' align=left>$hds3</td></tr>";
+ $thdr .= "<tr $color><th colspan='4' align=middle>$hdr1up</th><th colspan='4' align=middle>$hdr1ov</th></tr>";
+ $thdr .= "<tr $color><td colspan='4' align=middle></td><td colspan='4' align=middle>If <b>'Time'</b> not defined, this ruleset will be ignored</td></tr>";
+ # formatting
+ $thdr .= "<tr><td/><td width='35%'/><td/><td/><td/><td width='35%'/><td/><td/></tr>";
+ }
+ else {
+ $thdr .= "<tr><td colspan='4' align=left>$hds3<hr></tr>";
+ $thdr .= "<tr $color><th colspan='4' align=middle>$hdr1up</th></tr>";
+ # formatting
+ $thdr .= "<tr><td width='5%'/><td/><td width='5%'/><td width='10%'/></tr>";
+ }
+
+ $res .= "<table cellspacing='0' width='100%'> $thdr $tbl </table>";
+
+ $rstyle = "";
+ $ha = "<div $color>" .
+ "<span onClick='document.getElementById(\"destrules\").style.display = \"block\";' style=\"cursor: pointer;\">" .
+ "<font size='-12'><big>Destination ruleset (click)</big>&nbsp;" .
+ "<img src='./themes/{$g['theme']}/images/icons/icon_pass.gif' title='Show rules'>&nbsp;" .
+ "</span>" .
+ "<span style=\"cursor: pointer;\">" .
+ "<img src='./themes/{$g['theme']}/images/icons/icon_block.gif' title='Hide rules' onClick='document.getElementById(\"destrules\").style.display = \"none\";'>" .
+ "</span>" .
+ "</div>";
+ $res = "<hr>$ha<div id=\"destrules\" style='DISPLAY: none'>$res</div>";
+
+ }
+ return $res;
+}
+
+# -----------------------------------------------------------------------------
+# check unique name
+# -----------------------------------------------------------------------------
+function sg_check_unique_name($module_id, $name, $log='') {
+ $res = true;
+ $id = (isset($_GET['id'])) ? $_GET['id'] : $_POST['id'];
+
+ $name_list = get_sgconf_items_list($module_id, 'name');
+ $name_val = (is_array($name_list)) ? array_count_values($name_list) : array();
+ $count_names = $name_val[$name];
+
+ # if count names = 1, then check if add new record with this name(not valid) / or this is a self record(valid)
+ # else if count names > 1 - not valid
+ if ($count_names === 1) {
+ $nm_key = array_search($name, $name_list);
+ # if this new record
+ if ($id >= count($name_list)) { $res = false; }
+ # if not self record
+ elseif ($nm_key && (intval($id) !== intval($nm_key))) { $res = false; }
+ }
+ elseif($count_names > 1) $res = false; # bad - not unique
+
+ return $res;
+}
+
+# ------------------------------------------------------------------------------
+# Install & deinstall
+# ------------------------------------------------------------------------------
+
+function squidguard_install_command() {
+ if (!is_service_running("squidGuard")) {
+ sg_init(convert_pfxml_to_sgxml());
+ sg_check_system();
+
+ # generate squidGuard blacklist entries file (check with squidGuard PORT)
+ $entries = array("ads", "aggressive", "audio-video", "drugs", "gambling", "hacking",
+ "mail", "porn", "proxy", "violence", "warez");
+ file_put_contents(SQUIDGUARD_WORKDIR . SQUIDGUARD_BLK_ENTRIES, implode("\n", $entries));
+ set_file_access(SQUIDGUARD_WORKDIR, OWNER_NAME, 0755);
+ set_file_access(SQUIDGUARD_DBHOME, OWNER_NAME, 0755);
+
+ sg_reconfigure();
+ }
+}
+
+function squidguard_deinstall_command() {
+ # remove entries from squid config
+ squid_reconfigure('remove redirector options');
+
+ # remove package and his depends
+ mwexec("pkg_delete squidGuard-1.2.0_1");
+ mwexec("rm -rf " . SQUIDGUARD_WORKDIR);
+ # i known't, really need delete blacklist base?
+ mwexec("rm -rf " . SQUIDGUARD_DBHOME);
+ mwexec("/bin/rm -f " . SQUIDGUARD_CONFBASE . "/squidGuard*");
+}
+
+# ------------------------------------------------------------------------------
+# SquidGuard print JavaSrcript
+# ------------------------------------------------------------------------------
+function squidGuard_print_javascript() {
+ $javascript = '';
+
+ $xml = ($_GET["xml"] !== '') ? $_GET["xml"] : $_POST["xml"];
+
+ # squidguard_default.xml
+ if ($xml === "squidguard_default.xml") {
+ $javascript .= "\n<script language='JavaScript'>";
+ $javascript .= "\n<!--";
+ $javascript .= "\n document.iform.dest.disabled=1;";
+ $javascript .= "\n//-->";
+ $javascript .= "\n</script>";
+ } # if
+
+ # squidguard_acl.xml
+ if ($xml === "squidguard_acl.xml") {
+ $javascript .= "\n<script language='JavaScript'>";
+ $javascript .= "\n<!--";
+ $javascript .= "\n document.iform.dest.disabled=1;";
+ $javascript .= "\n//-->";
+ $javascript .= "\n</script>";
+
+ } # if
+
+ if ($xml === "squidguard_time.xml") {
+ $javascript .= "\n<script language='JavaScript'>";
+ $javascript .= "\n<!--";
+ $javascript .= "\n function on_updatecontrols() {";
+ $javascript .= "\n for (var i=0; i<99; i++) {";
+ $javascript .= "\n var elm = document.iform.elements['timetype' + i];";
+ $javascript .= "\n if (elm) {";
+ $javascript .= "\n document.iform.elements['timetype' + i].onclick = on_updatecontrols;";
+ $javascript .= "\n if (document.iform.elements['timetype' + i].value == 'weekly') {";
+ $javascript .= "\n document.iform.elements['timedays' + i].disabled = 0;";
+ $javascript .= "\n document.iform.elements['daterange' + i].disabled = 1;";
+ $javascript .= "\n }";
+ $javascript .= "\n else {";
+ $javascript .= "\n document.iform.elements['timedays' + i].disabled = 1;";
+ $javascript .= "\n document.iform.elements['daterange' + i].disabled = 0;";
+ $javascript .= "\n }";
+ $javascript .= "\n }";
+ $javascript .= "\n }";
+ $javascript .= "\n }";
+ $javascript .= "\n on_updatecontrols();";
+ $javascript .= "\n ";
+ $javascript .= "\n//-->";
+ $javascript .= "\n</script>";
+ }
+
+ if ($xml === "squidguard_src.xml") { ### will deleted ###
+ $javascript .= "\n<script language='JavaScript'>";
+ $javascript .= "\n<!--";
+ $javascript .= "\n function on_updatecontrols() {";
+ $javascript .= "\n document.iform.elements['order'].disabled = 0;";
+ $javascript .= "\n document.iform.elements['order'].onfocus = on_orderfocus;";
+ $javascript .= "\n }";
+ $javascript .= "\n function on_orderfocus() {";
+ $javascript .= "\n document.iform.elements['order'].blur();";
+ $javascript .= "\n }";
+ $javascript .= "\n function on_moveup() {";
+ $javascript .= "\n var order = parseInt(document.iform.elements['order'].value)";
+ $javascript .= "\n if (order > 0)";
+ $javascript .= "\n order = order - 1;";
+ $javascript .= "\n else order = 0;";
+ $javascript .= "\n document.iform.elements['order'].value = order;";
+ $javascript .= "\n }";
+ $javascript .= "\n function on_movedown() {";
+ $javascript .= "\n var order = parseInt(document.iform.elements['order'].value)";
+ $javascript .= "\n if (order >= 0)";
+ $javascript .= "\n order = order + 1;";
+ $javascript .= "\n else order = 0;";
+ $javascript .= "\n document.iform.elements['order'].value = order;";
+ $javascript .= "\n }";
+ $javascript .= "\n on_updatecontrols();";
+ $javascript .= "\n ";
+ $javascript .= "\n//-->";
+ $javascript .= "\n</script>";
+ }
+
+ print($javascript);
+}
+
+# ==============================================================================
+# Converter
+# ==============================================================================
+# convert_pfxml_to_sgxml
+# -----------------------------------------------------------------
+function convert_pfxml_to_sgxml() {
+
+ capability_update_source();
+
+ global $config;
+ $sgxml = array();
+ $pfxml = $config['installedpackages'][MODULE_GENERAL]['config'][0];
+
+ $sgxml[F_LOGDIR] = SQUIDGUARD_LOGDIR;
+ $sgxml[F_DBHOME] = SQUIDGUARD_DBHOME;
+ $sgxml[F_BINPATH] = SQUIDGUARD_BINPATH;
+ $sgxml[F_WORKDIR] = SQUIDGUARD_WORKDIR;
+ $sgxml[F_SGCONF_XML] = SQUIDGUARD_WORKDIR . SQUIDGUARD_CONFXML;
+ $sgxml[F_ENABLED] = $pfxml[F_SQUIDGUARDENABLE];
+ $sgxml[F_BLACKLISTENABLED] = $pfxml[F_BLACKLIST];
+ $sgxml[F_SOURCES] = convert_pfxml_to_sgxml_source($config);
+ $sgxml[F_DESTINATIONS] = convert_pfxml_to_sgxml_destination($config);
+ $sgxml[F_REWRITES] = convert_pfxml_to_sgxml_rewrite($config);
+ $sgxml[F_TIMES] = convert_pfxml_to_sgxml_time($config);
+ $sgxml[F_ACLS] = convert_pfxml_to_sgxml_acl($config);
+ $sgxml[F_DEFAULT] = convert_pfxml_to_sgxml_default($config);
+
+ # other
+ $sgxml['view_gui_log'] = $pfxml['view_gui_log'];
+
+ # transparent
+ $squidxml = $config['installedpackages']['squid']['config'][0];
+ if(isset($squidxml['transparent_proxy'])) {
+ $lanip = $config['interfaces']['lan']['ipaddr'];
+ $guiport = $config['system']['webgui']['port'];
+ $guiprotocol = $config['system']['webgui']['protocol'];
+
+ $sgxml[F_SQUID_TRANSPARENT_MODE] = 'on';
+ $sgxml[F_CURRENT_LAN_IP] = $lanip;
+ $sgxml[F_CURRENT_GUI_PORT] = $guiport;
+ $sgxml[F_CURRENT_GUI_PROTO] = $guiprotocol;
+ } else {
+ unset($sgxml[F_SQUID_TRANSPARENT_MODE]);
+ unset($sgxml[F_CURRENT_LAN_IP]);
+ unset($sgxml[F_CURRENT_GUI_PORT]);
+ unset($sgxml[F_CURRENT_GUI_PROTO]);
+ }
+
+ # store cfg cache
+ $cfg_xml = dump_xml_config($sgxml, F_SQUIDGUARD);
+ file_put_contents($sgxml[F_SGCONF_XML], $cfg_xml);
+
+ return $sgxml;
+}
+
+# -----------------------------------------------------------------
+# convert_pfxml_to_sgxml_source
+# sgxml_source: [name][ip][desc][log]
+# -----------------------------------------------------------------
+# Changes 04-01-2008 :
+# Source fields moved to ACL page. Source page - will remove
+# But in XML internal config nothing to change
+# -----------------------------------------------------------------
+# Changes 21-07-2008 :
+# Source IP and domain move to one field, added 'username'.
+function convert_pfxml_to_sgxml_source($pfconfig) {
+ $sgxml = array();
+ $pfxml = $pfconfig['installedpackages'][MODULE_ACL]['config'];
+ if (is_array($pfxml)) {
+ foreach($pfxml as $pfx) {
+ $sgx = array();
+ $sgx[F_NAME] = $pfx['name'];
+ $sgx[F_SOURCE] = $pfx[F_SOURCE];
+ $sgx[F_LOG] = $pfx[F_ENABLELOG];
+ $sgx[F_DESCRIPTION] = $pfx['description'];
+ $sgxml[F_ITEM][] = $sgx;
+ }
+ }
+ return $sgxml;
+}
+
+# -----------------------------------------------------------------
+# convert_pfxml_to_sgxml_destination
+# sgxml_destination: [name][domains][expr][urls][redir][desc][log]
+# -----------------------------------------------------------------
+function convert_pfxml_to_sgxml_destination($pfconfig) {
+ $sgxml = array();
+ $pfxml = $pfconfig['installedpackages'][MODULE_DESTINATION]['config'];
+ if (is_array($pfxml)) {
+ foreach($pfxml as $pfx) {
+ $sgx = array();
+ $sgx[F_NAME] = $pfx['name'];
+ $sgx[F_URLS] = $pfx['urls'];
+ $sgx[F_DOMAINS] = $pfx[F_DOMAINS];
+ $sgx[F_EXPRESSIONS] = $pfx['expressions'];
+ $sgx[F_RMOD] = isset($pfx[F_RMOD]) ? $pfx[F_RMOD] : RMOD_NONE;
+ $sgx[F_REDIRECT] = $pfx[F_REDIRECT];
+ $sgx[F_DESCRIPTION] = $pfx['description'];
+ $sgx[F_LOG] = $pfx[F_ENABLELOG];
+ $sgxml[F_ITEM][] = $sgx;
+ }
+ }
+ return $sgxml;
+}
+
+# -----------------------------------------------------------------
+# convert_pfxml_to_sgxml_rewrite
+# sgxml_rewrite: [name][desc][log][items(array): [targeturl][replaceto]]
+# -----------------------------------------------------------------
+function convert_pfxml_to_sgxml_rewrite($pfconfig) {
+ $sgxml = array();
+
+ $pfxml = $pfconfig['installedpackages'][MODULE_REWRITE]['config'];
+ if (is_array($pfxml)) {
+ foreach($pfxml as $pfx) {
+ $sgx = array();
+ $sgx[F_NAME] = $pfx['name'];
+ $sgx[F_DESCRIPTION] = $pfx['description'];
+ $sgx[F_LOG] = $pfx[F_ENABLELOG];
+
+ if (is_array($pfx['row'])) {
+ foreach($pfx['row'] as $pfx_row) {
+ $sgx_row = array();
+ $sgx_row[F_TARGETURL] = $pfx_row['targeturl'];
+ $sgx_row[F_REPLACETO] = $pfx_row['replaceto'];
+
+ $mode = '';
+ if (strpos($pfx_row[F_MODE], 'nocase') !== false) $mode .= 'i';
+ if (strpos($pfx_row[F_MODE], 'redirect') !== false) $mode .= 'r';
+ $sgx_row[F_MODE] = $mode; # ! sys options only - not for GUI !
+
+ $sgx[F_ITEM][] = $sgx_row;
+ }
+ }
+
+ $sgxml[F_ITEM][] = $sgx;
+ }
+ }
+
+ # additional: google safeserach
+ $sgxml[F_ITEM][] = squidguard_adt_rewrite_safesrch();
+
+ return $sgxml;
+}
+
+# -----------------------------------------------------------------
+# convert_pfxml_to_sgxml_time
+# sgxml_time: [name][desc][items(array): [timetype][timedays][daterange][timerange]]
+# -----------------------------------------------------------------
+function convert_pfxml_to_sgxml_time($pfconfig) {
+ $sgxml = array();
+
+ $pfxml = $pfconfig['installedpackages'][MODULE_TIME]['config'];
+ if (is_array($pfxml)) {
+ foreach($pfxml as $pfx) {
+ $sgx = array();
+ $sgx[F_NAME] = $pfx[F_NAME];
+ $sgx[F_DESCRIPTION] = $pfx[F_DESCRIPTION];
+
+ if (is_array($pfx['row'])) {
+ foreach($pfx['row'] as $pfx_row) {
+ $sgx_row = array();
+ $sgx_row[F_TIMETYPE] = $pfx_row[F_TIMETYPE];
+ $sgx_row[F_TIMEDAYS] = $pfx_row[F_TIMEDAYS];
+ $sgx_row[F_DATERANGE] = $pfx_row[F_DATERANGE];
+ $sgx_row[F_TIMERANGE] = $pfx_row[F_TIMERANGE];
+ $sgx[F_ITEM][] = $sgx_row;
+ }
+ }
+
+ $sgxml[F_ITEM][] = $sgx;
+ }
+ }
+
+ return $sgxml;
+}
+
+# -----------------------------------------------------------------
+# convert_pfxml_to_sgxml_acl
+# sgxml_acl: [name][desc][disabled][timename][destname][redirect][rewritename][over_redirect][over_rewritename]
+# -----------------------------------------------------------------
+function convert_pfxml_to_sgxml_acl($pfconfig) {
+ $sgxml = array();
+
+ $pfxml = $pfconfig['installedpackages'][MODULE_ACL]['config'];
+ if (is_array($pfxml)) {
+ foreach($pfxml as $pfx) {
+ $sgx = array();
+ $sgx[F_NAME] = $pfx[F_NAME]; # [04-01-2008] new ver
+ $sgx[F_DESCRIPTION] = $pfx[F_DESCRIPTION];
+ $sgx[F_DISABLED] = $pfx[F_DISABLED];
+ $sgx[F_TIMENAME] = $pfx[F_TIME];
+ $sgx[F_REDIRECT] = $pfx[F_REDIRECT];
+ $sgx[F_RMOD] = isset($pfx[F_RMOD]) ? $pfx[F_RMOD] : RMOD_NONE;
+ $sgx[F_REWRITENAME] = $pfx[F_REWRITE];
+ $sgx[F_LOG] = $pfx[F_ENABLELOG];
+ $sgx[F_NOTALLOWINGIP] = $pfx[F_NOTALLOWINGIP];
+ $sgx[F_ORDER] = $pfx[F_ORDER];
+
+ # for overtime
+ $sgx[F_OVERREDIRECT] = $pfx[F_REDIRECT]; # disabled ->- $pfx[F_OVERREDIRECT];
+ $sgx[F_OVERREWRITENAME] = $pfx[F_OVERREWRITE];
+
+ # destinations
+ if (strpos($pfx['dest'], '[') === false) {
+ $sgx[F_DESTINATIONNAME] = trim($pfx['dest']);
+ $sgx[F_OVERDESTINATIONNAME] = '';
+ }
+ else {
+ $sgx[F_DESTINATIONNAME] = trim( substr($pfx['dest'], 0, strpos($pfx['dest'], '[')) );
+ $sgx[F_OVERDESTINATIONNAME] = trim( strstr($pfx['dest'], '[') );
+ $sgx[F_OVERDESTINATIONNAME] = trim( str_replace(']', '', $sgx[F_OVERDESTINATIONNAME]) );
+ $sgx[F_OVERDESTINATIONNAME] = trim( str_replace('[', '', $sgx[F_OVERDESTINATIONNAME]) );
+ }
+
+ # !ATTENTION! '!all' must be convert to 'none'
+ $sgx[F_DESTINATIONNAME] = str_replace("!all", "none", $sgx[F_DESTINATIONNAME]);
+ $sgx[F_OVERDESTINATIONNAME] = str_replace("!all", "none", $sgx[F_OVERDESTINATIONNAME]);
+
+ # if empty - adding 'none'
+ if (!$sgx[F_DESTINATIONNAME]) $sgx[F_DESTINATIONNAME] = "none";
+ if (!$sgx[F_OVERDESTINATIONNAME]) $sgx[F_OVERDESTINATIONNAME] = "none";
+
+ # safesearch
+ if ($pfx[SAFESEARCH] === 'on') {
+ # assign safesearch rewrite
+ $sgx[F_REWRITENAME] = SAFESEARCH;
+ $sgx[F_OVERREWRITENAME] = SAFESEARCH;
+ }
+
+ $sgxml[F_ITEM][] = $sgx;
+ }
+ }
+ return $sgxml;
+}
+
+# -----------------------------------------------------------------
+# convert_pfxml_to_sgxml_default
+# sgxml_acl: [name][desc][disabled][timename][destname][redirect][rewritename][over_redirect][over_rewritename]
+# -----------------------------------------------------------------
+function convert_pfxml_to_sgxml_default($pfconfig) {
+ $pfxml = $pfconfig['installedpackages'][MODULE_DEFAULT]['config'];
+
+ $pfx = $pfxml[0];
+ $sgx = array();
+ $sgx[F_NAME] = 'default';
+ $sgx[F_DESCRIPTION] = '';
+ $sgx[F_DISABLED] = '';
+ $sgx[F_TIMENAME] = $pfx[F_TIME];
+ $sgx[F_RMOD] = isset($pfx[F_RMOD]) ? $pfx[F_RMOD] : RMOD_INT_ERRORPAGE;
+ $sgx[F_REDIRECT] = $pfx[F_REDIRECT];
+ $sgx[F_REWRITENAME] = $pfx[F_REWRITE];
+ $sgx[F_LOG] = $pfx[F_ENABLELOG];
+ $sgx[F_NOTALLOWINGIP] = $pfx[F_NOTALLOWINGIP];
+
+ # destinations
+ if (strpos($pfx['dest'], '[') === false)
+ $sgx[F_DESTINATIONNAME] = trim($pfx['dest']);
+ else $sgx[F_DESTINATIONNAME] = trim( substr($pfx['dest'], 0, strpos($pfx['dest'], '[')) );
+
+ # !ATTENTION! '!all' must be convert to 'none'
+ $sgx[F_DESTINATIONNAME] = str_replace("!all", "none", $sgx[F_DESTINATIONNAME]);
+
+ # if empty - adding 'none'
+ if (!$sgx[F_DESTINATIONNAME]) $sgx[F_DESTINATIONNAME] = "none";
+
+ # safesearch
+ if ($pfx[SAFESEARCH] === 'on') {
+ # assign safesearch rewrite
+ $sgx[F_REWRITENAME] = SAFESEARCH;
+ }
+
+ return $sgx;
+}
+
+# =================================================================
+# Capability
+# =================================================================
+# convert old ver. squidguard config.
+function capability_update_source() {
+ # ! use global var $config ONLY !
+ global $config;
+ $conf_changed = false;
+
+ if (isset($config['installedpackages'][MODULE_ACL]['config'])) {
+ $tconf = &$config['installedpackages'][MODULE_ACL]['config'];
+ foreach($tconf as $key => $cfg) {
+ if (isset($cfg['iplist'])) {
+ $tconf[$key][F_SOURCE] .= " " . $cfg['iplist'];
+ unset($tconf[$key]['iplist']);
+ $conf_changed = true;
+ }
+ if (isset($cfg[F_DOMAINS])) {
+ $tconf[$key][F_SOURCE] .= " " . $cfg[F_DOMAINS];
+ unset($tconf[$key][F_DOMAINS]);
+ $conf_changed = true;
+ }
+ }
+
+ if ($conf_changed) write_config('Convert old ver. squidguard config.');
+ }
+}
+# ------------------------------------------------------------------
+# get_item_id - get item 'id' from get/post
+# ------------------------------------------------------------------
+function get_item_id()
+{
+ return isset($_GET['id']) ? $_GET['id'] : $_POST['id'];
+}
+
+# ==================================================================
+# additional
+# ==================================================================
+# safesearch rewrite
+function squidguard_adt_rewrite_safesrch()
+{
+ $res = array();
+
+ # safesearch
+ $res[F_NAME] = SAFESEARCH;
+ $res[F_DESCRIPTION] = "Google, Yandex safesearch";
+ $res[F_LOG] = 'on';
+ squidguard_adt_safesrch_add(&$res[F_ITEM]);
+
+ return $res;
+}
+
+function squidguard_adt_safesrch_add($rewrite_item)
+{
+ if (!is_array($rewrite_item)) $rewrite_item = array();
+
+ # Google
+ $rewrite_item[] = array(F_TARGETURL => '(google\..*/search?.*q=.*)', F_REPLACETO => '\1\&safe=active', F_MODE => 'i');
+ $rewrite_item[] = array(F_TARGETURL => '(google\..*/images.*q=.*)', F_REPLACETO => '\1\&safe=active', F_MODE => 'i');
+ $rewrite_item[] = array(F_TARGETURL => '(google\..*/groups.*q=.*)', F_REPLACETO => '\1\&safe=active', F_MODE => 'i');
+ $rewrite_item[] = array(F_TARGETURL => '(google\..*/news.*q=.*)', F_REPLACETO => '\1\&safe=active', F_MODE => 'i');
+
+ # Yandex
+ $rewrite_item[] = array(F_TARGETURL => '(yandex\..*/yandsearch?.*text=.*)', F_REPLACETO => '\1\&fyandex=1', F_MODE => 'i');
+
+ # Yahoo
+ $rewrite_item[] = array(F_TARGETURL => '(search\.yahoo\..*/search.*p=.*)', F_REPLACETO => '\1\&vm=r', F_MODE => 'i');
+
+ # MSN Live search
+ $rewrite_item[] = array(F_TARGETURL => '(search\.live\..*/.*q=.*)', F_REPLACETO => '\1\&adlt=strict', F_MODE => 'i');
+ $rewrite_item[] = array(F_TARGETURL => '(search\.msn\..*/.*q=.*)', F_REPLACETO => '\1\&adlt=strict', F_MODE => 'i');
+
+ return $rewrite_item;
+}
+?>
diff --git a/config/squidGuard/squidguard.xml b/config/squidGuard/squidguard.xml
new file mode 100644
index 00000000..b00e9ed8
--- /dev/null
+++ b/config/squidGuard/squidguard.xml
@@ -0,0 +1,164 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+
+ <name>squidguardgeneral</name>
+ <version>1.2.0_1</version>
+ <title>Proxy Content filter SquidGuard: General settings</title>
+ <include_file>/usr/local/pkg/squidguard.inc</include_file>
+
+ <!-- Installation -->
+ <menu>
+ <name>Proxy Content filter</name>
+ <tooltiptext>Modify the proxy server's filter settings</tooltiptext>
+ <section>Services</section>
+ <url>/pkg_edit.php?xml=squidguard.xml&amp;id=0</url>
+ </menu>
+
+ <tabs>
+ <tab>
+ <text>General settings</text>
+ <url>/pkg_edit.php?xml=squidguard.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Default</text>
+ <url>/pkg_edit.php?xml=squidguard_default.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>ACL</text>
+ <url>/pkg.php?xml=squidguard_acl.xml</url>
+ </tab>
+ <tab>
+ <text>Destinations</text>
+ <url>/pkg.php?xml=squidguard_dest.xml</url>
+ </tab>
+ <tab>
+ <text>Times</text>
+ <url>/pkg.php?xml=squidguard_time.xml</url>
+ </tab>
+ <tab>
+ <text>Rewrites</text>
+ <url>/pkg.php?xml=squidguard_rewr.xml</url>
+ </tab>
+ <tab>
+ <text>Log</text>
+ <url>/pkg_edit.php?xml=squidguard_log.xml</url>
+ </tab>
+ </tabs>
+
+ <service>
+ <name>squidGuard</name>
+ <description>Proxy server filter Service</description>
+ <executable>squidGuard</executable>
+ </service>
+
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.org/packages/config/squidGuard/squidguard.inc</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.org/packages/config/squidGuard/squidguard_configurator.inc</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.org/packages/config/squidGuard/squidguard_acl.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.org/packages/config/squidGuard/squidguard_default.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.org/packages/config/squidGuard/squidguard_dest.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.org/packages/config/squidGuard/squidguard_rewr.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.org/packages/config/squidGuard/squidguard_time.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.org/packages/config/squidGuard/squidguard_log.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.org/packages/config/squidGuard/sgerror.php</item>
+ </additional_files_needed>
+
+ <fields>
+ <field>
+ <fielddescr>Enable</fielddescr>
+ <fieldname>squidguard_enable</fieldname>
+ <description>Check this for enable squidGuard</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Blacklist</fielddescr>
+ <fieldname>blacklist</fieldname>
+ <description>Check this for enable blacklist</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Blacklist proxy</fielddescr>
+ <fieldname>blacklist_proxy</fieldname>
+ <description>
+ Blacklist upload proxy - enter here, or leave blank.
+ Format: host:[port login:pass] . Default proxy port 1080.
+ Example: '192.168.0.1:8080 user:pass'
+ </description>
+ <type>input</type>
+ <size>100</size>
+ </field>
+ <field>
+ <fielddescr>Blacklist URL</fielddescr>
+ <fieldname>blacklist_url</fieldname>
+ <description>Enter FTP, HTTP or LOCAL (pfSense) URL blacklist archive, or leave blank.</description>
+ <type>input</type>
+ <size>100</size>
+ </field>
+ <field>
+ <fielddescr>View GUI log</fielddescr>
+ <fieldname>view_gui_log</fieldname>
+ <description>Check this for view GUI log</description>
+ <type>checkbox</type>
+ </field>
+ </fields>
+ <custom_add_php_command/>
+ <custom_php_validation_command>
+ squidguard_validate(&amp;$_POST, &amp;$input_errors);
+ </custom_php_validation_command>
+ <custom_php_command_before_form>
+ squidguard_before_form(&amp;$pkg);
+ </custom_php_command_before_form>
+ <custom_php_after_form_command>
+ squidGuard_print_javascript();
+ </custom_php_after_form_command>
+ <custom_php_resync_config_command>
+ squidguard_resync();
+ </custom_php_resync_config_command>
+ <custom_php_install_command>
+ squidguard_install_command();
+ squidguard_resync();
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ squidguard_deinstall_command();
+ </custom_php_deinstall_command>
+</packagegui> \ No newline at end of file
diff --git a/config/squidGuard/squidguard_acl.xml b/config/squidGuard/squidguard_acl.xml
new file mode 100644
index 00000000..a71979a3
--- /dev/null
+++ b/config/squidGuard/squidguard_acl.xml
@@ -0,0 +1,278 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+
+ <name>squidguardacl</name>
+ <version>none</version>
+ <title>Proxy Content filter SquidGuard: Access Control List (ACL)</title>
+ <include_file>/usr/local/pkg/squidguard.inc</include_file>
+
+ <delete_string>A proxy server user has been deleted.</delete_string>
+ <addedit_string>A proxy server user has been created/modified.</addedit_string>
+
+ <tabs>
+ <tab>
+ <text>General settings</text>
+ <url>/pkg_edit.php?xml=squidguard.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Default</text>
+ <url>/pkg_edit.php?xml=squidguard_default.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>ACL</text>
+ <url>/pkg.php?xml=squidguard_acl.xml</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Destinations</text>
+ <url>/pkg.php?xml=squidguard_dest.xml</url>
+ </tab>
+ <tab>
+ <text>Times</text>
+ <url>/pkg.php?xml=squidguard_time.xml</url>
+ </tab>
+ <tab>
+ <text>Rewrites</text>
+ <url>/pkg.php?xml=squidguard_rewr.xml</url>
+ </tab>
+ <tab>
+ <text>Log</text>
+ <url>/pkg_edit.php?xml=squidguard_log.xml</url>
+ </tab>
+ </tabs>
+
+ <adddeleteeditpagefields>
+ <columnitem>
+ <fielddescr>Disabled</fielddescr>
+ <fieldname>disabled</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Name</fielddescr>
+ <fieldname>name</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Source</fielddescr>
+ <fieldname>source</fieldname>
+ </columnitem>
+ <!--columnitem>
+ <fielddescr>Destinations</fielddescr>
+ <fieldname>dest</fieldname>
+ </columnitem-->
+ <columnitem>
+ <fielddescr>Time</fielddescr>
+ <fieldname>time</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Description</fielddescr>
+ <fieldname>description</fieldname>
+ </columnitem>
+ </adddeleteeditpagefields>
+
+ <fields>
+ <field>
+ <fielddescr>Disabled</fielddescr>
+ <fieldname>disabled</fieldname>
+ <description>Check this for disable this ACL rule.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Name</fielddescr>
+ <fieldname>name</fieldname>
+ <description>
+ Enter the unique name here.
+ Name must consist of minimum 2 symbols, first from which letter. &lt;br&gt;
+ All other symbols must be [a-Z_0-9].
+ </description>
+ <type>input</type>
+ <required/>
+ <size>100</size>
+ </field>
+ <field>
+ <fielddescr>Order</fielddescr>
+ <fieldname>order</fieldname>
+ <description>
+ Select the new position for ACL item. ACL are evaluated on a first-match source basis.&lt;br&gt;
+ &lt;b&gt;Note:&lt;/b&gt; &lt;br&gt;
+ Search for a suitable ACL by field 'source' will occur before the first match. If you want to define an exception for some sources (IP) from the IP range, put them on first of the list. &lt;br&gt;
+ &lt;b&gt;For example:&lt;/b&gt; &lt;br&gt;
+ ACL with single (or short range) source ip 10.0.0.15, must be placed before ACL with more large ip range 10.0.0.0/24 &lt;br&gt;
+ </description>
+ <type>select</type>
+ </field>
+ <field>
+ <fielddescr>Source IP adresses and domains</fielddescr>
+ <fieldname>source</fieldname>
+ <description>
+ Enter source IP address or domain or "username" here. For separate use space.
+ &lt;br&gt;&lt;b&gt;Example:&lt;/b&gt;
+ &lt;br&gt;ip: 192.168.0.1 or subnet 192.168.0.0/24 or subnet 192.168.1.0/255.255.255.0 or range 192.168.1.1-192.168.1.10
+ &lt;br&gt;domain: foo.bar match foo.bar or *.foo.bar
+ &lt;br&gt;username: 'user1'
+ </description>
+ <type>textarea</type>
+ <cols>65</cols>
+ <rows>3</rows>
+ <required/>
+ </field>
+ <!--field>
+ <fielddescr>Source IP addresses</fielddescr>
+ <fieldname>iplist</fieldname>
+ <description>
+ Enter source IP addresses here with space(' ') divider.
+ IP addresses must have format:&lt;br&gt;
+ single example: '192.168.0.1' &lt;br&gt;
+ range examples: '192.168.0.0/24', '192.168.1.0/255.255.255.0', '192.168.1.1-192.168.1.10'
+ </description>
+ <type>textarea</type>
+ <cols>65</cols>
+ <rows>3</rows>
+ </field>
+ <field>
+ <fielddescr>Source Domains</fielddescr>
+ <fieldname>domains</fieldname>
+ <description>
+ Enter source domains names here with space(' ') divider.
+ Example: &lt;b&gt;'foo.bar'&lt;/b&gt; match &lt;b&gt;'foo.bar'&lt;/b&gt; or &lt;b&gt;'*.foo.bar'&lt;/b&gt;.
+ </description>
+ <type>textarea</type>
+ <cols>65</cols>
+ <rows>3</rows>
+ </field-->
+ <field>
+ <fielddescr>Time</fielddescr>
+ <fieldname>time</fieldname>
+ <description>Enter time name in current which this rule permitted.</description>
+ <type>select</type>
+ </field>
+ <field>
+ <fielddescr>Destination</fielddescr>
+ <fieldname>dest</fieldname>
+ <description></description>
+ <type>input</type>
+ <size>100</size>
+ </field>
+ <field>
+ <fielddescr>Not to allow IP addresses in URL</fielddescr>
+ <fieldname>notallowingip</fieldname>
+ <description>
+ To make sure that people don't bypass the URL filter.
+ by simply using the IP addresses instead of the fully qualified domain names, you can check this option.
+ </description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Redirect mode</fielddescr>
+ <fieldname>redirect_mode</fieldname>
+ <description>
+ Select redirect mode here.
+ &lt;br&gt; Note: if you use 'transparent proxy', then 'int' redirect mode will not accessible.
+<!-- &lt;br&gt;&lt;b&gt; int size limit :&lt;/b&gt; if content size 0 or > 'size limit', then client moved to 'blank image' page; -->
+ &lt;br&gt; Options:
+ &lt;A title="To 'url' will added special client information;" &gt;
+ &lt;span style="background-color: #dddddd;" &gt;ext url err page&lt;/span&gt;&lt;/A&gt; ,
+ &lt;A title="Client view 'url' content without any notification about;" &gt;
+ &lt;span style="background-color: #dddddd;" &gt; ext url redirect&lt;/span&gt;&lt;/A&gt; ,
+ &lt;A title="Client will moved to specified url with displaying url in addres bar;" &gt;
+ &lt;span style="background-color: #dddddd;" &gt; ext url as 'move'&lt;/span&gt;&lt;/A&gt; ,
+ &lt;A title="Client will moved to specified url with showing progress(only!) in status bar;" &gt;
+ &lt;span style="background-color: #dddddd;" &gt; ext url as 'found'.&lt;/span&gt;&lt;/A&gt;
+ &lt;/u&gt;
+ </description>
+ <type>select</type>
+ <value>rmod_none</value>
+ <options>
+ <option><name>none</name> <value>rmod_none</value></option>
+ <option><name>int error page (enter error message)</name> <value>rmod_int</value></option>
+ <option><name>int blank page </name> <value>rmod_int_bpg</value></option>
+<!-- <option><name>int blank image</name> <value>rmod_int_bim</value></option> -->
+<!-- <option><name>int size limit (enter size in bytes)</name> <value>rmod_int_szl</value></option> -->
+ <option><name>ext url err page (enter URL)</name> <value>rmod_ext_err</value></option>
+ <option><name>ext url redirect (enter URL)</name> <value>rmod_ext_rdr</value></option>
+ <option><name>ext url move (enter URL)</name> <value>rmod_ext_mov</value></option>
+ <option><name>ext url found (enter URL)</name> <value>rmod_ext_fnd</value></option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Redirect</fielddescr>
+ <fieldname>redirect</fieldname>
+ <description>
+ Enter external redirection URL, error message or size (bytes) here.
+ </description>
+ <type>textarea</type>
+ <cols>65</cols>
+ <rows>2</rows>
+ </field>
+<!-- not need now
+ <field>
+ <fielddescr>Overtime redirect</fielddescr>
+ <fieldname>overredirect</fieldname>
+ <description>
+ Enter external redirection URL, error message or size (bytes) here.
+ </description>
+ <type>textarea</type>
+ <cols>65</cols>
+ <rows>2</rows>
+ </field>
+-->
+ <field>
+ <fielddescr>Spec: Use safe search engine</fielddescr>
+ <fieldname>safesearch</fieldname>
+ <description>
+ To protect your children from adult content, you can use the protected mode of search engines.
+ Now it is supported by Google, Yandex, Yahoo, MSN, Live Search. Make sure that the search engines can, and others, it is recommended to prohibit.
+ &lt;br&gt;Note: ! This option overrides 'Rewrite' setting. !
+ </description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Rewrite</fielddescr>
+ <fieldname>rewrite</fieldname>
+ <description>Enter rewrite condition name for this rule, or leave blank.</description>
+ <type>select</type>
+ </field>
+ <field>
+ <fielddescr>Overtime rewrite</fielddescr>
+ <fieldname>overrewrite</fieldname>
+ <description>Enter rewrite condition name for this rule, or leave blank.</description>
+ <type>select</type>
+ </field>
+ <field>
+ <fielddescr>Description</fielddescr>
+ <fieldname>description</fieldname>
+ <description>You may enter a description here for your reference (not parsed).</description>
+ <type>input</type>
+ <size>100</size>
+ </field>
+ <field>
+ <fielddescr>Enable log</fielddescr>
+ <fieldname>enablelog</fieldname>
+ <description>Check this for enable log.</description>
+ <type>checkbox</type>
+ </field>
+ </fields>
+
+ <custom_php_validation_command>
+ squidguard_validate_acl(&amp;$_POST, &amp;$input_errors);
+ </custom_php_validation_command>
+ <custom_php_command_before_form>
+ squidguard_before_form_acl(&amp;$pkg);
+ </custom_php_command_before_form>
+ <custom_php_after_form_command>
+ squidGuard_print_javascript();
+ </custom_php_after_form_command>
+ <custom_php_resync_config_command>
+ squidguard_resync_acl();
+ </custom_php_resync_config_command>
+ <custom_delete_php_command>
+ squidguard_resync_acl();
+ </custom_delete_php_command>
+ <custom_add_php_command>
+ </custom_add_php_command>
+ <custom_add_php_command_late>
+ </custom_add_php_command_late>
+</packagegui> \ No newline at end of file
diff --git a/config/squidGuard/squidguard_configurator.inc b/config/squidGuard/squidguard_configurator.inc
new file mode 100644
index 00000000..f683a19c
--- /dev/null
+++ b/config/squidGuard/squidguard_configurator.inc
@@ -0,0 +1,2106 @@
+<?php
+# ------------------------------------------------------------------------------
+/* squidguard_configurator.inc
+ (C)2006-2008 Serg Dvoriancev
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+# ------------------------------------------------------------------------------
+# SquidGuard Configurator
+# email: dv_serg@mail.ru
+# ------------------------------------------------------------------------------
+# squidGuard inline options:
+# squidGuard -C all - update database
+# squidGuard -c <configfile> - create squidGuard with specified config file
+# ------------------------------------------------------------------------------
+# Notes:
+# for work squidGuard need present ALL destinations;
+# if dest not present in config - then this item will ignored in operations
+# (in rebuild DB for example)
+# ------------------------------------------------------------------------------
+# Directories:
+# work path - $workdir
+# log path - $workdir + $logdir
+# ------------------------------------------------------------------------------
+
+require_once('globals.inc');
+require_once('config.inc');
+require_once('util.inc');
+require_once('pfsense-utils.inc');
+require_once('pkg-utils.inc');
+require_once('filter.inc');
+require_once('service-utils.inc');
+require_once('squid.inc');
+
+/* Allow additional execution time 0 = no limit. */
+ini_set('max_execution_time', '3600');
+ini_set('max_input_time', '3600');
+ini_set('memory_limit', '32M');
+
+# ------------------------------------------------------------------------------
+# files header
+# ------------------------------------------------------------------------------
+define('FILES_DB_HEADER', '
+# ------------------------------------------------------------------------------
+# File created by squidGuard package GUI
+# (C)2006-2008 Serg Dvoriancev
+# ------------------------------------------------------------------------------
+');
+
+define('CONFIG_SG_HEADER', "
+# ============================================================
+# SquidGuard configuration file
+# This file generated automaticly with SquidGuard configurator
+# (C)2006 Serg Dvoriancev
+# email: dv_serg@mail.ru
+# ============================================================
+");
+
+define('ACL_WARNING_ABSENSE_PASS', "!WARNING! Absence PASS 'all' or 'none' added as 'none'");
+
+# ------------------------------------------------------------------------------
+# squid config options
+# ------------------------------------------------------------------------------
+define('REDIRECTOR_OPTIONS_REM', '# squidGuard options');
+define('REDIRECTOR_PROGRAM_OPT', 'redirect_program');
+define('REDIRECT_BYPASS_OPT', 'redirector_bypass');
+define('REDIRECT_CHILDREN_OPT', 'redirect_children');
+
+# ------------------------------------------------------------------------------
+# setup count redirector processes will started
+# * for big count users service increase this option, but you need use this on powerful system
+# ------------------------------------------------------------------------------
+define('REDIRECTOR_PROCESS_COUNT', '3');
+
+# ------------------------------------------------------------------------------
+# squidguard config options
+# ------------------------------------------------------------------------------
+# define default redirection url (redirector get this url for all blocked url's)
+# * !ATTENTION! this url must be exists; IF url not exist, redirector will't block
+# (returned to squid some url, what blocked)
+# ------------------------------------------------------------------------------
+define('REDIRECT_BASE_URL', '/sgerror.php');
+define('REDIRECT_URL_ARGS', '&a=%a&n=%n&i=%i&s=%s&t=%t&u=%u');
+
+# ------------------------------------------------------------------------------
+# squidguard system defines
+# ------------------------------------------------------------------------------
+define('SQUID_CONFIGFILE', '/usr/local/etc/squid/squid.conf');
+define('TMP_DIR', '/var/tmp');
+
+define('SQUIDGUARD_CONFIGFILE', '/squidGuard.conf');
+define('SQUIDGUARDCONF_LOGFILE', '/sg_configurator.log');
+define('SQUIDGUARD_ACCESSBLOCK_FILE', 'block.log');
+define('SQUIDGUARD_CONFBASE_DEF', '/usr/local/etc/squid');
+define('SQUIDGUARD_LOGDIR_DEF', '/tmp');
+define('SQUIDGUARD_WORKDIR_DEF', '/usr/local/etc/squidGuard');
+define('SQUIDGUARD_BINPATH_DEF', '/usr/local/bin');
+define('SQUIDGUARD_TMP', '/var/tmp/squidGuard'); # SG temp
+define('SQUIDGUARD_VAR', '/var/squidGuard'); # SG variables
+define('SQUIDGUARD_STATE', '/squidGuard.state');
+define('SQUIDGUARD_REBUILD', '/squidGuard.rebuild');
+
+# DB home catalog contains 'Blacklist' and 'User' sub-catalogs
+define('SQUIDGUARD_DBHOME_DEF', '/var/db/squidGuard');
+define('SQUIDGUARD_DB_BLACKLIST', '/bl');
+define('SQUIDGUARD_DB_USER', '/usr');
+define('SQUIDGUARD_BL_UNPACK', '/unpack');
+define('SQUIDGUARD_BL_DB', '/db');
+
+# DB/Blacklist defines
+define('SQUIDGUARD_BLK_ENTRIES', '/blacklist.files');
+define('BLACKLIST_ARCHIVE', '/blacklists.tar');
+define('BLK_LOCALFILE', '/tmp/sg_blacklists.tar');
+define('DB_REBUILD_SH', '/tmp/squidGuard_db_rebuild.sh');
+define('DB_REBUILD_CONF', '/tmp/squidGuard_db_rebuild.conf');
+define('DB_REBUILD_BLK_CONF', '/squidGuard_blk_rebuild.conf');
+define('BLK_TEMP', '/tmp/sg_blk');
+define('SG_BLK_ARC', '/arcdb'); # blk db archive
+define('SG_INFO_FILE', '/var/squidGuard/sg_db_upd.inf');
+
+# error_res
+define('SG_ERR0', "Error! Check squidGuard configuration data.");
+
+# redirect mode
+define('RMOD_NONE', 'rmod_none');
+define('RMOD_INT_ERRORPAGE', 'rmod_int');
+define('RMOD_INT_BLANKPAGE', 'rmod_int_bpg');
+define('RMOD_INT_BLANKIMG', 'rmod_int_bim');
+define('RMOD_INT_SIZELIMIT', 'rmod_int_szl');
+define('RMOD_EXT_ERR', 'rmod_ext_err');
+define('RMOD_EXT_RDR', 'rmod_ext_rdr');
+define('RMOD_EXT_MOVED', 'rmod_ext_mov');
+define('RMOD_EXT_FOUND', 'rmod_ext_fnd');
+
+# GUI options
+define('SQUIDGUARD_LOG_MAXCOUNT', 500); # max log lines
+
+# 0-all, 1-medium; 2-low
+define('SQUIDGUARD_LOG_LEVEL', 0);
+
+#
+define('FLT_DEFAULT_ALL', 'all');
+define('FLT_NOTALLOWIP', '!in-addr');
+
+# owner user name (squid system user - need for define rights access)
+define('OWNER_NAME', 'proxy');
+
+# Debug
+define('DEBUG_ON', 'true');
+
+# ==============================================================================
+# black list
+# ==============================================================================
+# known black list standard names
+# ------------------------------------------------------------------------------
+define('FLT_AD', 'ads');
+define('FLT_AGGRESSIVE', 'aggressive');
+define('FLT_AUDIOVIDEO', 'audio-video');
+define('FLT_DRUGGS', 'druggs');
+define('FLT_GAMBLING', 'gambling');
+define('FLT_HACKING', 'hacking');
+define('FLT_MAIL', 'mail');
+define('FLT_PORN', 'porn');
+define('FLT_PROXY', 'proxy');
+define('FLT_VIOLENCE', 'viol');
+define('FLT_WAREZ', 'warez');
+
+# ==============================================================================
+# SquidGuard Configurator
+# ==============================================================================
+$squidguard_config = array(); # squidGuard config array
+
+# call default init
+sg_init();
+
+# ------------------------------------------------------------------------------
+# squidguard system fields
+# ------------------------------------------------------------------------------
+define('F_SQUIDGUARD', 'squidGuard');
+define('F_LOGDIR', 'logdir');
+define('F_DBHOME', 'dbhome');
+define('F_WORKDIR', 'workdir');
+define('F_BINPATH', 'binpath');
+define('F_PROCCESSCOUNT', 'process_count');
+define('F_SQUIDCONFIGFILE', 'squid_configfile');
+define('F_ENABLED', 'enabled');
+define('F_BLACKLISTENABLED', 'blacklist_enabled');
+define('F_SGCONF_XML', 'sgxml_file');
+
+# other fields
+define('F_ITEM', 'item');
+define('F_TIMES', 'times');
+define('F_SOURCES', 'sources');
+define('F_DESTINATIONS', 'destinations');
+define('F_REWRITES', 'rewrites');
+define('F_ACLS', 'acls');
+define('F_DEFAULT', 'default');
+define('F_NAME', 'name');
+define('F_DESCRIPTION', 'description');
+define('F_IP', 'ip');
+define('F_URLS', 'urls');
+define('F_DOMAINS', 'domains');
+define('F_EXPRESSIONS', 'expressions');
+define('F_REDIRECT', 'redirect');
+define('F_TARGETURL', 'targeturl');
+define('F_REPLACETO', 'replaceto');
+define('F_LOG', 'log');
+define('F_ITEM', 'item');
+define('F_DISABLED', 'disabled');
+define('F_TIMENAME', 'timename');
+define('F_DESTINATIONNAME', 'destname');
+define('F_REDIRECT', 'redirect');
+define('F_REWRITE', 'rewrite');
+define('F_MODE', 'mode');
+define('F_REWRITENAME', 'rewritename');
+define('F_OVERDESTINATIONNAME', 'overdestname');
+define('F_OVERREDIRECT', 'overredirect');
+define('F_OVERREWRITE', 'overrewrite');
+define('F_OVERREWRITENAME', 'overrewritename');
+define('F_TIMETYPE', 'timetype');
+define('F_TIMEDAYS', 'timedays');
+define('F_DATRANGE', 'daterange');
+define('F_TIMERANGE', 'sg_timerange');
+define('F_RMOD', 'redirect_mode'); # [redirect_mode] = rmod_int <base- use sgerror.php>; rmod_301; rmod_302;
+define('F_NOTALLOWINGIP', 'notallowingip'); # not allowing ip in URL
+define('F_USERNAME', 'username');
+define('F_ORDER', 'order');
+
+# transparent mode
+define('F_SQUID_TRANSPARENT_MODE', 'squid_transparent_mode');
+define('F_CURRENT_LAN_IP', 'current_lan_ip');
+define('F_CURRENT_GUI_PORT', 'current_gui_port');
+define('F_CURRENT_GUI_PROTO', 'current_gui_protocol');
+
+# ------------------------------------------------------------------------------
+# sg_init - initialize config array
+# ------------------------------------------------------------------------------
+function sg_init($init = '')
+{
+ global $squidguard_config;
+
+ $squidguard_config = array();
+ if(empty($init) or !is_array($init) ) {
+ # default init (for generate minimal config)
+ $squidguard_config[F_LOGDIR] = SQUIDGUARD_LOGDIR_DEF;
+ $squidguard_config[F_DBHOME] = SQUIDGUARD_DBHOME_DEF;
+ $squidguard_config[F_WORKDIR] = SQUIDGUARD_WORKDIR_DEF;
+ $squidguard_config[F_BINPATH] = SQUIDGUARD_BINPATH_DEF;
+ $squidguard_config[F_SQUIDCONFIGFILE] = SQUID_CONFIGFILE;
+ $squidguard_config[F_PROCCESSCOUNT] = REDIRECTOR_PROCESS_COUNT;
+ } else {
+ $squidguard_config = $init;
+ }
+
+ return $squidguard_config;
+}
+
+# ------------------------------------------------------------------------------
+# sg_loadconfig_xml
+# ------------------------------------------------------------------------------
+function sg_load_configxml($filename)
+{
+ global $squidguard_config;
+
+ sg_init();
+ if (file_exists($filename)) {
+ $xmlconf = file_get_contents($filename);
+
+ if (!empty($xmlconf)) {
+ $squidguard_config = $xmlconf[F_SQUIDGUARD];
+ sg_addlog("sg_load_configxml: Success update from '$filename'.", 1);
+ } else
+ sg_addlog("sg_load_configxml: Error, file '$filename' is empty.", 2);
+ } else
+ sg_addlog("sg_load_configxml: Error, file '$filename' does not exists.", 2);
+}
+
+# ------------------------------------------------------------------------------
+# sg_saveconfig_xml
+# ------------------------------------------------------------------------------
+function sg_save_configxml($filename)
+{
+ global $squidguard_config;
+
+ file_put_contents($filename, dump_xml_config($squidguard_config, F_SQUIDGUARD));
+}
+
+# ------------------------------------------------------------------------------
+# sg_reconfigure - squidguard reconfiguration
+# ------------------------------------------------------------------------------
+function sg_reconfigure()
+{
+ global $squidguard_config;
+ $conf_file = SQUIDGUARD_LOGDIR_DEF . SQUIDGUARD_CONFIGFILE;
+
+ # 1. check system
+ sg_check_system();
+
+ # 2. reconfigure user db
+ sg_reconfigure_user_db();
+
+ # 3. generate squidGuard config
+ $conf = sg_create_config();
+ if ($conf) {
+ if ($squidguard_config[F_WORKDIR])
+ $conf_file = $squidguard_config[F_WORKDIR] . SQUIDGUARD_CONFIGFILE;
+ file_put_contents($conf_file, $conf);
+ file_put_contents('/usr/local/etc/squid' . SQUIDGUARD_CONFIGFILE, $conf); # << squidGuard want config '/usr/local/etc/squid' by default
+ set_file_access($squidguard_config[F_WORKDIR], OWNER_NAME, 0755);
+ sg_addlog("sg_reconfigure: save squidGuard config to '$conf_file'.", 1);
+ } else
+ sg_addlog("sg_reconfigure: error make squidGuard config.", 2);
+
+ # 4. reconfigure squid
+ squid_reconfigure();
+}
+
+# ------------------------------------------------------------------------------
+# squid_reconfigure
+# Insert in '/usr/local/squid/etc/squid.conf' options:
+# redirector_bypass on
+# redirect_program /usr/local/squidGuard/bin/squidGuard -c /path_to_config_file
+# redirect_children 1
+# ------------------------------------------------------------------------------
+
+function squid_reconfigure($remove_only = '')
+{
+ global $config;
+ global $squidguard_config;
+ $conf = '';
+ $cust_opt = $config['installedpackages']['squid']['config'][0]['custom_options'];
+
+ # remove old options
+ if (!empty($cust_opt)) {
+ $conf = explode(";", $cust_opt);
+ foreach ($conf as $key => $c_opt) {
+ $t_opt = ltrim($c_opt);
+ if ((strpos($t_opt, REDIRECTOR_PROGRAM_OPT) === 0) or
+ (strpos($t_opt, REDIRECT_BYPASS_OPT) === 0) or
+ (strpos($t_opt, REDIRECT_CHILDREN_OPT) === 0))
+ unset($conf[$key]);
+ }
+ sg_addlog("squid_reconfigure: Remove old redirector options from Squid config.", 1);
+ }
+
+ # add new options - if squidGuard enabled
+ if (empty($remove_only) && ($squidguard_config[F_ENABLED] === 'on')) {
+ $redirector_path = $squidguard_config[F_BINPATH] . '/squidGuard';
+ $redirector_conf = $squidguard_config[F_WORKDIR] . SQUIDGUARD_CONFIGFILE;
+
+ $conf[] = REDIRECTOR_PROGRAM_OPT . " $redirector_path -c $redirector_conf";
+ $conf[] = REDIRECT_BYPASS_OPT . " on";
+ $conf[] = REDIRECT_CHILDREN_OPT . " " . REDIRECTOR_PROCESS_COUNT;
+
+ sg_addlog("squid_reconfigure: Add new redirector options to Squid config.", 1);
+ }
+
+ # update config
+ if (is_array($conf)) $conf = implode(";", $conf);
+
+ $config['installedpackages']['squid']['config'][0]['custom_options'] = $conf;
+ write_config('Update redirector options to squid config.');
+
+ squid_resync();
+}
+
+# ------------------------------------------------------------------------------
+# sg_check_system - check squidguard catalog's and access right's
+# ------------------------------------------------------------------------------
+function sg_check_system()
+{
+ global $squidguard_config;
+
+ # check work_dir & create if not exists
+ $work_dir = $squidguard_config[F_WORKDIR];
+ if (!empty($work_dir)) {
+ # check dir's
+ if (!file_exists($work_dir)) {
+ mwexec("mkdir -p $work_dir");
+ set_file_access($work_dir, OWNER_NAME, 0755);
+ sg_addlog("sg_check_system: Create work dir '$work_dir'.", 1);
+ }
+ }
+ unset($work_dir);
+
+ # check log_dir & create if not exists
+ $log_dir = $squidguard_config[F_LOGDIR];
+ if (!empty($log_dir)) {
+ if (!file_exists($log_dir)) {
+ mwexec("mkdir -p $log_dir");
+ sg_addlog("sg_check_system: Create log dir '$log_dir'.", 1);
+ }
+ # set access right - need start any time;
+ # (SG possible start from console and log file will have only root access)
+ set_file_access($log_dir, OWNER_NAME, 0755);
+ }
+ unset($log_dir);
+
+ # check db dir
+ $db_dir = $squidguard_config[F_DBHOME];
+ if (!empty($db_dir)) {
+ if (!file_exists($db_dir)) {
+ mwexec("mkdir -p $db_dir");
+ sg_addlog("sg_check_system: Create db dir '$db_dir'.", 1);
+ }
+ # set access right
+ set_file_access($db_dir, OWNER_NAME, 0755);
+ }
+ unset($db_dir);
+}
+# ==============================================================================
+# squidGuard DB
+# ==============================================================================
+# sg_reconfigure_user_db - reconfigure(update) db user entries
+# ------------------------------------------------------------------------------
+function sg_reconfigure_user_db()
+{
+ global $squidguard_config;
+ $dbhome = $squidguard_config[F_DBHOME];
+
+ sg_addlog("sg_reconfigure_user_db: Begin with '$dbhome'", 1);
+
+ # create user DB catalog, if not extsts
+ if (!file_exists($dbhome)) {
+ if (!mkdir($dbhome, 0755)) {
+ sg_addlog("sg_reconfigure_user_db: Error create user DB directory '$dbhome'.", 2);
+ return;
+ }
+ set_file_access($dbhome, OWNER_NAME, 0755);
+ sg_addlog("sg_reconfigure_user_db: Create user DB directory '$dbhome'.", 1);
+ }
+
+ # update destinations to db
+ $dests = $squidguard_config[F_DESTINATIONS];
+ if(!empty($dests)){
+ $dst_names = Array();
+ $dst_list = Array();
+
+ sg_addlog("sg_reconfigure_user_db: Add user entries", 1);
+ foreach($dests[F_ITEM] as $dst) {
+ $path = "$dbhome/" . $dst[F_NAME];
+ $dst_names[] = $path;
+ $dst_list["usr_{$dst[F_NAME]}"] = $dst[F_NAME];
+
+ # 1. check destination catalog and create them, if need
+ if (!file_exists($path)) {
+ if (!mkdir ($path, 0755)) {
+ sg_addlog("sg_reconfigure_user_db: Error create dir '$path'.", 2);
+ return;
+ }
+ sg_addlog("sg_reconfigure_user_db: Create dir '$path'.", 1);
+ }
+
+ # 2. build domains file
+ $domains = $dst[F_DOMAINS];
+ if (!empty($domains)) {
+ $content = trim(str_replace(" ", "\n", $domains));
+ file_put_contents($path . '/domains', $content);
+ sg_addlog("sg_reconfigure_user_db: -- add {$dst[F_NAME]} domains '$domains';", 1);
+ }
+ unset($domains);
+
+ # 3. build urls file
+ $urls = $dst[F_URLS];
+ if (!empty($urls)) {
+ $content = trim(str_replace(" ", "\n", $urls));
+ file_put_contents($path . '/urls', $content);
+ sg_addlog("sg_reconfigure_user_db: -- add {$dst[F_NAME]} urls '$content';", 1);
+ }
+ unset($urls);
+
+ # 4. build expression file
+ $expr = $dst[F_EXPRESSIONS];
+ if (!empty($expr)) {
+ $content = trim(str_replace("|", " ", $expr)); # delete first and last unnecessary '|' symbol
+ $content = str_replace(" ", "|", $content);
+ file_put_contents($path . '/expressions', $content);
+ sg_addlog("sg_reconfigure_user_db: -- add {$dst[F_NAME]} expressions '$content';", 1);
+ }
+ unset($expr);
+ }
+
+ # 5. recursive set files access
+ set_file_access($dbhome, OWNER_NAME, 0755);
+
+ # 6. rebuild user db ('/var/db/squidGuard')
+ sg_rebuild_db("_usrdb", $dbhome, $dst_list);
+ } else
+ sg_addlog("sg_reconfigure_user_db: Nothing. User destinations list empty.", 2);
+
+ # 7. remove unused db entries
+ sg_remove_unused_db_entries();
+}
+
+# ------------------------------------------------------------------------------
+# sg_remove_unused_db_entries
+# ------------------------------------------------------------------------------
+function sg_remove_unused_db_entries()
+{
+ global $squidguard_config;
+ $db_entries = array();
+ $file_list = '';
+ $dbhome = $squidguard_config[F_DBHOME];
+ $workdir = $squidguard_config[F_WORKDIR];
+
+ # black list entries
+ # * worked only with 'blacklist entries list file - else may be deleted black list entry
+ if (file_exists($workdir . SQUIDGUARD_BLK_ENTRIES)) {
+ $file_for_del = array();
+
+ # load blk entries
+ $db_entries = explode("\n", file_get_contents($workdir . SQUIDGUARD_BLK_ENTRIES));
+
+ # $db_entries + add user entries
+ $dests = $squidguard_config[F_DESTINATIONS];
+ if (!empty($dests)) {
+ foreach($dests[F_ITEM] as $dst)
+ $db_entries[] = $dst[F_NAME];
+ }
+
+ # diff between file list and entries list
+ $file_list = scan_dir($dbhome);
+ if (is_array($file_list) and is_array($db_entries)) {
+ $file_for_del = array_diff($file_list, $db_entries);
+ }
+
+ # delete
+ if (is_array($file_for_del) and !empty($file_for_del)) {
+ foreach($file_for_del as $fd) {
+ $file_fd = "$dbhome/$fd";
+ if (!empty($fd) && ($fd != ".") && ($fd != "..")) {
+ if (file_exists($file_fd)) {
+ mwexec("rm -R $file_fd");
+ sg_addlog("sg_remove_unused_db_entries: Removed file '$file_fd'.", 1);
+ } else
+ sg_addlog("sg_remove_unused_db_entries: File'$file_fd' not found.", 2);
+ }
+ }
+ }
+ }
+}
+# ------------------------------------------------------------------------------
+# sg_rebuild_db Rebuild squidGuard DB from list items
+# ------------------------------------------------------------------------------
+# $shtag - rebuild SH script TAG
+# $rdb_dbhome - DB directory (default: '/var/db/squidGuard')
+# $rdb_itemslist - items list as ['dest_key']='dest_DB_path'
+# dest_DB_path - path without '$rdb_dbhome'
+# example: ['ads_ban']='ads/banners' -> '/var/db/squidGuard/ads/banners'
+# ------------------------------------------------------------------------------
+function sg_rebuild_db($shtag, $rdb_dbhome, $rdb_itemslist)
+{
+ global $squidguard_config;
+ $conf = '';
+ $conf_path = '';
+ $logdir = $squidguard_config[F_LOGDIR];
+ $dbhome = $squidguard_config[F_DBHOME];
+
+ # current dbhome dir
+ if (!empty($rdb_dbhome)) $dbhome = $rdb_dbhome;
+ sg_addlog("sg_rebuild_db: Begin with path '$dbhome'.", 1);
+
+ # define - where config will placed
+ $conf_path = "/tmp/squidGuard_rebuild.conf" . $shtag;
+
+ # make rebuild config; include all found dest items
+ $conf = sg_create_simple_config($dbhome, $rdb_itemslist);
+ file_put_contents($conf_path, $conf);
+ set_file_access($conf_path, OWNER_NAME, 0750);
+ sg_addlog("sg_rebuild_db: Create temporary config '$conf_path'.", 1);
+
+ # *** SH script ***
+ $sh_scr = Array();
+ $sh_scr[] = "#!/bin/sh";
+ $sh_scr[] = "cd $dbhome";
+ $sh_scr[] = $squidguard_config[F_BINPATH] . "/squidGuard -c $conf_path -C all";
+ $sh_scr[] = "wait"; # wait while SG rebuild DB
+
+ # set DB owner and right access
+ $sh_scr[] = "chown -R -v " . OWNER_NAME . " $dbhome";
+
+ # restart squid for changes to take effects
+ $sh_scr[] = "/usr/local/sbin/squid -k reconfigure";
+
+ # store & exec sh
+ $sh_scr = implode("\n", $sh_scr);
+ $shfile = DB_REBUILD_SH . $shtag;
+ file_put_contents($shfile, $sh_scr);
+ set_file_access($shfile, OWNER_NAME, 0750);
+ # ! not background exec !
+ mwexec($shfile);
+ sg_addlog("sg_rebuild_db: Started SH script '$shfile'.", 1);
+}
+
+# ==============================================================================
+# Log
+# ------------------------------------------------------------------------------
+# sg_addlog
+# ------------------------------------------------------------------------------
+function sg_addlog($log, $level = 0)
+{
+ global $squidguard_config;
+
+ # log level
+ if ($level < SQUIDGUARD_LOG_LEVEL) return;
+
+ $logfile = '';
+ $logfile = SQUIDGUARD_LOGDIR_DEF . SQUIDGUARDCONF_LOGFILE;
+ $log_content = array();
+
+ setlocale(LC_TIME, '');
+ $dt = date("d.m.Y H:i:s");
+
+ # define logfile
+ if (!empty($squidguard_config)) {
+ if (file_exists($squidguard_config[F_LOGDIR]))
+ $logfile = $squidguard_config[F_LOGDIR] . SQUIDGUARDCONF_LOGFILE;
+ } else
+ $log_content[] = "$dt : " . "sg_addlog: Error: squidguard_config is empty";
+
+ $tmplog = '';
+ if (file_exists($logfile))
+ $tmplog = file_get_contents($logfile);
+ $log_content = explode("\n", $tmplog);
+ unset($tmplog);
+
+ # shrink to MAXCOUNT log entries
+ $log_content[] = "$dt : $log";
+ if (count($log_content) > SQUIDGUARD_LOG_MAXCOUNT)
+ array_splice($log_content, 0, SQUIDGUARD_LOG_MAXCOUNT - count($log_content));
+
+ file_put_contents($logfile, implode("\n", $log_content));
+}
+# ------------------------------------------------------------------------------
+# sg_getlog
+# ------------------------------------------------------------------------------
+function sg_getlog($last_entries_count)
+{
+ global $squidguard_config;
+ $log_content = '';
+ $logfile = SQUIDGUARD_LOGDIR_DEF . SQUIDGUARDCONF_LOGFILE;
+
+ # define logfile
+ if (!empty($squidguard_config) && file_exists($squidguard_config[F_LOGDIR]))
+ $logfile = $squidguard_config[F_LOGDIR] . SQUIDGUARDCONF_LOGFILE;
+
+ # get log last 100 entries
+ if (file_exists($logfile)) {
+ $log_content = explode("\n", file_get_contents($logfile));
+ if (count($log_content) > $last_entries_count)
+ array_splice($log_content, 0, $last_entries_count - count($log_content));
+
+ # insert log file name on top
+ $log_content[0] = $logfile;
+ $log_content = implode("\n", $log_content);
+ }
+
+ return $log_content;
+}
+
+# ==============================================================================
+# make config
+# ==============================================================================
+# sg_create_config
+# ------------------------------------------------------------------------------
+
+function sg_create_config()
+{
+ global $squidguard_config;
+ $sgconf = array();
+ $sg_tag = new TSgTag;
+ $error_res = '';
+ $temp_str = '';
+
+ if(!is_array($squidguard_config) || empty($squidguard_config)) {
+ sg_addlog("sg_create_config: Error squidguard config data.", 2);
+ return sg_create_simple_config('', '', SG_ERR0 . " (sg_create_config: [1]).");
+ }
+
+ # check configuration data
+ if (!sg_check_config_data(&$error_res)) {
+ sg_addlog("sg_create_config: Error config data. It's all error_res: \n$error_res", 2);
+ sg_addlog("sg_create_config: Terminated.", 2);
+ return sg_create_simple_config('', '', SG_ERR0 . " (sg_create_config: [2]).");
+ }
+
+ # --- Header ---
+ $sgconf[] = CONFIG_SG_HEADER;
+ $sgconf[] = "logdir {$squidguard_config[F_LOGDIR]}";
+ $sgconf[] = "dbhome {$squidguard_config[F_DBHOME]}";
+
+ # --- Times ---
+ if ($squidguard_config[F_TIMES]) {
+ $temp_str = '';
+ foreach($squidguard_config[F_TIMES][F_ITEM] as $tm) {
+ $sg_tag->clear();
+ $sg_tag->set("time", $tm[F_NAME], "", $tm[F_DESCRIPTION]);
+
+ foreach($tm[F_ITEM] as $itm) {
+ $dts = ($itm[F_TIMETYPE] === "weekly") ? $itm[F_TIMEDAYS] : $itm[F_DATERANGE];
+ $sg_tag->items[] = "{$itm[F_TIMETYPE]} $dts {$itm[F_TIMERANGE]}";
+ }
+ $sgconf[] = "";
+ $sgconf[] = $sg_tag->tag_text();
+
+ # log
+ $temp_str .= " {$tm[F_NAME]}";
+ }
+ # log
+ $temp_str = !empty($temp_str) ? $temp_str : "Nothing.";
+ sg_addlog("sg_create_config: add times: \n $temp_str", 1);
+ }
+
+ # --- Sources ---
+ if ($squidguard_config[F_SOURCES]) {
+ $temp_str = '';
+ foreach($squidguard_config[F_SOURCES][F_ITEM] as $src) {
+ $sg_tag->clear();
+ $sg_tag->set("src", $src[F_NAME], "", $src[F_DESCRIPTION]);
+
+ # separate IP, domains, usernames
+ $tsrc = explode(" ", trim($src[F_SOURCE]));
+ foreach($tsrc as $sr) {
+ $sr = trim($sr);
+ if (empty($sr)) continue;
+ if (is_ipaddr_valid($sr)) $sg_tag->items[] = "ip $sr";
+ elseif (is_domain_valid($sr)) $sg_tag->items[] = "domain $sr";
+ elseif (is_username($sr)) $sg_tag->items[] = "user " . str_replace("'", "", $sr);
+ }
+ if ($src[F_LOG]) $sg_tag->items[] = "log " . SQUIDGUARD_ACCESSBLOCK_FILE;
+
+ $sgconf[] = "";
+ $sgconf[] = $sg_tag->tag_text();
+
+ # log
+ $temp_str .= " " . $src[F_NAME];
+ }
+ # log
+ $temp_str = !empty($temp_str) ? $temp_str : "Nothing.";
+ sg_addlog("sg_create_config: add sources: \n $temp_str", 1);
+ }
+
+ # --- Blacklist ---
+ # Note! Blacklist must be added to config permanently. It's need for rebuild DB now
+
+ $db_entries = sg_entries_blacklist();
+ if (($squidguard_config[F_BLACKLISTENABLED] === 'on') and $db_entries) {
+ $log_entr_added = '';
+ $log_entr_ignored = '';
+ sg_addlog("sg_create_config: add blacklist entries", 1);
+ foreach($db_entries as $key => $ent) {
+ $ent_state = array();
+ $file_dms = "{$squidguard_config[F_DBHOME]}/$ent/domains";
+ $file_urls = "{$squidguard_config[F_DBHOME]}/$ent/urls";
+ $file_expr = "{$squidguard_config[F_DBHOME]}/$ent/expressions";
+
+ # check blacklist acl state
+ if (file_exists($file_dms)) {
+ $ent_state['exists'] = 'on';
+ $ent_state[F_DOMAINS] = 'on';
+ }
+ if (file_exists($file_urls)) {
+ $ent_state['exists'] = 'on';
+ $ent_state[F_URLS] = 'on';
+ }
+ if (file_exists($file_expr)) {
+ $ent_state['exists'] = 'on';
+ $ent_state[F_EXPRESSIONS] = 'on';
+ }
+
+ # create config if blacklist item exists
+ if ($ent_state['exists']) {
+ $sg_tag->clear();
+ $sg_tag->set("dest", $ent, "", "");
+
+ if ($ent_state[F_DOMAINS]) $sg_tag->items[] = "domainlist $ent/domains";
+ if ($ent_state[F_EXPRESSIONS]) $sg_tag->items[] = "expressionlist $ent/expressions";
+ if ($ent_state[F_URLS]) $sg_tag->items[] = "urllist $ent/urls";
+ $sg_tag->items[] = "log ". SQUIDGUARD_ACCESSBLOCK_FILE;
+
+ $sgconf[] = "";
+ $sgconf[] = $sg_tag->tag_text();
+
+ # log
+ $log_entr_added .= " $ent;";
+ } else {
+ $sgconf[] = "\t# Config ERROR: Destination '$ent' not found in DB";
+ $log_entr_ignored .= " $ent;";
+ }
+ }
+
+ # log 'added' and 'ignored'
+ if (!empty($log_entr_added)) sg_addlog("sg_create_config: added: \n $log_entr_added \n", 1);
+ if (!empty($log_entr_ignored)) sg_addlog("sg_create_config: ignored: \n $log_entr_ignored \n", 2);
+ }
+
+ # --- Destinations ---
+ if ($squidguard_config[F_DESTINATIONS]) {
+ $temp_str = '';
+ foreach($squidguard_config[F_DESTINATIONS][F_ITEM] as $dst) {
+ $dstname = $dst[F_NAME];
+ $sg_tag->clear();
+ $sg_tag->set("dest", $dst[F_NAME], "", $dst[F_DESCRIPTION]);
+
+ if ($dst[F_DOMAINS])
+ $sg_tag->items[] = "domainlist $dstname/domains";
+ if ($dst[F_EXPRESSIONS])
+ $sg_tag->items[] = "expressionlist $dstname/expressions";
+ if ($dst[F_URLS])
+ $sg_tag->items[] = "urllist $dstname/urls";
+ if ($dst[F_RMOD] != RMOD_NONE)
+ $sg_tag->items[] = "redirect " . sg_redirector_base_url($dst[F_REDIRECT], $dst[F_RMOD]);
+ if ($dst[F_LOG])
+ $sg_tag->items[] = "log " . SQUIDGUARD_ACCESSBLOCK_FILE;
+
+ $sgconf[] = "";
+ $sgconf[] = $sg_tag->tag_text();
+
+ # log
+ $temp_str .= " $dstname;";
+ }
+ # log
+ $temp_str = !empty($temp_str) ? $temp_str : "Nothing.";
+ sg_addlog("sg_create_config: add destinations: \n $temp_str", 1);
+ }
+
+ # --- Rewrites ---
+ if ($squidguard_config[F_REWRITES]) {
+ $temp_str = '';
+ $log_entr_added = '';
+ $log_entr_err = '';
+ foreach($squidguard_config[F_REWRITES][F_ITEM] as $rew) {
+ $sg_tag->clear();
+ $sg_tag->set("rew", $rew[F_NAME], "", "");
+
+ if (is_array($rew[F_ITEM])) {
+ foreach ($rew[F_ITEM] as $rw)
+ $sg_tag->items[] = "s@{$rw[F_TARGETURL]}@{$rw[F_REPLACETO]}@{$rw[F_MODE]}";
+
+ if ($rew[F_LOG])
+ $sg_tag->items[] = "log " . SQUIDGUARD_ACCESSBLOCK_FILE;
+
+ $sgconf[] = "";
+ $sgconf[] = $sg_tag->tag_text();
+ # log
+ $log_entr_added .= " {$rew[F_NAME]};";
+ }
+ else {
+ $sgconf[] = "";
+ $sgconf[] = "# Rewrite {$rew[F_NAME]} error.";
+ # log
+ $log_entr_err .= " {$rew[F_NAME]};";
+ }
+ }
+
+ # log
+ sg_addlog("sg_create_config: add rewrites: \n success $log_entr_added \n error $log_entr_err", 1);
+ }
+
+ # ----------------------------------------
+ $entry_blacklist = sg_entries_blacklist();
+
+ # --- ACL ---
+ $sg_tag->clear();
+ $sg_tag->set("acl", "", "", "");
+ if ($squidguard_config[F_ACLS]) {
+ $temp_str = '';
+ $log_entr_added = '';
+ foreach($squidguard_config[F_ACLS][F_ITEM] as $acl) {
+ if (!$acl[F_DISABLED]) {
+ $sg_acltag = new TSgTag;
+ $sg_acltag->set($acl[F_NAME], "", $acl[F_TIMENAME], $acl[F_DESCRIPTION]);
+
+ # delete blacklist entries from 'pass' if blacklist disabled
+ if ($squidguard_config[F_BLACKLISTENABLED] !== 'on') {
+ acl_remove_blacklist_items(&$acl[F_DESTINATIONNAME]);
+ acl_remove_blacklist_items(&$acl[F_OVERDESTINATIONNAME]);
+ }
+
+ # not allowing IP in URL
+ if ($acl[F_NOTALLOWINGIP]) {
+ $acl[F_DESTINATIONNAME] = "!in-addr {$acl[F_DESTINATIONNAME]}";
+ $acl[F_OVERDESTINATIONNAME] = "!in-addr {$acl[F_OVERDESTINATIONNAME]}";
+ }
+
+ # re-order acl pass (<allow><deny<all|none>)
+ $acl[F_DESTINATIONNAME] = sg_aclpass_reorder($acl[F_DESTINATIONNAME]);
+ $acl[F_OVERDESTINATIONNAME] = sg_aclpass_reorder($acl[F_OVERDESTINATIONNAME]);
+
+ # ontime
+ $sg_acltag->items[] = "pass {$acl[F_DESTINATIONNAME]}";
+ if ($acl[F_RMOD] != RMOD_NONE)
+ $sg_acltag->items[] = "redirect " . sg_redirector_base_url($acl[F_REDIRECT], $acl[F_RMOD]);
+ if ($acl[F_REWRITENAME])
+ $sg_acltag->items[] = "rewrite {$acl[F_REWRITENAME]}";
+ if ($acl[F_LOG])
+ $sg_acltag->items[] = "log " . SQUIDGUARD_ACCESSBLOCK_FILE;
+
+ # overtime
+ if ($acl[F_TIMENAME]) {
+ $sg_acltag->items[] = "} else {";
+ $sg_acltag->items[] = "pass {$acl[F_OVERDESTINATIONNAME]}";
+ if ($acl[F_REDIRECMODE] !== RMOD_NONE)
+ $sg_acltag->items[] = "redirect " . sg_redirector_base_url($acl[F_OVERREDIRECT], $acl[F_RMOD]);
+ if ($acl[F_OVERREWRITENAME])
+ $sg_acltag->items[] = "rewrite {$acl[F_OVERREWRITENAME]}";
+ if ($acl[F_LOG])
+ $sg_acltag->items[] = "log " . SQUIDGUARD_ACCESSBLOCK_FILE;
+ }
+ $sg_tag->items[] = $sg_acltag;
+ }
+ $log_entr_added .= " {$acl[F_NAME]};";
+ }
+ # log
+ $log_entr_added = !empty($log_entr_added) ? $log_entr_added : "Nothing.";
+ sg_addlog("sg_create_config: add ACL's: \n $log_entr_added", 1);
+ }
+
+ # --- Default ---
+ $sg_tag_def = new TSgTag;
+ $sg_tag_def->set("default", "", "", "");
+ $def = $squidguard_config[F_DEFAULT];
+ sg_addlog("sg_create_config: add Default", 1);
+ if ($def) {
+ $temp_str = '';
+
+ # delete blacklist entries from 'pass' if blacklist disabled
+ if ($squidguard_config[F_BLACKLISTENABLED] !== 'on')
+ acl_remove_blacklist_items(&$def[F_DESTINATIONNAME]);
+
+ # not allowing IP in URL
+ if ($def[F_NOTALLOWINGIP])
+ $def[F_DESTINATIONNAME] = "!in-addr " . $def[F_DESTINATIONNAME];
+
+ # re-order acl pass (<allow><deny<all|none>)
+ $def[F_DESTINATIONNAME] = sg_aclpass_reorder($def[F_DESTINATIONNAME]);
+
+ # ! 'Default' must use without times !
+ $sg_tag_def->items[] = "pass {$def[F_DESTINATIONNAME]}";
+ if ($def[F_RMOD] !== RMOD_NONE)
+ $sg_tag_def->items[] = "redirect " . sg_redirector_base_url($def[F_REDIRECT], $def[F_RMOD]);
+ if ($def[F_REWRITENAME])
+ $sg_tag_def->items[] = "rewrite {$def[F_REWRITENAME]}";
+ if ($def[F_LOG])
+ $sg_tag_def->items[] = "log " . SQUIDGUARD_ACCESSBLOCK_FILE;
+
+ } # <- if def
+ else {
+ $msg = "Error: ACL 'default' is empty, will use default 'block all'";
+ $sg_tag_def->items[] = "# $msg";
+ $sg_tag_def->items[] = "pass none";
+ $sg_tag_def->items[] = "redirect " . sg_redirector_base_url('', RMOD_INT_ERRORPAGE);
+ sg_addlog("sg_create_config: $msg.", 2);
+ }
+
+ # --- ACL end ---
+ $sg_tag->items[] = $sg_tag_def; # add 'default' ACL object
+ $sgconf[] = "";
+ $sgconf[] = $sg_tag->tag_text();
+
+ # delete "\n" chars before each string - SG bug (first string of config must be not empty)
+ foreach ($sgconf as $key => $val) $sgconf[$key] = ltrim($sgconf[$key], "\n");
+ return implode("\n", $sgconf);
+}
+
+# ------------------------------------------------------------------------------
+# sg_create_simple_config
+# Create config for DB rebuilding
+# Default rule - block all
+# Variables:
+# $blk_dbhome - temporary DB home dir, may be different with DBHOME
+# $blk_destlist - is array as [dst_name] = 'path',
+# where path - catalog without dbhome path
+# For example: dbhome is '/var/db/squidGuard/',
+# path can be 'usr/ads' or 'bl/poxy'
+# $redirect_to - redirector string
+# ------------------------------------------------------------------------------
+function sg_create_simple_config($blk_dbhome, $blk_destlist, $redirect_to = "404")
+{
+ global $squidguard_config;
+ $sgconf = array();
+ $logdir = $squidguard_config[F_LOGDIR];
+ $dbhome = $squidguard_config[F_DBHOME];
+
+ # current dbhome dir
+ if (!empty($blk_dbhome)) $dbhome = $blk_dbhome;
+ sg_addlog("sg_create_simple_config: Begin with dbhome='$dbhome'.", 1);
+
+ # header
+ $sgconf[] = CONFIG_SG_HEADER;
+
+ # init section
+ $sgconf[] = "logdir $logdir";
+ $sgconf[] = "dbhome $dbhome";
+ $sgconf[] = "";
+
+ # destination section
+ if (is_array($blk_destlist)) {
+ foreach($blk_destlist as $dst => $dpath) {
+ $tmp_s = array();
+
+ # check item elements
+ if (file_exists("$dbhome/$dpath/domains")) $tmp_s[] = "\t domainlist $dpath/domains";
+ if (file_exists("$dbhome/$dpath/urls")) $tmp_s[] = "\t urllist $dpath/urls";
+ if (file_exists("$dbhome/$dpath/expressions")) $tmp_s[] = "\t expressionlist $dpath/expressions";
+
+ # create only valid items
+ if (!empty($tmp_s)) {
+ $tmp_s = implode("\n", $tmp_s);
+ $sgconf[] = "dest $dst {\n $tmp_s \n}\n";
+ sg_addlog("sg_create_simple_config: -- added item '$dst' = '$dbhome/$dpath'.");
+ } else
+ sg_addlog("sg_create_simple_config: -- ignored empty item '$dst' = '$dbhome/$dpath'.");
+ }
+ }
+
+ # acl section
+ $sgconf[] = "acl {\n\t default {\n\t\t pass all ";
+ $sgconf[] = "\t\t redirect " . sg_redirector_base_url($redirect_to, RMOD_INT_ERRORPAGE); # use sgerror only!
+ $sgconf[] = "\t } \n}";
+
+ # delete "\n" chars before each string - SG bug (first string of config must be not empty)
+ foreach ($sgconf as $key => $val) $sgconf[$key] = ltrim($sgconf[$key], "\n");
+
+ return implode("\n", $sgconf);
+}
+
+# -------------------------------------------------------------------------------------------------
+# sg_redirector_base_url
+# $url - url where redirect to
+# $use_internal - ignore 'Redirect mode' option, use internal (for rebuild config, for example)
+#
+# -------------------------------------------------------------------------------------------------
+function sg_redirector_base_url($rdr_info, $redirect_mode)
+{
+ global $squidguard_config;
+ $rdr_path = '';
+
+ # gui port, ip & proto
+ $guiip = (!empty($squidguard_config[F_CURRENT_LAN_IP])) ? $squidguard_config[F_CURRENT_LAN_IP] : '127.0.0.1';
+ $guiport = (!empty($squidguard_config[F_CURRENT_GUI_PORT])) ? $squidguard_config[F_CURRENT_GUI_PORT] : '80';
+ $guiproto = ($squidguard_config[F_CURRENT_GUI_PROTO] === "https") ? "https" : "http";
+ $rdr_path = "$guiproto://$guiip:$guiport" . REDIRECT_BASE_URL;
+
+ # check redirect
+ $errmsg = '';
+ if (!sg_check_redirect($redirect_mode, $rdr_info, &$errmsg)) {
+ $redirect_mode = RMOD_INT_ERRORPAGE;
+ $rdr_info = "Redirect settings error. $errmsg Check you configuration.";
+ sg_addlog("sg_redirector_base_url: ERROR: $errmsg");
+ }
+
+ switch($redirect_mode) {
+ case RMOD_EXT_ERR: $rdr_path = "$rdr_info" . REDIRECT_URL_ARGS; break;
+ case RMOD_EXT_RDR: $rdr_path = "$rdr_info"; break;
+ case RMOD_EXT_MOVED: $rdr_path = "301:$rdr_info"; break;
+ case RMOD_EXT_FOUND: $rdr_path = "302:$rdr_info"; break;
+ case RMOD_INT_BLANKPAGE: $rdr_path .= "?url=blank&msg=" . rawurlencode($rdr_info) . REDIRECT_URL_ARGS; break;
+ case RMOD_INT_BLANKIMG: $rdr_path .= "?url=blank_img&msg=" . rawurlencode($rdr_info) . REDIRECT_URL_ARGS; break;
+ case RMOD_INT_SIZELIMIT: $rdr_path .= "?url=maxlen_$rdr_info" . REDIRECT_URL_ARGS; break;
+ case RMOD_INT_ERRORPAGE:
+ default: $rdr_path .= "?url=" . rawurlencode("403 $rdr_info") . REDIRECT_URL_ARGS; break;
+ }
+
+ sg_addlog("sg_redirector_base_url: Select redirector base url ($rdr_path)");
+ return $rdr_path;
+}
+
+# -------------------------------------------------------------------------------------------------
+# sg_aclpass_reorder
+# -------------------------------------------------------------------------------------------------
+function sg_aclpass_reorder($pass)
+{
+ $ar_pass = explode(" ", $pass);
+
+ # 'pass' order: <allow> <deny> <all|none>
+ if (is_array($ar_pass)) {
+ $pass_end = '';
+ $pass_fst = array(); # whitelist - '^' prefix (will deleted)
+ $pass_sec = array(); # blacklist - '!' prefix
+ $pass_lst = array(); # allow
+ foreach ($ar_pass as $val) {
+ $tk = trim($val);
+ if ($tk === 'all' or $tk === 'none')
+ $pass_end = $val;
+ elseif (strpos($tk, "^") !== false)
+ # delete '^' prefix
+ $pass_fst[] = str_replace('^', '', $val);
+ elseif (strpos($tk, "!") !== false)
+ $pass_sec[] = $val;
+ else
+ $pass_lst[] = $val;
+ }
+ $ar_pass = array_merge($pass_fst, $pass_sec, $pass_lst);
+ $ar_pass[] = $pass_end;
+ }
+ return implode(" ", $ar_pass);
+}
+
+# ------------------------------------------------------------
+# sg_check_config_data
+# ------------------------------------------------------------
+function sg_check_config_data ($input_errors)
+{
+ global $squidguard_config;
+ $elog = array();
+ $times = sg_list_itemsfield($squidguard_config[F_TIMES], F_NAME);
+ $sources = sg_list_itemsfield($squidguard_config[F_SOURCES], F_NAME);
+ $destinations = sg_list_itemsfield($squidguard_config[F_DESTINATIONS], F_NAME);
+ $rewrites = sg_list_itemsfield($squidguard_config[F_REWRITES], F_NAME);
+ $acls = array();
+
+ # --- Times ---
+ if ($squidguard_config[F_TIMES]) {
+ $key_tm = array_count_values($times);
+ foreach($squidguard_config[F_TIMES][F_ITEM] as $tm) {
+ # check name as unique and name format
+ $tm_name = $tm[F_NAME];
+ $err_s = '';
+ if (!check_name_format($tm_name, &$err_s))
+ $elog[] = "(T1) TIME '$tm_name' error: >>> $err_s";
+
+ if ($key_tm[$tm_name] > 1)
+ $elog[] = "(T2) TIME '$tm_name' error: duplicate time name '$tm_name'";
+
+ # check time items format
+ sg_check_time($tm, &$elog);
+ }
+ }
+
+ # --- Sources ---
+ if ($squidguard_config[F_SOURCES]) {
+ $key_src = array_count_values($sources);
+ foreach($squidguard_config[F_SOURCES][F_ITEM] as $src) {
+ # check name as unique and name format
+ $src_name = $src[F_NAME];
+ $err_s = '';
+ if (!check_name_format($src_name, &$err_s))
+ $elog[] = "(A1) ACL '$src_name'error: $err_s";
+
+ if ($key_src[$src_name] > 1)
+ $elog[] = "(A2) ACL '$src_name' error: duplicate source name '$src_name'";
+
+ sg_check_src($src, $elog);
+ }
+ }
+
+ # --- Destinations ---
+ if ($squidguard_config[F_DESTINATIONS]) {
+ $key_dst = array_count_values($destinations);
+ foreach($squidguard_config[F_DESTINATIONS][F_ITEM] as $dst) {
+ # check name as unique and name format
+ $dst_name = $dst[F_NAME];
+ $err_s = '';
+ if (!check_name_format($dst_name, &$err_s))
+ $elog[] = "(D1) DEST '$dst_name' error: $err_s";
+
+ if ($key_dst[$dst_name] > 1)
+ $elog[] = "(D2) DEST '$dst_name' error: duplicate destination name '$dst_name'";
+ #
+ sg_check_dest($dst, &$elog);
+ }
+ }
+
+ # --- Blacklist ---
+ $blk_entries_file = $squidguard_config[F_WORKDIR] . SQUIDGUARD_BLK_ENTRIES;
+ if (file_exists($blk_entries_file)) {
+ $blk_entr = explode("\n", file_get_contents($blk_entries_file));
+ foreach($blk_entr as $entr) {
+ if ($entr) {
+ $destinations[] = $entr;
+ # check entry for exists
+ $dbfile = $squidguard_config[F_DBHOME] . "/$entr";
+ if (!file_exists($dbfile))
+ $elog[] = "(B1) BLACKLIST '$entr' error: file '$dbfile' not found";
+ }
+ }
+ }
+
+ # --- Rewrites ---
+ if ($squidguard_config[F_REWRITES]) {
+ $key_rw = array_count_values($rewrites);
+ foreach($squidguard_config[F_REWRITES][F_ITEM] as $rw) {
+ # check check name as unique and name format
+ $rw_name = $rw[F_NAME];
+ $err_s = '';
+ if (!check_name_format($rw_name, &$err_s))
+ $elog[] = "(R1) REWRITE '$rw_name' error: $err_s";
+
+ if ($key_rw[$rw_name] > 1)
+ $elog[] = "(R2) REWRITE '$rw_name' error: duplicate rewrite name '$rw_name'";
+ }
+ }
+
+ $key_times = array_count_values($times);
+ $key_sources = array_count_values($sources);
+ $key_destinations = array_count_values($destinations);
+ $key_rewrites = array_count_values($rewrites);
+
+ # --- ACLs ---
+ if ($squidguard_config[F_ACLS]) {
+ $acls = array();
+ foreach($squidguard_config[F_ACLS][F_ITEM] as $acl) {
+ # skip disabled acl
+ if ($acls[F_DISABLED]) continue;
+
+ $acl_name = $acl[F_NAME];
+
+ # check acl name for unique and exists (as source items)
+ if ($acl_name and !$key_sources[$acl_name])
+ $elog[] = "(A1) ACL '$acl_name' error: acl name '$acl_name' not found";
+
+ $acls[] = $acl_name;
+ $key_acls = array_count_values($acls);
+ if ($key_acls[$acl_name] > 1)
+ $elog[] = "(A2) ACL '$acl_name' error: duplicate acl name '$acl_name'";
+
+ # check time
+ $time = $acl[F_TIMENAME];
+ if ($time and !$key_times[$time]) # time name must exists
+ $elog[] = "(A3) ACL '$acl_name' error: time name '$time' not found";
+
+ # check destinations
+ if ($acl[F_DESTINATIONNAME]) {
+ $acldest = $acl[F_DESTINATIONNAME];
+ $acldest = str_replace("!", "", $acldest);
+ $acldest = str_replace("^", "", $acldest);
+ $acldest = explode(" ", $acldest);
+ $key_acldest = array_count_values($acldest);
+ foreach($acldest as $adest) {
+ # check duplicates destinations in acl
+ if ($key_acldest[$adest] > 1)
+ $elog[] = "(A4) ACL '$acl_name' error: duplicate destination name '$adest'. Any destination must included once.";
+ # check destinations for exists
+ if ($adest and ($adest != 'all') and ($adest != 'none') and !$key_destinations[$adest])
+ $elog[] = "(A5) ACL '$acl_name' error: destination name '$adest' not found";
+ }
+ } else {
+ $elog[] = "(A6) ACL '$acl_name' error: ontime pass list is empty. Added 'none'.";
+ $acl[F_DESTINATIONNAME] = "none";
+ }
+
+ # check overtime destinations
+ if ($time) {
+ if ($acl[F_OVERDESTINATIONNAME]) {
+ $acloverdest = $acl[F_OVERDESTINATIONNAME];
+ $acloverdest = str_replace("!", "", $acloverdest);
+ $acloverdest = str_replace("^", "", $acloverdest);
+ $acloverdest = explode(" ", $acloverdest);
+ $key_acloverdest = array_count_values($acloverdest);
+ foreach($acloverdest as $adest) {
+ # check duplicates destinations in acl
+ if ($key_acloverdest[$adest] > 1)
+ $elog[] = "(A7) ACL '$acl_name' error: duplicate overtime destination name '$adest'. Any destination must included once.";
+ # check destinations for exists
+ if ($adest and ($adest != 'all') and ($adest != 'none') and !$key_destinations[$adest])
+ $elog[] = "(A8) ACL '$acl_name' error: overtime destination name '$adest' not found";
+ }
+ } else {
+ $elog[] = "(A9) ACL '$acl_name' error: overtime pass list is empty. Added 'none'.";
+ $acl[F_OVERDESTINATIONNAME] = "none";
+ }
+ }
+
+ # check rewrite
+ $rew = $acl[F_REWRITENAME];
+ if ($rew and !$key_rewrites[$rew])
+ $elog[] = "(AA) ACL '$acl_name' error: rewrite name '$rew' not found";
+
+ # check overtime rewrite
+ $overrew = $acl[F_OVERREWRITENAME];
+ if ($time and $overrew and !$key_rewrites[$overrew])
+ $elog[] = "(AB) ACL '$acl_name' error: overtime rewrite name '$overrew' not found";
+
+ # check redirect
+ $redir = $acl[F_REDIRECT];
+ $overredir = $acl[F_OVERREDIRECT];
+ }
+ }
+
+ # --- Default ---
+ if ($squidguard_config[F_ACLS]) {
+ $def = $squidguard_config[F_DEFAULT];
+
+ # check time
+ $time = $def[F_TIMENAME];
+ if ($time and !$key_times[$time]) # time name must exists
+ $elog[] = "(DF1) ACL 'default' error: time name '$time' not found";
+
+ # check destinations
+ if ($def[F_DESTINATIONNAME]) {
+ $defdest = $def[F_DESTINATIONNAME];
+ $defdest = str_replace("!", "", $defdest);
+ $defdest = str_replace("^", "", $defdest);
+ $defdest = explode(" ", $defdest);
+ $key_defdest = array_count_values($defdest);
+ foreach($defdest as $adest) {
+ # check duplicates destinations in acl
+ if ($key_defdest[$adest] > 1)
+ $elog[] = "(DF2) ACL 'default' error: duplicate destination name '$adest'. Any destination must included once.";
+ # check destinations for exists
+ if ($adest and ($adest != 'all') and ($adest != 'none') and !$key_destinations[$adest])
+ $elog[] = "(DF3) ACL 'default' error: destination name '$adest' not found";
+ }
+ } else {
+ $elog[] = "(DF4) ACL 'default' error: ontime pass list is empty. Added 'none'.";
+ $def[F_DESTINATIONNAME] = "none";
+ }
+
+ # check rewrite
+ $rew = $def[F_REWRITENAME];
+ if ($rew and !$key_rewrites[$rew])
+ $elog[] = "(DF5) ACL 'default' error: rewrite name '$rew' not found";
+
+ # check overtime rewrite
+ $overrew = $def[F_OVERREWRITENAME];
+ if ($time and $overrew and !$key_rewrites[$overrew])
+ $elog[] = "(DF6) ACL 'default' error: overtime rewrite name '$overrew' not found";
+
+ # check redirect
+ $redir = $def[F_REDIRECT];
+ $overredir = $def[F_OVERREDIRECT];
+ }
+
+ # update log
+ if (!empty($elog)) {
+ $input_errors = (is_array($input_errors)) ? array_merge($input_errors, $elog) : implode("\n", $elog);
+ }
+
+ return empty($elog);
+}
+
+# =============================================================================
+# Blacklist
+# =============================================================================
+# sg_reconfigure_blacklist($source_filename, $opt)
+# $source_filename - file name or url
+# $opt - option:
+# '' or 'local' - update from local file
+# 'url' - update from url
+# -----------------------------------------------------------------------------
+function sg_reconfigure_blacklist($source_filename, $opt = '')
+{
+ global $squidguard_config;
+ $sf = trim($source_filename);
+ $sf_contents = '';
+
+ sg_addlog("sg_reconfigure_blacklist: Begin with '$sf'.", 1);
+
+ # 1. check system
+ sg_check_system();
+
+ # 2. upload
+ if ($sf[0] === "/") { # local file - example '/tmp/blacklists.tar'
+ sg_addlog("sg_reconfigure_blacklist: Update from file '$sf'.", 1);
+ if (file_exists($sf)) {
+ $sf_contents = file_get_contents($sf);
+ } else {
+ sg_addlog("sg_reconfigure_blacklist: Error, file '$sf' not found.", 2);
+ return;
+ }
+ }
+ # from url
+ else {
+ sg_addlog("sg_reconfigure_blacklist: Upload from url '$sf'.", 1);
+ $sf_contents = sg_uploadfile_from_url($sf, BLK_LOCALFILE, $opt);
+ }
+
+ # 3. update
+ if (empty($sf_contents)) {
+ sg_addlog("sg_reconfigure_blacklist: Error content from '$sf'.", 2);
+ return;
+ }
+ # save black list archive content to local file
+ file_put_contents(BLK_LOCALFILE, $sf_contents);
+
+ # 4. update blacklist
+ sg_update_blacklist(BLK_LOCALFILE);
+}
+
+# ------------------------------------------------------------------------------
+# sg_update_blacklist - update blacklist from file
+# How it's work:
+# - unpack tar archive to temp dir
+# - copy subdir's tree to one-level temp DB
+# - copy unrebuilded temp db to work db (for user's can configure with new Blacklist)
+# - create Blacklist files listing and copy to values dir and temp DB dir
+# - background rebuild temp DB via sh script (longer proccess) and copy to work DB
+# ------------------------------------------------------------------------------
+
+function sg_update_blacklist($from_file)
+{
+ global $squidguard_config;
+ $dbhome = SQUIDGUARD_DBHOME_DEF;
+ $workdir = SQUIDGUARD_WORKDIR_DEF;
+ $tmp_unpack_dir = SQUIDGUARD_TMP . SQUIDGUARD_BL_UNPACK;
+ $arc_db_dir = SQUIDGUARD_VAR . SG_BLK_ARC;
+
+ sg_addlog("sg_update_blacklist: Begin with '$from_file'.", 1);
+
+ if (file_exists($from_file)) {
+ # check work and DB dir's
+ if (file_exists($squidguard_config[F_DBHOME])) $dbhome = $squidguard_config[F_DBHOME];
+ if (file_exists($squidguard_config[F_WORKDIR])) $workdir = $squidguard_config[F_WORKDIR];
+ # delete old tmp dir's
+ if (file_exists($tmp_unpack_dir)) mwexec("rm -R . $tmp_unpack_dir");
+ if (file_exists($arc_db_dir)) mwexec("rm -R . $arc_db_dir");
+ # create new tmp/arc dir's
+ mwexec("mkdir -p -m 0755 $tmp_unpack_dir");
+ mwexec("mkdir -p -m 0755 $arc_db_dir");
+
+ # 1. unpack archive
+ mwexec("tar zxvf $from_file -C $tmp_unpack_dir");
+ set_file_access($tmp_unpack_dir, OWNER_NAME, 0755);
+ sg_addlog("sg_update_blacklist: Unpack uploaded file '$from_file' -> '$tmp_unpack_dir'.", 1);
+
+ # 2. copy blacklist to squidGuard base & create entries list
+ if (file_exists($tmp_unpack_dir)) {
+ $blk_items = array();
+ $blk_list = array();
+
+ # scan blacklist items
+ scan_blacklist_cat($tmp_unpack_dir, "blk", & $blk_items);
+
+ # move blacklist catalog structure to 'one level' (from tmp_DB to arch_DB)
+ foreach ($blk_items as $key => $val) {
+ $current_dbpath = "$arc_db_dir/$key";
+ if (count($val)) {
+ # make blk_list for config file
+ $blk_list[$key] = $key;
+
+ # delete '$current_dbpath' for correct moving
+ # need moving $val['path'] to $current_dbpath
+ # if $current_dbpath exists,
+ # then $val['path'] will created as subdir - !it's worng!
+ if (file_exists($current_dbpath))
+ mwexec("rm -R $current_dbpath");
+ mwexec("mv -f {$val['path']}/ $current_dbpath");
+ sg_addlog("sg_update_blacklist: Move {$val['path']}/ -> $current_dbpath.", 1);
+ }
+ }
+ set_file_access($arc_db_dir, OWNER_NAME, 0755);
+
+ # -- DISABLED -- copy unrebuilded blacklist from arch_DB_to work DB & set access rights
+# mwexec("cp -R $arc_db_dir/ $dbhome");
+# set_file_access($dbhome, OWNER_NAME, 0755);
+
+ # create entries list
+ if (count($blk_items)) {
+ # save to temp DB
+ $blklist_file = SQUIDGUARD_VAR . SQUIDGUARD_BLK_ENTRIES;
+ file_put_contents($blklist_file, implode("\n", array_keys($blk_items)));
+ set_file_access ($blklist_file, OWNER_NAME, 0755);
+
+ # -- DISABLED -- save copy to squidGuard config dir
+# $blklist_file = "{$squidguard_config[F_WORKDIR]}/" . SQUIDGUARD_BLK_ENTRIES;
+# file_put_contents($blklist_file, implode("\n", array_keys($blk_items)));
+# set_file_access ($blklist_file, OWNER_NAME, 0755);
+ sg_addlog("sg_update_blacklist: Create DB entries list '$blklist_file'.", 1);
+ }
+
+ # make rebuild config (included all found dest items) & save to work dir
+ $conf_path = SQUIDGUARD_VAR . DB_REBUILD_BLK_CONF; # "/tmp/squidGuard_rebuild_blk.conf";
+ file_put_contents($conf_path, sg_create_simple_config($arc_db_dir, $blk_list));
+ set_file_access($conf_path, OWNER_NAME, 0755);
+ sg_addlog("sg_update_blacklist: Create rebuild config '$conf_path'.", 1);
+
+ # *** SH script ***********************************************
+ $sh_scr = Array();
+ $sh_scr[] = "#!/bin/sh";
+ $sh_scr[] = "cd $arc_db_dir";
+ $sh_scr[] = $squidguard_config[F_BINPATH] . "/squidGuard -c $conf_path -C all";
+ $sh_scr[] = "wait"; # wait while SG rebuild DB
+ $sh_scr[] = "chown -R -v " . OWNER_NAME . " $arc_db_dir";
+ $sh_scr[] = "chmod -R -v 0755 $arc_db_dir";
+
+ # copy temp db to '/var/db/squidGuard (-R - recursive; -p - copy access rights)
+ # '$bl_temp_dbhome/' - slash in end of path - copy only dir content (not self dir)
+ $sh_scr[] = "cp -R -p $arc_db_dir/ $dbhome";
+ $sh_scr[] = "cp -f -p $blklist_file " . SQUIDGUARD_WORKDIR_DEF;
+ # set DB owner and right access
+ $sh_scr[] = "chown -R -v " . OWNER_NAME . " $dbhome";
+ $sh_scr[] = "chmod -R -v 0755 $dbhome";
+
+ # if new blacklist some as already installed, then restart squid for changes to take effects
+ $blk_items_old = '';
+ $blk_file_old = $squidguard_config[F_WORKDIR] . SQUIDGUARD_BLK_ENTRIES;
+ if (file_exists($blk_items_old))
+ $blk_items_old = file_get_contents($blk_file_old);
+ if (!empty($blk_items_old) && ($blk_items_old === implode("\n", array_keys($blk_items)))) {
+ $sh_scr[] = "/usr/local/sbin/squid -k reconfigure";
+ $sh_scr[] = "wait"; # wait while process
+ }
+ unset($blk_file_old);
+ unset($blk_items_old);
+
+ # store & exec sh
+ $sh_scr = implode("\n", $sh_scr);
+ $shfile = DB_REBUILD_SH . "_blk";
+ file_put_contents($shfile, $sh_scr);
+ set_file_access($shfile, OWNER_NAME, 0755); # 0755 - script will execute
+ # kill exists rebuild processes
+# mwexec("kill `ps auxw | grep \"$shfile\" | grep -v \"grep\" | awk '{print $2}'`"); # sh script
+ mwexec("kill `ps auxw | grep \"squidGuard_blk_rebuild\" | grep -v \"grep\" | awk '{print $2}'`"); # squidGuard process
+ mwexec_bg("nice -n 5 $shfile");
+ sg_addlog("sg_update_blacklist: Started sh script '$shfile'.", 1);
+
+ # clearing temp
+# mwexec("rm -R $bl_temp");
+ }
+ }
+}
+
+
+# -----------------------------------------------------------------------------
+# sg_blacklist_rebuild_DB - update blacklist from file
+# -----------------------------------------------------------------------------
+function sg_entries_blacklist()
+{
+ global $squidguard_config;
+ $contents = '';
+
+ $fl = SQUIDGUARD_WORKDIR_DEF . SQUIDGUARD_BLK_ENTRIES;
+ if (file_exists($squidguard_config[F_WORKDIR]))
+ $fl = $squidguard_config[F_WORKDIR] . SQUIDGUARD_BLK_ENTRIES;
+ if (file_exists($fl))
+ $contents = explode("\n", file_get_contents($fl));
+
+ return $contents;
+}
+# -----------------------------------------------------------------------------
+# sg_blacklist_rebuild_db - rebuild current Blacklist DB (default: '/var/db/squidGuard')
+# -----------------------------------------------------------------------------
+function sg_blacklist_rebuild_db()
+{
+ global $squidguard_config;
+ $dst_list = array();
+ $dbhome = $squidguard_config[F_DBHOME];
+ $workdir = $squidguard_config[F_WORKDIR];
+
+ # current dbhome and work dir's
+ sg_addlog("sg_blacklist_rebuild_db: Start with path '$dbhome'.", 1);
+
+ # make dest list
+ $blklist_file = "$workdir/" . SQUIDGUARD_BLK_ENTRIES;
+ if (file_exists($blklist_file)) {
+ $blklist = explode("\n", file_get_contents($blklist_file));
+ if (is_array($blklist))
+ foreach($blklist as $bl) { $dst_list[$bl] = $bl; }
+ }
+
+ # rebuild user db ('/var/db/squidGuard')
+ sg_rebuild_db("_blkdb", $dbhome, $dst_list);
+}
+
+# ========================== UTILS =============================================
+# sg_uploadfile_from_url
+# upload file and put them to $destination_file
+# return = upload content
+# ------------------------------------------------------------------------------
+function sg_uploadfile_from_url($url_file, $destination_file, $proxy = '')
+{
+ # open destination file
+ sg_addlog("sg_uploadfile_from_url: begin url'$url_file' proxy'$proxy'", 1);
+
+ $result = '';
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, $url_file);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ if (!empty($proxy)) {
+ $ip = '';
+ $login = '';
+ $s = trim($proxy);
+ if (strpos($s, ' ')) {
+ $ip = substr($s, 0, strpos($s, ' '));
+ $login = substr($s, strpos($s, ' ') + 1);
+ } else $ip = $s;
+
+ if($ip != '') {
+ curl_setopt($ch, CURLOPT_PROXY, $ip);
+ if($login != '')
+ curl_setopt($ch, CURLOPT_PROXYUSERPWD, $login);
+ }
+ }
+ $result=curl_exec ($ch);
+ curl_close ($ch);
+ if (!empty($destination_file))
+ file_put_contents($destination_file, $result);
+ else sg_addlog("sg_uploadfile_from_url: Error upload file", 2);
+
+ # for test
+ file_put_contents(BLK_LOCALFILE, $result);
+
+ return $result;
+}
+
+# ==============================================================================
+# self utils
+# ==============================================================================
+# Set file access
+# ------------------------------------------------------------------------------
+function set_file_access($dir, $owner, $mod)
+{
+ $mod = sprintf("%o", $mod);
+ if (!file_exists($dir)) return;
+ # recursive change access
+ mwexec("chown -R -v $owner $dir");
+ mwexec("chgrp -R -v $owner $dir");
+ mwexec("chmod -R -v $mod $dir");
+}
+# ------------------------------------------------------------------------------
+# scan_dir - build files listing for $dir
+# ------------------------------------------------------------------------------
+function scan_dir($dir)
+{
+ $files = array();
+ if (file_exists($dir)) {
+ $dh = opendir($dir);
+ while (false !== ($filename = readdir($dh))) {
+ # skip '.' and '..' names
+ if (($filename !== '.') and ($filename !== '..')) $files[] = $filename;
+ }
+ sort($files);
+ }
+ return $files;
+}
+# ------------------------------------------------------------------------------
+# restore_arc_blacklist - copy arc blacklist to db
+# ------------------------------------------------------------------------------
+function restore_arc_blacklist()
+{
+ global $squidguard_config;
+ $dbhome = SQUIDGUARD_DBHOME_DEF;
+ $blklist_file = SQUIDGUARD_WORKDIR_DEF . SQUIDGUARD_BLK_ENTRIES;
+ $arc_db_dir = SQUIDGUARD_VAR . SG_BLK_ARC;
+ $arc_blklist_file = SQUIDGUARD_VAR . SQUIDGUARD_BLK_ENTRIES;
+
+ if (file_exists($arc_db_dir) and file_exists($arc_blklist_file)) {
+
+ # copy arc blacklist to work DB with permissions
+ mwexec("cp -R -p $arc_db_dir/ $dbhome");
+ set_file_access($dbhome, OWNER_NAME, 0755);
+ sg_addlog("restore_arc_blacklist: Restore blacklist archive from '$arc_db_dir'.", 1);
+
+ # copy black list file
+ copy($arc_blklist_file, $blklist_file);
+ set_file_access($blklist_file, OWNER_NAME, 0755);
+ sg_addlog("restore_arc_blacklist: Restore black list file from '$arc_blklist_file' to '$blklist_file'.", 1);
+ } else {
+ sg_addlog("restore_arc_blacklist: Error, file '$arc_db_dir' or '$blklist_file' not found.", 2);
+ }
+}
+
+# ------------------------------------------------------------------------------
+# scan_blacklist_cat - scan all dirs and subdirs tree and make blk enrties list
+# $cur_dir - start directory
+# $key_name - current key name
+# ------------------------------------------------------------------------------
+# blk entry[key]:
+# ["domains"] domains file path
+# ["urls"] urls file path
+# ["expressions"] expressions file path
+# ------------------------------------------------------------------------------
+function scan_blacklist_cat($curdir, $key_name, $cat_array)
+{
+
+ if (file_exists($curdir) and is_dir($curdir)) {
+ $blk_entry = array();
+ $files = scan_dir($curdir);
+
+ foreach($files as $fls) {
+ $fls_file = "$curdir/$fls";
+
+ if (($fls != ".") and ($fls != "..")) {
+ if (is_file($fls_file)) {
+
+ # add files path
+ switch(strtolower($fls)) {
+ case "domains":
+ $blk_entry["domains"] = $fls_file;
+ $blk_entry["path"] = $curdir;
+ break;
+ case "urls":
+ $blk_entry["urls"] = $fls_file;
+ $blk_entry["path"] = $curdir;
+ break;
+ case "expressions":
+ $blk_entry["expressions"] = $fls_file;
+ $blk_entry["path"] = $curdir;
+ break;
+ }
+ }
+ elseif (is_dir($fls_file)) {
+ $fls_key = $key_name . "_" . $fls;
+
+ # recursive call
+ scan_blacklist_cat($fls_file, $fls_key, & $cat_array);
+ }
+ }
+ }
+
+ if (count($blk_entry))
+ $cat_array[$key_name] = $blk_entry;
+ }
+}
+
+# ******************************************************************************
+# squidguard utils
+# ******************************************************************************
+# sg_list_itemsfield - get items field list
+# ------------------------------------------------------------------------------
+function sg_list_itemsfield($xml_items, $fld_name)
+{
+ $ls = array();
+ if (is_array($xml_items[F_ITEM]))
+ foreach($xml_items[F_ITEM] as $it) {
+ $ls[] = $it[$fld_name];
+ }
+ return $ls;
+}
+
+# ------------------------------------------------------------------------------
+# is_url - check url an err_codes
+# ------------------------------------------------------------------------------
+function is_url($url)
+{
+ if (empty($url)) return false;
+ if (eregi("^http://", $url)) return true;
+ if (eregi("^https://", $url)) return true;
+ if (strstr("blank", $url)) return true;
+ if (strstr("blank_img", $url)) return true;
+ if (eregi("^((30[1235]{1})|(40[0-9]{1})|(41[0-7]{1})|(50[0-5]{1}))", $url)) return true; # http error code 30x, 4xx, 50x.
+ return false;
+}
+
+# url as 'domain/path': 'mydomain.com/index.php'
+function is_dest_url($url)
+{
+ $fmt = "[a-zA-Z0-9_-]";
+
+ if (empty($url)) return false;
+ if (eregi("^(($fmt){1,}\.){1,}($fmt){2,}(/(.[^\*][^ ])*)", $url)) return true;
+ return false;
+}
+# ------------------------------------------------------------------------------
+# is_masksubnet - check ip/mask
+# ------------------------------------------------------------------------------
+function is_masksubnet($subnet)
+{
+ if (!is_string($subnet))
+ return false;
+
+ list($ip,$msk) = explode('/', $subnet);
+ if (!is_ipaddr($ip) || !is_ipaddr($msk))
+ return false;
+
+ return true;
+}
+# ------------------------------------------------------------------------------
+# is_iprange - check ip1-ip2
+# ------------------------------------------------------------------------------
+function is_iprange($ip_range) {
+ if (!is_string($ip_range)) return false;
+
+ list($ip1,$ip2) = explode('-', $ip_range);
+ if (!is_ipaddr($ip1) || !is_ipaddr($ip2)) return false;
+
+ # ip2 < ip1 - wrong
+ if (ipcmp(ip2, ip1) === -1) return false;
+
+ return true;
+}
+# ------------------------------------------------------------------------------
+# is_ipaddr_valid - validate IP, subnet, IP range
+# ------------------------------------------------------------------------------
+function is_ipaddr_valid($val)
+{
+ return is_string($val) && (is_ipaddr($val) || is_masksubnet($val) || is_subnet($val) || is_iprange($val));
+}
+
+# ------------------------------------------------------------------------------
+# is_domain_valid - check domain format
+# ------------------------------------------------------------------------------
+function is_domain_valid($domain)
+{
+ $dm_fmt = "([a-z0-9\-]{1,})";
+ $dm_fmt = "^(($dm_fmt{1,}\.){1,}$dm_fmt{2,})+$"; # example: (my.)(super.)(domain.)com
+ return is_string($domain) && eregi($dm_fmt, trim($domain));
+}
+
+# ------------------------------------------------------------------------------
+# is_username - check username
+# ------------------------------------------------------------------------------
+function is_username($username)
+{
+ $unm_fmt = "^\'[a-zA-Z_0-9\-]{1,}\'$";
+ return is_string($username) && eregi($unm_fmt, trim($username));
+}
+# ------------------------------------------------------------------------------
+# check name
+# ------------------------------------------------------------------------------
+function check_name_format ($name, $input_errors)
+{
+ $elog = array();
+ $val = trim($name);
+
+ if ((strlen($val) < 2) || (strlen($val) > 16))
+ $elog[] = " Size of name '$val' must be between [2..16].";
+
+ # All symbols must be [a-zA-Z_0-9\-] First symbol = letter.
+ if (!eregi("^([a-zA-Z]{1})([a-zA-Z_0-9\-]+)$", $val))
+ $elog[] = " Invalid name $name. Valid name symbols: ['a-Z', '_', '0-9', '-']. First symbol must be a letter.";
+
+ # update log
+ if (!empty($elog)) {
+ $input_errors = (is_array($input_errors)) ? array_merge($input_errors, $elog) : implode("\n", $elog);
+ }
+
+ return empty($elog);
+}
+# ******************************************************************************
+# squidguard check
+# ******************************************************************************
+# check redirect
+# ------------------------------------------------------------------------------
+function sg_check_redirect($rdr_mode, $rdr_info, $err_msg)
+{
+ $res = true;
+ switch($rdr_mode) {
+ case RMOD_EXT_ERR: case RMOD_EXT_RDR: case RMOD_EXT_MOVED: case RMOD_EXT_FOUND:
+ $res = is_url($rdr_info);
+ if (!$res) $err_msg = "Valid URL expected, but '$rdr_info' found.";
+ break;
+ case RMOD_INT_SIZELIMIT:
+ $res = is_numeric($rdr_path);
+ if (!$res) $err_msg = "Valid number value expected, but '$rdr_info' found.";
+ break;
+ case RMOD_INT_BLANKPAGE: case RMOD_INT_BLANKIMG: case RMOD_INT_ERRORPAGE:
+ default:
+ $res = true; break;
+ }
+ return $res;
+}
+
+# ------------------------------------------------------------------------------
+# sg_check_time
+# ------------------------------------------------------------------------------
+function sg_check_time($sgtime, $input_errors)
+{
+ $err = '';
+ $days = array("*", "mon", "tue", "wed", "thu", "fri", "sat", "sun");
+ $timetypes = array("weekly", "date");
+
+ if (is_array($sgtime[F_ITEM])) {
+ # check date and time
+ foreach ($sgtime[F_ITEM] as $item) {
+ if (!in_array(trim($item[F_TIMETYPE]), $timetypes))
+ $err .= " Invalid type '{$item[F_TIMETYPE]}'.";
+ if (!in_array(trim($item[F_TIMEDAYS]), $days))
+ $err .= " Invalid week day '{$item[F_TIMEDAYS]}'.";
+ if (trim($item[F_DATERANGE])) $err .= check_date(trim($item[F_DATERANGE]));
+ if (trim($item[F_TIMERANGE])) $err .= check_time(trim($item[F_TIMERANGE]));
+ }
+ }
+
+ # errors update
+ if (!empty($err)) $input_errors[] = "TIME '{$sgtime[F_NAME]}': $err";
+ return empty($err);
+}
+
+# ------------------------------------------------------------------------------
+# sg_check_dest
+# ------------------------------------------------------------------------------
+function sg_check_dest($sgx, $input_errors)
+{
+ $elog = array();
+ $dm = explode(" ", $sgx[F_DOMAINS]);
+# $ex = explode(" ", $sgx[F_EXPRESSIONS]);
+ $ur = explode(" ", $sgx[F_URLS]);
+ array_packitems(&$dm);
+ array_packitems(&$ur);
+
+ # domain
+ foreach ($dm as $d_it)
+ if ($d_it && !is_domain_valid($d_it)) $elog[] = "Item '$d_it' is not a domain.";
+
+ # url
+ foreach ($ur as $u_it)
+ if ($u_it && !is_dest_url($u_it)) $elog[] = "Item '$u_it' is not a url.";
+
+ # check redirect
+ sg_check_redirect($sgx[F_RMOD], $sgx[F_REDIRECT], &$elog);
+
+ # update log
+ if (!empty($elog)) {
+ $elog = "DEST '{$sgx[F_NAME]}': " . implode(" ", $elog);
+ if (is_array($input_errors))
+ $input_errors[] = $elog;
+ else $input_errors = $elog;
+ }
+ return empty($elog);
+}
+
+# ------------------------------------------------------------------------------
+# sg_check_src
+# ------------------------------------------------------------------------------
+function sg_check_src($sgx, $input_errors)
+{
+ $elog = array();
+
+ # source may be as one ('source') field or as two ('ip' and 'domain') fields
+ $src = (isset($sgx[F_SOURCE])) ? $sgx[F_SOURCE] : $sgx[F_IP] . " " . $sgx[F_DOMAINS];
+ $src = explode(" ", $src);
+ foreach ($src as $s_item) {
+ if ($s_item) {
+ if (!is_ipaddr_valid($s_item) and !is_domain_valid($s_item) and !is_username($s_item))
+ $elog[] = "SRC '{$sgx[F_NAME]}': Item '$s_item' is not a ip address or a domain or a 'username'.";
+ }
+ }
+
+ # update log
+ if (!empty($elog)) {
+ $input_errors = (is_array($input_errors)) ? array_merge($input_errors, $elog) : implode("\n", $elog);
+ }
+
+ return empty($elog);
+}
+# ------------------------------------------------------------------------------
+# check rebuild blacklist
+# ------------------------------------------------------------------------------
+function is_blacklist_update_started()
+{
+ return exec("ps auxw | grep \"[s]quidGuard_blk_rebuild\" | awk '{print $2}' | wc -l | awk '{ print $1 }'");
+}
+
+# ------------------------------------------------------------------------------
+# Strings
+# ------------------------------------------------------------------------------
+# str_pack_spaces - replace two and more space to single
+# ------------------------------------------------------------------------------
+function str_packspaces($str)
+{
+ while(strpos($str, ' ')) $str = str_replace(' ', ' ', $str);
+}
+
+function array_packitems($arval)
+{
+ if (is_array($arval)) {
+ $arval = array_map("trim", $arval); # trim all items
+ $arval = array_diff($arval, array(' ', '')); # exclude ' ' abd '' elements
+ $arval = array_unique($arval); # unique items
+ $arval = array_values($arval); # pack array
+ }
+ return $arval;
+}
+
+# -----------------------------------------------------------------------------
+# check date
+# date or date range format: 'yyyy-mm-dd', 'yyyy-m-d', 'yyyy.mm.dd' 'yyyy.mm.dd-yyyy.mm.dd'
+# date mask format: '*-mm-dd', 'yyyy-*-dd', 'yyyy.mm.*' (but not for range)
+# -----------------------------------------------------------------------------
+function check_date($date)
+{
+ $err = '';
+ $val = trim($date);
+ $dtfmt = "([0-9]{4})\.([0-9]{2})\.([0-9]{2})";
+
+ # check date range
+ if (eregi("^{$dtfmt}-{$dtfmt}$", $val)) {
+ $val = explode("-", str_replace(".", '', $val));
+ if (intval($val[0]) >= intval($val[1]))
+ $err .= "Invalid date range, begin range must be less than the end. {$val[0]} - {$val[1]}";
+ }
+ elseif (!eregi("^(([0-9]{4})|[*])\.(([0-9]{2})|[*])\.(([0-9]{2})|[*])$", $val)) {
+ $err .= "Bad date format.";
+ }
+
+ if ($err)
+ $err = " Invalid date '$date'.
+ $err
+ You mast use date or date range format: 'yyyy.mm.dd' and 'yyyy.mm.dd-yyyy.mm.dd'.
+ Also possible use mask * (mean any). Example: '*-10-01', '1990-*-*'.";
+ return $err;
+}
+
+# -----------------------------------------------------------------------------
+# check time
+# -----------------------------------------------------------------------------
+function check_time($time)
+{
+ $err = '';
+ $time = trim($time);
+
+ if (empty($time)) return '';
+
+ # time range format: 'HH:MM-HH:MM'
+ if (!eregi("^([0-2][0-9])\:([0-5][0-9])-([0-2][0-9])\:([0-5][0-9])$", $time))
+ $err = "Invalid time range '$time'. You must use 'HH:MM-HH:MM' time range format. ";
+ else {
+ $tms = str_replace("-", "\n", $time);
+ $tmsview = explode("\n", $tms);
+ $tms = str_replace(":", "", $tms);
+ $tms = explode("\n", $tms);
+ if ($tms[0] >= 2400)
+ $err .= "Invalid time range var1='{$tmsview[0]}' must be < '24:00'. ";
+ if ($tms[1] > 2400)
+ $err .= "Invalid time range var2='{$tmsview[1]}' must be <= '24:00'. ";
+ if ($tms[0] >= $tms[1])
+ $err .= "Invalid time range var1='{$tmsview[0]}' must be < var2='{$tmsview[1]}'. ";
+ }
+
+ return $err;
+}
+
+# -----------------------------------------------------------------------------
+# acl_remove_blacklist_items
+# -----------------------------------------------------------------------------
+function acl_remove_blacklist_items($items)
+{
+ # add !items and ^items
+ $db_entries = sg_entries_blacklist();
+ $tdb_entries = array();
+ foreach ($db_entries as $ent) {
+ $tdb_entries[] = $ent;
+ $tdb_entries[] = "!$ent";
+ $tdb_entries[] = "^$ent";
+ }
+ $db_entries = $tdb_entries;
+ unset($tdb_entries);
+
+ # delete blacklist entries from 'pass' if blacklist disabled
+ $items = explode(" ", $items);
+ $items = implode(" ", array_diff($items, $db_entries));
+ return $items;
+}
+
+# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+# classes
+# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+class TSgTag
+{
+ var $tag;
+ var $name;
+ var $time;
+ var $items;
+ var $desc;
+
+ function __construct() {
+ $this->clear();
+ }
+
+ function clear() {
+ $this->tag = '';
+ $this->name = '';
+ $this->time = '';
+ $this->items = array();
+ $this->desc = '';
+ }
+
+ function set($tag, $name, $time, $desc) {
+ $this->tag = $tag;
+ $this->name = $name;
+ $this->time = $time;
+ $this->desc = $desc;
+ }
+
+ function tag_text($offset = 0) {
+ $str = array();
+ $off = str_repeat("\t", $offset);
+
+ $str[] = $off . "# {$this->desc}";
+ if (empty($this->time))
+ $str[] = $off . "{$this->tag} {$this->name} {";
+ else $str[] = $off . "{$this->tag} {$this->name} within {$this->time} {";
+
+ # get items
+ foreach($this->items as $it) {
+ if (is_a($it, "TSgTag"))
+ $str[] = $off . $it->tag_text($offset + 1); # sub tag
+ else $str[] = $off . "\t{$it}"; # item
+ }
+
+ $str[] = $off . "}";
+ return implode("\n", $str);
+ }
+}
+
+?>
diff --git a/config/squidGuard/squidguard_default.xml b/config/squidGuard/squidguard_default.xml
new file mode 100644
index 00000000..78401918
--- /dev/null
+++ b/config/squidGuard/squidguard_default.xml
@@ -0,0 +1,142 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+
+ <name>squidguarddefault</name>
+ <version>none</version>
+ <title>Proxy Content filter SquidGuard: Default</title>
+ <include_file>/usr/local/pkg/squidguard.inc</include_file>
+
+ <tabs>
+ <tab>
+ <text>General settings</text>
+ <url>/pkg_edit.php?xml=squidguard.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Default</text>
+ <url>/pkg_edit.php?xml=squidguard_default.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>ACL</text>
+ <url>/pkg.php?xml=squidguard_acl.xml</url>
+ </tab>
+ <tab>
+ <text>Destinations</text>
+ <url>/pkg.php?xml=squidguard_dest.xml</url>
+ </tab>
+ <tab>
+ <text>Times</text>
+ <url>/pkg.php?xml=squidguard_time.xml</url>
+ </tab>
+ <tab>
+ <text>Rewrites</text>
+ <url>/pkg.php?xml=squidguard_rewr.xml</url>
+ </tab>
+ <tab>
+ <text>Log</text>
+ <url>/pkg_edit.php?xml=squidguard_log.xml</url>
+ </tab>
+ </tabs>
+
+ <fields>
+ <field>
+ <fielddescr>Default destination</fielddescr>
+ <fieldname>dest</fieldname>
+ <description></description>
+ <type>input</type>
+ <size>100</size>
+ </field>
+ <field>
+ <fielddescr>Not to allow IP addresses in URL</fielddescr>
+ <fieldname>notallowingip</fieldname>
+ <description>
+ To make sure that people don't bypass the URL filter
+ by simply using the IP addresses instead of the fully qualified domain names, you can check this option.
+ </description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Redirect mode</fielddescr>
+ <fieldname>redirect_mode</fieldname>
+ <description>
+ Select redirect mode here.
+ &lt;br&gt; Note: if you use 'transparent proxy', then 'int' redirect mode will not accessible.
+<!-- &lt;br&gt;&lt;b&gt; int size limit :&lt;/b&gt; if content size 0 or > 'size limit', then client moved to 'blank image' page; -->
+ &lt;br&gt; Options:
+ &lt;A title="To 'url' will added special client information;" &gt;
+ &lt;span style="background-color: #dddddd;" &gt;ext url err page&lt;/span&gt;&lt;/A&gt; ,
+ &lt;A title="Client view 'url' content without any notification about;" &gt;
+ &lt;span style="background-color: #dddddd;" &gt; ext url redirect&lt;/span&gt;&lt;/A&gt; ,
+ &lt;A title="Client will moved to specified url with displaying url in addres bar;" &gt;
+ &lt;span style="background-color: #dddddd;" &gt; ext url as 'move'&lt;/span&gt;&lt;/A&gt; ,
+ &lt;A title="Client will moved to specified url with showing progress(only!) in status bar;" &gt;
+ &lt;span style="background-color: #dddddd;" &gt; ext url as 'found'.&lt;/span&gt;&lt;/A&gt;
+ &lt;/u&gt;
+ </description>
+ <type>select</type>
+ <value>rmod_none</value>
+ <options>
+ <!--option><name>none</name> <value>rmod_none</value></option-->
+ <option><name>int error page (enter error message)</name> <value>rmod_int</value></option>
+ <option><name>int blank page </name> <value>rmod_int_bpg</value></option>
+ <!--option><name>int blank image</name> <value>rmod_int_bim</value></option-->
+ <!--option><name>int size limit (enter size in bytes)</name> <value>rmod_int_szl</value></option-->
+ <option><name>ext url err page (enter URL)</name> <value>rmod_ext_err</value></option>
+ <option><name>ext url redirect (enter URL)</name> <value>rmod_ext_rdr</value></option>
+ <option><name>ext url move (enter URL)</name> <value>rmod_ext_mov</value></option>
+ <option><name>ext url found (enter URL)</name> <value>rmod_ext_fnd</value></option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Redirect info</fielddescr>
+ <fieldname>redirect</fieldname>
+ <description>
+ Enter external redirection URL, error message or size (bytes) here.
+ </description>
+ <type>textarea</type>
+ <cols>65</cols>
+ <rows>2</rows>
+ </field>
+ <field>
+ <fielddescr>Spec: Use safe search engine</fielddescr>
+ <fieldname>safesearch</fieldname>
+ <description>
+ To protect your children from adult content, you can use the protected mode of search engines.
+ Now it is supported by Google, Yandex, Yahoo, MSN, Live Search. Make sure that the search engines can, and others, it is recommended to prohibit.
+ &lt;br&gt;Note: ! This option overrides 'Rewrite' setting. !
+ </description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Rewrite</fielddescr>
+ <fieldname>rewrite</fieldname>
+ <description>Enter rewrite condition name for this rule, or leave blank.</description>
+ <type>select</type>
+ </field>
+ <field>
+ <fielddescr>Enable log</fielddescr>
+ <fieldname>enablelog</fieldname>
+ <description>Check this for enable log.</description>
+ <type>checkbox</type>
+ </field>
+ </fields>
+
+ <custom_php_validation_command>
+ squidguard_validate_acl(&amp;$_POST, &amp;$input_errors);
+ </custom_php_validation_command>
+ <custom_php_command_before_form>
+ squidguard_before_form_acl(&amp;$pkg, false);
+ </custom_php_command_before_form>
+ <custom_php_after_form_command>
+ squidGuard_print_javascript();
+ </custom_php_after_form_command>
+ <custom_add_php_command/>
+ <custom_php_resync_config_command>
+// squidguard_resync();
+ </custom_php_resync_config_command>
+</packagegui> \ No newline at end of file
diff --git a/config/squidGuard/squidguard_dest.xml b/config/squidGuard/squidguard_dest.xml
new file mode 100644
index 00000000..fa9d4ac2
--- /dev/null
+++ b/config/squidGuard/squidguard_dest.xml
@@ -0,0 +1,190 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+
+ <name>squidguarddest</name>
+ <version>none</version>
+ <title>Proxy Content filter SquidGuard: Destinations</title>
+ <include_file>/usr/local/pkg/squidguard.inc</include_file>
+
+ <delete_string>A proxy server user has been deleted.</delete_string>
+ <addedit_string>A proxy server user has been created/modified.</addedit_string>
+
+ <tabs>
+ <tab>
+ <text>General settings</text>
+ <url>/pkg_edit.php?xml=squidguard.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Default</text>
+ <url>/pkg_edit.php?xml=squidguard_default.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>ACL</text>
+ <url>/pkg.php?xml=squidguard_acl.xml</url>
+ </tab>
+ <tab>
+ <text>Destinations</text>
+ <url>/pkg.php?xml=squidguard_dest.xml</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Times</text>
+ <url>/pkg.php?xml=squidguard_time.xml</url>
+ </tab>
+ <tab>
+ <text>Rewrites</text>
+ <url>/pkg.php?xml=squidguard_rewr.xml</url>
+ </tab>
+ <tab>
+ <text>Log</text>
+ <url>/pkg_edit.php?xml=squidguard_log.xml</url>
+ </tab>
+ </tabs>
+
+ <adddeleteeditpagefields>
+ <columnitem>
+ <fielddescr>Destination name</fielddescr>
+ <fieldname>name</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Domain list</fielddescr>
+ <fieldname>domains</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>URL list</fielddescr>
+ <fieldname>urls</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Expressions</fielddescr>
+ <fieldname>expressions</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Redirect</fielddescr>
+ <fieldname>redirect</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Description</fielddescr>
+ <fieldname>description</fieldname>
+ </columnitem>
+ </adddeleteeditpagefields>
+
+ <fields>
+ <field>
+ <fielddescr>Name</fielddescr>
+ <fieldname>name</fieldname>
+ <description>
+ Enter the unique name here.
+ Name must consist of minimum 2 symbols, first from which letter. &lt;br&gt;
+ All other symbols must be [a-Z_0-9].
+ </description>
+ <type>input</type>
+ <size>100</size>
+ <required/>
+ </field>
+ <field>
+ <fielddescr>Domains list</fielddescr>
+ <fieldname>domains</fieldname>
+ <description>
+ Enter destination domains here. For separate domains names use ' '(space).
+ &lt;p&gt; &lt;b&gt;Example:&lt;/b&gt; 'mail.ru e-mail.ru yahoo.com' .
+ </description>
+ <type>textarea</type>
+ <cols>60</cols>
+ <rows>10</rows>
+ </field>
+ <field>
+ <fielddescr>Expressions</fielddescr>
+ <fieldname>expressions</fieldname>
+ <description>
+ Enter word fragments, what may be contains in destinations URL path.
+ For separate expression words use '|'.
+ &lt;p&gt; &lt;b&gt;Example:&lt;/b&gt; 'mail|casino|game' .
+ </description>
+ <type>textarea</type>
+ <cols>60</cols>
+ <rows>10</rows>
+ </field>
+ <field>
+ <fielddescr>URLs list</fielddescr>
+ <fieldname>urls</fieldname>
+ <description>
+ Enter url's here.
+ For separate urls's use ' '(space).
+ &lt;p&gt; &lt;b&gt;Example:&lt;/b&gt; 'host.com/xxx 12.10.220.125/alisa' .
+ </description>
+ <type>textarea</type>
+ <cols>60</cols>
+ <rows>10</rows>
+ </field>
+ <field>
+ <fielddescr>Redirect mode</fielddescr>
+ <fieldname>redirect_mode</fieldname>
+ <description>
+ Select redirect mode here.
+ &lt;br&gt; Note: if you use 'transparent proxy', then 'int' redirect mode will not accessible.
+<!-- &lt;br&gt;&lt;b&gt; int size limit :&lt;/b&gt; if content size 0 or > 'size limit', then client moved to 'blank image' page; -->
+ &lt;br&gt; Options:
+ &lt;A title="To 'url' will added special client information;" &gt;
+ &lt;span style="background-color: #dddddd;" &gt;ext url err page&lt;/span&gt;&lt;/A&gt; ,
+ &lt;A title="Client view 'url' content without any notification about;" &gt;
+ &lt;span style="background-color: #dddddd;" &gt; ext url redirect&lt;/span&gt;&lt;/A&gt; ,
+ &lt;A title="Client will moved to specified url with displaying url in addres bar;" &gt;
+ &lt;span style="background-color: #dddddd;" &gt; ext url as 'move'&lt;/span&gt;&lt;/A&gt; ,
+ &lt;A title="Client will moved to specified url with showing progress(only!) in status bar;" &gt;
+ &lt;span style="background-color: #dddddd;" &gt; ext url as 'found'.&lt;/span&gt;&lt;/A&gt;
+ &lt;/u&gt;
+ </description>
+ <type>select</type>
+ <value>rmod_none</value>
+ <options>
+ <option><name>none</name> <value>rmod_none</value></option>
+ <option><name>int error page (enter error message)</name> <value>rmod_int</value></option>
+ <option><name>int blank page </name> <value>rmod_int_bpg</value></option>
+ <option><name>int blank image</name> <value>rmod_int_bim</value></option>
+<!-- <option><name>int size limit (enter size in bytes)</name> <value>rmod_int_szl</value></option> -->
+ <option><name>ext url err page (enter URL)</name> <value>rmod_ext_err</value></option>
+ <option><name>ext url redirect (enter URL)</name> <value>rmod_ext_rdr</value></option>
+ <option><name>ext url move (enter URL)</name> <value>rmod_ext_mov</value></option>
+ <option><name>ext url found (enter URL)</name> <value>rmod_ext_fnd</value></option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Redirect</fielddescr>
+ <fieldname>redirect</fieldname>
+ <description>
+ Enter external redirection URL, error message or size (bytes) here.
+ </description>
+ <type>textarea</type>
+ <cols>60</cols>
+ <rows>2</rows>
+ </field>
+ <field>
+ <fielddescr>Enable log</fielddescr>
+ <fieldname>enablelog</fieldname>
+ <type>checkbox</type>
+ <description>Check this for enable log.</description>
+ </field>
+ <field>
+ <fielddescr>Description</fielddescr>
+ <fieldname>description</fieldname>
+ <description>You may enter a description here for your reference (not parsed).</description>
+ <type>input</type>
+ <size>90</size>
+ </field>
+ </fields>
+
+ <custom_delete_php_command/>
+ <custom_php_validation_command>
+ squidguard_validate_destination($_POST, &amp;$input_errors);
+ </custom_php_validation_command>
+ <custom_php_resync_config_command>
+ </custom_php_resync_config_command>
+ <custom_php_after_form_command>
+ squidGuard_print_javascript();
+ </custom_php_after_form_command>
+</packagegui> \ No newline at end of file
diff --git a/config/squidGuard/squidguard_log.xml b/config/squidGuard/squidguard_log.xml
new file mode 100644
index 00000000..ae781562
--- /dev/null
+++ b/config/squidGuard/squidguard_log.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+
+ <name>squidguardlog</name>
+ <version>none</version>
+ <title>Proxy Content filter SquidGuard: Log</title>
+ <include_file>/usr/local/pkg/squidguard.inc</include_file>
+
+ <delete_string>A proxy server user has been deleted.</delete_string>
+ <addedit_string>A proxy server user has been created/modified.</addedit_string>
+
+ <tabs>
+ <tab>
+ <text>General settings</text>
+ <url>/pkg_edit.php?xml=squidguard.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Default</text>
+ <url>/pkg_edit.php?xml=squidguard_default.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>ACL</text>
+ <url>/pkg.php?xml=squidguard_acl.xml</url>
+ </tab>
+ <tab>
+ <text>Destinations</text>
+ <url>/pkg.php?xml=squidguard_dest.xml</url>
+ </tab>
+ <tab>
+ <text>Times</text>
+ <url>/pkg.php?xml=squidguard_time.xml</url>
+ </tab>
+ <tab>
+ <text>Rewrites</text>
+ <url>/pkg.php?xml=squidguard_rewr.xml</url>
+ </tab>
+ <tab>
+ <text>Log</text>
+ <url>/pkg_edit.php?xml=squidguard_log.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ </tabs>
+
+ <fields>
+ <field>
+ <fielddescr>Log type</fielddescr>
+ <fieldname>logtype</fieldname>
+ <description></description>
+ <type>select</type>
+ <value>access_log</value>
+ <options>
+ <option><name>Blocked URL's log</name><value>block_log</value></option>
+ <option><name>Configurator log</name><value>configurator_log</value></option>
+ <option><name>squidGuard log</name><value>squidguard_log</value></option>
+ <option><name>squid config</name><value>squid_config</value></option>
+ <option><name>squidGuard config</name><value>squidguard_config</value></option>
+ </options>
+ </field>
+ </fields>
+
+ <custom_php_command_before_form>
+ squidguard_before_form_log(&amp;$pkg);
+ </custom_php_command_before_form>
+ <custom_php_after_form_command>
+ squidGuard_print_javascript();
+ </custom_php_after_form_command>
+ <custom_php_validation_command>
+ </custom_php_validation_command>
+ <custom_php_resync_config_command>
+ </custom_php_resync_config_command>
+</packagegui>
diff --git a/config/squidGuard/squidguard_rewr.xml b/config/squidGuard/squidguard_rewr.xml
new file mode 100644
index 00000000..d126a9ae
--- /dev/null
+++ b/config/squidGuard/squidguard_rewr.xml
@@ -0,0 +1,142 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+
+ <name>squidguardrewrite</name>
+ <version>none</version>
+ <title>Proxy Content filter SquidGuard: Rewrites</title>
+ <include_file>/usr/local/pkg/squidguard.inc</include_file>
+
+ <tabs>
+ <tab>
+ <text>General settings</text>
+ <url>/pkg_edit.php?xml=squidguard.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Default</text>
+ <url>/pkg_edit.php?xml=squidguard_default.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>ACL</text>
+ <url>/pkg.php?xml=squidguard_acl.xml</url>
+ </tab>
+ <tab>
+ <text>Destinations</text>
+ <url>/pkg.php?xml=squidguard_dest.xml</url>
+ </tab>
+ <tab>
+ <text>Times</text>
+ <url>/pkg.php?xml=squidguard_time.xml</url>
+ </tab>
+ <tab>
+ <text>Rewrites</text>
+ <url>/pkg.php?xml=squidguard_rewr.xml</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Log</text>
+ <url>/pkg_edit.php?xml=squidguard_log.xml</url>
+ </tab>
+ </tabs>
+
+ <adddeleteeditpagefields>
+ <columnitem>
+ <fielddescr>Name</fielddescr>
+ <fieldname>name</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Description</fielddescr>
+ <fieldname>description</fieldname>
+ </columnitem>
+ </adddeleteeditpagefields>
+
+ <fields>
+ <field>
+ <fielddescr>Name</fielddescr>
+ <fieldname>name</fieldname>
+ <description>
+ Enter the unique name here.
+ Name must consist of minimum 2 symbols, first from which letter. &lt;br&gt;
+ All other symbols must be [a-Z_0-9].
+ </description>
+ <type>input</type>
+ <required/>
+ <size>100</size>
+ </field>
+ <field>
+ <fielddescr>
+ &lt;b&gt;Rewrite rule.&lt;/b&gt;&lt;br&gt;
+ Define how url will be replaced.</fielddescr>
+ <type>rowhelper</type>
+ <rowhelper>
+ <rowhelperfield>
+ <fielddescr>Target URL or regular expression</fielddescr>
+ <fieldname>targeturl</fieldname>
+ <type>input</type>
+ <size>45</size>
+ </rowhelperfield>
+ <rowhelperfield>
+ <fielddescr>Replace to URL</fielddescr>
+ <fieldname>replaceto</fieldname>
+ <type>input</type>
+ <size>45</size>
+ </rowhelperfield>
+ <rowhelperfield>
+ <fielddescr>Opt.</fielddescr>
+ <fieldname>mode</fieldname>
+ <type>select</type>
+ <value>no</value>
+ <options>
+ <option> <name>---------</name> <value>no</value> </option>
+ <option> <name>no case </name> <value>nocase</value> </option>
+ <option> <name>redirect </name> <value>redirect</value> </option>
+ <option> <name>no case + redirect</name> <value>nocase_redirect</value> </option>
+ </options>
+ </rowhelperfield>
+<!-- <rowhelperfield>
+ <fielddescr>Http 301</fielddescr>
+ <fieldname>http301</fieldname>
+ <type>checkbox</type>
+ </rowhelperfield>
+ <rowhelperfield>
+ <fielddescr>Http 302</fielddescr>
+ <fieldname>http302</fieldname>
+ <type>checkbox</type>
+ </rowhelperfield>
+-->
+ </rowhelper>
+ </field>
+ <field>
+ <fielddescr>Enable log</fielddescr>
+ <fieldname>enablelog</fieldname>
+ <description>Check this for enable log.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Description</fielddescr>
+ <fieldname>description</fieldname>
+ <description>You may enter a description here for your reference (not parsed).&lt;br&gt;
+ &lt;b&gt; Note: &lt;/b&gt; &lt;br&gt;
+ &lt;b&gt;Rewrite rule&lt;/b&gt; - define how url will are replaced.&lt;br&gt;
+ &lt;b&gt;Target URL or regular expression&lt;/b&gt; - contains destination url or regular expression. Regular expression example: */cc32e46.exe &lt;br&gt;
+ &lt;b&gt;Replace to&lt;/b&gt; - contains replacing url.
+ </description>
+ <type>input</type>
+ <size>100</size>
+ </field>
+ </fields>
+
+ <custom_php_after_form_command>
+ squidGuard_print_javascript();
+ </custom_php_after_form_command>
+ <custom_php_validation_command>
+ squidguard_validate_rewrite($_POST, &amp;$input_errors);
+ </custom_php_validation_command>
+ <custom_php_resync_config_command>
+// squidguard_resync_rewrite();
+ </custom_php_resync_config_command>
+</packagegui>
diff --git a/config/squidGuard/squidguard_time.xml b/config/squidGuard/squidguard_time.xml
new file mode 100644
index 00000000..623f7d0a
--- /dev/null
+++ b/config/squidGuard/squidguard_time.xml
@@ -0,0 +1,143 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+
+ <name>squidguardtime</name>
+ <version>none</version>
+ <title>Proxy Content filter SquidGuard: Times</title>
+ <include_file>/usr/local/pkg/squidguard.inc</include_file>
+
+ <delete_string>A proxy server user has been deleted.</delete_string>
+ <addedit_string>A proxy server user has been created/modified.</addedit_string>
+
+ <tabs>
+ <tab>
+ <text>General settings</text>
+ <url>/pkg_edit.php?xml=squidguard.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Default</text>
+ <url>/pkg_edit.php?xml=squidguard_default.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>ACL</text>
+ <url>/pkg.php?xml=squidguard_acl.xml</url>
+ </tab>
+ <tab>
+ <text>Destinations</text>
+ <url>/pkg.php?xml=squidguard_dest.xml</url>
+ </tab>
+ <tab>
+ <text>Times</text>
+ <url>/pkg.php?xml=squidguard_time.xml</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Rewrites</text>
+ <url>/pkg.php?xml=squidguard_rewr.xml</url>
+ </tab>
+ <tab>
+ <text>Log</text>
+ <url>/pkg_edit.php?xml=squidguard_log.xml</url>
+ </tab>
+ </tabs>
+
+ <adddeleteeditpagefields>
+ <columnitem>
+ <fielddescr>Timename</fielddescr>
+ <fieldname>name</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Description</fielddescr>
+ <fieldname>description</fieldname>
+ </columnitem>
+ </adddeleteeditpagefields>
+ <fields>
+ <field>
+ <fielddescr>Name</fielddescr>
+ <fieldname>name</fieldname>
+ <description>
+ Enter the unique name here.
+ Name must consist of minimum 2 symbols, first from which letter. &lt;br&gt;
+ All other symbols must be [a-Z_0-9].
+ </description>
+ <type>input</type>
+ <required/>
+ <size>100</size>
+ </field>
+ <field>
+ <fielddescr>Values</fielddescr>
+ <type>rowhelper</type>
+ <rowhelper>
+ <rowhelperfield>
+ <fielddescr>Time type</fielddescr>
+ <fieldname>timetype</fieldname>
+ <description></description>
+ <type>select</type>
+ <value>weekly</value>
+ <options>
+ <option><name>Weekly</name><value>weekly</value></option>
+ <option><name>Date</name><value>date</value></option>
+ </options>
+ </rowhelperfield>
+ <rowhelperfield>
+ <fielddescr>Days</fielddescr>
+ <fieldname>timedays</fieldname>
+ <description></description>
+ <type>select</type>
+ <value>*</value>
+ <options>
+ <option><name>all</name><value>*</value></option>
+ <option><name>mon</name><value>mon</value></option>
+ <option><name>tue</name><value>tue</value></option>
+ <option><name>wed</name><value>wed</value></option>
+ <option><name>thu</name><value>thu</value></option>
+ <option><name>fri</name><value>fri</value></option>
+ <option><name>sat</name><value>sat</value></option>
+ <option><name>sun</name><value>sun</value></option>
+ </options>
+ </rowhelperfield>
+ <rowhelperfield>
+ <fielddescr>Date or Date range</fielddescr>
+ <fieldname>daterange</fieldname>
+ <type>input</type>
+ <size>40</size>
+ </rowhelperfield>
+ <rowhelperfield>
+ <fielddescr>Time range</fielddescr>
+ <fieldname>sg_timerange</fieldname>
+ <description>00:00-08:00</description>
+ <type>input</type>
+ <size>20</size>
+ <value>00:00-23:59</value>
+ </rowhelperfield>
+ </rowhelper>
+ </field>
+ <field>
+ <fielddescr>Description</fielddescr>
+ <fieldname>description</fieldname>
+ <description>You may enter a description here for your reference (not parsed). &lt;br&gt;
+ &lt;b&gt; Note: &lt;/b&gt; &lt;br&gt;
+ Field &lt;b&gt;'Date or date range'&lt;/b&gt; have format 'yyyy.mm.dd'; 'yyyy.mm.dd-yyyy.mm.dd'; or use '*' in format. &lt;br&gt;
+ Example: '2007.05.01'; '2007.04.14-2007.04.17'; '*.12.24'; '2007.*.01'; &lt;br&gt;
+ Field &lt;b&gt;'Time range'&lt;/b&gt; have format 'hh:mm-hh:mm'. Example: '08:00-18:00';
+ </description>
+ <type>input</type>
+ <size>80</size>
+ </field>
+ </fields>
+
+ <custom_php_after_form_command>
+ squidGuard_print_javascript();
+ </custom_php_after_form_command>
+ <custom_php_validation_command>
+ squidguard_validate_times(&amp;$_POST, &amp;$input_errors);
+ </custom_php_validation_command>
+ <custom_php_resync_config_command>
+// squidguard_resync_time();
+ </custom_php_resync_config_command>
+</packagegui>
diff --git a/config/sshterm/diag_shell_head.php b/config/sshterm/diag_shell_head.php
new file mode 100644
index 00000000..a16f0835
--- /dev/null
+++ b/config/sshterm/diag_shell_head.php
@@ -0,0 +1,82 @@
+<?php
+/*
+ diag_ping.php
+ part of m0n0wall (http://m0n0.ch/wall)
+
+ Copyright (C) 2003-2005 Bob Zoller (bob@kludgebox.com) and Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+$pgtitle = array(gettext("Diagnostics"), gettext("Shell"));
+
+require("guiconfig.inc");
+
+if ($_POST) {
+ unset($input_errors);
+ /* NOP */
+}
+
+$pgtitle = "Diagnostics: Shell";
+include("head.inc");
+/* put your custom HTML head content here */
+/* using some of the $pfSenseHead function calls */
+echo $pfSenseHead->getHTML();
+
+?>
+<body link="#000000" vlink="#000000" alink="#000000" onload="<?= $jsevents["body"]["onload"] ?>">
+<? include("fbegin.inc"); ?>
+
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+ <form action="diag_ping.php" method="post" name="iform" id="iform">
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="10%" valign="top" class="vncellreq"><?=gettext("SSH Terminal");?>:</td>
+ <td align="left" valign="top" width="90%">
+ <applet width="640"
+ height="480"
+ archive="SSHTermApplet-signed.jar,SSHTermApplet-jdkbug-workaround-signed.jar"
+ code="com.sshtools.sshterm.SshTermApplet"
+ codebase="java"
+ style="border-style: solid; border-width: 1; padding-left: 4; padding-right: 4; padding-top: 1; padding-bottom: 1">
+ <param name="sshapps.connection.host" value="<?= $config['interfaces']['lan']['ipaddr'] ?>">
+ <param name="sshapps.connection.userName" value="root">
+ <param name="sshapps.connection.authenticationMethod" value="password">
+ <param name="sshapps.connection.connectImmediately" value="true">
+ <param name="sshapps.connection.sshapps.connection.showConnectionDialog" value="false">
+ <param name="sshterm.ui.scrollBar" value="true">
+ <param name="sshapps.ui.toolBar" value="false">
+ <param name="sshapps.ui.menuBar" value="true">
+ <param name="sshapps.ui.statusBar" value="true">
+ <param name="sshapps.ui.disabledActions" value="Open,About">
+
+ </applet>
+ </td>
+ </tr>
+ </table>
+</form>
+</td></tr></table>
+<?php include("fend.inc"); ?>
diff --git a/config/sshterm/diag_shell_releng.php b/config/sshterm/diag_shell_releng.php
new file mode 100644
index 00000000..00e4d49b
--- /dev/null
+++ b/config/sshterm/diag_shell_releng.php
@@ -0,0 +1,75 @@
+<?php
+/*
+ diag_ping.php
+ part of m0n0wall (http://m0n0.ch/wall)
+
+ Copyright (C) 2003-2005 Bob Zoller (bob@kludgebox.com) and Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+$pgtitle = "Diagnostics: Shell";
+require("guiconfig.inc");
+
+if ($_POST) {
+ unset($input_errors);
+ /* NOP */
+}
+
+include("head.inc"); ?>
+<body link="#000000" vlink="#000000" alink="#000000">
+<? include("fbegin.inc"); ?>
+<p class="pgtitle"><?=$pgtitle?></p>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+ <form action="diag_ping.php" method="post" name="iform" id="iform">
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td width="10%" valign="top" class="vncellreq">SSH Terminal:</td>
+ <td width="90%">
+ <applet width="640"
+ height="480"
+ archive="SSHTermApplet-signed.jar,SSHTermApplet-jdkbug-workaround-signed.jar"
+ code="com.sshtools.sshterm.SshTermApplet"
+ codebase="java"
+ style="border-style: solid; border-width: 1; padding-left: 4; padding-right: 4; padding-top: 1; padding-bottom: 1">
+ <param name="sshapps.connection.host" value="<?= $config['interfaces']['lan']['ipaddr'] ?>">
+ <param name="sshapps.connection.userName" value="root">
+ <param name="sshapps.connection.authenticationMethod" value="password">
+ <param name="sshapps.connection.connectImmediately" value="true">
+ <param name="sshapps.connection.sshapps.connection.showConnectionDialog" value="false">
+ <param name="sshterm.ui.scrollBar" value="true">
+ <param name="sshapps.ui.toolBar" value="false">
+ <param name="sshapps.ui.menuBar" value="true">
+ <param name="sshapps.ui.statusBar" value="true">
+ <param name="sshapps.ui.disabledActions" value="Open,About">
+
+ </applet>
+ </td>
+ </tr>
+ </table>
+</form>
+</td></tr></table>
+<?php include("fend.inc"); ?>
diff --git a/config/sshterm/sshterm.xml b/config/sshterm/sshterm.xml
new file mode 100644
index 00000000..80907d0a
--- /dev/null
+++ b/config/sshterm/sshterm.xml
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>sshterm</name>
+ <version>1.0</version>
+ <title>Diagnostics: Shell</title>
+ <aftersaveredirect />
+ <!-- Menu is where this packages menu will appear -->
+ <menu>
+ <name>Shell</name>
+ <section>Diagnostics</section>
+ <configfile>sshterm.xml</configfile>
+ <url>/diag_shell.php</url>
+ </menu>
+ <!--
+ configpath gets expanded out automatically and config
+ items will be stored in that location
+ -->
+ <configpath>['installedpackages']['sshterm']['config']</configpath>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.org/packages/config/sshterm/diag_shell_head.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.org/packages/config/sshterm/diag_shell_releng.php</item>
+ </additional_files_needed>
+ <!--
+ fields gets invoked when the user adds or edits a item.
+ the following items will be parsed and rendered for the
+ user as a gui with input, and selectboxes.
+ -->
+ <fields />
+ <custom_php_command_before_form>
+ </custom_php_command_before_form>
+ <custom_delete_php_command>
+ </custom_delete_php_command>
+ <custom_php_resync_config_command>
+ </custom_php_resync_config_command>
+ <custom_php_install_command>
+ $version = file_get_contents("/etc/version");
+
+ if (strpos($version, "HEAD") !== false) {
+ unlink("/usr/local/www/diag_shell_releng.php");
+ rename("/usr/local/www/diag_shell_head.php",
+ "/usr/local/www/diag_shell.php");
+ } else {
+ unlink("/usr/local/www/diag_shell_head.php");
+ rename("/usr/local/www/diag_shell_releng.php",
+ "/usr/local/www/diag_shell.php");
+ }
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ </custom_php_deinstall_command>
+</packagegui>
diff --git a/config/stunnel.xml b/config/stunnel.xml
new file mode 100644
index 00000000..85e43081
--- /dev/null
+++ b/config/stunnel.xml
@@ -0,0 +1,168 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ stunnel.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007-2008 Scott Ullrich
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>stunnel</name>
+ <version>4.18</version>
+ <title>Services: Secure Tunnel</title>
+ <!-- Menu is where this packages menu will appear -->
+ <menu>
+ <name>STunnel</name>
+ <tooltiptext>The stunnel program is designed to work as an SSL encryption wrapper between remote client and local (inetd-startable) or remote server. It can be used to add SSL functionality to commonly used inetd daemons like POP2, POP3, and IMAP servers without any changes in the programs' code. It will negotiate an SSL connection using the OpenSSL or SSLeay libraries. It calls the underlying crypto libraries, so stunnel supports whatever cryptographic algorithms you compiled into your crypto package.</tooltiptext>
+ <section>Services</section>
+ <configfile>stunnel.xml</configfile>
+ </menu>
+ <!-- configpath gets expanded out automatically and config items will be
+ stored in that location -->
+ <configpath>['installedpackages']['package']['$packagename']['configuration']</configpath>
+ <!-- adddeleteeditpagefields items will appear on the first page where you can add / delete or edit
+ items. An example of this would be the nat page where you add new nat redirects -->
+ <adddeleteeditpagefields>
+ <columnitem>
+ <fielddescr>Description</fielddescr>
+ <fieldname>description</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Listen on IP</fielddescr>
+ <fieldname>localip</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Listen on Port</fielddescr>
+ <fieldname>localport</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Redirects to IP</fielddescr>
+ <fieldname>redirectip</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Redirects to Port</fielddescr>
+ <fieldname>redirectport</fieldname>
+ </columnitem>
+ </adddeleteeditpagefields>
+ <!-- fields gets invoked when the user adds or edits a item. the following items
+ will be parsed and rendered for the user as a gui with input, and selectboxes. -->
+ <fields>
+ <field>
+ <fielddescr>Description</fielddescr>
+ <fieldname>description</fieldname>
+ <description>Enter a description for this redirection.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Listen on IP</fielddescr>
+ <fieldname>localip</fieldname>
+ <description>Enter the local IP address to bind this redirection to.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Listen on port</fielddescr>
+ <fieldname>localport</fieldname>
+ <description>Enter the local port to bind this redirection to.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Redirects to IP</fielddescr>
+ <fieldname>redirectip</fieldname>
+ <description>Enter the IP address to redirect this to.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Redirects to Port</fielddescr>
+ <fieldname>redirectport</fieldname>
+ <description>Enter the port to redirect to.</description>
+ <type>input</type>
+ </field>
+ </fields>
+ <service>
+ <name>stunnel</name>
+ <rcfile>/usr/local/etc/rc.d/stunnel.sh</rcfile>
+ <executable>stunnel</executable>
+ </service>
+ <custom_add_php_command_late>
+ <![CDATA[
+ conf_mount_rw();
+ config_lock();
+ $fout = fopen("/usr/local/etc/stunnel/stunnel.conf","w");
+ fwrite($fout, "cert = /usr/local/etc/stunnel/stunnel.pem \n");
+ fwrite($fout, "chroot = /var/tmp/stunnel \n");
+ fwrite($fout, "setuid = stunnel \n");
+ fwrite($fout, "setgid = stunnel \n");
+ foreach($config['installedpackages']['stunnel']['config'] as $pkgconfig) {
+ fwrite($fout, "\n[" . $pkgconfig['description'] . "]\n");
+ fwrite($fout, "accept = " . $pkgconfig['localip'] . ":" . $pkgconfig['localport'] . "\n");
+ fwrite($fout, "connect = " . $pkgconfig['redirectip'] . ":" . $pkgconfig['redirectport'] . "\n");
+ fwrite($fout, "TIMEOUTclose = 0\n\n");
+ }
+ fclose($fout);
+ conf_mount_ro();
+ config_unlock();
+ system("/usr/bin/killall stunnel 2>/dev/null");
+ system("/usr/local/etc/rc.d/stunnel.sh start 2>/dev/null");
+ ]]>
+ </custom_add_php_command_late>
+ <custom_php_install_command>
+ <![CDATA[
+ safe_mkdir("/usr/local/etc/stunnel");
+ system("/usr/bin/openssl req -new -x509 -days 365 -nodes -out /usr/local/etc/stunnel/stunnel.pem -keyout /usr/local/etc/stunnel/stunnel.pem 2>/dev/null");
+ chmod("/usr/local/etc/stunnel/stunnel.pem", 600);
+ system("/bin/mkdir /var/tmp/stunnel");
+ system("/bin/mkdir /var/tmp/stunnel/var");
+ system("/bin/mkdir /var/tmp/stunnel/var/tmp");
+ system("/usr/sbin/chown -R stunnel:stunnel /var/tmp/stunnel");
+ chmod("/var/tmp/stunnel/var/tmp/", 1777);
+ $fout = fopen("/usr/local/etc/rc.d/stunnel.sh","w");
+ system("/usr/sbin/chown -R stunnel:stunnel /var/tmp/stunnel/var/stunnel");
+ fwrite($fout, "#!/bin/sh\n");
+ fwrite($fout, "# PACKAGE: STunnel\n");
+ fwrite($fout, "# EXECUTABLE: stunnel\n");
+ fwrite($fout, "/usr/local/sbin/stunnel /usr/local/etc/stunnel/stunnel.conf\n\n");
+ fclose($fout);
+ chmod("/usr/local/etc/rc.d/stunnel.sh", 0555);
+ ]]>
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ <![CDATA[
+ rmdir_recursive("/var/tmp/stunnel");
+ rmdir_recursive("/usr/local/etc/stunnel*");
+ ]]>
+ </custom_php_deinstall_command>
+</packagegui>
diff --git a/config/test_package/test_package.php b/config/test_package/test_package.php
new file mode 100644
index 00000000..8d68cf39
--- /dev/null
+++ b/config/test_package/test_package.php
@@ -0,0 +1,14 @@
+<?php
+
+/* DISABLE_PHP_LINT_CHECKING */
+
+class CommitTest {
+ function __construct() {
+ }
+
+ public function testFunction() {
+ }
+}
+
+
+?> \ No newline at end of file
diff --git a/config/test_package/test_package.xml b/config/test_package/test_package.xml
new file mode 100644
index 00000000..192a2d54
--- /dev/null
+++ b/config/test_package/test_package.xml
@@ -0,0 +1,213 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>Snort</name>
+ <version>2.6.0.2</version>
+ <title>Services: Snort</title>
+ <include_file>/usr/local/pkg/snort.inc</include_file>
+ <menu>
+ <name>Snort</name>
+ <tooltiptext>Setup snort specific settings</tooltiptext>
+ <section>Services</section>
+ <url>/pkg_edit.php?xml=snort.xml&amp;id=0</url>
+ </menu>
+ <service>
+ <name>snort</name>
+ <rcfile>snort.sh</rcfile>
+ <executable>snort</executable>
+ </service>
+ <tabs>
+ <tab>
+ <text>Snort Settings</text>
+ <url>/pkg_edit.php?xml=snort.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Update Snort Rules</text>
+ <url>/snort_download_rules.php</url>
+ </tab>
+ <tab>
+ <text>Snort Rulesets</text>
+ <url>/snort_rulesets.php</url>
+ </tab>
+ <tab>
+ <text>Snort Blocked</text>
+ <url>/snort_blocked.php</url>
+ </tab>
+ <tab>
+ <text>Snort Whitelist</text>
+ <url>/pkg.php?xml=snort_whitelist.xml</url>
+ </tab>
+ <tab>
+ <text>Snort Alerts</text>
+ <url>/snort_alerts.php</url>
+ </tab>
+ </tabs>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>077</chmod>
+ <item>http://www.pfsense.com/packages/config/snort/snort.inc</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/bin/</prefix>
+ <chmod>077</chmod>
+ <item>http://www.pfsense.com/packages/config/snort/bin/snort2c</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>077</chmod>
+ <item>http://www.pfsense.com/packages/config/snort/snort_download_rules.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>077</chmod>
+ <item>http://www.pfsense.com/packages/config/snort/snort_rulesets.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>077</chmod>
+ <item>http://www.pfsense.com/packages/config/snort/snort_whitelist.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>077</chmod>
+ <item>http://www.pfsense.com/packages/config/snort/snort_blocked.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>077</chmod>
+ <item>http://www.pfsense.com/packages/config/snort/snort_check_for_rule_updates.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>077</chmod>
+ <item>http://www.pfsense.com/packages/config/snort/snort_alerts.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/pf/</prefix>
+ <chmod>077</chmod>
+ <item>http://www.pfsense.com/packages/config/snort/snort_dynamic_ip_reload.php</item>
+ </additional_files_needed>
+ <fields>
+ <field>
+ <fielddescr>Interface</fielddescr>
+ <fieldname>iface_array</fieldname>
+ <description>Select all WAN type interfaces</description>
+ <type>interfaces_selection</type>
+ <size>3</size>
+ <value>lan</value>
+ <multiple>true</multiple>
+ </field>
+ <field>
+ <fielddescr>Performance</fielddescr>
+ <fieldname>performance</fieldname>
+ <description>ac method is the fastest startup but consumes more a lot more memory. acs/ac-banded and ac-sparsebands/mwm/lowmem methods use quite a bit less.</description>
+ <type>select</type>
+ <options>
+ <option>
+ <name>lowmem</name>
+ <value>lowmem</value>
+ </option>
+ <option>
+ <name>ac-std</name>
+ <value>ac-std</value>
+ </option>
+ <option>
+ <name>ac</name>
+ <value>ac</value>
+ </option>
+ <option>
+ <name>ac-banded</name>
+ <value>ac-banded</value>
+ </option>
+ <option>
+ <name>ac-sparsebands</name>
+ <value>ac-sparsebands</value>
+ </option>
+
+ <option>
+ <name>mwm</name>
+ <value>mwm</value>
+ </option>
+ <option>
+ <name>acs</name>
+ <value>acs</value>
+ </option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Oinkmaster code</fielddescr>
+ <fieldname>oinkmastercode</fieldname>
+ <description>Obtain a snort.org Oinkmaster code and paste here.</description>
+ <type>input</type>
+ <size>60</size>
+ <value></value>
+ </field>
+ <field>
+ <fielddescr>Block offenders</fielddescr>
+ <fieldname>blockoffenders</fieldname>
+ <description>Automatically block hosts that generate a snort alert.</description>
+ <type>checkbox</type>
+ <size>60</size>
+ </field>
+ <field>
+ <fielddescr>Update rules automatically</fielddescr>
+ <fieldname>automaticrulesupdate</fieldname>
+ <description>Automatically check for and update rules once a week from snort.org.</description>
+ <type>checkbox</type>
+ </field>
+ </fields>
+ <custom_add_php_command>
+ sync_package_snort();
+ </custom_add_php_command>
+ <custom_php_resync_config_command>
+ sync_package_snort();
+ </custom_php_resync_config_command>
+ <custom_php_install_command>
+ sync_package_snort_reinstall();
+ </custom_php_install_command>
+</packagegui> \ No newline at end of file
diff --git a/config/tftp/tftp.inc b/config/tftp/tftp.inc
new file mode 100644
index 00000000..a7053df9
--- /dev/null
+++ b/config/tftp/tftp.inc
@@ -0,0 +1,279 @@
+<?php
+/* $Id$ */
+/*
+/* ========================================================================== */
+/*
+ tftp_inc.php
+ Copyright (C) 2008 Mark J Crane
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+function guid()
+{
+ if (function_exists('com_create_guid')){
+ return com_create_guid();
+ }else{
+ mt_srand((double)microtime()*10000);//optional for php 4.2.0 and up.
+ $charid = strtoupper(md5(uniqid(rand(), true)));
+ $hyphen = chr(45);// "-"
+ $uuid = chr(123)// "{"
+ .substr($charid, 0, 8).$hyphen
+ .substr($charid, 8, 4).$hyphen
+ .substr($charid,12, 4).$hyphen
+ .substr($charid,16, 4).$hyphen
+ .substr($charid,20,12)
+ .chr(125);// "}"
+ return $uuid;
+ }
+}
+//echo guid();
+
+
+function pkg_is_service_running($servicename)
+{
+ exec("/bin/ps ax | awk '{ print $5 }'", $psout);
+ array_shift($psout);
+ foreach($psout as $line) {
+ $ps[] = trim(array_pop(explode(' ', array_pop(explode('/', $line)))));
+ }
+ if(is_service_running($servicename, $ps) or is_process_running($servicename) ) {
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+function byte_convert( $bytes ) {
+
+ if ($bytes<=0)
+ return '0 Byte';
+
+ $convention=1000; //[1000->10^x|1024->2^x]
+ $s=array('B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB');
+ $e=floor(log($bytes,$convention));
+ return round($bytes/pow($convention,$e),2).' '.$s[$e];
+}
+
+
+function php_sync_package()
+{
+
+ //global $config;
+ //sync_package_tftp_files();
+
+ //if (pkg_is_service_running('inetd')) {
+ // sync_package_tftp();
+ //}
+
+}
+
+
+function php_install_command()
+{
+
+ global $config;
+ conf_mount_rw();
+ config_lock();
+
+ if (!is_dir('/tftpboot')) {
+ // Create the directory
+ exec("mkdir /tftpboot");
+
+ //Set the directory permissions
+ exec("chmod -R 777 /tftpboot");
+
+ }
+
+ if (!is_dir('/usr/local/www/tftp')) {
+ // Create the directory
+ exec("mkdir /usr/local/www/tftp");
+ }
+
+
+ //rename PHP files from .tmp to .php
+ exec("cp /tmp/tftp_files.tmp /usr/local/www/tftp/tftp_files.php");
+ unlink_if_exists("/tmp/tftp_files.tmp");
+
+ //prepare inetd.conf for tftp
+ $filename = "/etc/inetd.conf";
+ $handle = fopen($filename,"rb");
+ $contents = fread($handle, filesize($filename));
+ fclose($handle);
+
+ $handle = fopen($filename,"w");
+ $contents = str_replace("#tftp", "tftp", $contents);
+ fwrite($handle, $contents);
+ unset($contents);
+ fclose($handle);
+ unset($filename);
+
+
+ // add a TFTP DHCP Option to the DHCP Server
+ $filename = "/usr/local/www/services_dhcp.php";
+ $fout = fopen($filename,"r");
+ $tmp = fread($fout, filesize($filename));
+ fclose($fout);
+
+ //tftp was not found in the string
+ if (strpos($tmp, "tftp") === false) {
+ $tmpsearch = "\$pconfig['netmask'] = \$config['dhcpd'][\$if]['netmask'];";
+ $tmpreplace = "\$pconfig['netmask'] = \$config['dhcpd'][\$if]['netmask'];\n";
+ $tmpreplace .= "\$pconfig['tftp'] = \$config['dhcpd'][\$if]['options']['tftp-server-name'];";
+ $tmp = str_replace($tmpsearch, $tmpreplace, $tmp);
+ unset($tmpsearch, $tmpreplace);
+
+ $tmpsearch = "\$config['dhcpd'][\$if]['filename'] = \$_POST['filename'];";
+ $tmpreplace = "\$config['dhcpd'][\$if]['filename'] = \$_POST['filename'];\n";
+ $tmpreplace .= " \$config['dhcpd'][\$if]['options']['tftp-server-name'] = \$_POST['tftp'];";
+ $tmp = str_replace($tmpsearch, $tmpreplace, $tmp);
+ unset($tmpsearch, $tmpreplace);
+
+ $tmpsearch = "function show_netboot_config() {";
+ $tmpreplace = "function show_tftp_config() {\n";
+ $tmpreplace .= " document.getElementById(\"showtftpbox\").innerHTML='';\n";
+ $tmpreplace .= " aodiv = document.getElementById('showtftp');\n";
+ $tmpreplace .= " aodiv.style.display = \"block\";\n";
+ $tmpreplace .= "}\n";
+ $tmpreplace .= "\n";
+ $tmpreplace .= "function show_netboot_config() {";
+ $tmp = str_replace($tmpsearch, $tmpreplace, $tmp);
+ unset($tmpsearch, $tmpreplace);
+
+ $tmpsearch = "<td width=\"22%\" valign=\"top\" class=\"vncell\">Enable Network booting</td>";
+ $tmpreplace .= "";
+ //$tmpreplace = " <tr>\n";
+ $tmpreplace .= "<td width=\"22%\" valign=\"top\" class=\"vncell\">TFTP server</td>\n";
+ $tmpreplace .= " <td width=\"78%\" class=\"vtable\">\n";
+ $tmpreplace .= " <div id=\"showtftpbox\">\n";
+ $tmpreplace .= " <input type=\"button\" onClick=\"show_tftp_config()\" value=\"Advanced\"></input> - Show TFTP configuration</a>\n";
+ $tmpreplace .= " </div>\n";
+ $tmpreplace .= " <div id=\"showtftp\" style=\"display:none\">\n";
+ $tmpreplace .= " <input name=\"tftp\" type=\"text\" class=\"formfld\" id=\"tftp\" size=\"20\" value=\"<"."?=htmlspecialchars(\$pconfig['tftp']);?".">\"><br>\n";
+ $tmpreplace .= " </div>\n";
+ $tmpreplace .= " </td>\n";
+ $tmpreplace .= " </tr>\n";
+ $tmpreplace .= "\n";
+ $tmpreplace .= " <tr>\n";
+ $tmpreplace .= " <td width=\"22%\" valign=\"top\" class=\"vncell\">Enable Network booting</td>";
+ $tmpreplace .= "\n";
+ $tmp = str_replace($tmpsearch, $tmpreplace, $tmp);
+ unset($tmpsearch, $tmpreplace);
+
+ $fout = fopen($filename,"w");
+ fwrite($fout, $tmp);
+ unset($tmp);
+ fclose($fout);
+ }
+ unset($tmp, $filename);
+
+
+
+ $filename = "/etc/inc/services.inc";
+ $fout = fopen($filename,"r");
+ $tmp = fread($fout, filesize($filename));
+ fclose($fout);
+
+ //tftp was not found in the string
+ if (strpos($tmp, "tftp") === false) {
+ $tmpsearch = "if (is_array(\$dhcpifconf['ntpserver']) && \$dhcpifconf['ntpserver'][0])";
+ $tmpreplace = "if (isset(\$dhcpifconf['options']['tftp-server-name'])) {\n";
+ $tmpreplace .= " \$dhcpdconf .= \" option tftp-server-name \\\"\".\$dhcpifconf['options']['tftp-server-name'].\"\\\";\".\"\\n\";\n";
+ $tmpreplace .= " }\n";
+ $tmpreplace .= " \n";
+ $tmpreplace .= " if (is_array(\$dhcpifconf['ntpserver']) && \$dhcpifconf['ntpserver'][0])";
+ $tmp = str_replace($tmpsearch, $tmpreplace, $tmp);
+ unset($tmpsearch, $tmpreplace);
+
+ $fout = fopen($filename,"w");
+ fwrite($fout, $tmp);
+ fclose($fout);
+ }
+ unset($tmp, $filename);
+
+
+ // if backup file exists restore it
+ $filename = 'tftp.bak.tgz';
+
+ //extract a specific directory to /usr/local/freeswitch
+ if (file_exists('/tmp/'.$filename)) {
+ system('cd /; tar xvpfz /tmp/tftp.bak.tgz');
+ system('chmod -R 744 /tftpboot/*');
+ unset($filename);
+ }
+
+ write_rcfile(array(
+ "file" => "tftp.sh",
+ "start" => "/usr/sbin/inetd",
+ "stop" => "killall -9 inetd"
+ )
+ );
+
+
+ //php_sync_package();
+ $handle = popen("/usr/sbin/inetd", "r");
+ pclose($handle);
+
+ //if (pkg_is_service_running('inetd')) {
+ // temp_sync_package();
+ //}
+
+ //conf_mount_ro();
+ //config_unlock();
+
+}
+
+
+function php_deinstall_command()
+{
+
+ //prepare inetd.conf for tftp
+ $filename = "/etc/inetd.conf";
+ $handle = fopen($filename,"rb");
+ $contents = fread($handle, filesize($filename));
+ fclose($handle);
+
+ $handle = fopen($filename,"w");
+ $contents = str_replace("tftp dgram", "#tftp dgram", $contents);
+ fwrite($handle, $contents);
+ unset($contents);
+ fclose($fout);
+ unset($filename);
+
+ exec("killall -9 inetd");
+
+ unlink_if_exists("/usr/local/pkg/tftp.xml");
+ unlink_if_exists("/usr/local/pkg/tftp.inc");
+ unlink_if_exists("/usr/local/www/tftp/tftp_files.php");
+
+ exec("rm -R /tftpboot");
+ unlink_if_exists("/usr/local/etc/rc.d/tftp.sh");
+ unlink_if_exists("/tmp/pkg_mgr_tftp.log");
+
+}
+
+?> \ No newline at end of file
diff --git a/config/tftp/tftp.xml b/config/tftp/tftp.xml
new file mode 100644
index 00000000..e7b69d6b
--- /dev/null
+++ b/config/tftp/tftp.xml
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ tftp.xml
+ Copyright (C) 2008 Mark J Crane
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description></description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>tftp Settings</name>
+ <version>1.0.2</version>
+ <title>TFTP: Settings</title>
+ <include_file>/usr/local/pkg/tftp.inc</include_file>
+ <menu>
+ <name>TFTP</name>
+ <tooltiptext>Add or Remove files for TFTP.</tooltiptext>
+ <section>Services</section>
+ <configfile>tftp.xml</configfile>
+ <url>/tftp/tftp_files.php</url>
+ </menu>
+ <service>
+ <name>tftp</name>
+ <rcfile>tftp.sh</rcfile>
+ <executable>inetd</executable>
+ <description>Trivial File Transport Protocol is a very simple file transfer protocol. Often used with routers, voip phones and more.</description>
+ </service>
+ <tabs>
+ <tab>
+ <text>Files</text>
+ <url>/tftp/tftp_files.php</url>
+ </tab>
+ </tabs>
+ <configpath>installedpackages->package->$packagename->configuration->tftp</configpath>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/tftp/tftp.inc</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/tmp/</prefix>
+ <chmod>0755</chmod>
+ <item>http://www.pfsense.com/packages/config/tftp/tftp_files.tmp</item>
+ </additional_files_needed>
+ <custom_add_php_command>
+ </custom_add_php_command>
+ <custom_php_resync_config_command>
+ php_sync_package();
+ </custom_php_resync_config_command>
+ <custom_delete_php_command>
+ php_sync_package();
+ </custom_delete_php_command>
+ <custom_php_install_command>
+ php_install_command();
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ php_deinstall_command();
+ </custom_php_deinstall_command>
+</packagegui> \ No newline at end of file
diff --git a/config/tftp/tftp_files.tmp b/config/tftp/tftp_files.tmp
new file mode 100644
index 00000000..f49ea76e
--- /dev/null
+++ b/config/tftp/tftp_files.tmp
@@ -0,0 +1,248 @@
+<?php
+/* $Id$ */
+/*
+ tftp_files.php
+ Copyright (C) 2008 Mark J Crane
+ All rights reserved.
+
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require("guiconfig.inc");
+require("/usr/local/pkg/tftp.inc");
+
+$filename = $_GET['filename'];
+if (($_GET['a'] == "download") && $_GET['t'] == "backup") {
+ $tmp = '/tmp/';
+ $filename = 'tftp.bak.tgz';
+ system('cd /;tar cvzf /tmp/tftp.bak.tgz tftpboot');
+}
+if (($_GET['a'] == "download") && file_exists("/tftpboot/".$filename)) {
+
+ session_cache_limiter('public');
+ $fd = fopen("/tftpboot/".$filename, "rb");
+ header("Content-Type: application/force-download");
+ header("Content-Type: application/octet-stream");
+ header("Content-Type: application/download");
+ header("Content-Description: File Transfer");
+ header('Content-Disposition: attachment; filename="'.$filename.'"');
+ header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
+ header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past
+ header("Content-Length: " . filesize("/tftpboot/".$filename));
+ fpassthru($fd);
+ exit;
+}
+
+
+if ($_GET['a'] == "other") {
+ if ($_GET['t'] == "restore") {
+ $tmp = '/tmp/';
+ $filename = 'tftp.bak.tgz';
+
+ //extract a specific directory to /tftpboot
+ if (file_exists('/tmp/'.$filename)) {
+ //echo "The file $filename exists";
+ system('cd /; tar xvpfz /tmp/'.$filename);
+ system('chmod -R 744 /tftpboot/*');
+ header( 'Location: tftp_files.php?savemsg=Backup+has+been+restored.' ) ;
+ }
+ else {
+ header( 'Location: tftp_files.php?savemsg=Restore+failed.+Backup+file+not+found.' ) ;
+ }
+
+ exit;
+ }
+}
+
+
+if (($_POST['submit'] == "Upload") && is_uploaded_file($_FILES['ulfile']['tmp_name'])) {
+ move_uploaded_file($_FILES['ulfile']['tmp_name'], "/tftpboot/" . $_FILES['ulfile']['name']);
+ $savemsg = "Uploaded file to /tftpboot/" . htmlentities($_FILES['ulfile']['name']);
+ system('chmod -R 744 /tftpboot/*');
+ unset($_POST['txtCommand']);
+}
+
+
+if ($_GET['act'] == "del") {
+ if ($_GET['type'] == 'tftp') {
+ unlink_if_exists("/tftpboot/".$_GET['filename']);
+ header("Location: tftp_files.php");
+ exit;
+ }
+}
+
+include("head.inc");
+
+?>
+
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<?php include("fbegin.inc"); ?>
+<p class="pgtitle">TFTP: Files</p>
+
+<?php
+if ($savemsg) {
+ print_info_box($savemsg);
+}
+?>
+
+<div id="mainlevel">
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+<tr><td class="tabnavtbl">
+<?php
+
+ $tab_array = array();
+ $tab_array[] = array(gettext("Files"), false, "/tftp/tftp_files.php");
+ display_top_tabs($tab_array);
+
+?>
+</td></tr>
+</table>
+
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabcont" >
+
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td><p><span class="vexpl"><span class="red"><strong>TFTP files<br />
+ </strong></span>
+ Trivial File Transport Protocol is a very simple file transfer
+ protocol. Use the file upload to add files to the /tftpboot directory.
+ Click on the file from the file list below to download it.
+ </span></p></td>
+ </tr>
+ </table>
+ <br />
+
+
+ <div id="niftyOutter">
+ <form action="tftp_files.php" method="POST" enctype="multipart/form-data" name="frmUpload" onSubmit="">
+ <table>
+
+ <tr>
+ <td align="right">File to upload:</td>
+ <td valign="top" class="label">
+ <input name="ulfile" type="file" class="button" id="ulfile">
+ </td>
+ </tr>
+ <tr>
+ <td valign="top">&nbsp;&nbsp;&nbsp;</td>
+ <td valign="top" class="label">
+ <input name="submit" type="submit" class="button" id="upload" value="Upload"></td>
+ </tr>
+
+ </table>
+ </div>
+ </form>
+
+ <br />
+ <br />
+
+ <?php
+ echo "<table width='690' cellpadding='0' cellspacing='0' border='0'>\n";
+ echo "<tr>\n";
+ echo "<td width='80%'>\n";
+ echo "<b>Backup / Restore</b><br />\n";
+ echo "The 'backup' button will tar gzip /tftpboot/ to /tmp/tftp.bak.tgz it then presents a file to download. \n";
+ echo "If the backup file does not exist in /tmp/tftp.bak.tgz then the 'restore' button will be hidden. \n";
+ echo "Use Diagnostics->Command->File to upload: to browse to the file and then click on upload it now ready to be restored. \n";
+ echo "<br /><br />\n";
+ echo "</td>\n";
+ echo "<td width='20%' valign='middle' align='right'>\n";
+ echo " <input type='button' value='backup' onclick=\"document.location.href='/tftp/tftp_files.php?a=download&t=backup';\" />\n";
+ if (file_exists('/tmp/tftp.bak.tgz')) {
+ echo " <input type='button' value='restore' onclick=\"document.location.href='/tftp/tftp_files.php?a=other&t=restore';\" />\n";
+ }
+ echo "</td>\n";
+ echo "</tr>\n";
+ echo "</table>\n";
+ echo "<br /><br />\n\n";
+ ?>
+
+
+ <table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td width="25%" class="listhdrr">File Name (download)</td>
+ <td width="50%" class="listhdr">Last Modified</td>
+ <td width="50%" class="listhdr">Size</td>
+ </tr>
+
+ <?php
+ if ($handle = opendir('/tftpboot')) {
+ while (false !== ($file = readdir($handle))) {
+ if ($file != "." && $file != "..") {
+
+ $tftp_filesize = filesize('/tftpboot/'.$file);
+ $tftp_filesize = byte_convert($tftp_filesize);
+
+ echo "<tr>\n";
+ echo " <td class=\"listlr\" ondblclick=\"\">\n";
+ echo " <a href=\"tftp_files.php?a=download&filename=".$file."\">\n";
+ echo " $file";
+ echo " </a>";
+ echo " </td>\n";
+ echo " <td class=\"listlr\" ondblclick=\"\">\n";
+ echo date ("F d Y H:i:s", filemtime('/tftpboot/'.$file));
+ echo " </td>\n";
+ echo " <td class=\"listlr\" ondblclick=\"\">\n";
+ echo " ".$tftp_filesize;
+ echo " </td>\n";
+ echo " <td valign=\"middle\" nowrap class=\"list\">\n";
+ echo " <table border=\"0\" cellspacing=\"0\" cellpadding=\"1\">\n";
+ echo " <tr>\n";
+ echo " <td valign=\"middle\"><form method='POST' action='/edit.php' target='_blank'><input type='hidden' name='savetopath' value='/tftpboot/".$file."'><input type='hidden' name='submit' value='Load'><input type='image' src=\"/themes/".$g['theme']."/images/icons/icon_e.gif\" width=\"17\" height=\"17\" border=\"0\"></form></td>\n";
+ echo " <td><a href=\"tftp_files.php?type=tftp&act=del&filename=".$file."\" onclick=\"return confirm('Do you really want to delete this file?')\"><img src=\"/themes/". $g['theme']."/images/icons/icon_x.gif\" width=\"17\" height=\"17\" border=\"0\"></a></td>\n";
+ echo " </tr>\n";
+ echo " </table>\n";
+ echo " </td>\n";
+ echo "</tr>\n";
+
+ }
+ }
+ closedir($handle);
+ }
+ ?>
+
+ <tr>
+ <td class="list" colspan="3"></td>
+ <td class="list"></td>
+ </tr>
+ </table>
+
+
+<br>
+<br>
+<br>
+<br>
+<br>
+<br>
+
+</td>
+</tr>
+</table>
+
+</div>
+
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/tinydns/new_zone_wizard.xml b/config/tinydns/new_zone_wizard.xml
new file mode 100644
index 00000000..82d8d62b
--- /dev/null
+++ b/config/tinydns/new_zone_wizard.xml
@@ -0,0 +1,226 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<pfsensewizard>
+<copyright>
+/* $Id$ */
+/*
+ new_zone_wizard.xml
+ part of pfSense (http://www.pfsense.org/)
+ Copyright (C) 2008 Scott Ullrich
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+</copyright>
+<totalsteps>2</totalsteps>
+<step>
+ <id>1</id>
+ <title>pfSense New Zone Wizard</title>
+ <disableheader>true</disableheader>
+ <description>This wizard will guide you through the adding a new domain name service zone to TinyDNS.</description>
+ <fields>
+ <field>
+ <name>Next</name>
+ <type>submit</type>
+ </field>
+ </fields>
+ <stepbeforeformdisplay>
+ </stepbeforeformdisplay>
+</step>
+<step>
+ <id>2</id>
+ <title>Domain Name</title>
+ <description>On this screen you will define various options for your new DNS Zone</description>
+ <fields>
+ <field>
+ <name>Domain Name</name>
+ <type>input</type>
+ <unsetfield>yes</unsetfield>
+ <arraynum>0</arraynum>
+ <description>Enter the domain name for this zone (example: pfsense.org)</description>
+ </field>
+ <field>
+ <name>Primary Nameserver</name>
+ <type>listtopic</type>
+ </field>
+ <field>
+ <name>Primary Nameserver</name>
+ <type>input</type>
+ <unsetfield>yes</unsetfield>
+ <arraynum>0</arraynum>
+ <description>Enter the primary nameserver for this domain (example: ns.pfsense.org)</description>
+ </field>
+ <field>
+ <name>Secondary Nameserver</name>
+ <type>listtopic</type>
+ </field>
+ <field>
+ <name>Secondary Nameserver</name>
+ <type>input</type>
+ <arraynum>1</arraynum>
+ <description>Enter the secondary nameserver for this domain (example: ns2.pfsense.org)</description>
+ </field>
+ <field>
+ <name>Mail Exchanger (optional)</name>
+ <type>listtopic</type>
+ </field>
+ <field>
+ <name>Mail exchanger record hostname</name>
+ <type>input</type>
+ <arraynum>1</arraynum>
+ <description>Enter the hostname of your Mail exchanger (MX) - (example: exchange.pfsense.org)</description>
+ </field>
+ <field>
+ <name>Mail exchanger record IP address</name>
+ <type>input</type>
+ <arraynum>1</arraynum>
+ <description>Enter the IP address of your Mail exchanger (MX) - (example: 9.10.11.12)</description>
+ </field>
+ <field>
+ <name>First A record (optional)</name>
+ <type>listtopic</type>
+ </field>
+ <field>
+ <name>First A record hostname</name>
+ <type>input</type>
+ <arraynum>1</arraynum>
+ <description>Enter the first A records hostname (example: www.pfsense.org)</description>
+ </field>
+ <field>
+ <name>First A record IP address</name>
+ <type>input</type>
+ <arraynum>1</arraynum>
+ <description>Enter the first A records IP address (example: 1.2.3.4)</description>
+ </field>
+ <field>
+ <name>Secondary A record (optional)</name>
+ <type>listtopic</type>
+ </field>
+ <field>
+ <name>Second A record IP hostname</name>
+ <type>input</type>
+ <arraynum>1</arraynum>
+ <description>Enter the second A records hostname (example: pfsense.org)</description>
+ </field>
+ <field>
+ <name>Second A record IP address</name>
+ <type>input</type>
+ <arraynum>1</arraynum>
+ <description>Enter the second A records IP address (example: 5.6.7.8)</description>
+ </field>
+ <field>
+ <name>Third A record (optional)</name>
+ <type>listtopic</type>
+ </field>
+ <field>
+ <name>Third A record IP hostname</name>
+ <type>input</type>
+ <arraynum>1</arraynum>
+ <description>Enter the third A records hostname (example: www2.pfsense.org)</description>
+ </field>
+ <field>
+ <name>Third A record IP address</name>
+ <type>input</type>
+ <arraynum>1</arraynum>
+ <description>Enter the third A records IP address (example: 9.10.11.12)</description>
+ </field>
+ <field>
+ <name>Next</name>
+ <type>submit</type>
+ </field>
+ </fields>
+ <stepsubmitbeforesave>
+ <![CDATA[
+
+ $changed = false;
+
+ if($_POST['domainname'] and $_POST['primarynameserver']) {
+ $tmp = array();
+ $tmp['hostname'] = $_POST['domainname'];
+ $tmp['recordtype'] = "SOA";
+ $tmp['ipaddress'] = $_POST['primarynameserver'];
+ $config['installedpackages']['tinydnsdomains']['config'][] = $tmp;
+ unset($tmp);
+ $changed = true;
+ }
+
+ if($_POST['domainname'] and $_POST['secondarynameserver']) {
+ $tmp = array();
+ $tmp['hostname'] = $_POST['domainname'];
+ $tmp['recordtype'] = "SOA";
+ $tmp['ipaddress'] = $_POST['secondarynameserver'];
+ $config['installedpackages']['tinydnsdomains']['config'][] = $tmp;
+ unset($tmp);
+ $changed = true;
+ }
+
+ if($_POST['firstarecordhostname'] and $_POST['firstarecordipaddress']) {
+ $tmp = array();
+ $tmp['hostname'] = $_POST['firstarecordhostname'];
+ $tmp['recordtype'] = "A";
+ $tmp['ipaddress'] = $_POST['firstarecordipaddress'];
+ $config['installedpackages']['tinydnsdomains']['config'][] = $tmp;
+ unset($tmp);
+ $changed = true;
+ }
+
+ if($_POST['secondarecordiphostname'] and $_POST['secondarecordipaddress']) {
+ $tmp = array();
+ $tmp['hostname'] = $_POST['secondarecordiphostname'];
+ $tmp['recordtype'] = "A";
+ $tmp['ipaddress'] = $_POST['secondarecordipaddress'];
+ $config['installedpackages']['tinydnsdomains']['config'][] = $tmp;
+ unset($tmp);
+ $changed = true;
+ }
+
+ if($_POST['thirdarecordiphostname'] and $_POST['thirdarecordipaddress']) {
+ $tmp = array();
+ $tmp['hostname'] = $_POST['thirdarecordiphostname'];
+ $tmp['recordtype'] = "A";
+ $tmp['ipaddress'] = $_POST['thirdarecordipaddress'];
+ $config['installedpackages']['tinydnsdomains']['config'][] = $tmp;
+ unset($tmp);
+ $changed = true;
+ }
+
+ if($_POST['mailexchangerrecordipaddress'] and $_POST['mailexchangerrecordhostname']) {
+ $tmp = array();
+ $tmp['hostname'] = $_POST['mailexchangerrecordhostname'];
+ $tmp['recordtype'] = "MX";
+ $tmp['ipaddress'] = $_POST['secondarecordipaddress'];
+ unset($tmp);
+ $changed = true;
+ }
+
+ if($changed) {
+ write_config("new_zone_wizard.xml is creating a new zone {$_POST['domainname']}");
+ require_once("/usr/local/pkg/tinydns.inc");
+ tinydns_create_zone_file();
+ tinydns_setup_ping_items();
+ tinydns_sync_on_changes();
+ }
+
+ Header("Location: /tinydns_status.php");
+ ]]>
+ </stepsubmitbeforesave>
+</step>
+</pfsensewizard>
diff --git a/config/tinydns/tinydns.inc b/config/tinydns/tinydns.inc
new file mode 100644
index 00000000..24de1cab
--- /dev/null
+++ b/config/tinydns/tinydns.inc
@@ -0,0 +1,964 @@
+<?php
+
+/* $Id$ */
+/*
+ tinydns.inc
+ Copyright (C) 2006, 2007, 2008 Scott Ullrich
+ Parts Copyright (C) 2007 Goffredo Andreone
+ part of pfSense
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require_once("filter.inc");
+
+function tinydns_custom_php_install_command() {
+ global $g, $config;
+ conf_mount_rw();
+ $fd = fopen("/usr/local/etc/rc.d/svscan.sh", "w");
+ if(!$fd) {
+ log_error("Could not open /usr/local/etc/rc.d/svscan.sh for writing.");
+ return;
+ }
+ $ipaddress = $config['installedpackages']['tinydns']['config'][0]['ipaddress'];
+
+ $minsegment = "10240";
+ $maxfilesize = "10240";
+ $maxsegment = "20480";
+ $maxfd = "100";
+ $maxchild = "40";
+
+ if($config['installedpackages']['tinydns']['config'][0]['minsegment'])
+ $minsegment = $config['installedpackages']['tinydns']['config'][0]['minsegment'];
+
+ if($config['installedpackages']['tinydns']['config'][0]['maxfilesize'])
+ $maxfilesize = $config['installedpackages']['tinydns']['config'][0]['maxfilesize'];
+
+ if($config['installedpackages']['tinydns']['config'][0]['maxsegment'])
+ $maxsegment = $config['installedpackages']['tinydns']['config'][0]['maxsegment'];
+
+ if($config['installedpackages']['tinydns']['config'][0]['maxfd'])
+ $maxfd = $config['installedpackages']['tinydns']['config'][0]['maxfd'];
+
+ if($config['installedpackages']['tinydns']['config'][0]['maxchild'])
+ $maxchild = $config['installedpackages']['tinydns']['config'][0]['maxchild'];
+
+ if($config['installedpackages']['tinydns']['config'][0]['refreshinterval'])
+ $refreshinterval = $config['installedpackages']['tinydns']['config'][0]['refreshinterval'];
+
+ $svscan = <<<EOD
+#!/bin/sh
+
+# PROVIDE: svscan
+# REQUIRE: LOGIN
+# KEYWORD: FreeBSD
+
+. /etc/rc.subr
+
+name="svscan"
+rcvar=`set_rcvar`
+command="/usr/local/bin/svscan"
+svscan_enable=\${svscan_enable-"YES"}
+svscan_servicedir=\${svscan_servicedir-"/service"}
+
+start_cmd="svscan_start"
+stop_postcmd="svscan_stop_post"
+
+load_rc_config \$name
+
+required_dirs="\${svscan_servicedir}"
+
+svscan_start () {
+ echo "Starting svscan."
+ /usr/bin/env \
+ PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin \
+ /usr/sbin/daemon -f /bin/sh -c "\$command \$svscan_servicedir 2>&1 | /usr/local/bin/readproctitle service errors: ................................................................................................................................................................................................................................................................................................................................................................................................................ &" > /dev/null
+ minicron {$refreshinterval} /var/run/ping_hosts.pid "/etc/ping_hosts.sh; cd /etc/tinydns/root && /usr/local/bin/tinydns-data"
+}
+
+svscan_stop_post () {
+ echo "Stopping svscan."
+ find -L "\$svscan_servicedir" -mindepth 1 -maxdepth 2 -type d \( \! -path "\$svscan_servicedir/*/*" -or -name 'log' \) -print0 | xargs -0 /usr/local/bin/svc -dx
+ PIDTOKILL=`cat /var/run/ping_hosts.pid`
+ kill $PIDTOKILL
+}
+
+run_rc_command "\$1"
+
+EOD;
+
+ fwrite($fd, $svscan);
+ fclose($fd);
+ conf_mount_ro();
+ filter_configure();
+
+ tinydns_custom_php_changeip_command();
+
+ exec("/usr/local/etc/rc.d/svscan.sh start");
+}
+
+function tinydns_custom_php_deinstall_command() {
+ global $g, $config;
+ conf_mount_rw();
+ /* destroy all daemontools items */
+ exec("/usr/sbin/pw groupdel Gtinydns");
+ exec("/usr/sbin/pw groupdel Gdnscache");
+ exec("/usr/sbin/pw groupdel Gdnslog");
+ exec("/usr/sbin/pw userdel Gtinydns");
+ exec("/usr/sbin/pw userdel Gdnscache");
+ exec("/usr/sbin/pw userdel Gdnslog");
+ exec("/usr/sbin/pw groupdel Gaxfrdns");
+ exec("rm /usr/local/www/*tinydns*");
+ exec("rm /usr/local/pkg/*tinydns*");
+ exec("rm /usr/local/pkg/pf/*tinydns*");
+ conf_mount_ro();
+ filter_configure();
+}
+
+function tinydns_custom_php_changeip_command() {
+ global $g, $config;
+ conf_mount_rw();
+
+ $ip = $config['interfaces']['lan']['ipaddr'];
+ $ipmask = $config['interfaces']['lan']['subnet'];
+ $arr = tinydns_get_ip_subnet_arpa($ip, $ipmask);
+ $dnscacheip = $ip;
+ $dnsuserip = $arr[0];
+
+ /* For now force $dnsserverip to to 127.0.0.1 unless a separate IP is specified */
+ $localhost = "127.0.0.1";
+ $dnsserverip = $localhost;
+ if($config['installedpackages']['tinydns']['config'][0]['ipaddress'] != $localhost AND $config['installedpackages']['tinydns']['config'][0]['ipaddress'] != "")
+ $dnsserverip = $config['installedpackages']['tinydns']['config'][0]['ipaddress'];
+ if($config['installedpackages']['tinydns']['config'][0]['regdhcpstatic'] OR $config['installedpackages']['tinydns']['config'][0]['regdhcp'])
+ $dnsserverip = $localhost;
+ $config['installedpackages']['tinydns']['config'][0]['ipaddress'] = $dnsserverip;
+
+ $updatecron = $config['installedpackages']['tinydns']['config'][0]['updatecron'];
+
+ /* Populate Zone Transfer array */
+ $ztipaddress = populate_zt_array();
+
+ /* setup daemon tools service area */
+ if(!is_dir("/service"))
+ exec("/bin/mkdir /service");
+
+ exec("/usr/sbin/pw useradd Gtinydns");
+ exec("/usr/sbin/pw useradd Gdnslog");
+ exec("/usr/sbin/pw useradd Gdnscache");
+ exec("/usr/sbin/pw useradd Gaxfrdns");
+
+ /* TinyDNS Server */
+ exec("/usr/local/bin/tinydns-conf Gtinydns Gdnslog /etc/tinydns {$dnsserverip}");
+ exec("/bin/ln -s /etc/tinydns /service/");
+
+ /* AXFRDNS - Zone transfers */
+ if(is_array($ztipaddress))
+ exec("/usr/local/bin/axfrdns-conf Gaxfrdns Gdnslog /etc/axfrdns /etc/tinydns {$dnsserverip}");
+ exec("/bin/ln -s /etc/axfrdns /service/");
+
+ exec("echo {$dnsserverip} > /etc/tinydns/env/IP");
+ exec("/usr/bin/killall -9 tinydns");
+
+ if($config['installedpackages']['tinydns']['config'][0]['enableforwarding']) {
+ if(!is_dir("/service/dnscache")) {
+ exec("/usr/sbin/pw useradd Gdnscache");
+ exec("/usr/local/bin/dnscache-conf Gdnscache Gdnslog /etc/dnscache {$dnscacheip}");
+ exec("/bin/ln -s /etc/dnscache /service/");
+ exec("/bin/cp /var/etc/resolv.conf /var/etc/resolv.conf.original");
+ exec("/bin/cp /var/etc/resolv.conf /var/etc/resolv.conf.dnscache");
+ }
+ exec("echo {$dnscacheip} > /etc/dnscache/env/IP");
+ tinydns_dnscache_forwarding_servers();
+ exec("touch /etc/dnscache/root/ip/{$dnsuserip}");
+ tinydns_create_soa_domain_list($dnsserverip);
+ exec("echo domain {$config['system']['domain']} > /var/etc/resolv.conf");
+ exec("echo nameserver {$dnscacheip} >> /var/etc/resolv.conf");
+ exec("/usr/bin/killall -9 dnscache");
+ } else {
+ if(file_exists("/var/etc/resolv.conf.original"))
+ exec("/bin/cp /var/etc/resolv.conf.original /var/etc/resolv.conf");
+ if(is_dir("/etc/dnscache")) {
+ dnscache_use_root_servers();
+ exec("/usr/bin/killall -9 dnscache");
+ }
+ }
+ conf_mount_ro();
+ filter_configure();
+}
+
+function populate_zt_array() {
+ global $g, $config;
+ /* Populate Zone Transfer array */
+ if($config['installedpackages']['tinydns']['config'][0]['row']) {
+ $ztipaddress = array();
+ foreach($config['installedpackages']['tinydns']['config'][0]['row'] as $zt) {
+ $tmp = array();
+ $tmp['ztipaddress'] = $zt['ztipaddress'];
+ $tmp['dnszone'] = $zt['dnszone'];
+ $ztipaddress[] = $tmp;
+ }
+ }
+ return $ztipaddress;
+}
+
+function tinydns_setup_axfrdns() {
+ global $g, $config;
+ /* Populate Zone Transfer array */
+ $ztipaddress = populate_zt_array();
+ if(!is_array($ztipaddress))
+ return;
+ $fd = fopen("/etc/axfrdns/tcp","w");
+ if(!$fd) {
+ log_error("Could not open /etc/axfrdns/tcp for writing");
+ return;
+ }
+ foreach($ztipaddress as $zt) {
+ if($zt['ztipaddress'] && $zt['dnszone'])
+ $zonet = "{$zt['ztipaddress']}:allow";
+ if($zt['dnszone'] <> "*")
+ $zonet .= ",AXFR=\"{$zt['dnszone']}\"";
+ fwrite($fd, $zone . "\n");
+ }
+ fclose($fd);
+ // Recompile database
+ exec("cd /service/axfrdns && /usr/local/bin/tinydns-data");
+}
+
+function tinydns_get_record_status($record, $pingthreshold = "", $wanpingthreshold = "") {
+ global $g, $config;
+ if(file_exists("/var/db/pingstatus/{$record}")) {
+ $status = "";
+ $status = file_get_contents("/var/db/pingstatus/{$record}");
+ if(stristr($status,"DOWN"))
+ return "DOWN";
+ }
+ if($pingthreshold) {
+ $current_ms = "";
+ if(file_exists("var/db/pingmsstatus/$record"))
+ $current_ms = file_get_contents("/var/db/pingmsstatus/$record");
+ if($pingthreshold > $current_ms)
+ return "DOWN";
+ }
+ if($wanpingthreshold) {
+ $current_avg = "";
+ if(file_exists("/var/db/wanaverage"))
+ $current_avg = file_get_contents("/var/db/wanaverage");
+ if($wanpingthreshold > $current_avg)
+ return "DOWN";
+ }
+ return "UP";
+}
+
+function tinydns_get_backup_record($record) {
+ global $g, $config;
+ if($config['installedpackages']['tinydnsdomains']) {
+ foreach($config['installedpackages']['tinydnsdomains']['config'] as $domain) {
+ if($domain['ipaddress'] == $record) {
+ /* if no failover host exists, simply return original record */
+ if(!$domain['row'])
+ return $record;
+ foreach($domain['row'] as $row) {
+ $status = tinydns_get_record_status($row['failoverip']);
+ if($status == "UP")
+ return $row['failoverip'];
+ }
+ }
+ }
+ }
+ return $record;
+}
+
+function tinydns_setup_ping_items() {
+ global $g, $config;
+ if(!$config['installedpackages']['tinydnsdomains'])
+ return;
+ $wanif = get_real_wan_interface();
+ $ip = find_interface_ip($wanif);
+ conf_mount_rw();
+ $processed = array();
+ /* XXX: make this work with other packages */
+ $fd = fopen("/var/db/pkgpinghosts", "w");
+ if(!$fd) {
+ log_error("Could not open /var/db/pkgpinghosts for writing.");
+ return;
+ }
+ config_lock();
+ /* write out each ip address so ping_hosts.sh can begin monitoring ip
+ * status and create a database of the status information that we can use.
+ */
+ foreach($config['installedpackages']['tinydnsdomains']['config'] as $domain) {
+ if(!in_array($domain['ipaddress'], $processed)) {
+ fwrite($fd, $ip . "|" . $domain['ipaddress'] . "|1|/usr/local/pkg/tinydns_down.php|/usr/local/pkg/tinydns_up.php\n");
+ $processed[] = $domain['ipaddress'];
+ }
+ if($domain['monitorip'] <> "")
+ $monitorip = $domain['monitorip'];
+ if($domain['row']) {
+ foreach($domain['row'] as $row) {
+ if($row['pingthreshold'])
+ $pingthreshold = $row['pingthreshold'];
+ else
+ $row['pingthreshold'] = "";
+ if($row['monitorip']) {
+ if(!in_array($row['monitorip'], $processed)) {
+ fwrite($fd, $ip . "|" . $row['monitorip'] . "|1|/usr/local/pkg/tinydns_down.php|/usr/local/pkg/tinydns_up.php|{$pingthreshold}\n");
+ $processed[] = $row['monitorip'];
+ }
+ } else {
+ if(!in_array($monitorip, $processed)) {
+ fwrite($fd, $ip . "|" . $monitorip . "|1|/usr/local/pkg/tinydns_down.php|/usr/local/pkg/tinydns_up.php|{$pingthreshold}\n");
+ $processed[] = $monitorip;
+ }
+ }
+ }
+ }
+ if($domain['monitorip']) {
+ if(!in_array($domain['monitorip'], $processed)) {
+ fwrite($fd, $ip . "|" . $domain['monitorip'] . "|1|/usr/local/pkg/tinydns_down.php|/usr/local/pkg/tinydns_up.php|{$pingthreshold}\n");
+ $processed[] = $domain['monitorip'];
+ }
+ } else {
+ if(!in_array($row['failoverip'], $processed)) {
+ fwrite($fd, $ip . "|" . $row['failoverip'] . "|1|/usr/local/pkg/tinydns_down.php|/usr/local/pkg/tinydns_up.php|{$pingthreshold}\n");
+ $processed[] = $row['failoverip'];
+ }
+ }
+ }
+ fclose($fd);
+ config_unlock();
+ conf_mount_ro();
+}
+
+function tinydns_create_zone_file() {
+ global $g, $config;
+ conf_mount_rw();
+ if(file_exists("/tmp/config.cache"))
+ unlink("/tmp/config.cache");
+ parse_config(true);
+ config_lock();
+ if(file_exists("/service/tinydns/root/data"))
+ exec("rm -f /service/tinydns/root/data");
+ if(!is_dir("/service/tinydns/root"))
+ return;
+ $fd = fopen("/service/tinydns/root/data", "w");
+ if(!$fd) {
+ log_error("Could not open /service/tinydns/root/data for writing.");
+ return;
+ }
+
+ /* For now do not allow registration of 'local' DNS data if tinyDNS not bound to 127.0.0.1 */
+ if($config['installedpackages']['tinydns']['config'][0]['ipaddress'] == "127.0.0.1") {
+ /* Load the root servers if Forwarding is enabled */
+ /* Register LAN IP and SOA Forward and Reverse DNS recors in TinyDNS Server*/
+ if($config['installedpackages']['tinydns']['config'][0]['enableforwarding']) {
+ $forwardingservers = tinydns_register_root_servers();
+ if($forwardingservers)
+ fwrite($fd, $forwardingservers);
+ if($config['system']['hostname']['domain']) {
+ $dhcpdhostname = $config['system']['hostname'];
+ if($config['dhcpd']['lan'])
+ $dhcpddomain = $config['system']['domain'];
+ $dhcpdlanip = $config['interfaces']['lan']['ipaddr'];
+ $dhcpdipmask = $config['interfaces']['lan']['subnet'];
+ $dhcpdfqdn = "{$dhcpdhostname}.{$dhcpddomain}";
+ tinydns_complete_soa_record($fd, $dhcpdlanip, $dhcpdipmask, $dhcpdhostname, $dhcpddomain);
+ }
+ }
+
+ /* Register Static IPs */
+ if($config['installedpackages']['tinydns']['config'][0]['regdhcpstatic']) {
+ foreach($config['dhcpd'] as $zone_key => $zone ) {
+ $dhcpdhostname = $config['system']['hostname'];
+ if ($zone['ddnsdomain'])
+ $dhcpddomain = $zone['ddnsdomain'];
+ else
+ $dhcpddomain = $config['system']['domain'];
+ $dhcpdlanip = $config['interfaces'][$zone_key]['ipaddr'];
+ $dhcpdipmask = $config['interfaces'][$zone_key]['subnet'];
+ $dhcpdfqdn = "{$dhcpdhostname}.{$dhcpddomain}";
+ tinydns_complete_soa_record($fd, $dhcpdlanip, $dhcpdipmask, $dhcpdhostname, $dhcpddomain);
+
+ if(is_array($zone['staticmap'])) {
+ foreach($zone['staticmap'] as $dhcpdstatic) {
+ $dhcpdhostname = $dhcpdstatic['hostname'];
+ $dhcpdfqdn = "{$dhcpdhostname}.{$dhcpddomain}";
+ $dhcpdlanip = $dhcpdstatic['ipaddr'];
+ $dhcpda = "={$dhcpdfqdn}:{$dhcpdlanip}";
+ if($dhcpdhostname)
+ fwrite($fd, $dhcpda . "\n");
+ }
+ }
+ }
+ }
+
+ /* Register Dynamic IPs */
+ if($config['installedpackages']['tinydns']['config'][0]['regdhcp']) {
+ $leasesfile = "{$g['dhcpd_chroot_path']}/var/db/dhcpd.leases";
+ $fl = fopen($leasesfile, "r");
+ if(!$fl) {
+ log_error("Could not open {$leasesfile} for reading.");
+ return;
+ }
+ tinydns_add_active_leases($fl,$fd, $dhcpddomain);
+ }
+ }
+
+ if($config['installedpackages']['tinydnsdomains']) {
+ for($x=0; $x< count($config['installedpackages']['tinydnsdomains']['config']); $x++) {
+ $domain = $config['installedpackages']['tinydnsdomains']['config'][$x];
+ $record_data = "";
+ $hostname = $domain['hostname'];
+ $ipaddress = $domain['ipaddress'];
+ $ttl = $domain['ttl'];
+ /* check record status, if it is down request
+ * backup server if defined.
+ */
+ if($domain['monitorip'])
+ $monitorip = $domain['monitorip'];
+ if($monitorip) {
+ $status = tinydns_get_record_status($monitorip);
+ if($status == "DOWN") {
+ if($debug)
+ log_error("$ipaddress monitor ip $monitorip is offline.");
+ $ipaddress = tinydns_get_backup_record($ipaddress);
+ if($debug)
+ log_error("tinydns_get_backup_record returned $ipaddress ");
+ }
+ }
+ $record_data = tinydns_get_rowline_data($ipaddress, $domain['recordtype'], $ttl, $hostname, $domain['rdns']);
+ if($record_data)
+ fwrite($fd, $record_data . "\n");
+ /* process load balanced items */
+ if($domain['row']) {
+ foreach($domain['row'] as $row) {
+ if($row['loadbalance']) {
+ if($row['pingthreshold'])
+ $pingthreshold = $row['pingthreshold'];
+ else
+ $pingthreshold = "";
+ if($row['wanpingthreshold'])
+ $wanpingthreshold = $row['wanpingthreshold'];
+ else
+ $wanpingthreshold = "";
+ $status = tinydns_get_record_status($row['failoverip'], $pingthreshold, $wanpingthreshold);
+ if($status == "DOWN") {
+ $record_data = tinydns_get_rowline_data($row['failoverip'], $domain['recordtype'], $ttl, $hostname, "");
+ fwrite($fd, $record_data . "\n");
+ }
+ }
+ }
+ }
+ }
+ }
+ fclose($fd);
+ /* tell tinydns to reload zone file */
+ exec("cd /service/tinydns/root && /usr/local/bin/tinydns-data");
+ config_unlock();
+ conf_mount_ro();
+}
+
+function tinydns_sync_on_changes() {
+ global $g, $config;
+ $synconchanges = $config['installedpackages']['tinydnssync']['config'][0]['synconchanges'];
+ if(!$synconchanges)
+ return;
+ $sync_hosts = $config['installedpackages']['tinydnssync']['config'];
+ foreach($sync_hosts as $sh) {
+ $sync_to_ip = $sh['ipaddress'];
+ $password = $sh['password'];
+ if($password and $sync_to_ip)
+ tinydns_do_xmlrpc_sync($sync_to_ip, $password);
+ }
+}
+
+function tinydns_do_xmlrpc_sync($sync_to_ip, $password) {
+ global $config, $g;
+
+ if(!$password)
+ return;
+
+ if(!$sync_to_ip)
+ return;
+
+ $xmlrpc_sync_neighbor = $sync_to_ip;
+ if($config['system']['webgui']['protocol'] != "") {
+ $synchronizetoip = $config['system']['webgui']['protocol'];
+ $synchronizetoip .= "://";
+ }
+ $port = $config['system']['webgui']['port'];
+ /* if port is empty lets rely on the protocol selection */
+ if($port == "") {
+ if($config['system']['webgui']['protocol'] == "http")
+ $port = "80";
+ else
+ $port = "443";
+ }
+ $synchronizetoip .= $sync_to_ip;
+
+ /* xml will hold the sections to sync */
+ $xml = array();
+ $xml['tinydnsdomains'] = $config['installedpackages']['tinydnsdomains'];
+
+ /* assemble xmlrpc payload */
+ $params = array(
+ XML_RPC_encode($password),
+ XML_RPC_encode($xml)
+ );
+
+ /* set a few variables needed for sync code borrowed from filter.inc */
+ $url = $synchronizetoip;
+ log_error("Beginning TinyDNS XMLRPC sync to {$url}:{$port}.");
+ $method = 'pfsense.merge_installedpackages_section_xmlrpc';
+ $msg = new XML_RPC_Message($method, $params);
+ $cli = new XML_RPC_Client('/xmlrpc.php', $url, $port);
+ $cli->setCredentials('admin', $password);
+ if($g['debug'])
+ $cli->setDebug(1);
+ /* send our XMLRPC message and timeout after 250 seconds */
+ $resp = $cli->send($msg, "250");
+ if(!$resp) {
+ $error = "A communications error occured while attempting tinydns XMLRPC sync with {$url}:{$port}.";
+ log_error($error);
+ file_notice("sync_settings", $error, "tinydns Settings Sync", "");
+ } elseif($resp->faultCode()) {
+ $cli->setDebug(1);
+ $resp = $cli->send($msg, "250");
+ $error = "An error code was received while attempting tinydns XMLRPC sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString();
+ log_error($error);
+ file_notice("sync_settings", $error, "tinydns Settings Sync", "");
+ } else {
+ log_error("tinydns XMLRPC sync successfully completed with {$url}:{$port}.");
+ }
+
+ /* tell tinydns to reload our settings on the destionation sync host. */
+ $method = 'pfsense.exec_php';
+ $execcmd = "require('/usr/local/pkg/tinydns.inc');\n";
+ $execcmd .= "tinydns_custom_php_changeip_command();\n";
+ $execcmd .= "tinydns_custom_php_install_command();\n";
+ $execcmd .= "tinydns_create_zone_file();\n";
+ $execcmd .= "tinydns_setup_ping_items();\n";
+
+ /* assemble xmlrpc payload */
+ $params = array(
+ XML_RPC_encode($password),
+ XML_RPC_encode($execcmd)
+ );
+
+ $msg = new XML_RPC_Message($method, $params);
+ $cli = new XML_RPC_Client('/xmlrpc.php', $url, $port);
+ $cli->setCredentials('admin', $password);
+ $resp = $cli->send($msg, "250");
+ if(!$resp) {
+ $error = "A communications error occured while attempting tinydns XMLRPC sync with {$url}:{$port} (pfsense.exec_php).";
+ log_error($error);
+ file_notice("sync_settings", $error, "tinydns Settings Sync", "");
+ } elseif($resp->faultCode()) {
+ $cli->setDebug(1);
+ $resp = $cli->send($msg, "250");
+ $error = "An error code was received while attempting tinydns XMLRPC sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString();
+ log_error($error);
+ file_notice("sync_settings", $error, "tinydns Settings Sync", "");
+ } else {
+ log_error("tinydns XMLRPC sync successfully completed with {$url}:{$port} (pfsense.exec_php).");
+ }
+
+ log_error("[tinydns] tinydns_xmlrpc_sync.php is ending.");
+}
+
+/* formats data as a tinydns data row item */
+/* A full description of the data format is available at 'man tinydns-data' */
+function tinydns_get_rowline_data($recordip, $recordtype, $ttl, $hostname, $rdns) {
+ if($ttl)
+ $ttl_string = ":{$ttl}";
+ else
+ $ttl_string = "";
+ switch ($recordtype) {
+ case "SOA":
+ $record_data = ".{$hostname}::{$recordip}{$ttl_string}";
+ break;
+ case "NS":
+ $record_data = "&{$hostname}:{$recordip}{$ttl_string}";
+ break;
+ case "MX":
+ $record_data = "@{$hostname}:{$recordip}::{$ttl_string}";
+ break;
+ case "PTR":
+ /* "^" creates "PTR" record only to allow reverse DNS */
+ $record_data = "^{$hostname}:{$recordip}{$ttl_string}";
+ break;
+ case "A":
+ /* "=" creates both "A" and "PTR" records to allow both forward and reverse DNS */
+ if($rdns)
+ $record_data = "={$hostname}:{$recordip}{$ttl_string}";
+ else
+ /* "+" creates "A" records only to allow forward DNS */
+ $record_data = "+{$hostname}:{$recordip}{$ttl_string}";
+ break;
+ case "CNAME":
+ $record_data = "C{$hostname}:{$recordip}{$ttl_string}";
+ break;
+ case "TXT":
+ /* "'" creates "TXT" record that can be used for SPF */
+ $record_data = "'{$hostname}:{$recordip}{$ttl_string}";
+ break;
+ }
+ return $record_data;
+}
+
+/* Returns the last IP byte and the Trimmed IP*/
+function tinydns_get_lastip_byte($ipsub) {
+ $len= strlen($ipsub);
+ $pos = strrpos($ipsub, ".");
+ $last_byte = "";
+ if ($pos === false) {
+ $last_byte = $ipsub;
+ return array ($last_byte,$ipsub);
+ }
+ $last_byte = substr($ipsub,$pos + 1);
+ $ipsub = substr($ipsub,0,$pos);
+ return array ($last_byte,$ipsub);
+}
+
+/* in-add.arpa IP calculated from D.C.B.A and Mask to A.B.C.D.in-addr.arpa */
+/* subnet IP calculated from A.B.C.D and Mask */
+function tinydns_get_ip_subnet_arpa($ip, $ipmask) {
+ $ipsub = $ip;
+ $arpaip = "";
+ $array = tinydns_get_lastip_byte($ipsub);
+ $a = $array[0];
+ $ipsub = $array[1];
+ $array = tinydns_get_lastip_byte($ipsub);
+ $b = $array[0];
+ $ipsub = $array[1];
+ $array = tinydns_get_lastip_byte($ipsub);
+ $c = $array[0];
+ $ipsub = $array[1];
+ $array = tinydns_get_lastip_byte($ipsub);
+ $d = $array[0];
+ $ipsub = $array[1];
+ switch ($ipmask) {
+ case ($ipmask <= 32 AND $ipmask > 24):
+ $s = 32 - $ipmask;
+ $a >> $s;
+ $arpaip = "{$a}.{$b}.{$c}.{$d}.in-addr.arpa";
+ $subnet = "{$d}.{$c}.{$b}.{$a}";
+ break;
+ case ($ipmask <= 24 AND $ipmask > 16):
+ $s = 24 - $ipmask;
+ $b >> $s;
+ $arpaip = "{$b}.{$c}.{$d}.in-addr.arpa";
+ $subnet = "{$d}.{$c}.{$b}";
+ break;
+ case ($ipmask <= 16 AND $ipmask > 8):
+ $s = 16 - $ipmask;
+ $c >> $s;
+ $arpaip = "{$c}.{$d}.in-addr.arpa";
+ $subnet = "{$d}.{$c}";
+ break;
+ case ($ipmask <= 8 AND $ipmask > 0):
+ $s = 8 - $ipmask;
+ $d >> $s;
+ $arpaip = "{$d}.in-addr.arpa";
+ $subnet = "{$d}";
+ break;
+ }
+ return array($subnet,$arpaip);
+}
+
+/* Create a Forward and a Reverse DNS (SOA, A, PTR) records for Fully Qualififed Domain Name*/
+function tinydns_complete_soa_record($fd, $ip, $ipmask, $nsname, $domain) {
+ $fqdn = "{$nsname}.{$domain}";
+ $rip = tinydns_get_ip_subnet_arpa($ip, $ipmask);
+ $soa = ".{$domain}::{$fqdn}";
+ $rsoa = ".{$rip[1]}::{$fqdn}";
+ $a = "={$fqdn}:{$ip}";
+ if($fqdn)
+ fwrite($fd, $soa . "\n");
+ if($rip)
+ fwrite($fd, $rsoa . "\n");
+ if($nsname)
+ fwrite($fd, $a . "\n");
+}
+
+/* Search for active leases in the dhcpd.leases file and add them to tinyDNS */
+/* Currently it will add duplicate leases that are ignored by thee tinyDNS server*/
+/* Should duplicate leases be purged by DCHCP server in a remove stale records operation? */
+function tinydns_add_active_leases($fl,$fd, $leasedomain) {
+ $i = 0;
+ $lip = strlen("lease") + 1;
+ $lis = strlen("binding state active");
+ $lic = strlen("client-hostname");
+ $leaseip = "";
+ $leasestatus = "";
+ $leasehostname = "";
+ while (!feof($fl)) {
+ $leases = fgets($fl, 4096);
+ $discard = ($leases[0] == "#") OR ($leases[0] == "\n");
+ if(!$discard) {
+ if($leaseip == "") {
+ if ($leaseip = strstr($leases,"lease")) {
+ $leaseip = substr($leaseip,$lip,strpos($leases,"{") - $lip - 1);
+ }
+ }
+ elseif($leasestatus == FALSE) {
+ if (stristr($leases,"binding state active")) {
+ $leasestatus = TRUE;
+ }
+ }
+ elseif($leasestatus == TRUE AND $leasehostname == "") {
+ if($leasehostname = stristr($leases,"client-hostname")) {
+ $qstrt = strpos($leasehostname,'"') + 1;
+ $qlen = strrpos($leasehostname,'"') - $qstrt;
+ $leasehostname = substr($leasehostname,$qstrt,$qlen);
+ }
+ }
+ if($leases[0] == "}") {
+ $leasefqdn = "{$leasehostname}.{$leasedomain}";
+ $leasea = "={$leasefqdn}:{$leaseip}";
+ if($leasehostname AND $leasestatus)fwrite($fd, $leasea . "\n");
+ $leaseip = "";
+ $leasehostname = "";
+ $leasestatus = FALSE;
+ }
+ $i = $i + 1;
+ }
+ }
+ fclose($fl);
+ $leaselines = $i;
+}
+
+function tinydns_get_dns_record_type($tinydnsrecord) {
+ $rtype = "";
+ $rtype2 = "";
+ $rdns = "";
+ switch ($tinydnsrecord) {
+ case($tinydnsrecord[0] == "."):
+ $rtype = "SOA";
+ $rtype2 = "NS";
+ break;
+ case($tinydnsrecord[0] == "="):
+ $rtype = "A";
+ $rtype2 = "PTR";
+ $rdns = "on";
+ break;
+ case($tinydnsrecord[0] == "+"):
+ $rtype = "A";
+ break;
+ case($tinydnsrecord[0] == "@"):
+ $rtype = "MX";
+ break;
+ case($tinydnsrecord[0] == "^"):
+ $rtype = "PTR";
+ $rdns = "on";
+ break;
+ case($tinydnsrecord[0] == "&"):
+ $rtype = "NS";
+ break;
+ case($tinydnsrecord[0] == "'"):
+ $rtype = "TXT";
+ break;
+ case($tinydnsrecord[0] == "C"):
+ $rtype = "CNAME";
+ break;
+ case($tinydnsrecord[0] == "Z"):
+ $rtype = "SOA";
+ break;
+ default:
+ $rtype = "";
+ }
+ return array ($rtype, $rtype2, $rdns);
+}
+
+/* This function will be replaced by an auto detect DNS cache servers routine */
+/* At the moment there is no tagging of DNSroute to a WAN port. It needs to be added */
+function tinydns_dnscache_forwarding_servers() {
+ $fr = fopen("/var/etc/resolv.conf.dnscache", "r");
+ if (! $fr) {
+ printf("Error: cannot open resolv.conf.dnscache in tinydns_register_forwarding_servers().\n");
+ return 1;
+ }
+
+ $lip = strlen("nameserver") + 1;
+ $j = 0;
+ $iprecords = "";
+ while (!feof($fr)) {
+ $routers = fgets($fr, 4096);
+ $discard = ($routers[0] == "\n");
+ if(!$discard) {
+ if ($routerip = strstr($routers,"nameserver")) {
+ $routerip = substr($routerip,$lip);
+ if($routerip) {
+ $j += 1;
+ $routera = "{$routerip}";
+ $iprecords .= $routera;
+ }
+ }
+ }
+ }
+ fclose($fr);
+ exec("echo 1 > /etc/dnscache/env/FORWARDONLY");
+ if(is_dir("/etc/dnscache/root/servers/"))
+ exec("rm -R /etc/dnscache/root/servers/");
+ exec("mkdir /etc/dnscache/root/servers/");
+ $fr = fopen("/etc/dnscache/root/servers/@", "w");
+ if (! $fr) {
+ printf("Error: cannot write to /etc/dnscache/root/servers/@ in tinydns_dnscache_forwarding_servers().\n");
+ return 1;
+ }
+ if($iprecords)
+ fwrite($fr, $iprecords);
+ fclose($fr);
+}
+
+/* This routine adds filenames to /etc/dnscache/root/servers/ with the contents pointing to the tinyDNS server */
+function tinydns_create_soa_domain_list($dnsserverip) {
+ if(file_exists("/service/tinydns/root/data"))
+ $tinydns_data = file_get_contents("/service/tinydns/root/data");
+ else
+ $tinydns_data = "";
+
+ $datalen = strlen($tinydns_data);
+ $startofrecord = 0;
+ while ($startofrecord < $datalen ) {
+ $endofrecord = strpos($tinydns_data,"\n",$startofrecord);
+ $dnsrecord = substr($tinydns_data,$startofrecord,$endofrecord-$startofrecord);
+ $startofrecord = $endofrecord + 1;
+
+ $col1 = strpos($dnsrecord,":");
+ $fqdn = substr($dnsrecord,1,$col1-1);
+ if($fqdn) {
+ $rtypes = tinydns_get_dns_record_type($dnsrecord);
+ if($rtypes[0] == "SOA") {
+ $fr = fopen("/etc/dnscache/root/servers/{$fqdn}", "w");
+ if (! $fr) {
+ printf("Error: cannot open /etc/dnscache/root/servers/{$fqdn} in tinydns_create_soa_domain_list().\n");
+ return 1;
+ }
+ if($fqdn)fwrite($fr, $dnsserverip);
+ fclose($fr);
+ }
+ }
+ }
+}
+
+/* This function is not called */
+/* At the moment there is no tagging of DNSroute to a WAN port. It needs to be added */
+function tinydns_register_forwarding_servers() {
+ $fr = fopen("/var/etc/resolv.conf", "r");
+ if (! $fr) {
+ printf("Error: cannot open resolv.conf in tinydns_register_forwarding_servers().\n");
+ return 1;
+ }
+
+ $lip = strlen("nameserver") + 1;
+ $j = 0;
+ $nsrecords = "";
+ $arecords = "";
+ while (!feof($fr)) {
+ $routers = fgets($fr, 4096);
+ $discard = ($routers[0] == "\n");
+ if(!$discard) {
+ if ($routerip = strstr($routers,"nameserver")) {
+ $routerip = substr($routerip,$lip);
+ if($routerip) {
+ $j += 1;
+ $routerfqdn = "DNSroute-{$j}.wan{$j}";
+ $routerns = "&::{$routerfqdn}";
+ $routera = "={$routerfqdn}:{$routerip}";
+ $nsrecords .= $routerns . "\n";
+ $arecords .= $routera;
+ }
+ }
+ }
+ }
+ fclose($fr);
+ $dnsroutes ="{$nsrecords}{$arecords}";
+ return $dnsroutes;
+}
+
+function tinydns_register_root_servers() {
+ $rootservers =<<<EOD
+&::a.root-servers.net
+&::b.root-servers.net
+&::c.root-servers.net
+&::d.root-servers.net
+&::e.root-servers.net
+&::f.root-servers.net
+&::g.root-servers.net
+&::h.root-servers.net
+&::i.root-servers.net
+&::j.root-servers.net
+&::k.root-servers.net
+&::l.root-servers.net
+&::m.root-servers.net
+=a.root-servers.net:198.41.0.4
+=b.root-servers.net:128.9.0.107
+=c.root-servers.net:192.33.4.12
+=d.root-servers.net:128.8.10.90
+=e.root-servers.net:192.203.230.10
+=f.root-servers.net:192.5.5.241
+=g.root-servers.net:192.112.36.4
+=h.root-servers.net:128.63.2.53
+=i.root-servers.net:192.36.148.17
+=j.root-servers.net:192.58.128.30
+=k.root-servers.net:193.0.14.129
+=l.root-servers.net:199.7.83.42
+=m.root-servers.net:202.12.27.33
+
+EOD;
+ return $rootservers;
+}
+
+function dnscache_use_root_servers() {
+ $rootservers =<<<EOD
+198.41.0.4
+128.9.0.107
+192.33.4.12
+128.8.10.90
+192.203.230.10
+192.5.5.241
+192.112.36.4
+128.63.2.53
+192.36.148.17
+192.58.128.30
+193.0.14.129
+199.7.83.42
+202.12.27.33
+
+EOD;
+
+ exec("echo 0 > /etc/dnscache/env/FORWARDONLY");
+ if(is_dir("/etc/dnscache/root/servers/"))
+ exec("rm -R /etc/dnscache/root/servers/");
+ exec("mkdir /etc/dnscache/root/servers/");
+ $fr = fopen("/etc/dnscache/root/servers/@", "w");
+ if (! $fr) {
+ printf("Error: cannot write to /etc/dnscache/root/servers/@ in dnscache_use_root_servers().\n");
+ return 1;
+ }
+ fwrite($fr, $rootservers);
+ fclose($fr);
+}
+
+?> \ No newline at end of file
diff --git a/config/tinydns/tinydns.xml b/config/tinydns/tinydns.xml
new file mode 100644
index 00000000..fc1c3482
--- /dev/null
+++ b/config/tinydns/tinydns.xml
@@ -0,0 +1,309 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>tinydns</name>
+ <version>1.0</version>
+ <title>DNS Server: Settings</title>
+ <aftersaveredirect>/pkg_edit.php?xml=tinydns.xml&amp;id=0</aftersaveredirect>
+ <include_file>/usr/local/pkg/tinydns.inc</include_file>
+ <menu>
+ <name>DNS Servers</name>
+ <tooltiptext></tooltiptext>
+ <section>Services</section>
+ <url>/tinydns_status.php</url>
+ </menu>
+ <service>
+ <name>DNS Server</name>
+ <rcfile>svscan.sh</rcfile>
+ <executable>tinydns</executable>
+ <description>TinyDNS DNS Server</description>
+ </service>
+ <tabs>
+ <tab>
+ <text>Settings</text>
+ <url>/pkg_edit.php?xml=tinydns.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Add/Edit Record</text>
+ <url>/tinydns_filter.php</url>
+ </tab>
+ <tab>
+ <text>Failover Status</text>
+ <url>/tinydns_status.php</url>
+ </tab>
+ <tab>
+ <text>Logs</text>
+ <url>/tinydns_view_logs.php</url>
+ </tab>
+ <tab>
+ <text>Zone Sync</text>
+ <url>/pkg_edit.php?xml=tinydns_sync.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>New domain wizard</text>
+ <url>/wizard.php?xml=new_zone_wizard.xml</url>
+ </tab>
+ </tabs>
+ <configpath>installedpackages->package->tinydns</configpath>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>077</chmod>
+ <item>http://www.pfsense.com/packages/config/tinydns/tinydns.inc</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/pf/</prefix>
+ <chmod>077</chmod>
+ <item>http://www.pfsense.com/packages/config/tinydns/tinydns_xmlrpc_sync.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>077</chmod>
+ <item>http://www.pfsense.com/packages/config/tinydns/tinydns_domains.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>077</chmod>
+ <item>http://www.pfsense.com/packages/config/tinydns/tinydns_status.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>077</chmod>
+ <item>http://www.pfsense.com/packages/config/tinydns/tinydns_dhcp_filter.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>077</chmod>
+ <item>http://www.pfsense.com/packages/config/tinydns/tinydns_filter.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>077</chmod>
+ <item>http://www.pfsense.com/packages/config/tinydns/tinydns_down.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>077</chmod>
+ <item>http://www.pfsense.com/packages/config/tinydns/tinydns_up.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>077</chmod>
+ <item>http://www.pfsense.com/packages/config/tinydns/tinydns_parse_logs.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>077</chmod>
+ <item>http://www.pfsense.com/packages/config/tinydns/tinydns_view_logs.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>077</chmod>
+ <item>http://www.pfsense.com/packages/config/tinydns/tinydns_sync.xml</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/wizards/</prefix>
+ <chmod>077</chmod>
+ <item>http://www.pfsense.com/packages/config/tinydns/new_zone_wizard.xml</item>
+ </additional_files_needed>
+ <fields>
+ <field>
+ <type>listtopic</type>
+ <name>Binding IP Address</name>
+ <fieldname>temp</fieldname>
+ </field>
+ <field>
+ <fielddescr>IP Address</fielddescr>
+ <fieldname>ipaddress</fieldname>
+ <description>Bind TinyDNS to this IP address. Enable DNS Forwarders bind TinyDNS to the LAN IP.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <type>listtopic</type>
+ <name>DNS-Cache server</name>
+ <fieldname>temp</fieldname>
+ </field>
+ <field>
+ <fielddescr>Enable DNS Forwarders</fielddescr>
+ <fieldname>enableforwarding</fieldname>
+ <description>Enable DNScache forwarder on LAN IP and register LAN's SOA, NS, A, and PTR Records with TinyDNS Server.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Register DHCP static mappings with server</fielddescr>
+ <fieldname>regdhcpstatic</fieldname>
+ <description>Register static DHCP leases with TinyDNS server using the Fully Qualified Domain Name specified in System: General.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr>Register DHCP leases with server</fielddescr>
+ <fieldname>regdhcp</fieldname>
+ <description>Register active DHCP leases with TinyDNS server using the Fully Qualified Domain Name specified in System: General.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <type>listtopic</type>
+ <name>Monitoring address refresh interval</name>
+ <fieldname>temp</fieldname>
+ </field>
+ <field>
+ <fielddescr>Refresh Interval</fielddescr>
+ <fieldname>refreshinterval</fieldname>
+ <description>Controls how often the monitoring ip adresses are polled</description>
+ <type>input</type>
+ </field>
+ <field>
+ <type>listtopic</type>
+ <name>Sync TinyDNS settings via XMLRPC</name>
+ <fieldname>temp</fieldname>
+ </field>
+ <field>
+ <fielddescr>XMLRPC Sync</fielddescr>
+ <fieldname>syncxmlrpc</fieldname>
+ <description>Sync TinyDNS configuration to backup firewalls</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <type>listtopic</type>
+ <name>Zone transfers</name>
+ <fieldname>temp</fieldname>
+ </field>
+ <field>
+ <fielddescr>Hosts allowed to perform DNS Zone Transfers - Note: this requires TCP port 53 firewall permit rule!</fielddescr>
+ <fieldname>none</fieldname>
+ <type>rowhelper</type>
+ <rowhelper>
+ <rowhelperfield>
+ <fielddescr>IP Address</fielddescr>
+ <fieldname>ztipaddress</fieldname>
+ <description>Enter the IP Address that is allowed to transfer zone records (ex: 4.2.2.1)</description>
+ <type>input</type>
+ <size>20</size>
+ </rowhelperfield>
+ <rowhelperfield>
+ <fielddescr>DNS Zone - Use * for all Zones</fielddescr>
+ <fieldname>dnszone</fieldname>
+ <description>Enter the DNS zone that this IP address is allowed to transfer (ex: domain.com)</description>
+ <type>input</type>
+ <size>20</size>
+ </rowhelperfield>
+ </rowhelper>
+ </field>
+ <field>
+ <type>listtopic</type>
+ <name>Advanced tunables (OPTIONAL)</name>
+ <fieldname>temp</fieldname>
+ </field>
+ <field>
+ <fielddescr>Minimum segment size</fielddescr>
+ <fieldname>minsegment</fieldname>
+ <description>Recommended size: 10240 or larger.</description>
+ <type>input</type>
+ <value>10240</value>
+ </field>
+ <field>
+ <fielddescr>Maximum file size</fielddescr>
+ <fieldname>maxfilesize</fieldname>
+ <description>Recommended size: 10240 or larger.</description>
+ <type>input</type>
+ <value>10240</value>
+ </field>
+ <field>
+ <fielddescr>Max Segment size</fielddescr>
+ <fieldname>maxsegment</fieldname>
+ <description>Recommended size: 20480 or larger.</description>
+ <type>input</type>
+ <value>20480</value>
+ </field>
+ <field>
+ <fielddescr>Maximum file descriptors</fielddescr>
+ <fieldname>maxfd</fieldname>
+ <description>Recommended size: 100 or larger.</description>
+ <type>input</type>
+ <value>100</value>
+ </field>
+ <field>
+ <fielddescr>Maximum children processes</fielddescr>
+ <fieldname>maxchild</fieldname>
+ <description>Recommended size: 40 or larger.</description>
+ <type>input</type>
+ <value>40</value>
+ </field>
+ </fields>
+ <custom_delete_php_command>
+ tinydns_custom_php_changeip_command();
+ tinydns_custom_php_install_command();
+ tinydns_create_zone_file();
+ tinydns_setup_ping_items();
+ tinydns_sync_on_changes();
+ </custom_delete_php_command>
+ <custom_add_php_command>
+ tinydns_custom_php_changeip_command();
+ tinydns_custom_php_install_command();
+ tinydns_create_zone_file();
+ tinydns_setup_ping_items();
+ tinydns_sync_on_changes();
+ </custom_add_php_command>
+ <custom_php_resync_config_command>
+ tinydns_custom_php_changeip_command();
+ tinydns_custom_php_install_command();
+ tinydns_create_zone_file();
+ tinydns_setup_ping_items();
+ tinydns_sync_on_changes();
+ </custom_php_resync_config_command>
+ <custom_php_install_command>
+ tinydns_custom_php_install_command();
+ tinydns_sync_on_changes();
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ tinydns_custom_php_deinstall_command();
+ tinydns_sync_on_changes();
+ </custom_php_deinstall_command>
+ <custom_php_command_before_form>
+ unset($_POST['temp']);
+ </custom_php_command_before_form>
+</packagegui> \ No newline at end of file
diff --git a/config/tinydns/tinydns_dhcp_filter.php b/config/tinydns/tinydns_dhcp_filter.php
new file mode 100644
index 00000000..c92abcf8
--- /dev/null
+++ b/config/tinydns/tinydns_dhcp_filter.php
@@ -0,0 +1,129 @@
+<?php
+/* $Id$ */
+/*
+ tinydns_dhcp_filter.php
+ Copyright (C) 2006 Scott Ullrich
+ Parts Copyright (C) 2007 Goffredo Andreone <GAndreone@imapro.com>
+ part of pfSense
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+##|+PRIV
+##|*IDENT=page-tinydns-dhcp-filter
+##|*NAME=TinyDNS: DHCP Domains
+##|*DESCR=Allow access to the TinyDNS View Domains page
+##|*MATCH=tinydns_dhcp_filter*
+##|-PRIV
+
+require("/usr/local/pkg/tinydns.inc");
+require("guiconfig.inc");
+
+$pgtitle = "TinyDNS: DHCP Domains";
+include("head.inc");
+
+$pfSversion = str_replace("\n", "", file_get_contents("/etc/version"));
+if(strstr($pfSversion, "1.2"))
+ $one_two = true;
+
+?>
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<?php include("fbegin.inc"); ?>
+
+<?php if($one_two): ?>
+<p class="pgtitle"><?=$pgtitle?></font></p>
+<?php endif; ?>
+
+<?php if ($savemsg) print_info_box($savemsg); ?>
+
+<div id="mainlevel">
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+<?php
+ $tab_array = array();
+ $tab_array[] = array(gettext("Settings"), false, "/pkg_edit.php?xml=tinydns.xml&id=0");
+ $tab_array[] = array(gettext("Add/Edit Record"), false, "/tinydns_filter.php");
+ $tab_array[] = array(gettext("Failover Status"), false, "/tinydns_status.php");
+ $tab_array[] = array(gettext("Logs"), false, "/tinydns_view_logs.php");
+ $tab_array[] = array(gettext("Zone Sync"), false, "/tinydns_xmlrpc_sync.php");
+ $tab_array[] = array(gettext("New domain wizard"), false, "/wizard.php?xml=new_zone_wizard.xml");
+ display_top_tabs($tab_array);
+?>
+</table>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabcont" >
+ <form action="tinydns_dhcp_filter.php" method="post">
+ </form>
+ </td>
+ </tr>
+ <tr>
+ <td class="tabcont" >
+ <table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td width="45%" class="listhdrr">Fully Qualified Domain Name (Hostname)</td>
+ <td width="15%" class="listhdrr">Record types</td>
+ <td width="5%" class="listhdrr">rDNS</td>
+ <td width="35%" class="listhdrr">IP Address or FQDN</td>
+ </tr>
+
+<?php
+if(file_exists("/service/tinydns/root/data"))
+ $tinydns_data = file_get_contents("/service/tinydns/root/data");
+else
+ $tinydns_data = "";
+
+$datalen = strlen($tinydns_data);
+$startofrecord = 0;
+while ($startofrecord < $datalen ){
+ $endofrecord = strpos($tinydns_data,"\n",$startofrecord);
+ $dnsrecord = substr($tinydns_data,$startofrecord,$endofrecord-$startofrecord);
+ $startofrecord = $endofrecord + 1;
+
+ $col1 = strpos($dnsrecord,":");
+ $fqdn = substr($dnsrecord,1,$col1-1);
+ $rtypes = tinydns_get_dns_record_type($dnsrecord);
+ if($rtypes[0] == "SOA")
+ $ip = substr($dnsrecord,$col1+2);
+ else
+ $ip = substr($dnsrecord,$col1+1);
+ /* For root-servers get rid of the leading colon */
+ if($ip[0] == ":")$ip = substr($ip,1);
+ if(!$rtypes[2])$rtypes[2] = "na";
+ if(!$fqdn)$fqdn = ".";
+ echo "<tr>";
+ echo "<td class=\"listlr\">$fqdn</td>";
+ echo "<td class=\"listlr\">$rtypes[0] $rtypes[1]</td>";
+ echo "<td class=\"listlr\">$rtypes[2]</td>";
+ echo "<td class=\"listlr\">$ip</td>";
+ echo "</tr>";
+}
+?>
+ </table>
+ </td>
+ </tr>
+</table>
+</div>
+<?php include("fend.inc"); ?>
+<meta http-equiv="refresh" content="60;url=<?php print $_SERVER['SCRIPT_NAME']; ?>">
+</body>
+</html>
diff --git a/config/tinydns/tinydns_domains.xml b/config/tinydns/tinydns_domains.xml
new file mode 100644
index 00000000..3e313511
--- /dev/null
+++ b/config/tinydns/tinydns_domains.xml
@@ -0,0 +1,234 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ tinydns_domains.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2008 Scott Ullrich
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>tinydnsdomains</name>
+ <version>none</version>
+ <title>TinyDNS: Domains</title>
+ <include_file>/usr/local/pkg/tinydns.inc</include_file>
+ <tabs>
+ <tab>
+ <text>Settings</text>
+ <url>/pkg_edit.php?xml=tinydns.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Add/Edit Record</text>
+ <url>/tinydns_filter.php</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Failover Status</text>
+ <url>/tinydns_status.php</url>
+ </tab>
+ <tab>
+ <text>Logs</text>
+ <url>/tinydns_view_logs.php</url>
+ </tab>
+ <tab>
+ <text>Sync</text>
+ <url>/pkg_edit.php?xml=tinydns_sync.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>New domain wizard</text>
+ <url>/wizard.php?xml=new_zone_wizard.xml</url>
+ </tab>
+ </tabs>
+ <configpath>installedpackages->package->tinydnsdomains</configpath>
+ <adddeleteeditpagefields>
+ <columnitem>
+ <fielddescr>Fully Qualified Domain Name (Hostname)</fielddescr>
+ <fieldname>hostname</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Record type</fielddescr>
+ <fieldname>recordtype</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>rDNS</fielddescr>
+ <fieldname>rdns</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>IP Address</fielddescr>
+ <fieldname>ipaddress</fieldname>
+ </columnitem>
+ </adddeleteeditpagefields>
+ <fields>
+ <field>
+ <type>listtopic</type>
+ <name>General</name>
+ <fieldname>temp</fieldname>
+ </field>
+ <field>
+ <fielddescr>Hostname or FQDN www.exampledomain.com</fielddescr>
+ <fieldname>hostname</fieldname>
+ <description>The DNS server will supply Records for the Fully Qualified Domain Name that is entered</description>
+ <type>input</type>
+ <size>35</size>
+ <required/>
+ </field>
+ <field>
+ <fielddescr>Record type</fielddescr>
+ <fieldname>recordtype</fieldname>
+ <description>DNS Record types. A, PTR, MX, NS, SOA, TXT, CNAME</description>
+ <type>select</type>
+ <size>1</size>
+ <required/>
+ <options>
+ <option><name></name><value></value></option>
+ <option><name>A</name><value>A</value></option>
+ <option><name>MX</name><value>MX</value></option>
+ <option><name>NS</name><value>NS</value></option>
+ <option><name>SOA</name><value>SOA</value></option>
+ <option><name>PTR</name><value>PTR</value></option>
+ <option><name>CNAME</name><value>CNAME</value></option>
+ <option><name>TXT</name><value>TXT</value></option>
+ </options>
+ </field>
+ <field>
+ <fielddescr> FQDN or IP Address</fielddescr>
+ <fieldname>ipaddress</fieldname>
+ <description>IP Address for A Records. FQDN or Hostname for SOA, PTR, CNAME Records. For NS Records an IP:FQDN</description>
+ <type>input</type>
+ <size>40</size>
+ <required/>
+ </field>
+ <field>
+ <fielddescr>DNS record time to live</fielddescr>
+ <fieldname>ttl</fieldname>
+ <type>input</type>
+ <size>35</size>
+ </field>
+ <field>
+ <type>listtopic</type>
+ <name>Reverse lookup</name>
+ <fieldname>temp</fieldname>
+ </field>
+ <field>
+ <fielddescr>Automatic PTR entry</fielddescr>
+ <fieldname>rdns</fieldname>
+ <description>Create a reverse DNS (PTR) entry for this A Record?</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <type>listtopic</type>
+ <name>Failover</name>
+ <fieldname>temp</fieldname>
+ </field>
+ <field>
+ <fielddescr>IP to ping to ensure service is up</fielddescr>
+ <fieldname>monitorip</fieldname>
+ <type>input</type>
+ <size>35</size>
+ </field>
+ <field>
+ <fielddescr>Time in minutes before DNS switches to backup host</fielddescr>
+ <fieldname>threshhold</fieldname>
+ <type>input</type>
+ <size>35</size>
+ </field>
+ <field>
+ <fielddescr>none</fielddescr>
+ <fieldname>none</fieldname>
+ <type>rowhelper</type>
+ <rowhelper>
+ <rowhelperfield>
+ <fielddescr>Failover IP</fielddescr>
+ <fieldname>failoverip</fieldname>
+ <description>Failover IP when host is not responding to ICMP/PING traffic</description>
+ <type>input</type>
+ <size>25</size>
+ </rowhelperfield>
+ <rowhelperfield>
+ <fielddescr>Load balance</fielddescr>
+ <fieldname>loadbalance</fieldname>
+ <description>Adds this member to active group when host is alive.</description>
+ <type>checkbox</type>
+ </rowhelperfield>
+ <rowhelperfield>
+ <fielddescr>Ping threshold</fielddescr>
+ <fieldname>pingthreshold</fieldname>
+ <description>When the MS time is surpassed, item will failover to next host</description>
+ <type>input</type>
+ <size>7</size>
+ </rowhelperfield>
+ <rowhelperfield>
+ <fielddescr>Wan ping threshold</fielddescr>
+ <fieldname>wanpingthreshold</fieldname>
+ <description>When the WAN MS ping time is surpassed, item will failover to next host</description>
+ <type>input</type>
+ <size>7</size>
+ </rowhelperfield>
+ <rowhelperfield>
+ <fielddescr>IP to ping to ensure service is up</fielddescr>
+ <fieldname>monitorip</fieldname>
+ <description>When the WAN MS ping time is surpassed, item will failover to next host</description>
+ <type>input</type>
+ <size>15</size>
+ </rowhelperfield>
+ </rowhelper>
+ </field>
+ </fields>
+ <custom_delete_php_command>
+ tinydns_create_zone_file();
+ tinydns_setup_ping_items();
+ tinydns_sync_on_changes();
+ </custom_delete_php_command>
+ <custom_add_php_command>
+ log_error("Begin tinydns add");
+ tinydns_create_zone_file();
+ log_error("Zone file done.");
+ tinydns_setup_ping_items();
+ log_error("Ping items done.");
+ tinydns_sync_on_changes();
+ </custom_add_php_command>
+ <custom_php_resync_config_command>
+ log_error("Begin tinydns resync");
+ tinydns_create_zone_file();
+ log_error("Zone file done.");
+ tinydns_setup_ping_items();
+ log_error("Ping items done.");
+ tinydns_sync_on_changes();
+ </custom_php_resync_config_command>
+ <custom_php_command_before_form>
+ unset($_POST['temp']);
+ </custom_php_command_before_form>
+</packagegui>
diff --git a/config/tinydns/tinydns_down.php b/config/tinydns/tinydns_down.php
new file mode 100644
index 00000000..19eaa4ae
--- /dev/null
+++ b/config/tinydns/tinydns_down.php
@@ -0,0 +1,42 @@
+#!/usr/local/bin/php -f
+<?php
+
+/* $Id$ */
+/*
+ tinydns_down.php
+ Copyright (C) 2006 Scott Ullrich
+ part of pfSense
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require_once("functions.inc");
+require_once("config.inc");
+require_once("/usr/local/pkg/tinydns.inc");
+
+tinydns_create_zone_file();
+tinydns_setup_ping_items();
+
+exit(0);
+
+?> \ No newline at end of file
diff --git a/config/tinydns/tinydns_filter.php b/config/tinydns/tinydns_filter.php
new file mode 100644
index 00000000..88819932
--- /dev/null
+++ b/config/tinydns/tinydns_filter.php
@@ -0,0 +1,38 @@
+<?php
+
+/* $Id$ */
+/*
+ tinydns_filter.php
+ Copyright (C) 2006 Scott Ullrich
+ part of pfSense
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/* for now, redirect to unsorted raw CoreGUI page */
+Header("Location: pkg.php?xml=tinydns_domains.xml");
+exit;
+
+require("/usr/local/pkg/tinydns.inc");
+
+?> \ No newline at end of file
diff --git a/config/tinydns/tinydns_parse_logs.php b/config/tinydns/tinydns_parse_logs.php
new file mode 100644
index 00000000..2b316d4c
--- /dev/null
+++ b/config/tinydns/tinydns_parse_logs.php
@@ -0,0 +1,96 @@
+#!/usr/local/bin/php
+<?php
+
+/* $Id$ */
+/*
+ tinydns_parse_logs.inc
+ Copyright (C) 2006 Scott Ullrich
+ part of pfSense
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+$query_type = array(
+ "0001" => "A",
+ "0002" => "NS",
+ "0005" => "CNAME",
+ "0006" => "SOA",
+ "000c" => "PTR",
+ "000f" => "MX",
+ "0010" => "TXT",
+ "001c" => "AAAA",
+ "0021" => "RT",
+ "0026" => "A6",
+ "00fb" => "IXFR",
+ "00fc" => "AXFR",
+ "00ff" => "*"
+ );
+
+$results = array(
+ "+" => "responded",
+ "-" => "not_authority",
+ "I" => "not_implemented/invalid",
+ "C" => "wrong_class",
+ "/" => "not_parsed"
+ );
+
+$fp = fopen('php://stdin', 'r');
+
+/* loop through stdin and process text */
+while (!feof($fp)) {
+ $stdintext = chop(fgets($fp));
+ preg_match('/^(\S+ \S+) ([^:]+):([^:]+):([^:]+) (\S+) (\S+) (\S+)$/', $stdintext, $items);
+ $stamp = $items[1];
+ $rawip = $items[2];
+ $port = $items[3];
+ $id = $items[4];
+ $result = $items[5];
+ $type = $items[6];
+ $name = $items[7];
+ if (isset($query_type[$type]))
+ $qtype = $query_type[$type];
+ else
+ $qtype = $type;
+ $desc = $results[$result];
+ $ip = decodeipaddress($rawip);
+ //echo "RAWIP: $rawip $ip";
+ printf("%s %15.15s:%-4.4s %-8.8s %-24.24s %s\n",$stamp,$ip,hexdec($port),$qtype,$desc,$name);
+}
+
+function decodeipaddress($text) {
+ preg_match('/(..)(..)(..)(..)/', $text, $hexitems);
+ $ipaddr = "";
+ unset($hexitems[0]);
+ $isfirst = true;
+ foreach($hexitems as $hexitem) {
+ if(!$isfirst)
+ $ipaddr .= ".";
+ $ipaddr .= hexdec($hexitem);
+ $isfirst = false;
+ }
+ return $ipaddr;
+}
+
+fclose($fp);
+
+?> \ No newline at end of file
diff --git a/config/tinydns/tinydns_status.php b/config/tinydns/tinydns_status.php
new file mode 100644
index 00000000..147001af
--- /dev/null
+++ b/config/tinydns/tinydns_status.php
@@ -0,0 +1,188 @@
+<?php
+/* $Id$ */
+/*
+ tinydns_status.php
+ part of pfSense (http://www.pfsense.com/)
+
+ Copyright (C) 2006 Scott Ullrich <sullrich@gmail.com>
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require("guiconfig.inc");
+
+/* Defaults to this page but if no settings are present, redirect to setup page */
+if(!$config['installedpackages']['tinydnsdomains']['config'])
+ Header("Location: /wizard.php?xml=new_zone_wizard.xml");
+
+if(!$config['installedpackages']['tinydns']['config'][0]['ipaddress'])
+ Header("Location: /pkg_edit.php?xml=tinydns.xml&id=0&savemsg=Please+set+the+binding+ip+address+for+server+operation");
+
+$pgtitle = "TinyDNS: Status";
+include("head.inc");
+
+$pfSversion = str_replace("\n", "", file_get_contents("/etc/version"));
+if(strstr($pfSversion, "1.2"))
+ $one_two = true;
+
+?>
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<?php include("fbegin.inc"); ?>
+
+<?php if($one_two): ?>
+<p class="pgtitle"><?=$pgtitle?></font></p>
+<?php endif; ?>
+
+<?php if ($savemsg) print_info_box($savemsg); ?>
+
+<div id="mainlevel">
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+<?php
+ $tab_array = array();
+ $tab_array[] = array(gettext("Settings"), false, "/pkg_edit.php?xml=tinydns.xml&id=0");
+ $tab_array[] = array(gettext("Add/Edit Record"), false, "/tinydns_filter.php");
+ $tab_array[] = array(gettext("Failover Status"), true, "/tinydns_status.php");
+ $tab_array[] = array(gettext("Logs"), false, "/tinydns_view_logs.php");
+ $tab_array[] = array(gettext("Zone Sync"), false, "/pkg_edit.php?xml=tinydns_sync.xml&id=0");
+ $tab_array[] = array(gettext("New domain wizard"), false, "/wizard.php?xml=new_zone_wizard.xml");
+ display_top_tabs($tab_array);
+?>
+</table>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabcont" >
+ <form action="tinydns_status.php" method="post">
+ </form>
+ </td>
+ </tr>
+ <tr>
+ <td class="tabcont" >
+ <table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td width="55%" class="listhdrr">IP</td>
+ <td width="15%" class="listhdrr">Status</td>
+ <td width="15%" class="listhdrr">In Service</td>
+ <td width="25%" class="listhdrr">Response time</td>
+ </tr>
+
+<?php
+$pingdir = return_dir_as_array("/var/db/pingstatus");
+if(file_exists("/service/tinydns/root/data"))
+ $tinydns_data = file_get_contents("/service/tinydns/root/data");
+else
+ $tinydns_data = "";
+if($config['installedpackages']['tinydnsdomains'])
+foreach($config['installedpackages']['tinydnsdomains']['config'] as $ping) {
+ if($ping['recordtype'] == "SOA")
+ continue;
+ if(!$ping['row'])
+ continue;
+ $ipaddress = $ping['ipaddress'];
+ $hostname = $ping['hostname'];
+ $monitorip = $ping['monitorip'];
+ if(file_exists("/var/db/pingstatus/$monitorip"))
+ $status = file_get_contents("/var/db/pingstatus/$monitorip");
+ else
+ $status = "N/A";
+ if(stristr($tinydns_data, "+{$hostname}:{$ipaddress}"))
+ $inservice = "<FONT COLOR='GREEN'>YES</FONT>";
+ else
+ $inservice = "<FONT COLOR='BLUE'>NO</FONT>";
+ echo "<tr>";
+ echo "<td class=\"listlr\">";
+ echo "$hostname<br>&nbsp;&nbsp;&nbsp;|->&nbsp;$ipaddress";
+ echo "</td>";
+ echo "<td class=\"listlr\">";
+ if(stristr($status,"DOWN"))
+ echo "<FONT COLOR='red'>DOWN</FONT>";
+ else
+ echo "UP";
+ echo "</td>";
+
+ echo "<td class=\"listlr\">";
+ echo $inservice;
+ echo "</td>";
+
+ echo "<td class=\"listlr\">";
+ if(!$monitorip)
+ $monitorip = $ipaddress;
+ if(file_exists("/var/db/pingmsstatus/$monitorip"))
+ $msstatus = file_get_contents("/var/db/pingmsstatus/$monitorip");
+ else
+ $msstatus = "N/A";
+ echo "<!-- " . $monitorip . " -->" . $msstatus;
+ echo "</td>";
+ echo "</tr>";
+
+ foreach($ping['row'] as $row) {
+ $ipaddress = $row['failoverip'];
+ $monitorip = $row['monitorip'];
+ if(file_exists("/var/db/pingstatus/$monitorip"))
+ $status = file_get_contents("/var/db/pingstatus/$monitorip");
+ else
+ $status = "N/A";
+ echo "<tr>";
+ echo "<td class=\"listlr\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|->&nbsp;&nbsp;";
+ echo $ipaddress;
+ if($row['loadbalance'])
+ echo " (LB)";
+ if(stristr($tinydns_data, "+{$hostname}:{$row['monitorip']}"))
+ $inservice = "<FONT COLOR='GREEN'>YES</FONT>";
+ else
+ $inservice = "<FONT COLOR='BLUE'>NO</FONT>";
+ echo "</td>";
+ echo "<td class=\"listlr\">";
+ if(stristr($status,"DOWN"))
+ echo "<FONT COLOR='red'>DOWN</FONT>";
+ else
+ echo "UP";
+ echo "</td>";
+
+ echo "<td class=\"listlr\">";
+ echo $inservice;
+ echo "</td>";
+
+ echo "<td class=\"listlr\">";
+ if(!$monitorip)
+ $monitorip = $ipaddress;
+ if(file_exists("/var/db/pingmsstatus/$monitorip"))
+ $msstatus = file_get_contents("/var/db/pingmsstatus/$monitorip");
+ else
+ $msstatus = "N/A";
+
+ echo "<!-- " . $monitorip . " -->" . $msstatus;
+ echo "</td>";
+ echo "</tr>";
+ }
+ echo "<tr><td>&nbsp;</td></tr>";
+}
+?>
+ </table>
+ </td>
+ </tr>
+</table>
+</div>
+<?php include("fend.inc"); ?>
+<meta http-equiv="refresh" content="60;url=<?php print $_SERVER['SCRIPT_NAME']; ?>">
+</body>
+</html>
diff --git a/config/tinydns/tinydns_sync.xml b/config/tinydns/tinydns_sync.xml
new file mode 100644
index 00000000..091ae90a
--- /dev/null
+++ b/config/tinydns/tinydns_sync.xml
@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ tinydns_sync.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2008 Scott Ullrich
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>tinydnssync</name>
+ <version>1.0</version>
+ <title>TinyDNS: Manual Sync</title>
+ <include_file>/usr/local/pkg/tinydns.inc</include_file>
+ <tabs>
+ <tab>
+ <text>Settings</text>
+ <url>/pkg_edit.php?xml=tinydns.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Add/Edit Record</text>
+ <url>/tinydns_filter.php</url>
+ </tab>
+ <tab>
+ <text>Failover Status</text>
+ <url>/tinydns_status.php</url>
+ </tab>
+ <tab>
+ <text>Logs</text>
+ <url>/tinydns_view_logs.php</url>
+ </tab>
+ <tab>
+ <text>Zone Sync</text>
+ <url>/pkg_edit.php?xml=tinydns_sync.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>New domain wizard</text>
+ <url>/wizard.php?xml=new_zone_wizard.xml</url>
+ </tab>
+ </tabs>
+ <configpath>installedpackages->package->tinydns</configpath>
+ <fields>
+ <field>
+ <type>listtopic</type>
+ <fieldname>temp</fieldname>
+ <name>Enbable DNS zone sync</name>
+ </field>
+ <field>
+ <fielddescr>Automatically sync DNS zone changes</fielddescr>
+ <fieldname>synconchanges</fieldname>
+ <description>pfSense will automatically sync changes to the hosts defined below.</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <type>listtopic</type>
+ <name>Sync host #1</name>
+ <fieldname>temp</fieldname>
+ </field>
+ <field>
+ <fielddescr>IP Address</fielddescr>
+ <fieldname>ipaddress</fieldname>
+ <description>The IP address of the first host that TinyDNS will Sync its DNS zone data to.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Password</fielddescr>
+ <fieldname>password</fieldname>
+ <description>Admin password of the first host that TinyDNS will Sync its DNS zone data to.</description>
+ <type>password</type>
+ </field>
+ <field>
+ <type>listtopic</type>
+ <name>Sync host #2</name>
+ <fieldname>temp</fieldname>
+ </field>
+ <field>
+ <fielddescr>IP Address 2</fielddescr>
+ <fieldname>ipaddress2</fieldname>
+ <description>OPTIONAL. The IP address of the second host that TinyDNS will Sync its DNS zone data to.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Password 2</fielddescr>
+ <fieldname>password2</fieldname>
+ <description>Admin password of the second host that TinyDNS will Sync its DNS zone data to.</description>
+ <type>password</type>
+ </field>
+ <field>
+ <type>listtopic</type>
+ <name>Sync host #3</name>
+ <fieldname>temp</fieldname>
+ </field>
+ <field>
+ <fielddescr>IP Address 3</fielddescr>
+ <fieldname>ipaddress3</fieldname>
+ <description>OPTIONAL. The IP address of the third host that TinyDNS will Sync its DNS zone data to.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Password 3</fielddescr>
+ <fieldname>password3</fieldname>
+ <description>Admin password of the third host that TinyDNS will Sync its DNS zone data to.</description>
+ <type>password</type>
+ </field>
+ </fields>
+ <custom_php_resync_config_command>
+ tinydns_sync_on_changes();
+ </custom_php_resync_config_command>
+ <custom_php_command_before_form>
+ unset($_POST['temp']);
+ </custom_php_command_before_form>
+</packagegui> \ No newline at end of file
diff --git a/config/tinydns/tinydns_up.php b/config/tinydns/tinydns_up.php
new file mode 100644
index 00000000..c06ad74c
--- /dev/null
+++ b/config/tinydns/tinydns_up.php
@@ -0,0 +1,42 @@
+#!/usr/local/bin/php -f
+<?php
+
+/* $Id$ */
+/*
+ tinydns_up.php
+ Copyright (C) 2006 Scott Ullrich
+ part of pfSense
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require_once("functions.inc");
+require_once("config.inc");
+require_once("/usr/local/pkg/tinydns.inc");
+
+tinydns_create_zone_file();
+tinydns_setup_ping_items();
+
+exit(0);
+
+?> \ No newline at end of file
diff --git a/config/tinydns/tinydns_view_logs.php b/config/tinydns/tinydns_view_logs.php
new file mode 100644
index 00000000..d205a630
--- /dev/null
+++ b/config/tinydns/tinydns_view_logs.php
@@ -0,0 +1,122 @@
+<?php
+/* $Id$ */
+/*
+ tinydns_view_logs.php
+ part of pfSense (http://www.pfsense.com/)
+
+ Copyright (C) 2006 Scott Ullrich <sullrich@gmail.com>
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require("guiconfig.inc");
+
+if($_REQUEST['getactivity']) {
+ $tinydnslogs = `cat /etc/tinydns/log/main/current | /usr/local/bin/tai64nlocal | php -f /usr/local/pkg/tinydns_parse_logs.php | grep -v ":0"`;
+ echo "TinyDNS Server logs as of " . date("D M j G:i:s T Y") . "\n\n";
+ echo $tinydnslogs;
+ exit;
+}
+
+/* Defaults to this page but if no settings are present, redirect to setup page */
+if(!$config['installedpackages']['tinydns']['config'][0])
+ Header("Location: /pkg_edit.php?xml=tinydns.xml&id=0");
+
+$pfSversion = str_replace("\n", "", file_get_contents("/etc/version"));
+if(strstr($pfSversion, "1.2"))
+ $one_two = true;
+
+$pgtitle = "TinyDNS: View Logs";
+include("head.inc");
+
+/* NEED TO FIX there are 2 logs /etc/tinydns/log/main/current and /etc/dnscache/log/main/current */
+
+/* NEED TO FIX */
+if ($_POST['clear']) {
+// exec("rm /etc/tinydns/log/main/current");
+// exec("touch /etc/tinydns/log/main/current");
+}
+
+?>
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<script src="/javascript/scriptaculous/prototype.js" type="text/javascript"></script>
+ <script type="text/javascript">
+ function getlogactivity() {
+ var url = "/tinydns_view_logs.php";
+ var pars = 'getactivity=yes';
+ var myAjax = new Ajax.Request(
+ url,
+ {
+ method: 'post',
+ parameters: pars,
+ onComplete: activitycallback
+ });
+ }
+ function activitycallback(transport) {
+ $('tinydnslogs').innerHTML = '<font face="Courier"><pre>' + transport.responseText + '</pre></font>';
+ setTimeout('getlogactivity()', 2500);
+ }
+ setTimeout('getlogactivity()', 1000);
+ </script>
+<?php include("fbegin.inc"); ?>
+
+<?php if($one_two): ?>
+<p class="pgtitle"><?=$pgtitle?></font></p>
+<?php endif; ?>
+
+<?php if ($savemsg) print_info_box($savemsg); ?>
+
+<div id="mainlevel">
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+<?php
+ $tab_array = array();
+ $tab_array[] = array(gettext("Settings"), false, "/pkg_edit.php?xml=tinydns.xml&id=0");
+ $tab_array[] = array(gettext("Add/Edit Record"), false, "/tinydns_filter.php");
+ $tab_array[] = array(gettext("Failover Status"), false, "/tinydns_status.php");
+ $tab_array[] = array(gettext("Logs"), true, "/tinydns_view_logs.php");
+ $tab_array[] = array(gettext("Zone Sync"), false, "/pkg_edit.php?xml=tinydns_sync.xml&id=0");
+ $tab_array[] = array(gettext("New domain wizard"), false, "/wizard.php?xml=new_zone_wizard.xml");
+ display_top_tabs($tab_array);
+?>
+</table>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td class="tabcont" >
+ <form action="tinydns_view_logs.php" method="post">
+ <br>
+ <div id="tinydnslogs">
+ <pre>One moment please, loading TinyDNS logs...</pre>
+ </div>
+ </td>
+ </tr>
+</table>
+<td align="left" valign="top">
+ <form id="filterform" name="filterform" action="tinydns_view_logs.php" method="post" style="margin-top: 14px;">
+ <p/>
+ <input id="submit" name="clear" type="submit" class="formbtn" value="<?=gettext("Clear log");?>" />
+ </form>
+</td>
+</div>
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/tinydns/tinydns_xmlrpc_sync.php b/config/tinydns/tinydns_xmlrpc_sync.php
new file mode 100644
index 00000000..0610e286
--- /dev/null
+++ b/config/tinydns/tinydns_xmlrpc_sync.php
@@ -0,0 +1,59 @@
+<?php
+
+/* $Id$ */
+/*
+ tinydns_xmlrcpc_sync.php
+ Copyright (C) 2006 Scott Ullrich
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/* NOTE: this file gets included from the pfSense filter.inc plugin process */
+
+require_once("config.inc");
+require_once("/usr/local/pkg/tinydns.inc");
+require_once("service-utils.inc");
+
+if($notnow) {
+
+ /* disabled until Ticket #1318 can be fixed */
+
+ if(!$config) {
+ log_error("\$config is not enabled from tinydns_xmlrpc_sync.php!!");
+ } else {
+ if($config['installedpackages']['carpsettings']['config'])
+ $password = $config['installedpackages']['carpsettings']['config'][0]['password'];
+ if($config['installedpackages']['carpsettings']['config'])
+ $syncip = $config['installedpackages']['carpsettings']['config'][0]['synchronizetoip'];
+ if($config['installedpackages']['carpsettings']['config'])
+ $syncxmlrpc = $config['installedpackages']['tinydns']['config'][0]['syncxmlrpc'];
+ /* option enabled? */
+ if($syncxmlrpc)
+ if($syncip)
+ if($password)
+ tinydns_do_xmlrpc_sync($syncip, $password);
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/config/upclient.xml b/config/upclient.xml
new file mode 100644
index 00000000..42f71a25
--- /dev/null
+++ b/config/upclient.xml
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>upclient</name>
+ <version>5.0.b8_2</version>
+ <title>upclient: Settings</title>
+ <aftersaveredirect>pkg_edit.php?xml=upclient.xml&amp;id=0</aftersaveredirect>
+ <menu>
+ <name>upclient</name>
+ <tooltiptext>Modify upclient settings.</tooltiptext>
+ <section>Services</section>
+ <configfile>upclient.xml</configfile>
+ <url>/pkg_edit.php?xml=upclient.xml&amp;id=0</url>
+ </menu>
+ <service>
+ <name>upclient</name>
+ <rcfile>upclient.sh</rcfile>
+ <executable>upclient</executable>
+ </service>
+ <configpath>installedpackages->package->$packagename->configuration->settings</configpath>
+ <fields>
+ <field>
+ <fielddescr>Authorization Key</fielddescr>
+ <fieldname>authkey</fieldname>
+ <description>This system's uptime authorization key.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Update Interval</fielddescr>
+ <fieldname>interval</fieldname>
+ <description>The interval between updates, in seconds (default 550).</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>Uptime Server</fielddescr>
+ <fieldname>server</fieldname>
+ <description>The server this system should send uptime reports to.</description>
+ <type>input</type>
+ </field>
+ </fields>
+ <custom_php_global_functions>
+ function sync_package_upclient() {
+ global $config;
+ conf_mount_rw();
+ config_lock();
+ $upclient_conf = $config['installedpackages']['upclient']['config'][0];
+ $fout = fopen("/usr/local/etc/upclient.conf", "w");
+ if($upclient_conf['authkey'] and $upclient_conf['server']) {
+ fwrite($fout, "PidFile = /var/run/upclient.pid # Location of pid file\n");
+ fwrite($fout, "AuthKey = {$upclient_conf['authkey']}\n");
+ $interval = $upclient_conf['interval'] ? $upclient_conf['interval'] : "550";
+ fwrite($fout, "Interval = {$interval}\n");
+ fwrite($fout, "UptimeServer = {$upclient_conf['server']}\n");
+ $static = &lt;&lt;&lt;EOD
+SendIdle = 1 # Send CPU idle percent
+SendUsage = 1 # Send CPU load percent
+SendOSName = 1 # Send name of your Operating System
+SendOSVersion = 1 # Send version of your OS
+SendCPU = 1 # Send CPU name of your machine
+SendCPUDetail = 1 # (BSD, Linux &amp; Solaris only)
+SendLoadAvg = 1 # Send 15-minute Load-average (unix only)
+
+EOD;
+ fwrite($fout, $static);
+ fclose($fout);
+ }
+ $start = "/usr/local/sbin/upclient &amp;";
+ write_rcfile(array(
+ "file" => "upclient.sh",
+ "start" => $start
+ )
+ );
+ restart_service("upclient");
+ conf_mount_ro();
+ config_unlock();
+ }
+ </custom_php_global_functions>
+ <custom_add_php_command>
+ sync_package_upclient();
+ </custom_add_php_command>
+</packagegui>
+
diff --git a/config/viralator.inc b/config/viralator.inc
new file mode 100644
index 00000000..dc4e6041
--- /dev/null
+++ b/config/viralator.inc
@@ -0,0 +1,86 @@
+<?php
+require_once('config.inc');
+
+define('VIRALATOR_DOWNLOADDIR', '/usr/local/www/viralator');
+define('SQUIRM_CONF', '/usr/local/etc/squirm/squirm.conf');
+define('SQUIRM_PATTERNS', '/usr/local/etc/squirm/squirm.patterns');
+define('FORBIDDEN_EXTS', 'html htm css php pl js vbs jpg jpeg gif png');
+
+function viralator_install_command() {
+ if (!is_dir(VIRALATOR_DOWNLOADDIR)) mkdir(VIRALATOR_DOWNLOADDIR);
+
+ if (!is_file(SQUIRM_CONF)) {
+ $conf = <<<EOD
+begin
+network 0.0.0.0/0
+pattern squirm.patterns get
+end
+
+EOD;
+ file_put_contents(SQUIRM_CONF, $conf);
+ }
+
+ if (!is_dir(VIRALATOR_DOWNLOADDIR))
+ make_dirs(VIRALATOR_DOWNLOADDIR);
+}
+
+function viralator_validate_input($post, $input_errors) {
+ if (trim($post['http_otherexts'])) {
+ foreach (explode(',', $post['http_otherexts']) as $ext) {
+ $ext = trim($ext);
+ if (in_array($ext, explode(' ', FORBIDDEN_EXTS)))
+ $input_errors[] = "The HTTP virus scanner can't scan *.$ext files.";
+ else if (!preg_match('/\w+/', $ext))
+ $input_errors[] = "*.ext is not a valid file extension.";
+ }
+ }
+}
+
+function viralator_get_real_lan_ip() {
+ global $config;
+
+ $lan_if = $config['interfaces']['lan']['if'];
+ $line = trim(shell_exec("ifconfig $lan_if | grep inet | grep -v inet6"));
+ list($dummy, $ip) = explode(' ', $line);
+
+ return $ip;
+}
+
+function viralator_escape_dots($value) {
+ return preg_replace('/\./', '\\.', $value);
+}
+
+function viralator_resync() {
+ global $config;
+ $settings = $config['installedpackages']['clamav']['config'][0];
+
+ $exts = (empty($settings['http_exts']) ? array() : explode(',', $settings['http_exts']));
+
+ if (trim($settings['http_otherexts'])) {
+ foreach (explode(',', $settings['http_otherexts']) as $ext)
+ $exts[] = trim($ext);
+ }
+
+ $towrite = '';
+
+ // TODO: Escape any interface Squid listens on
+ $lan_ip = viralator_get_real_lan_ip();
+ if (is_ipaddr($lan_ip)) {
+ $escaped = viralator_escape_dots($lan_ip);
+ $towrite .= "abort regexi (^http://$escaped/.*)\n";
+ }
+
+ foreach (explode(' ', FORBIDDEN_EXTS) as $ext)
+ $towrite .= "abort .$ext\n";
+
+ foreach ($exts as $ext)
+ $towrite .= "regexi (^.*\\.$ext\$) http://$lan_ip/viralator.pl?url=\\1\n";
+
+ file_put_contents(SQUIRM_PATTERNS, $towrite);
+
+ if (is_package_installed('squid')) {
+ require_once('squid.inc');
+ squid_resync();
+ }
+}
+?>
diff --git a/config/viralator.xml b/config/viralator.xml
new file mode 100644
index 00000000..7573af94
--- /dev/null
+++ b/config/viralator.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>none</name>
+ <version>none</version>
+ <title>none</title>
+ <include_file>viralator.inc</include_file>
+ <additional_files_needed>
+ <item>http://www.pfsense.org/packages/config/viralator.inc</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <item>http://www.pfsense.org/packages/All/viralator.tgz</item>
+ </additional_files_needed>
+ <custom_php_install_command>
+ viralator_install_command();
+ </custom_php_install_command>
+</packagegui>
diff --git a/config/widentd.xml b/config/widentd.xml
new file mode 100644
index 00000000..ca73d436
--- /dev/null
+++ b/config/widentd.xml
@@ -0,0 +1,122 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ authng.xml
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 to whom it may belong
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>widentd</name>
+ <version>1.03_1</version>
+ <title>Services: widentd</title>
+ <menu>
+ <name>widentd</name>
+ <tooltiptext>Modify widentd settings.</tooltiptext>
+ <section>Services</section>
+ <url>pkg_edit.php?xml=widentd.xml&amp;id=0</url>
+ </menu>
+ <service>
+ <name>widentd</name>
+ <rcfile>widentd.sh</rcfile>
+ <executable>widentd</executable>
+ </service>
+ <configpath>installedpackages->package->$packagename->configuration->settings</configpath>
+ <fields>
+ <field>
+ <fielddescr>Listening interface</fielddescr>
+ <fieldname>interface</fieldname>
+ <description>Enter the desired listening interface here.</description>
+ <type>interfaces_selection</type>
+ </field>
+ <field>
+ <fielddescr>Username</fielddescr>
+ <fieldname>username</fieldname>
+ <description>Enter the username you'd like displayed via widentd.</description>
+ <type>input</type>
+ </field>
+ <field>
+ <fielddescr>System name</fielddescr>
+ <fieldname>sysname</fieldname>
+ <description>Enter the system name you'd like displayed via widentd</description>
+ <type>input</type>
+ <value>pfSense</value>
+ </field>
+ </fields>
+ <custom_php_global_functions>
+ function sync_package_widentd() {
+ conf_mount_rw();
+ config_lock();
+ global $config;
+ if (!isset($config['installedpackages']['widentd']['config'][0]['interface'])) {
+ $config['installedpackages']['widentd']['config'][0]['interface'] = 'WAN';
+ }
+ if (!isset($config['installedpackages']['widentd']['config'][0]['username'])) {
+ $config['installedpackages']['widentd']['config'][0]['username'] = 'user';
+ }
+ if (!isset($config['installedpackages']['widentd']['config'][0]['sysname'])) {
+ $config['installedpackages']['widentd']['config'][0]['sysname'] = 'UNIX';
+ }
+ $int = convert_friendly_interface_to_real_interface_name($config['installedpackages']['widentd']['config'][0]['interface']);
+ $ip = find_interface_ip($int);
+ $user = $config['installedpackages']['widentd']['config'][0]['username'];
+ $system = $config['installedpackages']['widentd']['config'][0]['sysname'];
+ $start = "/usr/local/sbin/widentd -u {$user} -o {$system} -i {$ip}";
+ $stop = "/usr/bin/killall widentd";
+ write_rcfile(array(
+ "file" => "widentd.sh",
+ "start" => $start,
+ "stop" => $stop
+ )
+ );
+ restart_service("widentd");
+ conf_mount_ro();
+ config_unlock();
+ }
+ </custom_php_global_functions>
+ <custom_add_php_command>
+ sync_package_widentd();
+ </custom_add_php_command>
+ <custom_php_install_command>
+ unlink_if_exists("/usr/local/etc/rc.d/widentd.sh");
+ </custom_php_install_command>
+</packagegui>
+
diff --git a/config/xsl/package.xsl b/config/xsl/package.xsl
new file mode 100644
index 00000000..cc2a69be
--- /dev/null
+++ b/config/xsl/package.xsl
@@ -0,0 +1,316 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* $Id$ */
+/* ========================================================================== */
+/*
+ package.xsl
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2007 Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ All rights reserved.
+
+ Based on m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+-->
+<xsl:stylesheet
+ version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:html="http://www.w3.org/1999/xhtml"
+ xmlns="http://www.w3.org/1999/xhtml"
+>
+ <xsl:output
+ method="xml"
+ doctype-system="http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"
+ doctype-public="-//W3C//DTD XHTML 1.1//EN"
+ />
+
+ <xsl:template match="/packagegui">
+ <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+ <head>
+ <meta name="DC.title">
+ <xsl:attribute name="content"><xsl:value-of select="//name"/></xsl:attribute>
+ </meta>
+ <meta name="DC.creator" content="Daniel S. Haischt" />
+ <meta name="DC.subject" content="Meta Data" />
+ <meta name="DC.description" content="Next gen user and group manager for pfSense" />
+ <meta name="DC.publisher" content="pfSense" />
+ <meta name="DC.date" content="2007-08-28T21:00:00+02:00" scheme="DCTERMS.W3CDTF" />
+ <meta name="DC.type" content="Text" scheme="DCTERMS.DCMIType" />
+ <meta name="DC.format" content="text/html" scheme="DCTERMS.IMT" />
+ <meta name="DC.language" content="en" scheme="DCTERMS.RFC3066" />
+ <meta name="DC.relation" content="http://dublincore.org/" scheme="DCTERMS.URI" />
+ <meta name="DC.coverage" content="Munich" scheme="DCTERMS.TGN" />
+ <meta name="DC.rights" content="All rights reserved" />
+ <meta http-equiv="Keywords" content="bsd license, altq, traffic shaping, packet, rule, Linux, OpenBSD, DragonFlyBSD, freebsd 5.3, vpn, stateful failover, carp, packet filter, m0n0wall, firewall" />
+ <style type="text/css">
+ @import url('http://www.pfsense.com/assets/site/style.css');
+ </style>
+ <script type="text/javascript" language="utf-8">
+ //<![CDATA[
+ function toggleContentItem(whichItem) {
+ var element = document.getElementById(whichItem);
+
+ element.style.visibility = 'visible';
+ element.style.display = 'block';
+ element.style.top = '0';
+ element.className = 'highLight';
+
+ if (whichItem != 'info-div') {
+ document.getElementById('info-div').style.visibility = 'hidden';
+ document.getElementById('info-div').style.display = 'none';
+ document.getElementById('info-div').className = '';
+ }
+ if (whichItem != 'license-div') {
+ document.getElementById('license-div').style.visibility = 'hidden';
+ document.getElementById('license-div').style.display = 'none';
+ document.getElementById('license-div').className = '';
+ }
+ if (whichItem != 'desc-div') {
+ document.getElementById('desc-div').style.visibility = 'hidden';
+ document.getElementById('desc-div').style.display = 'none';
+ document.getElementById('desc-div').className = '';
+ }
+ if (whichItem != 'req-div') {
+ document.getElementById('req-div').style.visibility = 'hidden';
+ document.getElementById('req-div').style.display = 'none';
+ document.getElementById('req-div').className = '';
+ }
+ if (whichItem != 'faq-div') {
+ document.getElementById('faq-div').style.visibility = 'hidden';
+ document.getElementById('faq-div').style.display = 'none';
+ document.getElementById('faq-div').className = '';
+ }
+ if (whichItem != 'files-div') {
+ document.getElementById('files-div').style.visibility = 'hidden';
+ document.getElementById('files-div').style.display = 'none';
+ document.getElementById('files-div').className = '';
+ }
+ if (whichItem != 'menu-div') {
+ document.getElementById('menu-div').style.visibility = 'hidden';
+ document.getElementById('menu-div').style.display = 'none';
+ document.getElementById('menu-div').className = '';
+ }
+ if (whichItem != 'tab-div') {
+ document.getElementById('tab-div').style.visibility = 'hidden';
+ document.getElementById('tab-div').style.display = 'none';
+ document.getElementById('tab-div').className = '';
+ }
+ if (whichItem != 'service-div') {
+ document.getElementById('service-div').style.visibility = 'hidden';
+ document.getElementById('service-div').style.display = 'none';
+ document.getElementById('service-div').className = '';
+ }
+ if (whichItem != 'rsync-div') {
+ document.getElementById('rsync-div').style.visibility = 'hidden';
+ document.getElementById('rsync-div').style.display = 'none';
+ document.getElementById('rsync-div').className = '';
+ }
+ if (whichItem != 'install-div') {
+ document.getElementById('install-div').style.visibility = 'hidden';
+ document.getElementById('install-div').style.display = 'none';
+ document.getElementById('install-div').className = '';
+ }
+ if (whichItem != 'deinstall-div') {
+ document.getElementById('deinstall-div').style.visibility = 'hidden';
+ document.getElementById('deinstall-div').style.display = 'none';
+ document.getElementById('deinstall-div').className = '';
+ }
+ }
+ ]]>
+ </script>
+ </head>
+ <body style="color: rgb(0, 0, 0); background-color: rgb(51, 51, 51);" alink="#cc0000" link="#cc0000" vlink="#cc0000">
+ <table style="width: 802px; text-align: left; margin-left: auto; margin-right: auto;" border="0" cellpadding="0" cellspacing="0">
+ <tbody>
+ <tr>
+ <td style="background-image: url(http://www.pfsense.com/assets/images/header1.gif); width: 811px; text-align: left; vertical-align: bottom; background-color: transparent; height: 65px;"></td>
+ </tr>
+ <tr>
+ <td style="background-image: url(http://www.pfsense.com/assets/images/header2.gif); height: 25px; width: 802px;">
+ <font color="#ffffff"><span class="headers"></span></font>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <table style="background-image: url(http://www.pfsense.com/assets/images/horizontal.gif); text-align: left; width: 802px;" border="0" cellpadding="0" cellspacing="0">
+ <tbody>
+ <tr>
+ <td style="width: 200px; text-align: center; vertical-align: top;">
+ <table style="width: 90%; text-align: left; margin-left: auto; margin-right: auto;" border="0" cellpadding="0" cellspacing="1">
+ <tbody>
+ <tr>
+ <td class="navigationHead" style="background-color: rgb(153, 0, 0);">Navigation</td>
+ </tr>
+ <tr style="padding: 0px; margin: 0px;">
+ <td height="100%" align="left" valign="top" class="navigation" style="padding: 0px; margin: 0px;">
+ <img src="http://www.pfsense.com/manager/media/images/_tx_.gif" alt="" height="4" />
+ <br />
+ <a href='#' id="infoa" onclick="toggleContentItem('info-div');">Info</a>
+ <a href='#' id="licensea" onclick="toggleContentItem('license-div');">License</a>
+ <a href='#' id="desca" onclick="toggleContentItem('desc-div');">Description</a>
+ <a href='#' id="reqa" onclick="toggleContentItem('req-div');">Minimum requirements</a>
+ <a href='#' id="faqa" onclick="toggleContentItem('faq-div');">FAQ</a>
+ <a href='#' id="addfilea" onclick="toggleContentItem('files-div');">Additional Files Being Installed</a>
+ <a href='#' id="addmenua" onclick="toggleContentItem('menu-div');">Menu Items Being Installed</a>
+ <a href='#' id="addtaba" onclick="toggleContentItem('tab-div');">Tabs Being Installed</a>
+ <a href='#' id="servicesa" onclick="toggleContentItem('service-div');">Services Being Installed</a>
+ <a href='#' id="rsynca" onclick="toggleContentItem('rsync-div');">custom_php_resync_config_command</a>
+ <a href='#' id="installa" onclick="toggleContentItem('install-div');">custom_php_install_command</a>
+ <a href='#' id="deinstalla" onclick="toggleContentItem('deinstall-div');">custom_php_deinstall_command</a>
+ <img src="http://www.pfsense.com/manager/media/images/_tx_.gif" height="4" alt="" />
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ <td style="text-align: left; vertical-align: top;">
+ <div id="info-div" style="padding-left: 6px; width: 500px;">
+ <h1>
+ <xsl:text>Info for package: </xsl:text>
+ <xsl:value-of select="//name"/>
+ </h1>
+ <h2>Version</h2>
+ <p>
+ <xsl:value-of select="//version" />
+ </p>
+ <h2>Title</h2>
+ <p>
+ <xsl:value-of select="//title" />
+ </p>
+ <h2>Include File</h2>
+ <p>
+ <xsl:value-of select="//include_file" />
+ </p>
+ <h2>Configpath</h2>
+ <p>
+ <code>
+ <xsl:value-of select="//configpath" />
+ </code>
+ </p>
+ </div>
+ <div id="license-div" style="padding-left: 6px; width: 500px; display: none; visibility: hidden;">
+ <h1>License</h1>
+ <p>
+ <pre style="font-size: 0.95em;">
+ <xsl:value-of select="//copyright" />
+ </pre>
+ </p>
+ </div>
+ <div id="desc-div" style="padding-left: 6px; width: 500px; display: none; visibility: hidden;">
+ <h1>Package Description</h1>
+ <xsl:value-of select="//description" />
+ </div>
+ <div id="req-div" style="padding-left: 6px; width: 500px; display: none; visibility: hidden;">
+ <h1>Requirements</h1>
+ <xsl:value-of select="//requirements" />
+ </div>
+ <div id="faq-div" style="padding-left: 6px; width: 500px; display: none; visibility: hidden;">
+ <h1>Frequently Asked Question</h1>
+ <xsl:value-of select="//faq" />
+ </div>
+ <div id="files-div" style="padding-left: 6px; width: 500px; display: none; visibility: hidden;">
+ <h1>Additional Files Being Installed</h1>
+ <xsl:for-each select="//additional_files_needed">
+ <p>
+ <b><xsl:text>Prefix: </xsl:text></b><xsl:value-of select="prefix" /><br />
+ <b><xsl:text>Chmod: </xsl:text></b><xsl:value-of select="chmod" /><br />
+ <b><xsl:text>Item: </xsl:text></b><xsl:value-of select="item" /><br />
+ </p>
+ </xsl:for-each>
+ </div>
+ <div id="menu-div" style="padding-left: 6px; width: 500px; display: none; visibility: hidden;">
+ <h1>Menu Items Being Installed</h1>
+ <xsl:for-each select="//menu">
+ <p>
+ <b><xsl:text>Name: </xsl:text></b><xsl:value-of select="name" /><br />
+ <b><xsl:text>Section: </xsl:text></b><xsl:value-of select="section" /><br />
+ <b><xsl:text>URL: </xsl:text></b><xsl:value-of select="url" /><br />
+ </p>
+ </xsl:for-each>
+ </div>
+ <div id="tab-div" style="padding-left: 6px; width: 500px; display: none; visibility: hidden;">
+ <h1>Tabs Being Installed</h1>
+ <xsl:for-each select="//tabs/tab">
+ <p>
+ <b><xsl:text>Text: </xsl:text></b><xsl:value-of select="text" /><br />
+ <b><xsl:text>URL: </xsl:text></b><xsl:value-of select="url" /><br />
+ <xsl:if test="active">
+ <b><xsl:text>Active: </xsl:text></b><xsl:text>YES</xsl:text><br />
+ </xsl:if>
+ </p>
+ </xsl:for-each>
+ </div>
+ <div id="service-div" style="padding-left: 6px; width: 500px; display: none; visibility: hidden;">
+ <h1>Services Being Installed</h1>
+ <xsl:for-each select="//service">
+ <p>
+ <b><xsl:text>Name: </xsl:text></b><xsl:value-of select="name" /><br />
+ <b><xsl:text>RC File: </xsl:text></b><xsl:value-of select="rcfile" /><br />
+ </p>
+ </xsl:for-each>
+ </div>
+ <div id="rsync-div" style="padding-left: 6px; width: 500px; display: none; visibility: hidden;">
+ <h1>custom_php_install_command</h1>
+ <p>
+ <pre><xsl:value-of select="custom_php_install_command" /></pre>
+ </p>
+ </div>
+ <div id="install-div" style="padding-left: 6px; width: 500px; display: none; visibility: hidden;">
+ <h1>custom_php_install_command</h1>
+ <p>
+ <pre><xsl:value-of select="custom_php_deinstall_command" /></pre>
+ </p>
+ </div>
+ <div id="deinstall-div" style="padding-left: 6px; width: 500px; display: none; visibility: hidden;">
+ <h1>custom_php_deinstall_command</h1>
+ <p>
+ <pre><xsl:value-of select="custom_php_deinstall_command" /></pre>
+ </p>
+ </div>
+ </td>
+ <td width="30px"></td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ </tr>
+ <tr style="color: rgb(255, 255, 255);">
+ <td style="background-image: url(http://www.pfsense.com/assets/images/footer.gif); width: 802px; height: 60px; text-align: center; vertical-align: middle;">
+ pfSense is (C) Copyright 2004, 2005, 2006 Scott Ullrich. All Rights Reserved.
+ <br />
+ MySQL: 0.0000 s, 0 request(s), PHP: 0.0052 s, total: 0.0052 s, document
+ retrieved from cache.
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </body>
+ </html>
+ </xsl:template>
+</xsl:stylesheet>
+
diff --git a/config/zabbix-agent.xml b/config/zabbix-agent.xml
new file mode 100644
index 00000000..54184b32
--- /dev/null
+++ b/config/zabbix-agent.xml
@@ -0,0 +1,164 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packagegui>
+ <name>zabbixagent</name>
+ <title>Services: Zabbix Agent</title>
+ <category>Monitoring</category>
+ <version>1.0</version>
+ <addedit_string>Zabbix Agent has been created/modified.</addedit_string>
+ <delete_string>Zabbix Agent has been deleted.</delete_string>
+ <restart_command>/usr/local/etc/rc.d/zabbix_agentd.sh restart</restart_command>
+ <menu>
+ <name>Zabbix Agent</name>
+ <tooltiptext>Setup Zabbix Agent specific settings</tooltiptext>
+ <section>Services</section>
+ <url>/pkg_edit.php?xml=zabbix-agent.xml&amp;id=0</url>
+ </menu>
+ <service>
+ <name>zabbix-agent</name>
+ <rcfile>zabbix-agentd.sh</rcfile>
+ <executable>zabbix_agentd</executable>
+ </service>
+ <tabs>
+ <tab>
+ <text>Settings</text>
+ <url>/pkg_edit.php?xml=zabbix-agent.xml&amp;id=0</url>
+ <active />
+ </tab>
+ </tabs>
+ <fields>
+ <field>
+ <fielddescr>Server</fielddescr>
+ <fieldname>server</fieldname>
+ <description>List of comma delimited IP addresses (or hostnames) of ZABBIX servers</description>
+ <value>127.0.0.1</value>
+ <type>input</type>
+ <size>60</size>
+ <required>true</required>
+ </field>
+ <field>
+ <fielddescr>Server Port</fielddescr>
+ <fieldname>serverport</fieldname>
+ <description>Server port for sending active check (generally 10051)</description>
+ <value>10051</value>
+ <type>input</type>
+ <size>60</size>
+ <required>true</required>
+ </field>
+ <field>
+ <fielddescr>Hostname</fielddescr>
+ <fieldname>hostname</fieldname>
+ <description>Unique hostname. Required for active checks.</description>
+ <value>localhost</value>
+ <type>input</type>
+ <size>60</size>
+ <required>true</required>
+ </field>
+ <field>
+ <fielddescr>Listen Port</fielddescr>
+ <fieldname>listenport</fieldname>
+ <value>10050</value>
+ <type>input</type>
+ <size>60</size>
+ <required>true</required>
+ <description>Listen port for sending active check (generally 10050)</description>
+ </field>
+ </fields>
+ <custom_php_install_command>
+ <![CDATA[
+ global $config, $g;
+
+ mwexec("mkdir -p /var/log/zabbix/");
+ mwexec("mkdir -p /var/run/zabbix/");
+
+ conf_mount_rw();
+
+ /* create a few directories and ensure the sample files are in place */
+ exec("/bin/mkdir -p /usr/local/etc/zabbix");
+ exec("/bin/mkdir -p /var/log/zabbix");
+ exec("/bin/mkdir -p /var/run/zabbix");
+
+ exec("/bin/rm -f /usr/local/etc/rc.d/zabbix_agentd");
+
+ $start = "/bin/mkdir -p /var/log/zabbix\n";
+ $start .= "/usr/sbin/chown -R zabbix:zabbix /var/log/zabbix\n";
+
+ $start .= "/bin/mkdir -p /var/run/zabbix\n";
+ $start .= "/usr/sbin/chown -R zabbix:zabbix /var/run/zabbix\n";
+
+ $start .= "echo \"Starting Zabbix Agent\"...\n";
+
+ /* start zabbix agent */
+ $start .= "/usr/local/bin/zabbix_agentd\n";
+
+ $stop = "echo \"Stopping Zabbix Agent\"\n";
+ $stop .= "/usr/bin/killall zabbix_agentd\n";
+
+ /* write out rc.d start/stop file */
+ write_rcfile(array(
+ "file" => "zabbix_agentd.sh",
+ "start" => "{$start}",
+ "restart" => "$stop\nsleep 5\n{$start}",
+ "stop" => "$stop"
+ )
+ );
+
+ conf_mount_ro();
+ ]]>
+ </custom_php_install_command>
+ <custom_php_command_before_form></custom_php_command_before_form>
+ <custom_php_after_head_command></custom_php_after_head_command>
+ <custom_php_after_form_command></custom_php_after_form_command>
+ <custom_php_validation_command>
+ <![CDATA[
+ global $_POST;
+
+ $ListenPort=$_POST['listenport'];
+ if (!preg_match("/^\d+$/", $ListenPort)) {
+ $input_errors[]='Listen Port is not numeric.';
+ }
+
+ $ServerPort=$_POST['serverport'];
+ if (!preg_match("/^\d+$/", $ServerPort)) {
+ $input_errors[]='Server Port is not numeric.';
+ }
+ ]]>
+ </custom_php_validation_command>
+ <custom_add_php_command></custom_add_php_command>
+ <custom_php_resync_config_command>
+ <![CDATA[
+ global $config;
+ global $g;
+
+ $Server=$config['installedpackages']['zabbixagent']['config'][0]['server'];
+ $ServerPort=$config['installedpackages']['zabbixagent']['config'][0]['serverport'];
+ $Hostname=$config['installedpackages']['zabbixagent']['config'][0]['hostname'];
+ $ListenPort=$config['installedpackages']['zabbixagent']['config'][0]['listenport'];
+
+ $conf = "Server=$Server\n";
+ $conf .= "ServerPort=$ServerPort\n";
+ $conf .= "Hostname=$Hostname\n";
+ $conf .= "ListenIP=0.0.0.0\n";
+ $conf .= "ListenPort=$ListenPort\n";
+ $conf .= "StartAgents=5\n";
+ $conf .= "DebugLevel=3\n";
+ $conf .= "PidFile=/var/run/zabbix/zabbix_agentd.pid\n";
+ $conf .= "LogFile=/var/log/zabbix/zabbix_agentd.log\n";
+ $conf .= "LogFileSize=1\n";
+ $conf .= "Timeout=3\n";
+
+ file_put_contents("/usr/local/etc/zabbix/zabbix_agentd.conf", $conf);
+
+ ]]>
+ </custom_php_resync_config_command>
+ <custom_php_resync_command></custom_php_resync_command>
+ <custom_php_deinstall_command>
+ <![CDATA[
+ exec("/usr/bin/killall zabbix_agentd");
+
+ exec("/bin/rm /usr/local/etc/rc.d/zabbix_agentd.sh");
+
+ exec("/bin/rm -r /var/log/zabbix/");
+ exec("/bin/rm -r /var/run/zabbix/");
+ ]]>
+ </custom_php_deinstall_command>
+</packagegui>