2
0
mirror of https://gitlab.com/apparmor/apparmor synced 2025-08-31 22:35:35 +00:00

Compare commits

..

138 Commits

Author SHA1 Message Date
John Johansen
323aee990b Bump release version to 2.8.5 2017-10-18 19:44:47 -07:00
Christian Boltz
6e4fa53b79 backport nscd profile additions from 2.9 branch
The most important change is /proc/[0-9]*/cmdline to allow paranoid mode.


Acked-by: Seth Arnold <seth.arnold@canonical.com>
2016-04-15 23:05:27 +02:00
Christian Boltz
d8a6681b2e Backport profile additions from the 2.9 branch
This patch backports most profile additions from the latest 2.9 branch
r3004, with the exception of new rule types (2.8 doesn't support dbus,
ptrace etc.) and some noisy cleanups (like /proc/*/ -> @{PROC}/@{pid}/).


Acked-by: Seth Arnold <seth.arnold@canonical.com>
2016-04-15 22:20:54 +02:00
Steve Beattie
6a8a099968 libapparmor: fix parsing for yet another format
Backport from trunk revision 2830

This patch fixes the libapparmor log parsing library to take into
account yet another log format style, as well as incorporating a
testcase for it.

Bugs:
  https://bugs.launchpad.net/apparmor/+bug/1399027
  https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=771400
  https://bugzilla.opensuse.org/show_bug.cgi?id=905368

Nominated-by: Steve Beattie <steve@nxnw.org>
Acked-by: John Johansen <john.johansen@canonical.com>

Bug: https://launchpad.net/bugs/1399027
2014-12-12 17:07:42 -08:00
Steve Beattie
b0273a9289 libaalogparse: fix for new kernel dmesg format
Merge from trunk revision 2647

The upstream kernel at some point between the 3.13 and 3.16 kernel
adjusted the output of audit messages to include an additional "audit:"
keyword. e.g. a 3.13 message would look like:

  kernel: [182243.243324] type=1400 audit(1409684003.960:273342): [SNIP]

whereas in 3.16, it looks like:

  kernel: [182243.243324] audit: type=1400 audit(1409684003.960:273342): [SNIP]
                          ^^^^^^

This patch adjust the libapparmor aalogparse grammar and lexer to
compensate for this change.

Nominated-by: Steve Beattie <steve@nxnw.org>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2014-12-12 17:03:07 -08:00
Christian Boltz
a21d7df05b fix filename for .../nscd/hosts (which was accidently changed to "host" 3 years ago)
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2014-11-18 00:28:51 +01:00
Steve Beattie
2c6dd0aa98 toplevel Makefile: use https URI by default for vcs export
Merge from trunk commit 2261.

Since --per-file-timestamps is broken over the SSH transport (see
https://bugs.launchpad.net/bzr/+bug/1257078), make the default use
a HTTPS URI instead.
2014-10-09 14:40:50 -07:00
Steve Beattie
6a347df2fb Prepare for apparmor 2.8.4 release. 2014-10-09 14:29:47 -07:00
Steve Beattie
ed2b8b3111 mod_apparmor: revert apache 2.4 api fix from commit 2131
This patch reverts commit 2131 which added support for the newer apache
2.4 ap_hook_check_access_ex() api, based on a report from Christian that
it broke apache's simple authentication.

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Christian Boltz <apparmor@cboltz.de>
2014-10-09 12:49:38 -07:00
Christian Boltz
5efe6e2cec ntpd on openSUSE Factory needs another location for the pid file.
References: https://bugzilla.novell.com/show_bug.cgi?id=899746
  

Acked-by: Seth Arnold <seth.arnold@canonical.com>
2014-10-06 19:58:49 +02:00
Seth Arnold
766485972a Merge changes from trunk -- almost entirely additions to abstractions, a
perl multiarch change to logprof.conf and new perl severity entries.

  intrigeri@boum.org 2014-09-10 Cherry-pick r2671 from master.
    intrigeri@boum.org 2014-09-10 Cherry-pick r2387 from master.
    intrigeri@boum.org 2014-09-10 Cherry-pick r2610 from master.
    intrigeri@boum.org 2014-09-10 Cherry-pick r2506 from master.
    intrigeri@boum.org 2014-09-10 Cherry-pick r2592 from master.
    intrigeri@boum.org 2014-09-10 Cherry-pick r2353 from master.
    intrigeri@boum.org 2014-09-10 Cherry-pick r2294 from master.
    intrigeri@boum.org 2014-09-10 Cherry-pick r2593 from master.
    intrigeri@boum.org 2014-09-10 Cherry-pick r2590 from master.
    intrigeri@boum.org 2014-09-10 Cherry-pick r2522 from master.
    intrigeri@boum.org 2014-09-10 Cherry-pick r2369 from master.
    intrigeri@boum.org 2014-09-10 Cherry-pick r2246 from master.
2014-09-12 16:13:45 -07:00
Seth Arnold
029875ef72 Remove <sys/sysctl.h> from parser_main.c to fix FTBFS on x32 platform.
As originally applied to trunk in 2667:

  The AppArmor parser failed to build on the x32 architecture due to a
  missing <sys/sysctl.h> header. This header is included by accident, a
  vestige of earlier days, and wasn't removed when the sysctls were
  removed. (Think Linux 2.0 or Linux 2.2 days.)

  See also https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=760378

  Thanks to Thorsten Glaser for the discovery and initial fix.
2014-09-10 18:36:10 -07:00
intrigeri
770746a320 Cherry-pick r2671 from master. 2014-09-10 17:41:44 -07:00
intrigeri
90bcee0f23 Cherry-pick r2387 from master. 2014-09-10 17:40:14 -07:00
intrigeri
2ace7d9dfa Cherry-pick r2610 from master. 2014-09-10 17:37:53 -07:00
intrigeri
95368e8fd0 Cherry-pick r2506 from master. 2014-09-10 17:37:27 -07:00
intrigeri
53fce179d9 Cherry-pick r2592 from master. 2014-09-10 17:37:02 -07:00
intrigeri
7566f992dd Cherry-pick r2353 from master. 2014-09-10 17:34:21 -07:00
intrigeri
3b1b013fc8 Cherry-pick r2294 from master. 2014-09-10 17:33:36 -07:00
intrigeri
e579d939ce Cherry-pick r2593 from master. 2014-09-10 17:32:57 -07:00
intrigeri
a591cf73b1 Cherry-pick r2590 from master. 2014-09-10 17:32:03 -07:00
intrigeri
97f6d4f52e Cherry-pick r2522 from master. 2014-09-10 17:24:07 -07:00
intrigeri
793013c3ce Cherry-pick r2369 from master. 2014-09-10 17:21:54 -07:00
intrigeri
fc03b984bd Cherry-pick r2246 from master. 2014-09-10 17:21:31 -07:00
Christian Boltz
e1092cfc72 add missing --display to aa-notify.pod
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2014-09-08 20:41:07 +02:00
Christian Boltz
90fe8b8d09 Fix for commit 2.8 branch r2140:
> Allow dnsmasq read access to IPv6 config

The commit did not match this part of the commit message  
> slightly modified (../conf/**/mtu -> ../conf/*/mtu)
which I'm fixing now.
2014-09-08 20:39:12 +02:00
Christian Boltz
6f6bce01a1 Allow dnsmasq read access to IPv6 config
The IPv6 Neighbor Discovery protocol (RFC 2461) suggests
implementations provide MTU in Router Advertisement (RA)
messages.  From section 4.2

MTU    SHOULD be sent on links that have a variable MTU
       (as specified in the document that describes how to
       run IP over the particular link type).  MAY be sent
       on other links.

dnsmasq supports this option and should have read access
to an interface's MTU.

Patch by James Fehlig <jfehlig@suse.com>


slightly modified (../conf/**/mtu -> ../conf/*/mtu)


Acked-by: Seth Arnold <seth.arnold@canonical.com>
2014-09-06 23:09:18 +02:00
Arthur Marble
c72c406357 parser: fix FTBFS when building with clang
Fix undefined reference error in parser/parser_interface.c.
http://clang.llvm.org/compatibility.html#inline has more details.

Debian bug: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=756807

Acked-by: Steve Beattie <steve@nxnw.org>
2014-08-29 12:26:59 -07:00
Christian Boltz
038c37c551 smbd: changed cachedir in openSUSE
openSUSE now compiles samba --with-cachedir=/var/lib/samba (instead of 
the default /var/cache/samba). This patch updates the smbd profile to 
match this change.

References: https://bugzilla.novell.com/show_bug.cgi?id=869787


Acked by: Seth Arnold <seth.arnold@canonical.com>
2014-08-11 23:24:23 +02:00
Christian Boltz
dedfb6d17a From: Jeff Mahoney <jeffm@suse.com>
Subject: perl-apparmor: Properly handle bare 'file' keyword
References: bnc#889652

The bare file keyword is a shortcut for /{**,}. There are also implied
permissions that go with it.

This patch accepts the file keyword as well as allowing for missing mode
specifiers.

Signed-off-by: Jeff Mahoney <jeffm@suse.com>

Acked-by: Steve Beattie <steve@nxnw.org>
2014-08-02 12:49:15 +02:00
Christian Boltz
08fcbcc8ec From: Jeff Mahoney <jeffm@suse.com>
Subject: perl-apparmor: Handle bare 'capability' keyword
References: bnc#889651

Specifying 'capability' implies all capabilities, but the perl code didn't
recognize it.

Signed-off-by: Jeff Mahoney <jeffm@suse.com>

Acked-by: Steve Beattie <steve@nxnw.org>
2014-08-02 12:48:30 +02:00
Christian Boltz
ff267dc1fc From: Jeff Mahoney <jeffm@suse.com>
Subject: perl-apparmor: Fix bare 'network' keyword handling
References: bnc#889650

The 'network' bare keyword was being printed as "audit network all" due to
two different bugs:

1) {audit}{all} was always being set to 1, regardless of whether the audit
   keyword was used
2) {rule} eq 'all' is the wrong test - it should be {rule}{all}

With these fixed, 'network' is properly handled.

Signed-off-by: Jeff Mahoney <jeffm@suse.com>

Acked-by: Steve Beattie <steve@nxnw.org>
2014-08-02 12:47:39 +02:00
Steve Beattie
47df23aca5 parser: remove leaked in C++ish bool
In commit rev 2127, backported from trunk, a bit of C++ish style code
leaked in, the use of a bool variable. This is problematic for pure C
code. This commit converts the bool to an int and adjusts the true and
false keywords to their corresponding macros as defined in parser.h.

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: John Johansen <john.johansen@canonical.com>
2014-07-30 03:49:49 -07:00
Steve Beattie
090c912431 utils: add CAP_AUDIT_READ to severity.db
Merge from trunk rev 2564.

This patch adds the new capability CAP_AUDIT_READ, added in the 3.16
kernel, to the utils severity.db. I set the severity level at 7,
since it seemed to offer less exposure than CAP_AUDIT_CONTROL and
CAP_AUDIT_WRITE, which are both considered severity 8.

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2014-07-21 22:56:11 -07:00
Steve Beattie
59ed7057b3 libapparmor: fix log parsing memory leaks
This patch fixes some memory leaks in the libapparmor log parsing
functions, specifically around handling records obtained from syslog
and records containing network addresses.

Bug: https://bugs.launchpad.net/bugs/1340927
Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2014-07-12 07:48:12 -07:00
Steve Beattie
b01c8f2a7a mod_apparmor: for apache 2.4, use new access control hook
Use ap_hook_check_access_ex() instead of
ap_hook_access_checker() for apache 2.4; see
http://httpd.apache.org/docs/2.4/developer/new_api_2_4.html#http_request

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2014-07-10 10:09:48 -07:00
Steve Beattie
afe682c65c mod_apparmor: try uri hat after AADefaultHatName, not before
Bug: https://bugs.launchpad.net/bugs/1322778

Between the apparmor 2.8.2 and 2.8.3, a bug was fixed in mod_apparmor
(in 2.8 revno 2120) that corrected the storage location for
AADefaultHatName.  The incorrect storage caused the hat specified by
the AADefaultHatName keyword to be the default value for AAHatName,
and meant that if both an AAHatName and an AADefaultHatName entry
were given in a vhost, mod_apparmor would not fall back to trying
AADefaultHatName if the hat specified in AAHatName did not exist in
the apache apparmor profile.

However, because the value specified in AADefaultHatName was the
default, if no AAHatName was specified, it would be attempted first,
before a hat based on the passed URI, rather than after as the
documentation stated and the code intended. By fixing the storage bug,
the attempted hat ordering now matched the documentation. But a number
of users came to rely on AADefaultHatName being attempted before the
URI. Additionally, because the 2.8 mod_apparmor attempts each hat
individually (rather than use the aa_change_hatv like trunk's
mod_apparmor), each attempt with the URI-based hatname is logged by the
kernel portion of apparmor, making system logs particularly noisy those
same users.

This patch re-adjusts the ordering so that the URI-based hat is
attempted after the hat specified by AADefaultHatName is attempted,
thus maintaining the actual behavior before the bug addressed in
revno 2120 was fixed.

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Seth Arnold <seth.arnold@canonical.com>

Bug: https://launchpad.net/bugs/1322778
2014-07-10 10:08:24 -07:00
Christian Boltz
979b1d9f22 abstractions/nameservice should allow /run/nscd/passwd etc. in addition
to /var/run/nscd/passwd.

References: https://bugzilla.novell.com/show_bug.cgi?id=886225


Acked-by: Seth Arnold <seth.arnold@canonical.com> for both trunk and 2.8.
2014-07-09 10:18:54 +02:00
Jamie Strandboge
2c21b2d732 Description: update nvidia abstraction for additional /proc and ~/.nv/GLCache
access
Bug-Ubuntu: https://launchpad.net/bugs/1325050

Acked-By: Jamie Strandboge <jamie@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2014-06-06 13:52:24 -05:00
John Johansen
409e8703cf Fix profile loads from cache files that contain multiple profiles
backport of dev commit 2510

v3: fix freeing of filename when undefined
v2: address tyhicks feedback
    refactor to have a common write routine
    fix issue with set profile load being done even if !kernel_load

Profile loads from cache files that contain multiple profiles can
result in multiple reloads of the same profile or error messages about
failure to load profiles if the --add option is used. eg.

  apparmor="STATUS" operation="profile_load"
  name="/usr/lib/apache2/mpm-prefork/apache2" pid=8631
  comm="apparmor_parser"
  <sth0R> [82932.058388] type=1400 audit(1395415826.937:616):
  apparmor="STATUS" operation="profile_load" name="DEFAULT_URI" pid=8631
  comm="apparmor_parser"
  <sth0R> [82932.058391] type=1400 audit(1395415826.937:617):
  apparmor="STATUS" operation="profile_load"
  name="HANDLING_UNTRUSTED_INPUT" pid=8631 comm="apparmor_parser"
  <sth0R> [82932.058394] type=1400 audit(1395415826.937:618):
  apparmor="STATUS" operation="profile_load" name="phpsysinfo" pid=8631
  comm="apparmor_parser"
  <sth0R> [82932.059058] type=1400 audit(1395415826.937:619):
  apparmor="STATUS" operation="profile_replace" info="profile can not be
  replaced" error=-17
  name="/usr/lib/apache2/mpm-prefork/apache2//DEFAULT_URI" pid=8631
  comm="apparmor_parser"
  <sth0R> [82932.059574] type=1400 audit(1395415826.937:620):
  apparmor="STATUS" operation="profile_replace" info="profile can not be
  replaced" error=-17
  name="/usr/lib/apache2/mpm-prefork/apache2//HANDLING_UNTRUSTED_INPUT"
  pid=8631 comm="apparmor_parser"


The reason this happens is that the cache file is a container that
can contain multiple profiles in sequential order
  profile1
  profile2
  profile3

The parser loads the entire cache file to memory and the writes the
whole file to the kernel interface. It then skips foward in the file
to the next profile and reloads the file from that profile into
the kernel.
  eg. First load
    profile1
    profile2
    profile3

  advance to profile2, do second load
    profile2
    profile3

  advance to profile3, do third load
    profile3


With older kernels the interface would stop after the first profile and
return that it had processed the whole file, thus while wasting compute
resources copying extra data no errors occurred. However newer kernels
now support atomic loading of multipe profiles, so that all the profiles
passed in to the interface get processed.

This means on newer kernels the current parser load behavior results
in multiple loads/replacements when a cache file contains more than
one profile (note: loads from a compile do not have this problem).

To fix this, detect if the kernel supports atomic set loads, and load
the cache file once. If it doesn't only load one profile section
from a cache file at a time.

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2014-05-08 09:37:01 -07:00
Steve Beattie
933658d8a6 Add dconf abstraction for querying dconf settings
Merge from trunk revno: 2209

An abstraction to grant the ability to query dconf settings. It does
not grant the ability to update or add settings, due to our current
inability to restrict where within the dconf hierarchy updates
can occur.

Nominated for 2.8 by intrigeri <intrigeri@boum.org>
Acked-by: Steve Beattie <steve@nxnw.org>
2014-03-10 10:25:55 -07:00
Seth Arnold
3df7f56154 Cherrypick revision 2412 from trunk, store magic token in unsigned int
Original log:
Store the aa_change_hat magic token in an unsigned long in the test suite

The magic token used in the test suite is incorrectly stored
as an int rather than unsigned long leading to failure like this:

running changehat_misc
/tmp/testlibCTcwOe/source/trusty/apparmor-2.8.95~2411/tests/regression/apparmor/prologue.inc: line 176: 20184
Killed                  $testexec "$@" > $outfile 2>&1
Error: changehat_twice failed. Test 'CHANGEHAT (subprofile->subprofile)' was expected to 'pass'. Reason for
failure 'killed by signal 9'

Signed-off-by: Seth Arnold <seth.arnold@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2014-03-04 10:57:23 -08:00
Jamie Strandboge
155bdd07af Add /var/www/html to abstractions/web-data, which is the path used on Debian
and its derivatives
Bug-Ubuntu: https://launchpad.net/bugs/1285653

Acked-By: Jamie Strandboge <jamie@canonical.com>
Acked-by: Christian Boltz <apparmor@cboltz.de>
2014-02-27 14:51:31 -06:00
Christian Boltz
96c2ee3e08 dnsmasq profile - NetworkManager integration
This is an updated version of the previous dnsmasq profile patch, again 
from develop7 [at] develop7.info


Acked-by: John Johansen <john.johansen@canonical.com>
2014-02-17 22:57:14 +01:00
Seth Arnold
1d07373407 bump versions in preparation for release 2014-02-16 21:01:10 -08:00
Steve Beattie
255954f240 mod_apparmor: include errno in log messages for failures
Merged from trunk revno: 2340

This patch includes the errno in the log messages generated by two
different failed aa_change_hat() calls and the failure to open
/dev/urandom to get the random token, to further ease failure
diagnosis.

2.8 Note: did not apply cleanly, required manual adjustment.

For 2.8:
Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Christian Boltz <apparmor@cboltz.de>
2014-02-14 16:51:11 -08:00
Steve Beattie
1c03c6249f mod_apparmor: fix AADefaultHatName storage
Merge from trunk revno: 2335

When defining an AADefaultHatName entry, it was being stored in the
passed mconfig location, which is not the module specific server
config, but instead the top level (i.e. no path defined) default
directory/location config. This would be superceded by a more specific
directory config if it applied to the request. Thus, if an AAHatName was
defined that applied, but the named hat was not defined in the apparmor
policy, mod_apparmor would not attempt to fall back to the defined
AADefaultHatName, but instead jump directly to trying the DEFAULT_URI
hat.

This patch fixes it by storing the defined AADefaultHatName correctly in
the module specific storage in the related server data structure. It
also adds a bit of developer debugging statements.

For 2.8:
Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Christian Boltz <apparmor@cboltz.de>
2014-02-14 16:43:37 -08:00
Steve Beattie
b0e00b01f2 mod_apparmor: improve initial and exit aa_change_hat call log message
Merge from trunk revno: 2334

This patch adds the name of the hat to the log message about the
initial aa_change_hat call, just to be explicit about what's happening
when debugging and changes the formatting slightly of the exiting
change_hat log message.

Patch history:
  v1: initial version
  v2: tweak output of exit trace message

For 2.8:
Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Christian Boltz <apparmor@cboltz.de>
2014-02-14 16:42:12 -08:00
Steve Beattie
a20f467bf0 mod_apparmor: convert change_hat to aa_change_hat()
Merge from trunk revno: 2333

mod_apparmor never got converted to use the renamed aa_change_hat()
call (there's a compatibility macro in sys/apparmor.h); this patch does
that as well as converting the type of the magic_token to long from int.

(This patch is somewhat mooted by a later patch in the series to
convert to using aa_change_hatv(), but would be a safer candidate
for e.g. the 2.8 branch.)

For 2.8:
Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Christian Boltz <apparmor@cboltz.de>
2014-02-14 16:40:57 -08:00
Steve Beattie
ba1e5a5b7c mod_apparmor: convert debug_dump_uri to use trace loglevel
Merge from trunk revno: 2332

This patch converts the debug_dump_uri() function to use the trace
loglevels and enable it all the time, rather than just when DEBUG is
defined at compile time.

For 2.8:
Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Christian Boltz <apparmor@cboltz.de>
2014-02-14 16:39:21 -08:00
Steve Beattie
11288e5b8d mod_apparmor: use trace1 loglevel for developer-oriented debug messages
Merged from trunk revno: 2331

Apache 2.4 added addition logging levels. This patch converts some of
the log messages that are more intended for mod_apparmor development
and debugging than for sysadmins configuring mod_apparmor to use trace1
(APLOG_TRACE1) level instead. Since apache 2.2. does not contain this
level (or define), we define it back to APLOG_DEBUG.

Patch history:
  v1: initial version
  v2: mark a couple of additional log messages as trace1 level

For 2.8:
Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Christian Boltz <apparmor@cboltz.de>
2014-02-14 16:38:04 -08:00
Steve Beattie
bea5043bb8 mod_apparmor: fix logging
Merge from trunk revno: 2330

The apache2 mod_apparmor module was failing to log debugging messages
when the apache loglevel was set to debug or lower (i.e. traceN). This
patch fixes it by using ap_log_rerror() (for request specific messages,
with the request passed for context) and ap_log_error() (more general
messages outside of a request context).

Also, the APLOG_USE_MODULE macro is called, to mark the log messages
as belonging to the apparmor module, so that the apache 2.4 feature
of enabling debug logging for just the apparmor module will work,
with an apache configuration entry like:

  LogLevel apparmor:debug

See

  http://ci.apache.org/projects/httpd/trunk/doxygen/group__APACHE__CORE__LOG.html

for specific about the ap_log_*error() and APLOG_USE_MODULE functions
and macros, and

  http://httpd.apache.org/docs/2.4/mod/core.html.en#loglevel

for the bits about module specific logging.

Patch history:
  v1: initial version
  v2: - revert to using ap_log_error with (the 2.4 specific)
        ap_server_conf outside of a request specific context, as the
        pool specific ap_log_perror messages weren't being reported.
      - add compatibility workaround for apache 2.2
  v3: keep commented out merge function's log call consistent with the
      others

For 2.8:
Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Christian Boltz <apparmor@cboltz.de> (on IRC)
2014-02-14 16:35:21 -08:00
Seth Arnold
692e1b29e6 Fix --create-cache-dire typo in apparmor_parser --help output.
Acked-by: Tyler Hicks <tyhicks@canonical.com>
2014-02-14 15:28:46 -08:00
Christian Boltz
3c7f5f5feb update abstractions/winbind
- some *.dat files live in a different directory nowadays (at least in 
  openSUSE)
- the openSUSE smb.conf includes the (autogenerated) dhcp.conf, so this
  file also needs to be readable.

References: https://bugzilla.novell.com/show_bug.cgi?id=863226

Acked-by: Seth Arnold <seth.arnold@canonical.com>
2014-02-14 23:38:10 +01:00
Christian Boltz
b7e854695b apparmor.vim says "attach_disconnect" is correct, but the parser only
likes "attach_disconnected".

Acked-By: Jamie Strandboge <jamie@canonical.com>
2014-01-29 23:18:52 +01:00
Steve Beattie
2b51489cef Subject: libapparmor: fix aa_change_hat token format string
Merge from trunk commit rev 2329.

This patch fixes the format string for the magic token in aa_change_hat
to match the type of the magic token (long). Without this, on 64
bit platforms, only the bottom 32 bits of the token would be used.
aa_change_hatv() has the correct format string, so an aa_change_hatv()
call followed by an exiting aa_change_hat() call would result in the
latter having a different token, which would cause the process to be
killed by apparmor.

(Hat tip to John Johansen for spotting the actual bug.)

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: John Johansen <john.johansen@canonical.com>
2014-01-23 13:18:25 -08:00
Christian Boltz
78cbf37db0 allow dnsmasq read config created by recent NetworkManager
(see  http://cgit.freedesktop.org/NetworkManager/NetworkManager/commit/?id=d82669d3fdaa7ec70ef1b64941c101ac810c394b 
for details)

Patch by develop7 [at] develop7.info

Acked-by: Jamie Strandboge <jamie@canonical.com>
2014-01-17 20:59:22 +01:00
Steve Beattie
9040d46cc4 parser: fix compilation failure on 32 bit systems
Merge from trunk revision 2308.

std::max in C++ requires that both arguments be the same type. The
previous fix added std::max comparisons between unsigned long numeric
constants and size_t, this fix casts the numeric constants to size_t.

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: John Johansen <john.johansen@canonical.com>
2014-01-10 11:08:38 -08:00
John Johansen
ac7ab1c089 Fix policy generation for small dfas
cherry-pick of r2303 from trunk

So there are multiple bugs in policy generation for small dfas.
- A bug where dfas reduced to only have a none accepting state
  drop the start state for accept tables in the chfa encoding

  eg. deny audit dbus,

  the accept and accept2 tables are resized to 1 but the cfha format
  requires at least 2. 1 for the none accepting state and 1 for the
  start state.
  the kernel check that the accept tables == other state table sizes
  caught this and rejected it.

- the next/check table needs to be padded to the largest base position
  used + 256 so no input can ever overflow the next/check table
  (next/check[base+c]).

  This is normally handled by inserting a transition which resizes
  the table. However in this case there where no transitions being
  inserted into the dfa. Resulting in a next/check table size of
  2, with a base pos of 0. Meaning the table needed to be padded
  to 256.

- there is an alignment bug for dfas within the container (see below)
  what follows is a hexdump of the generated policy. With the
  different parts broken out. There are 2 dfas (policy and older file) and
  it is the second dfa that is out of alignment.

  The aadfa blob wrapper should be making sure that the start of the actual
  dfa is in alignment but this is not happening. In this example


00000000  04 08 00 76 65 72 73 69  6f 6e 00 02 05 00 00 00  |...version......|
00000010  04 08 00 70 72 6f 66 69  6c 65 00 07 05 40 00 2f  |...profile...@./|
00000020  68 6f 6d 65 2f 75 62 75  6e 74 75 2f 62 7a 72 2f  |home/ubuntu/bzr/|
00000030  61 70 70 61 72 6d 6f 72  2f 74 65 73 74 73 2f 72  |apparmor/tests/r|
00000040  65 67 72 65 73 73 69 6f  6e 2f 61 70 70 61 72 6d  |egression/apparm|
00000050  6f 72 2f 71 75 65 72 79  5f 6c 61 62 65 6c 00 04  |or/query_label..|
00000060  06 00 66 6c 61 67 73 00  07 02 00 00 00 00 02 00  |..flags.........|
00000070  00 00 00 02 00 00 00 00  08 02 00 00 00 00 02 00  |................|
00000080  00 00 00 02 00 00 00 00  02 00 00 00 00 04 07 00  |................|
00000090  63 61 70 73 36 34 00 07  02 00 00 00 00 02 00 00  |caps64..........|
000000a0  00 00 02 00 00 00 00 02  00 00 00 00 08 04 09 00  |................|
000000b0  70 6f 6c 69 63 79 64 62  00 07

begin of policy dfa blob wrapper
000000b0                                 04 06 00 61 61 64  |policydb.....aad|
000000c0  66 61 00 06

size of the following blob (in little endian) so 0x80
000000c0              80 00 00 00  

begin of actual policy dfa, notice alignment on 8 byte boundry
000000c0                           1b 5e 78 3d 00 00 00 18  |fa.......^x=....|
000000d0  00 00 00 80 00 00 6e 6f  74 66 6c 65 78 00 00 00  |......notflex...|
000000e0  00 01 00 04 00 00 00 00  00 00 00 01 00 00 00 00  |................|
000000f0  00 07 00 04 00 00 00 00  00 00 00 01 00 00 00 00  |................|
00000100  00 02 00 04 00 00 00 00  00 00 00 02 00 00 00 00  |................|
00000110  00 00 00 00 00 00 00 00  00 04 00 02 00 00 00 00  |................|
00000120  00 00 00 02 00 00 00 00  00 08 00 02 00 00 00 00  |................|
00000130  00 00 00 02 00 00 00 00  00 03 00 02 00 00 00 00  |................|
00000140  00 00 00 02 00 00 00 00  08

dfa blob wrapper
00000140                              04 06 00 61 61 64 66  |............aadf|
00000150  61 00 06

size of the following blob (in little endian) so 0x4c8
00000150          c8 04 00 00

begin of file dfa, notice alignment. NOT on 8 byte boundry
                               1b  5e 78 3d 00 00 00 18 00  |a.......^x=.....|
00000160  00 04 c8 00 00 6e 6f 74  66 6c 65 78 00 00 00 00  |.....notflex....|
00000170  01 00 04 00 00 00 00 00  00 00 06 00 00 00 00 00  |................|
00000180  00 00 00 00 9f c2 7f 00  00 00 00 00 00 00 00 00  |................|
00000190  04 00 30 00 00 00 00 00  07 00 04 00 00 00 00 00  |..0.............|
000001a0  00 00 06 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000001b0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000001c0  02 00 04 00 00 00 00 00  00 00 06 00 00 00 00 00  |................|
000001d0  00 00 00 00 00 00 01 00  00 00 01 00 00 00 02 00  |................|
000001e0  00 00 00 00 00 00 00 00  04 00 02 00 00 00 00 00  |................|
000001f0  00 00 06 00 00 00 00 00  02 00 00 00 05 00 05 00  |................|
00000200  08 00 02 00 00 00 00 00  00 01 02 00 00 00 03 00  |................|
00000210  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000260  00 00 00 00 00 00 00 00  00 00 02 00 04 00 00 00  |................|
00000270  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000410  03 00 02 00 00 00 00 00  00 01 02 00 00 00 02 00  |................|
00000420  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000470  00 00 00 00 00 00 00 00  00 00 01 00 03 00 04 00  |................|
00000480  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000610  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00

end of container
00000610                                                08  |................|
00000620

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2014-01-09 17:43:59 -08:00
Steve Beattie
5ed40d9399 libapparmor: require libtoolize instead of libtool
Merge from trunk revision 2295:

libtoolize is the standard mechanism for incorporating libtool support
into a library; however, libapparmor's autogen.sh script specifically
looks for the existence of the libtool binary rather than libtoolize.
The libtoolize tool automatically generates a libtool script and does
not require the existence of the libtool binary, so we no longer need
to check for it.

The autogen.sh script aborting because it can't find the libtool
binary causes a spurious build failure in Ubuntu 14.04, due to the
libtool binary being separated out into its own package, and which
is not a strict dependency for libtool.

(I also added setting the package variable so that the error message
emitted will indicate that the failure is in building libapparmor.)

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: John Johansen <john.johansen@canonical.com>
2014-01-03 21:53:14 -08:00
Christian Boltz
6b18bb00ff samba (nmbd and smbd) need to create /var/run/samba and /var/cache/samba
at startup (at least on systems where /var/run is on a tmpfs)

References: https://bugzilla.novell.com/show_bug.cgi?id=856651

Acked-by: Steve Beattie <steve@nxnw.org> for trunk and 2.8. Thanks!
2013-12-23 22:16:59 +01:00
Christian Boltz
c184f1ac39 add /var/lib/ca-certificates/ to abstractions/ssl_certs.
update-ca-certificates (from ca-certificates-1_201310161709-1.1.noarch) 
stores certs in this directory now.

References: https://bugzilla.novell.com/show_bug.cgi?id=852018

Acked-by: Seth Arnold <seth.arnold@canonical.com>
2013-11-26 00:42:19 +01:00
Christian Boltz
d8793a07e8 Update samba profiles for samba 4.x
The patch includes changes needed for Samba 4.x, which also includes 
some small abstraction updates.

References: https://bugzilla.novell.com/show_bug.cgi?id=845867
References: https://bugzilla.novell.com/show_bug.cgi?id=846054

Acked-by: Seth Arnold <seth.arnold@canonical.com>
2013-11-20 01:11:01 +01:00
Christian Boltz
1a8423937e ntpd needs access to /var/lib/ntp/drift/driftfile and
/var/lib/ntp/drift/driftfile.TEMP

References: https://bugzilla.novell.com/show_bug.cgi?id=850374

Acked-by: Seth Arnold <seth.arnold@canonical.com>
2013-11-14 21:51:29 +01:00
John Johansen
01b23e02fa The apparmor parser build fails when bison 3 is used. The following
patch is needed to fix the build.

patch from: Jan Rękorajski <baggins@pld-linux.org>
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2013-11-05 14:46:54 -08:00
Christian Boltz
6417e87d59 dnsmasq profile - update for libvirt files
dnsmasq needs read access to more files in /var/lib/libvirt/dnsmasq/
(at least *.conf and *.addnhosts)

Since this directory contains only files that are intended for dnsmasq 
(also confirmed by Jim Fehlig, the SUSE libvirt maintainer), the best 
way is to just allow "/var/lib/libvirt/dnsmasq/* r,"

References: https://bugzilla.novell.com/show_bug.cgi?id=848215


+1'd for trunk and 2.8 by Jamie Strandboge <jamie@canonical.com>
2013-10-30 21:43:45 +01:00
John Johansen
68f86b7cfd On Ubuntu saucy fontconfig reads user configs from
$HOME/.config/fontconfig/conf.d/* and
$HOME/.config/fontconfig/fonts.conf

/etc/fonts/conf.d/50-user.conf:
        <!--
            Load per-user customization files where stored on XDG Base Directory
            specification compliant places. it should be usually:
              $HOME/.config/fontconfig/conf.d
              $HOME/.config/fontconfig/fonts.conf
        -->
        <include ignore_missing="yes" prefix="xdg">fontconfig/conf.d</include>
        <include ignore_missing="yes" prefix="xdg">fontconfig/fonts.conf</include>


abstractions/fonts should allow read access to those files:

From: Felix Geyer debfx@ubuntu.com
Acked-by: John Johansen <john.johansen@canonical.com>
2013-10-14 16:31:38 -07:00
John Johansen
19a1f0aa8c Rev 2203 (rev 2097 on the 2.8 branch) created a regression such that
cache files will be written out even if the '--skip-bad-cache' option
is given and the cached features file differs from the features of
the currently running kernel. The patch below fixes the regression.

From: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2013-10-14 01:51:21 -07:00
John Johansen
3d8c3806e2 Add an option to create the cache directory if it is missing
Signed-off-by: John Johansen john.johansen@canonical.com
Acked-by: Tyler Hicks <tyhicks@canonical.com>
2013-09-29 01:39:22 -07:00
John Johansen
fefb397c56 Moves the cache clearing logic into the create cache routine, because if
we are writing a new cache .features file the cache dir should be cleared
out.

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Tyler Hicks <tyhicks@canonical.com>
2013-09-29 01:13:55 -07:00
John Johansen
f6a0a3c502 The parser is not correctly clearing cache files if cache-loc is specified.
Fix this and unify creation and use of cacheloc so that we can hopefully
avoid these bugs.

Signed-off-by: John Johansen <john.johansen@canonical.com>
2013-09-23 15:26:51 -07:00
John Johansen
01bdac1444 The feature file is not being written to the proper location if the parameter
--cache-loc= is specified. This results in using the .features file from
/etc/apparmor.d/cache or always recompiling policy.

The former case is particularly bad as the .features file in
/etc/apparmor.d/cache/ may not correspond to the file in the specified
cache location.

bug: launchpad.net/bugs/1229393

Signed-off-by: John Johansen <john.johansen@canonical.com>
2013-09-23 14:56:16 -07:00
Christian Boltz
204a96ed58 aa-unconfined displays less unconfined processes in some languages (for
example with LANG=pt_BR) because a regex relies on netstat output.

Enforce LANG=C to make sure aa-unconfined always sees the expected output.

Acked-by: Steve Beattie <steve@nxnw.org>
2013-09-20 13:23:47 +02:00
Christian Boltz
c854a5b81e fix broken URLs in various utils/*.pod files.
(The broken URLs were introduced in r1582.)

for utils/*.pod:
  Acked-by: Steve Beattie <steve@nxnw.org> 

for the other directories:
  Patch by Steve Beattie
  Acked-by: Christian Boltz <apparmor@cboltz.de>
2013-09-19 21:21:43 +02:00
Christian Boltz
dcde62755e ntpd needs read access to openssl.cnf
Patch-Author: Stefan Seyfried <seife+obs@b1-systems.com>

After this change in ntp:

* Mo Aug 19 2013 crrodriguez@opensuse.org
- Build with -DOPENSSL_LOAD_CONF , ntp must respect and use
  the system's openssl configuration.

we need to read openssl.cnf or starting of ntpd will fail silently(!)


Patch v2 by Christian Boltz: use abstractions/openssl instead of
allowing /etc/ssl/openssl.cnf directly

Acked-by: Steve Beattie <steve@nxnw.org>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2013-09-17 00:25:59 +02:00
Christian Boltz
8d597e7b07 fix some (mis)translations in utils/po/de.po
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2013-09-14 00:39:03 +02:00
Jamie Strandboge
b1f45986d8 p11-kit needs access to /usr/share/p11-kit/modules
Acked-By: Jamie Strandboge <jamie@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org> (for trunk and 2.8)
2013-09-12 09:25:56 -05:00
Steve Beattie
fc3c98532b profiles - Allow reading /etc/machine-id in the dbus-session abstraction.
Merge from trunk commit rev 2181
From: intrigeri <intrigeri@boum.org>

D-Bus now uses /etc/machine-id in some cases:
https://bugs.freedesktop.org/show_bug.cgi?id=35228

Acked-by: Steve Beattie <steve@nxnw.org>
2013-09-11 16:05:13 -07:00
Christian Boltz
d2d79c0777 use grep instead of ~~ (smartmatch)
Patch by Kshitij Gupta <kgupta8592@gmail.com>

A previous bugreport [1] was fixed using the smartmatch operator,
which raised the minimum Perl version requirement to >=5.10.1 .
However in Perl5.18 the smartmatch operator has again become
"experimental" [2] so the following patch replace smartmatch operator
with grep and thereby avoiding the requirement hike and avoiding
warnings.

[1] https://bugs.launchpad.net/apparmor/+bug/1180230

[2] http://blogs.perl.org/users/mike_b/2013/06/a-little-nicer-way-to-use-smartmatch-on-perl-518.html

ACKed-by: Christian Boltz <apparmor@cboltz.de>
2013-08-23 22:04:45 +02:00
Seth Arnold
3b47558827 Bump libapparmor's AA_LIB_REVISION in preparation for 2.8.2 release.
Bump common/Version in preparation for 2.8.2 release.
2013-08-15 16:14:58 -07:00
Steve Beattie
2fec3758ed Subject: [patch] fix apparmor cache tempfile location to use passed arg v2
Merge from trunk revision 2142

This patch fixes problems in the handling of both the final cache
name location and the temporary cache file when an alternate location
is specified.

The first issue is that if the alternate cache directory location was
specified, the alternate directory name would be used as the final
location for the cache file, rather than the alternate directory +
the basename of the profile.

The second issue is that it would generate the temporary file that it
stores the cache file in [basedir]/cache even if an alternate cache
location was specified on the command line. This causes a problem
if [basedir]/cache is on a separate device than the alternate cache
location, because the rename() of the tempfile into the final location
would fail (which the parser would not check the return code of).

This patch fixes the above by incorporating the basename into the cache
file name if the alternate cache location has been specified, bases the
temporary cache file name on the destination cache name (such that they
end up in the same directory), and finally detects if the rename fails
and unlinks the temporary file if that happens (rather than leave it
around). It also has been updated to add a couple of testcases to verify
that writing and reading from an alternate cache location work.

Patch history:
  v1: first draft of patch
  v2: add testcases, convert PERROR() to pwarn() if rename() fails for
      placing cachefile into place.

For 2.8 branch:

Signed-off-by: Steve Beattie <sbeattie@ubuntu.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2013-07-29 09:52:18 -07:00
Seth Arnold
09c2da3a69 Fix $options -> @options in previous patch. Fix tabs -> spaces.
Acked-by: Seth Arnold <seth.arnold@canonical.com>
Acked-by: Steve Beattie <sbeattie@ubuntu.com>
2013-07-09 16:03:09 -07:00
Seth Arnold
9d5269b601 Merge intrigeri's abstractions/fonts improvements 2013-07-08 17:45:20 -07:00
Seth Arnold
28a97bf3c5 Kshitij Gupta fixed a display bug in aa-logprof, aa-genprof, with the Glob
and Glob with Ext putting duplicate entries in the list.

The fix introduced a Perl 5.10.1 or higher dependency, so start documenting
minimum required versions of packages.

Acked-By: Christian Boltz <apparmor@cboltz.de>
2013-07-07 18:33:48 -07:00
Seth Arnold
b77a05aa52 Fix potential NULL-write in aa_getprocattr() error path
https://bugs.launchpad.net/apparmor/+bug/1196880

Patch by Gernot Vormayr <gvormayr@gmail.com>

Acked-by: Seth Arnold <seth.arnold@canonical.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2013-07-02 11:53:31 -07:00
Steve Beattie
2c6e1b6e0f Subject: libapparmor - use python-config if it exists when configuring
Merge from trunk commit 2108

Author: Dmitrijs Ledkovs <dmitrij.ledkov@ubuntu.com>
Nominated-by: Steve Beattie <sbeattie@ubuntu.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>

Modifiy the libapparmor macro for python to use python-config if it
exists to determine what CPPFLAGS and LDFLAGS to use when building
the python swig libraries. Without this addition, python detection
fails on ubuntu 13.04. I've confirmed that with this patch applied,
the python libraries still build successfully on older releases as well
(as far back as ubuntu 11.10).
2013-07-02 10:35:36 -07:00
Christian Boltz
b0fd46af26 add Dolphin (default Kubuntu file manager) to the list of file managers in
abstractions/ubuntu-browsers.d/ubuntu-integration.

Patch by Felix Geyer <debfx@ubuntu.com>

Acked-by: Seth Arnold <seth.arnold at canonical.com>
Acked-by: Christian Boltz <apparmor@cboltz.de> 

(backport of trunk r2133)
2013-07-01 17:51:11 +02:00
Christian Boltz
9687641741 merge https://code.launchpad.net/~kensington/apparmor/apparmor/+merge/169010
Michael Palimaka 2013-06-13 Add missing key shortcuts for hu linguas.

(backport of trunk r2132)
2013-07-01 17:45:50 +02:00
Seth Arnold
6e67ef7cc3 Move poppler's cMaps from gnome to fonts; gnome includes fonts
Acked-By: Christian Boltz <apparmor@cboltz.de>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2013-05-30 14:46:31 -07:00
Jamie Strandboge
76e23529af cherrypick r2119 from trunk:
deny writes to upstart user sessions jobs in abstractions/private-files

Acked-By: Jamie Strandboge <jamie@canonical.com>
Acked-by: Steve Beattie <sbeattie@ubuntu.com>
2013-05-13 14:58:28 -05:00
Jamie Strandboge
d345d4a93a cherrypick r2118 from trunk:
add @{HOME}/.gnome2/keyrings/** to abstractions/private-files-strict

Acked-By: Jamie Strandboge <jamie@canonical.com>
Acked-by: Steve Beattie <sbeattie@ubuntu.com>
2013-05-13 14:57:35 -05:00
Christian Boltz
bd09ea910b Backport the python3 compability changes from trunk r2052 to
the 2.8 branch.

Original commit message:
    committer: Jamie Strandboge <jamie@canonical.com>
    Initial port to python3 for utilities. Thanks to Dmitrijs Ledkovs
    Acked-By: Jamie Strandboge <jamie@canonical.com>

Most of trunk r2052 also applies to the 2.8 branch. The only difference
is the last section of changes in utils/vim/create-apparmor.vim.py

Acked-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <sbeattie@ubuntu.com>
Skimmed-by: Seth Arnold <seth.arnold@canonical.com>
2013-05-07 22:38:18 +02:00
John Johansen
18d66a09f6 This is a minimal fix to apparmor 2.8 for cache failures when the feature
file is larger than the feature buffer used for cache version comparison.

Ideally this would be dynamically allocated but for 2.8 just bumping the
buffer size is the quick fix.

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <sbeattie@ubuntu.com>
2013-05-02 11:30:19 -07:00
Jamie Strandboge
5d439f2fcc cherrypick 2111 from trunk:
add read access to @{PROC}/sys/vm/overcommit_memory as used by glibc. See
  http://sourceware.org/git/?p=glibc.git;a=commit;h=9fab36eb583c0e585e83a01253299afed9ea9a11

Acked-By: Christian Boltz <apparmor@cboltz.de>
Acked-By: Jamie Strandboge <jamie@canonical.com>
2013-04-09 08:18:40 -05:00
Jamie Strandboge
e9353b757c cherrypick r2110 from trunk:
update pulseaudio directory and cookie file paths

Acked-By: Christian Boltz <apparmor@cboltz.de>
Acked-By: Jamie Strandboge <jamie@canonical.com>
2013-04-09 08:17:39 -05:00
Christian Boltz
8029059d73 Add missing permissions to the nscd profile.
Also deny capability block_suspend because nobody can imagine why it 
would be needed.

References: https://bugzilla.novell.com/show_bug.cgi?id=807104

Acked-by: Seth Arnold <seth.arnold@canonical.com>

(backport of trunk r2109)
2013-03-05 22:12:37 +01:00
Christian Boltz
05251eef06 abstractions/mysql: changed paths and MariaDB support
abstractions/mysql  contains
   /var/lib/mysql/mysql.sock rw,
   /usr/share/mysql/charsets/ r,
   /usr/share/mysql/charsets/*.xml r,

but the files moved (at least on openSUSE) to
    /usr/share/mysql-community-server/charsets/*.xml
    /var/run/mysql/mysql.sock
This causes denials for all applications using MySQL on 12.2 and 
Factory.

MariaDB has the *.xml files in
    /usr/share/mariadb/charsets/*.xml
and also seems to use /var/run/mysql/ for the socket.

Since MariaDB is basically a drop-in replacement for MySQL, it makes
sense to allow access to it via abstractions/mysql.

References: https://bugzilla.novell.com/show_bug.cgi?id=798183

Acked-by: Seth Arnold <seth.arnold@canonical.com>
2013-01-13 14:41:56 +01:00
Steve Beattie
3158465820 Bump libapparmor's AA_LIB_REVISION in preparation for 2.8.1 release. 2013-01-09 16:23:51 -08:00
Steve Beattie
a27cd136b6 prepare for 2.8.1 release 2013-01-09 15:36:12 -08:00
Steve Beattie
e7e6aa9ed2 Subject: profiles - adjust pulseaudio in abstraction
Merge from trunk commit 2102

Original message:
  I was testing out a profile for pulseaudio and hit an issue where my
  pulseaudio process was getting the firefox profile applied to it. This
  is because in abstractions/ubuntu-browsers.d/multimedia the rule for
  pulseaudio is /usr/bin/pulseaudio ixr; attached is a patch to change it
  to Pixr, so as to use a global pulseaudio policy if it exists.

Signed-off-by: Steve Beattie <sbeattie@ubuntu.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2013-01-09 15:15:59 -08:00
John Johansen
e478b9b37d The following patch extends the libraries log parsing to support more date
time formats. As this is causing failures on some systems

currently the only supported format is
  <Month> ## hh:mm:ss

extend this to
  <Month> ## hh:mm:ss(.ms)?((+|-)timezone)?

  yyyy-mm-dd hh:mm:ss(.ms)?((+|-)timezone)?

  yyyy-mm-ddThh:mm:ss(.ms)?((+|-)timezone)?
2013-01-08 12:51:07 -08:00
Steve Beattie
98a1594e88 Subject: aa-decode test script
Merge from trunk commit 2077

Original message:
  Subject: aa-decode test script v3
  
  This patch adds a test script/driver for the aa-decode utility. The only
  change from the previous versions is to support overriding the location
  of the aa-decode to test via the APPARMOR_DECODE environment variable
  and documenting the utils/ tests in the top level README.
  
  The aa-decode test can be run directly from the commandline in the utils
  directory like so:
  
    test/test-aa-decode.py -v
  
  Signed-off-by: Steve Beattie <sbeattie@ubuntu.com>
  Acked-By: Christian Boltz <apparmor@cboltz.de>

Nominated-by: Steve Beattie <sbeattie@ubuntu.com>
Acked-By: Christian Boltz <apparmor@cboltz.de>
2013-01-04 15:06:47 -08:00
Steve Beattie
e6614df4a5 Backported merge of various fixes from trunk in preparation of the 2.8.1
release. In this merge are the following trunk commits:

2050 - parser - network rules debugging statements
2057 - update ubuntu-browsers.d/java for IcedTea 7
2058 - let sanitized-helper also allow access to /usr/local
2059 - ubuntu-integration does not work properly with exo-open
2062 - support alternate ping install location in /usr
2064 - parser - update apparmor_parser man page
2065 - parser - correct apparmor_parser -N command privilege
2066 - parser - *just* the updated caching test message from this commit
2065.1.1 - profiles update fonts abstraction for new fontconfig paths
2065.1.{3,4} - profiles - Gnome applications are now quite interested
       in reading /usr/share/poppler/cMap/**
2069 - profiles - update extras README with mail list info
2074 - tests - fix clone test on arm
2076 - parser tests - fix test driver for exec() failure
2079 - libapparmor - add pkgconfig support
2083 - parser tests - fix fine grained timestamp detection in caching tests
2090 - nvidia abstractions cleanups
2092 - update skype profile
2093 - add XCompose to abstractions/X
2096 - dnsmasq network-manager integration
2013-01-04 10:11:00 -08:00
Steve Beattie
701537325e Subject: dnsmasq network-manager integration
Merge from trunk commit 2096

Original message:
  Subject: profiles - dnsmasq: allow writes to
   /{,var/}run/sendsigs.omit.d/*dnsmasq.pid for network manager
   integration
  
  Author: Jamie Strandboge <jamie@canonical.com>
  Description: allow writes to /{,var/}run/sendsigs.omit.d/*dnsmasq.pid
   for network manager integration
  Bug-Ubuntu: https://launchpad.net/bugs/941808
  
  Acked-by: Steve Beattie <sbeattie@ubuntu.com>

Nominated-by: Christian Boltz <apparmor@cboltz.de>
Acked-by: Steve Beattie <sbeattie@ubuntu.com>
2013-01-04 09:46:39 -08:00
Steve Beattie
dca6359ad5 Subject: add XCompose to abstractions/X
Merge from trunk commit 2093

Original message:
  Subject: profiles - add user's XCompose file to X abstraction
  
  In testing the skype profile, I found access to my @{HOME}/.XCompose
  was being rejected. This patch updates the X abstraction to take a
  user's defined XCompose key shortcuts into account.
  
  Signed-off-by: Steve Beattie <sbeattie@ubuntu.com>
  Acked-By: Jamie Strandboge <jamie@canonical.com>

Nominated-by: Christian Boltz <apparmor@cboltz.de>
Acked-by: Steve Beattie <sbeattie@ubuntu.com>
2013-01-04 09:45:19 -08:00
Steve Beattie
6e02694f6f Subject: update skype profile
Merge from trunk commit 2092 (w/ dropping the last modified timestamp
entirely)

Original message:
  Subject: profiles - update skype profile
  
  Author: Jamie Strandboge <jamie@canonical.com>
  Bug-Ubuntu: https://launchpad.net/bugs/933440 Forwarded: yes
  
  This is a very slightly updated version of the skype profile
  update that Jamie Strandboge submitted, but did not get a review.
  The only addition over the previously submitted version is rw access
  to @{HOME}/.config/Skype/Skype.conf.
  
  (This commit incorporates the additional @{HOME}/.kde4 change proposed
  by Christian Boltz <apparmor@cboltz.de>)
  
  Signed-off-by: Steve Beattie <sbeattie@ubuntu.com>
  Acked-By: Jamie Strandboge <jamie@canonical.com>

Nominated-by: Christian Boltz <apparmor@cboltz.de>
Acked-by: Steve Beattie <sbeattie@ubuntu.com>
2013-01-04 09:38:29 -08:00
Steve Beattie
fc6889ae8e Subject: nvidia abstractions cleanups
Merge from trunk commit 2090

Original message:
  Subject: profiles - nvidia abstraction cleanups
  
  This patch modifies the nvidia abstraction to add the livdpau wrapper
  config file for nvidia workarounds. It also converts the /proc/
  rules to use the @{PROC} tunable. And finally, it converts the
  ubuntu-browsers.d/multimedia abstraction to use the nvidia abstraction.
  
  Signed-off-by: Steve Beattie <sbeattie@ubuntu.com>
  Acked-By: Jamie Strandboge <jamie@canonical.com>

Nominated-by: Christian Boltz <apparmor@cboltz.de>
Acked-by: Steve Beattie <sbeattie@ubuntu.com>
2013-01-04 09:34:43 -08:00
Steve Beattie
0a97828f30 Subject: parser tests - fix fine grained timestamp detection in
caching tests

Merge from trunk commit 2083

Original message:
  This patch modifies the parser's caching test to more accurately detect
  whether or not the filesystem has a fine enough timestamp resolution.
  Occasionally even on filesystems like ext3, the two files' creation
  dates would differ when created less than a second apart, which would
  typically cause the 'Cache is used when cache is newer' test to fail
  because the cached file would have the same timestamp as the profile.
  
  The fix creates 10 files 0.1 seconds apart and ensures that all ten
  have distinct timestamps.
  
  (The occasional failure was caught in testing runs like
   https://bugs.launchpad.net/qa-regression-testing/+bug/1087061/ )
  
  Signed-off-by: Steve Beattie <sbeattie@ubuntu.com>
  Acked-by: John Johansen <john.johansen@canonical.com>

Nominated-by: Steve Beattie <sbeattie@ubuntu.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2013-01-03 17:28:44 -08:00
Steve Beattie
84e7cdb5ee Subject: libapparmor - add pkgconfig support
Merge from trunk commit 2079

Original message:
  Given that we want to do more apparmor things in user space (dbus
  mediation, file picker, etc.), making it easier for other source bases
  to detect the presence of libapparmor would be beneficial. This patch
  adds pkg-config support to the build infrastructure for libapparmor.
  
  Signed-off-by: Steve Beattie <sbeattie@ubuntu.com>
  Acked-by: Kees Cook <kees@ubuntu.com>

Nominated-by: Steve Beattie <sbeattie@ubuntu.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2013-01-03 17:26:27 -08:00
Steve Beattie
6654dfe251 Subject: parser tests - fix test driver for exec() failure
Merge from trunk commit 2076

Original message:
  Subject: two fixes to the parser's simple test driver
  
  This patch fixes two issue with the simple test driver. The first is
  that child exec that actually ran the parser was located inside the
  eval statement. This meant that if the exec failed for some reason
  (like the parser didn't exist), the child wouldn't actually die,
  but would pop out of the eval and continue running through the loop
  of test profiles (while the parent process does the same). This meant
  that if the script ran on the full testsuite with a misconfiguration,
  it would explode creating O(n^2) processes, where n is the number of
  testcase files -- with over 25k testcases, that's a lot. The fis is to
  lift the child exec outside the eval{}, then an exec() failure causes
  the child process to die correctly.
  
  The second fix is that several of the testcases were added with the
  DESCRIPTION field added in lower case (i.e. #=Description blah blah).
  This fix makes the regex that pulls out the description not be
  case-sensitive.
  
  Signed-off-by: Steve Beattie <sbeattie@ubuntu.com>
  Acked-By: John Johansen <john.johansen@canonical.com>

Nominated-by: Steve Beattie <sbeattie@ubuntu.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2013-01-03 17:22:00 -08:00
Steve Beattie
a99e93c412 Subject: tests - fix clone test on arm
Merge from trunk commit 2074.

Original message:
  apparmor: Fix clone test on quantal arm omap-4
  
  It turns out that PAGE_SIZE isn't defined on all architectures.
  
  This fixes a regression test failure happening on Ubuntu quantal
  on the arm ti-omap4 architecture.
  
  Signed-off-by: John Johansen <john.johansen@canonical.com>
  Acked-By: Steve Beattie <sbeattie@ubuntu.com>

Nominated-by: Steve Beattie <sbeattie@ubuntu.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2013-01-03 16:47:10 -08:00
Steve Beattie
ae12cc8e42 Subject: update mailing list address in extras README
Merge mailing list update from profiles/apparmor/profiles/extras/README
in trunk commit 2069.

Nominated-by: Christian Boltz <apparmor@cboltz.de>
Acked-by: Steve Beattie <sbeattie@ubuntu.com>
2013-01-03 16:43:41 -08:00
Steve Beattie
590a39e194 Subject: update gnome abstraction to allow reading
/usr/share/poppler/cMap/**

Merge from trunk commit 2065.1.3

Original message:
  Gnome applications are now quite interested in reading
  /usr/share/poppler/cMap/**. These files are included in the poppler-data
  package on Ubuntu, and their 'r' denials create quite a bit of noise.
  Apparently they are needed to display PDF documents containing CJK
  characters with libpoppler. I added it to the gnome abstraction because
  several applications not linked against poppler are consulting this
  data.
  
  Acked-By: Jamie Strandboge <jamie@canonical.com>
  Acked-By: Steve Beattie <sbeattie@ubuntu.com>

Nominated-by: Christian Boltz <apparmor@cboltz.de>
Acked-by: Steve Beattie <sbeattie@ubuntu.com>
2013-01-03 16:34:57 -08:00
Steve Beattie
0da19a9474 Subject: update fonts abstraction for new fontconfig paths
Merge from trunk commit 2065.1.1.

Original message:
  update fonts abstraction for new fontconfig paths
  
  Acked-By: Jamie Strandboge <jamie@canonical.com>
  Acked-By: Steve Beattie <sbeattie@ubuntu.com>

Nominated-by: Christian Boltz <apparmor@cboltz.de>
Acked-by: Steve Beattie <sbeattie@ubuntu.com>
2013-01-03 16:27:15 -08:00
Steve Beattie
06aa9b0a54 Subject: update caching test message
Merge from just the parser/tst/caching.sh portion of trunk commit 2066.

Original message:
  apparmor: abstract out the directory walking routine
  
  The apparmor_parser has 3 different directory walking routines.
Abstract
  them out and use a single common routine.
  
  Signed-off-by: John Johansen <john.johansen@canonical.com>
  Acked-By: Steve Beattie <sbeattie@ubuntu.com>
 
Nominated-by: Steve Beattie <sbeattie@ubuntu.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2013-01-03 16:20:14 -08:00
Steve Beattie
76925a236c Merge from trunk commit 2065:
Original message:
  apparmor: correct apparmor_parser -N command privilege

  Fix the apparmor_parsers -N command (which dumps the list of profile
  names found in a policy file) to be available without privilege and
  also make it be recognized as a command instead of an option so that
  it can conflict with -a -r -R -S and -o.

  Currently it can be specified with these commands but will cause the
  parser to short circuit just dumping the names and not doing the actual
  profile compile or load.

  Signed-off-by: John Johansen <john.johansen@canonical.com>
  Acked-By: Steve Beattie <sbeattie@ubuntu.com>

Nominated-by: Steve Beattie <sbeattie@ubuntu.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2013-01-03 16:12:20 -08:00
Steve Beattie
626b9a9d36 Merge from trunk commit 2064:
Original message:
  apparmor: update apparmor_parser man page

  Rework and update the apparmor_parser man page. It reworks some of the
  text but mostly just reorganizes the commands and options into logical
  grouping to make it easier to sort out how the various commands and
  options work.

  Signed-off-by: John Johansen <john.johansen@canonical.com>
  Acked-By: Steve Beattie <sbeattie@ubuntu.com>

Nominated-by: Steve Beattie <sbeattie@ubuntu.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2013-01-03 15:58:28 -08:00
Steve Beattie
4fdb2dd24e Merge from trunk commit 2062:
Original message:
  /bin/ping moved to /usr/bin/ping on openSUSE (usrMerge)
  Update the profile to make sure it's still used.

  Acked-by: John Johansen <john.johansen@canonical.com>

Nominated-by: Steve Beattie <sbeattie@ubuntu.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2013-01-03 15:55:57 -08:00
Steve Beattie
6e0996981b Merge from trunk commit 2059:
Original message:
  Author: Mark Ramsell <mramsell@qazonline.net>
  Description: ubuntu-integration does not work properly with exo-open
  Bug-Ubuntu: https://launchpad.net/bugs/987578

  Acked-By: Jamie Strandboge <jamie@canonical.com>

Nominated-by: Steve Beattie <sbeattie@ubuntu.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2013-01-03 15:54:16 -08:00
Steve Beattie
8e33b4a173 Merge from trunk commit 2058:
Original message:
  Description: let sanitized-helper also allow access to /usr/local.
    Patch based on work by Reuben Thomas
  Bug-Ubuntu: https://launchpad.net/bugs/1013887

  Acked-By: Jamie Strandboge <jamie@canonical.com>

Nominated-by: Steve Beattie <sbeattie@ubuntu.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2013-01-03 15:44:14 -08:00
Steve Beattie
3e18698c78 Merge from trunk commit 2057:
Original message:
  Description: update ubuntu-browsers.d/java for IcedTea 7
  Bug-Ubuntu: https://launchpad.net/bugs/1003856

  Acked-By: Jamie Strandboge <jamie@canonical.com>

Nominated-by: Steve Beattie <sbeattie@ubuntu.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2013-01-03 15:37:41 -08:00
Steve Beattie
0fc26d7c47 Merge from trunk commit 2050:
Original Message:
  While integrating 3.4-rc1, I ran into a problem where network rules
  weren't being processed. It ultimately boiled down to a kernel
  issue but I found it useful to see what the parser thought it was
  working with. Since the parser already has a debugging mode that
  will show things like capabilities, it was an obvious extension to
  add network rules.

  Signed-off-by: Jeff Mahoney <jeffm@suse.com>
  Acked-by: John Johansen <john.johansen@canonical.com>

Nominated-by: Steve Beattie <sbeattie@ubuntu.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2013-01-03 14:38:38 -08:00
Christian Boltz
78cd88c56d fix aa-decode by backporting all changes from trunk to 2.8 branch
Acked-By: John Johansen (up to r2072)
Acked-by: Steve Beattie <sbeattie@ubuntu.com> (including r2088)


In detail, the changes are (bzr log from trunk):
------------------------------------------------------------
revno: 2088
committer: Christian Boltz <apparmor@cboltz.de>
branch nick: apparmor
timestamp: Tue 2013-01-01 20:15:04 +0100
message:
  speed up aa-decode by using a bash regex matching instead of calling egrep for each line.

  Acked-by: Steve Beattie <sbeattie@ubuntu.com>

  (Patch sent 2012-11-01, Acked-by from 2013-01-01)
------------------------------------------------------------
revno: 2072
committer: Christian Boltz <apparmor@cboltz.de>
branch nick: apparmor
timestamp: Tue 2012-10-16 00:19:49 +0200
message:
  Fix aa-decode handling of stdin

  Handling stdin was totally broken (= no output) with the current log
  format because aa-decode expected name= to be the last entry in the
  log line.

  This patch for stdin handling
  - fixes the pattern to match the current log format (name= is NOT the
    last part in the log entry)
  - uses bash replacement to avoid some sed calls (which also means the
    script now needs an explicit "#!/bin/bash")
  - prints decoded filenames in double instead of single quotes to be
    consistent with filenames that were not encoded
  - also prints lines that do not contain an encoded filename (instead of
    grepping them away)
  - replace tr calls by perl's uc() (also for non-stdin mode)
  - also handle encoded profile names (introduced by Steve)
  - don't fail if a file or profile name contains a '

  In other words: you can pipe your audit.log through aa-decode, and the
  only difference to the raw audit.log is that filenames are decoded.


  Acked-By: Steve Beattie <sbeattie@ubuntu.com>
------------------------------------------------------------
revno: 2068
committer: Christian Boltz <apparmor@cboltz.de>
branch nick: apparmor
timestamp: Mon 2012-09-17 23:55:28 +0200
message:
  fix error handling in aa-decode

  Acked-By: Steve Beattie <sbeattie@ubuntu.com>

  Looks-Good-By: ;-)  Seth Arnold <seth.arnold@gmail.com>
------------------------------------------------------------
2013-01-01 20:26:19 +01:00
John Johansen
c48e4a76d3 Add a small sleep call to the onexec test to give the forked process a
chance to run before verifying it's current and future confinement
state. In testing the combined sleeps added roughly a second to
onexec.sh's total time on relatively reasonable hardware.

Signed-off-by: Steve Beattie <sbeattie@ubuntu.com>
Acked-By: John Johansen <john.johansen@canonical.com> (via IRC)
2012-12-19 05:38:49 -08:00
Christian Boltz
bbaa1fa6d1 add CAP_BLOCK_SUSPEND to severity.db
(backported from trunk)

Acked-by: John Johansen <john.johansen@canonical.com>
2012-12-17 13:34:41 +01:00
Steve Beattie
ecd14e46b9 Add a testcase for the issue fixed in commit 2059.
Signed-off-by: Steve Beattie <sbeattie@ubuntu.com>
Acked-by: John Johansen <john.johansen@canonical.com>
2012-12-10 17:01:24 -08:00
John Johansen
e0c94c9039 fix a nasty little bug that can surface in apparmor 2.8 when
Hats/children profiles are used.

the matchflags in the dfa backend are not getting properly reset, which
results in a previously processed profiles match flags being used. This is
not a problem for most permissions but can result in x conflict errors.

Note: this should not result in profiles with the wrong x transitions loaded
as it causes compilation to file with an x conflict.

This is a minimal patch targeted at the 2.8 release. As such I have just
updated the delete_ruleset routine to clear the flags as it is already
being properly called for every rule set.

Apparmor 2.9/3.0 will have a different approach where it is not possible
to reuse the flags.

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <sbeattie@ubuntu.com>
2012-12-10 15:12:22 -08:00
John Johansen
b5c6e11aca Add kernel patches for 3.5 and 3.6 kernels 2012-11-20 17:00:59 -08:00
John Johansen
fd6a33f89e Update documentation of change_hat and change_profile apis
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Seth Arnold <seth.arnold@gmail.com>
2012-11-20 16:52:43 -08:00
John Johansen
276ef3facf So the library version has not been being correctly bumped.
Make this a little bit easier to follow

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2012-10-12 11:41:51 -07:00
John Johansen
4a42d74351 The apparmor coredump regression test was broken.
- It failed to remove coredump files named "core"
- It failed to properly detect "core.<pid>" files
- And it would fail if the coredump_pattern had been modified to
  a different location.

This lead one of the tests to report it was passing when it
wasn't because it was detecting the previous tests core file.

- Fix the test to set the coredump_pattern, to dump into the
  tmpdir used for the test.
- Make it so it will only detect the core file for the pid of
  the last test run.
- And extend the test to have a couple of extra test cases.

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Kees Cook <kees@ubuntu.com>
2012-10-01 10:57:11 -07:00
John Johansen
00bf73f7c2 apparmor: add clearing the profile cache when inconsistent
Add the ability to clear out the binary profile cache. This removes the
need to have a separate script to handle the logic of checking and
removing the cache if it is out of date.

The parser already does all the checking to determine cache validity
so it makes sense to allow the parser to clear out inconsistent cache
when it has been instructed to update the cache.

Signed-off-by: John Johnansen <john.johansen@canonical.com>
2012-08-09 00:37:25 -07:00
Christian Boltz
b0a05c5b3d ls moved from /bin/ to /usr/bin/ on openSUSE (usrMove)
Acked-by: John Johansen <john.johansen@canonical.com>
2012-08-06 13:57:22 +02:00
John Johansen
563a49adc4 The previous patch to fix policy compilation around the network flag had a
serious flaw. The test for the network flag was being applied against both
the kernel flags and the cache flags. This means that if either the kernel
or the cache did not have the flag set then network mediation would be
turned off.

Thus if a kernel was booted without the flag, and a cache was generated
based on that kernel and then the system was rebooted into a kernel with
the network flag present, the parser on generating the new policy would
detect the old cache did not support network and turn it off for the
new policy as well.

This can be fixed by either removing the old cache first or regenerating
the cache twice. As the first generation will write that networking is
supported in the cache (even though the policy will have it disabled), and
the second generation will generate the correct policy.

The following patch moves the test so that it is only applied to the kernel
flags set.

Signed-off-by: John Johansen <john.johansen@canonical.com>
2012-07-17 16:00:53 -07:00
John Johansen
107b5113bd Fix the parser so it checks for the presence of the network feature in the
compatibility interface. Previously it was assuming that if the compatibility
interface was present that network rules where also present, this is not
necessarily true and causes apparmor to break when only the compatibility
patch is applied.

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Kees Cook <kees@ubuntu.com>
2012-07-01 01:35:05 -07:00
John Johansen
c1c1b229c1 Have build check for presence of awk and fail with a sensible error message
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
2012-06-29 16:42:39 -07:00
John Johansen
9fbfa4c7e0 Original Author: mancha@mancha.user.oftc.net
create-apparmor.vim.py was failing on systems with python 2.5, fix that
    
Acked-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <sbeattie@ubuntu.com>
2012-06-08 14:27:05 -07:00
Steve Beattie
77de4e26cd update REPO_URL for 2.8 branch 2012-05-31 11:32:33 -07:00
2265 changed files with 107837 additions and 154858 deletions

View File

@@ -2,7 +2,6 @@ apparmor-*
parser/po/*.mo
parser/af_names.h
parser/cap_names.h
parser/tst_lib
parser/tst_misc
parser/tst_regex
parser/tst_symtab
@@ -19,14 +18,13 @@ parser/*.8
parser/*.7.html
parser/*.5.html
parser/*.8.html
parser/common
parser/apparmor_parser
parser/libapparmor_re/parse.cc
parser/libapparmor_re/regexp.cc
parser/techdoc.aux
parser/techdoc.log
parser/techdoc.pdf
parser/techdoc.toc
profiles/apparmor.d/local/*.*
libraries/libapparmor/Makefile
libraries/libapparmor/Makefile.in
libraries/libapparmor/aclocal.m4
@@ -43,32 +41,20 @@ libraries/libapparmor/install-sh
libraries/libapparmor/libtool
libraries/libapparmor/ltmain.sh
libraries/libapparmor/missing
libraries/libapparmor/test-driver
libraries/libapparmor/ylwrap
libraries/libapparmor/doc/Makefile
libraries/libapparmor/doc/Makefile.in
libraries/libapparmor/doc/*.2
libraries/libapparmor/doc/aa_*.3
libraries/libapparmor/include/Makefile
libraries/libapparmor/include/Makefile.in
libraries/libapparmor/include/sys/Makefile
libraries/libapparmor/include/sys/Makefile.in
libraries/libapparmor/src/.deps
libraries/libapparmor/src/.libs
libraries/libapparmor/src/Makefile
libraries/libapparmor/src/Makefile.in
libraries/libapparmor/src/af_protos.h
libraries/libapparmor/src/change_hat.lo
libraries/libapparmor/src/features.lo
libraries/libapparmor/src/grammar.lo
libraries/libapparmor/src/kernel.lo
libraries/libapparmor/src/kernel_interface.lo
libraries/libapparmor/src/libaalogparse.lo
libraries/libapparmor/src/libimmunix_warning.lo
libraries/libapparmor/src/policy_cache.lo
libraries/libapparmor/src/private.lo
libraries/libapparmor/src/scanner.lo
libraries/libapparmor/src/libapparmor.pc
libraries/libapparmor/src/libapparmor.la
libraries/libapparmor/src/libimmunix.la
libraries/libapparmor/src/grammar.c
@@ -84,20 +70,12 @@ libraries/libapparmor/swig/perl/Makefile
libraries/libapparmor/swig/perl/Makefile.PL
libraries/libapparmor/swig/perl/Makefile.in
libraries/libapparmor/swig/perl/Makefile.perl
libraries/libapparmor/swig/perl/Makefile.perle
libraries/libapparmor/swig/perl/MYMETA.json
libraries/libapparmor/swig/perl/MYMETA.yml
libraries/libapparmor/swig/perl/blib
libraries/libapparmor/swig/perl/libapparmor_wrap.c
libraries/libapparmor/swig/perl/pm_to_blib
libraries/libapparmor/swig/python/LibAppArmor.py
libraries/libapparmor/swig/python/build/
libraries/libapparmor/swig/python/libapparmor_wrap.c
libraries/libapparmor/swig/python/Makefile
libraries/libapparmor/swig/python/Makefile.in
libraries/libapparmor/swig/python/setup.py
libraries/libapparmor/swig/python/test/Makefile
libraries/libapparmor/swig/python/test/Makefile.in
libraries/libapparmor/swig/ruby/Makefile
libraries/libapparmor/swig/ruby/Makefile.in
libraries/libapparmor/testsuite/.deps
@@ -116,6 +94,10 @@ libraries/libapparmor/testsuite/libaalogparse.test/Makefile
libraries/libapparmor/testsuite/libaalogparse.test/Makefile.in
libraries/libapparmor/testsuite/test_multi/out
changehat/mod_apparmor/.libs
changehat/mod_apparmor/common
changehat/pam_apparmor/common
changehat/tomcat_apparmor/common
utils/common
utils/*.8
utils/*.8.html
utils/*.5
@@ -183,5 +165,3 @@ tests/regression/apparmor/unix_fd_server
tests/regression/apparmor/unlink
tests/regression/apparmor/xattrs
tests/regression/apparmor/coredump
**/__pycache__/
*.orig

View File

@@ -1,30 +1,24 @@
#
#
.PHONY: all
all:
@echo "*** See README for information how to build AppArmor ***"
exit 1
OVERRIDE_TARBALL=yes
COMMONDIR=common
include ${COMMONDIR}/Make.rules
include common/Make.rules
DIRS=libraries/libapparmor \
binutils \
parser \
DIRS=parser \
profiles \
utils \
libraries/libapparmor \
changehat/mod_apparmor \
changehat/pam_apparmor \
profiles \
tests
#REPO_URL?=lp:apparmor
#REPO_URL?=lp:apparmor/2.8
# --per-file-timestamps is failing over SSH, https://bugs.launchpad.net/bzr/+bug/1257078
REPO_URL?=https://code.launchpad.net/~apparmor-dev/apparmor/master
REPO_URL?=https://code.launchpad.net/~apparmor-dev/apparmor/2.8
# alternate possibilities to export from
#REPO_URL=.
#REPO_URL="bzr+ssh://bazaar.launchpad.net/~sbeattie/+junk/apparmor-dev/"
COVERITY_DIR=cov-int
RELEASE_DIR=apparmor-${VERSION}
__SETUP_DIR?=.
@@ -33,31 +27,21 @@ __SETUP_DIR?=.
# embedded in ${VERSION}
TAG_VERSION=$(subst ~,-,${VERSION})
# Add exclusion entries arguments for tar here, of the form:
# --exclude dir_to_exclude --exclude other_dir
TAR_EXCLUSIONS=
.PHONY: tarball
tarball: clean
REPO_VERSION=`$(value REPO_VERSION_CMD)` && \
make export_dir __EXPORT_DIR=${RELEASE_DIR} __REPO_VERSION=$${REPO_VERSION} && \
make setup __SETUP_DIR=${RELEASE_DIR} && \
tar ${TAR_EXCLUSIONS} -cvzf ${RELEASE_DIR}.tar.gz ${RELEASE_DIR}
REPO_VERSION=`$(value REPO_VERSION_CMD)` ; \
make export_dir __EXPORT_DIR=${RELEASE_DIR} __REPO_VERSION=$${REPO_VERSION} ; \
make setup __SETUP_DIR=${RELEASE_DIR} ; \
tar --exclude deprecated -cvzf ${RELEASE_DIR}.tar.gz ${RELEASE_DIR}
.PHONY: snapshot
snapshot: clean
$(eval REPO_VERSION:=$(shell $(value REPO_VERSION_CMD)))
$(eval SNAPSHOT_NAME=apparmor-$(VERSION)~$(REPO_VERSION))
make export_dir __EXPORT_DIR=${SNAPSHOT_NAME} __REPO_VERSION=${REPO_VERSION} && \
make setup __SETUP_DIR=${SNAPSHOT_NAME} && \
tar ${TAR_EXCLUSIONS} -cvzf ${SNAPSHOT_NAME}.tar.gz ${SNAPSHOT_NAME}
REPO_VERSION=`$(value REPO_VERSION_CMD)` ; \
SNAPSHOT_DIR=apparmor-${VERSION}~$${REPO_VERSION} ;\
make export_dir __EXPORT_DIR=$${SNAPSHOT_DIR} __REPO_VERSION=$${REPO_VERSION} ; \
make setup __SETUP_DIR=$${SNAPSHOT_DIR} ; \
tar --exclude deprecated -cvzf $${SNAPSHOT_DIR}.tar.gz $${SNAPSHOT_DIR} ;
.PHONY: coverity
coverity: snapshot
cd $(SNAPSHOT_NAME)/libraries/libapparmor && ./configure --with-python
$(foreach dir, $(filter-out utils profiles tests, $(DIRS)), \
cov-build --dir $(COVERITY_DIR) -- make -C $(SNAPSHOT_NAME)/$(dir);)
tar -cvzf $(SNAPSHOT_NAME)-$(COVERITY_DIR).tar.gz $(COVERITY_DIR)
.PHONY: export_dir
export_dir:
@@ -67,7 +51,7 @@ export_dir:
.PHONY: clean
clean:
-rm -rf ${RELEASE_DIR} ./apparmor-${VERSION}~* ${COVERITY_DIR}
-rm -rf ${RELEASE_DIR} ./apparmor-${VERSION}~*
for dir in $(DIRS); do \
make -C $$dir clean; \
done
@@ -75,12 +59,6 @@ clean:
.PHONY: setup
setup:
cd $(__SETUP_DIR)/libraries/libapparmor && ./autogen.sh
# parser has an extra doc to build
make -C $(__SETUP_DIR)/parser extra_docs
# libraries/libapparmor needs configure to have run before
# building docs
$(foreach dir, $(filter-out libraries/libapparmor tests, $(DIRS)), \
make -C $(__SETUP_DIR)/$(dir) docs;)
.PHONY: tag
tag:

53
README
View File

@@ -27,7 +27,6 @@ Source Layout
AppArmor consists of several different parts:
binutils/ source for basic utilities written in compiled languages
changehat/ source for using changehat with Apache, PAM and Tomcat
common/ common makefile rules
desktop/ empty
@@ -63,20 +62,14 @@ the following order.
libapparmor:
$ cd ./libraries/libapparmor
$ sh ./autogen.sh
$ sh ./configure --prefix=/usr --with-perl --with-python # see below
$ sh ./configure --prefix=/usr --with-perl # see below
$ make
$ make check
$ make install
[an additional optional argument to libapparmor's configure is --with-ruby, to
generate Ruby bindings to libapparmor.]
Binary Utilities:
$ cd binutils
$ make
$ make check
$ make install
[optional arguments to libapparmor's configure include --with-python
and --with-ruby, to generate python and ruby bindings to libapparmor,
respectively.]
Utilities:
@@ -88,7 +81,7 @@ $ make install
parser:
$ cd parser
$ make # depends on libapparmor having been built first
$ make
$ make check
$ make install
@@ -112,7 +105,7 @@ $ make check # depends on the parser having been built first
$ make install
[Note that for the parser, binutils, and utils, if you only wish to build/use
[Note that for the parser and the utils, if you only with to build/use
some of the locale languages, you can override the default by passing
the LANGS arguments to make; e.g. make all install "LANGS=en_US fr".]
@@ -155,7 +148,10 @@ $ make check
Utils
-----
Tests for the Python utilities exist in the test/ subdirectory.
There are some simple tests available, including basic perl syntax
checks for the perl modules and executables. There are also minimal
checks on the python utilities and python-based tests in the test/
subdirectory.
$ cd utils
$ make check
@@ -196,27 +192,6 @@ $ ./stress.sh
(see stress.sh -h for options)
Coverity Support
----------------
Coverity scans are available to AppArmor developers at
https://scan.coverity.com/projects/apparmor.
In order to submit a Coverity build for analysis, the cov-build binary
must be discoverable from your PATH. See the "To Setup" section of
https://scan.coverity.com/download?tab=cxx to obtain a pre-built copy of
cov-build.
To generate a compressed tarball of an intermediate Coverity directory:
$ make coverity
The compressed tarball is written to
apparmor-<SNAPSHOT_VERSION>-cov-int.tar.gz, where <SNAPSHOT_VERSION>
is something like 2.10.90~3328, and must be uploaded to
https://scan.coverity.com/projects/apparmor/builds/new for analysis. You must
include the snapshot version in Coverity's project build submission form, in
the "Project Version" field, so that it is quickly obvious to all AppArmor
developers what snapshot of the AppArmor repository was used for the analysis.
-----------------------------------------------
Building and Installing AppArmor Kernel Patches
-----------------------------------------------
@@ -232,10 +207,12 @@ The AppArmor userspace utilities are written with some assumptions about
installed and available versions of other tools. This is a (possibly
incomplete) list of known version dependencies:
The Python utilities require a minimum of Python 2.7 (deprecated) or Python 3.3.
Python 3.x is recommended. Python 2.x support is deprecated since AppArmor 2.11.
AppArmor.pm (used by aa-audit, aa-autodep, aa-complain, aa-disable,
aa-enforce, aa-genprof, aa-logprof, aa-unconfined) requires minimum
Perl 5.10.1.
Some utilities (aa-exec, aa-notify and aa-decode) require Perl 5.10.1 or newer.
Python scripts require minimum Python 2.7. Some utilities may require
Python 3.3. Python 3.0, 3.1, 3.2 are largely untested.
Most shell scripts are written for POSIX-compatible sh. aa-decode expects
bash, probably version 3.2 and higher.

View File

@@ -1,157 +0,0 @@
# ----------------------------------------------------------------------
# Copyright (c) 2015
# Canonical Ltd. (All rights reserved)
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of version 2 of the GNU General Public
# License published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# ----------------------------------------------------------------------
NAME=aa-binutils
all:
COMMONDIR=../common/
include $(COMMONDIR)/Make.rules
DESTDIR=/
BINDIR=${DESTDIR}/usr/bin
LOCALEDIR=/usr/share/locale
MANPAGES=aa-enabled.1 aa-exec.1
WARNINGS = -Wall
EXTRA_WARNINGS = -Wsign-compare -Wmissing-field-initializers -Wformat-security -Wunused-parameter
CPP_WARNINGS =
ifndef CFLAGS
CFLAGS = -g -O2 -pipe
ifdef DEBUG
CFLAGS += -pg -D DEBUG
endif
ifdef COVERAGE
CFLAGS = -g -pg -fprofile-arcs -ftest-coverage
endif
endif #CFLAGS
EXTRA_CFLAGS = ${CFLAGS} ${CPPFLAGS} ${EXTRA_CXXFLAGS} ${CPP_WARNINGS}
#INCLUDEDIR = /usr/src/linux/include
INCLUDEDIR =
ifdef INCLUDEDIR
CFLAGS += -I$(INCLUDEDIR)
endif
# Internationalization support. Define a package and a LOCALEDIR
EXTRA_CFLAGS+=-DPACKAGE=\"${NAME}\" -DLOCALEDIR=\"${LOCALEDIR}\"
SRCS = aa_enabled.c
HDRS =
TOOLS = aa-enabled aa-exec
AALIB = -Wl,-Bstatic -lapparmor -Wl,-Bdynamic -lpthread
ifdef USE_SYSTEM
# Using the system libapparmor so Makefile dependencies can't be used
LIBAPPARMOR_A =
INCLUDE_APPARMOR =
APPARMOR_H =
LIBAPPARMOR_LDFLAGS =
else
LIBAPPARMOR_SRC = ../libraries/libapparmor/
LOCAL_LIBAPPARMOR_INCLUDE = $(LIBAPPARMOR_SRC)/include
LOCAL_LIBAPPARMOR_LDPATH = $(LIBAPPARMOR_SRC)/src/.libs
LIBAPPARMOR_A = $(LOCAL_LIBAPPARMOR_LDPATH)/libapparmor.a
INCLUDE_APPARMOR = -I$(LOCAL_LIBAPPARMOR_INCLUDE)
APPARMOR_H = $(LOCAL_LIBAPPARMOR_INCLUDE)/sys/apparmor.h
LIBAPPARMOR_LDFLAGS = -L$(LOCAL_LIBAPPARMOR_LDPATH)
endif
EXTRA_CFLAGS += $(INCLUDE_APPARMOR)
LDFLAGS += $(LIBAPPARMOR_LDFLAGS)
ifdef V
VERBOSE = 1
endif
ifndef VERBOSE
VERBOSE = 0
endif
ifeq ($(VERBOSE),1)
BUILD_OUTPUT =
Q =
else
BUILD_OUTPUT = > /dev/null 2>&1
Q = @
endif
export Q VERBOSE BUILD_OUTPUT
po/%.pot: %.c
$(MAKE) -C po $(@F) NAME=$* SOURCES=$*.c
# targets arranged this way so that people who don't want full docs can
# pick specific targets they want.
arch: $(TOOLS)
manpages: $(MANPAGES)
docs: manpages
indep: docs
$(Q)$(MAKE) -C po all
all: arch indep
.PHONY: coverage
coverage:
$(MAKE) clean $(TOOLS) COVERAGE=1
ifndef USE_SYSTEM
$(LIBAPPARMOR_A):
@if [ ! -f $@ ]; then \
echo "error: $@ is missing. Pick one of these possible solutions:" 1>&2; \
echo " 1) Build against the in-tree libapparmor by building it first and then trying again. See the top-level README for help." 1>&2; \
echo " 2) Build against the system libapparmor by adding USE_SYSTEM=1 to your make command." 1>&2;\
return 1; \
fi
endif
aa-enabled: aa_enabled.c $(LIBAPPARMOR_A)
$(CC) $(LDFLAGS) $(EXTRA_CFLAGS) -o $@ $< $(LIBS) $(AALIB)
aa-exec: aa_exec.c $(LIBAPPARMOR_A)
$(CC) $(LDFLAGS) $(EXTRA_CFLAGS) -o $@ $< $(LIBS) $(AALIB)
.SILENT: check
.PHONY: check
check: check_pod_files tests
.SILENT: tests
tests: $(TOOLS) $(TESTS)
echo "no tests atm"
.PHONY: install
install: install-indep install-arch
.PHONY: install-arch
install-arch: arch
install -m 755 -d ${BINDIR}
install -m 755 ${TOOLS} ${BINDIR}
.PHONY: install-indep
install-indep: indep
$(MAKE) -C po install NAME=${NAME} DESTDIR=${DESTDIR}
$(MAKE) install_manpages DESTDIR=${DESTDIR}
ifndef VERBOSE
.SILENT: clean
endif
.PHONY: clean
clean: pod_clean
rm -f core core.* *.o *.s *.a *~ *.gcda *.gcno
rm -f gmon.out
rm -f $(TOOLS) $(TESTS)
$(MAKE) -s -C po clean

View File

@@ -1,94 +0,0 @@
# This publication is intellectual property of Canonical Ltd. Its contents
# can be duplicated, either in part or in whole, provided that a copyright
# label is visibly located on each copy.
#
# All information found in this book has been compiled with utmost
# attention to detail. However, this does not guarantee complete accuracy.
# Neither Canonical Ltd, the authors, nor the translators shall be held
# liable for possible errors or the consequences thereof.
#
# Many of the software and hardware descriptions cited in this book
# are registered trademarks. All trade names are subject to copyright
# restrictions and may be registered trade marks. Canonical Ltd
# essentially adheres to the manufacturer's spelling.
#
# Names of products and trademarks appearing in this book (with or without
# specific notation) are likewise subject to trademark and trade protection
# laws and may thus fall under copyright restrictions.
#
=pod
=head1 NAME
aa-enabled - test whether AppArmor is enabled
=head1 SYNOPSIS
B<aa-enabled> [options]
=head1 DESCRIPTION
B<aa-enabled> is used to determine if AppArmor is enabled.
=head1 OPTIONS
B<aa-enabled> accepts the following arguments:
=over 4
=item -h, --help
Display a brief usage guide.
=item -q, --quiet
Do not output anything to stdout. This option is intended to be used by
scripts that simply want to use the exit code to determine if AppArmor is
enabled.
=back
=head1 EXIT STATUS
Upon exiting, B<aa-enabled> will set its exit status to the following values:
=over 4
=item B<0>
if AppArmor is enabled.
=item B<1>
if AppArmor is not enabled/loaded.
=item B<2>
intentionally not used as an B<aa-enabled> exit status.
=item B<3>
if the AppArmor control files aren't available under /sys/kernel/security/.
=item B<4>
if B<aa-enabled> doesn't have enough privileges to read the apparmor control files.
=item B<64>
if any unexpected error or condition is encountered.
=back
=head1 BUGS
If you find any bugs, please report them at
L<https://bugs.launchpad.net/apparmor/+filebug>.
=head1 SEE ALSO
apparmor(7), apparmor.d(5), aa_is_enabled(2), and L<http://wiki.apparmor.net>.
=cut

View File

@@ -1,92 +0,0 @@
/*
* Copyright (C) 2015 Canonical Ltd.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
* License published by the Free Software Foundation.
*/
#include <errno.h>
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libintl.h>
#define _(s) gettext(s)
#include <sys/apparmor.h>
void print_help(const char *command)
{
printf(_("%s: [options]\n"
" options:\n"
" -q | --quiet Don't print out any messages\n"
" -h | --help Print help\n"),
command);
exit(1);
}
/* Exit statuses and meanings are documented in the aa-enabled.pod file */
static void exit_with_error(int saved_errno, int quiet)
{
int err;
switch(saved_errno) {
case ENOSYS:
if (!quiet)
printf(_("No - not available on this system.\n"));
exit(1);
case ECANCELED:
if (!quiet)
printf(_("No - disabled at boot.\n"));
exit(1);
case ENOENT:
if (!quiet)
printf(_("Maybe - policy interface not available.\n"));
exit(3);
case EPERM:
case EACCES:
if (!quiet)
printf(_("Maybe - insufficient permissions to determine availability.\n"));
exit(4);
}
if (!quiet)
printf(_("Error - %s\n"), strerror(saved_errno));
exit(64);
}
int main(int argc, char **argv)
{
int enabled;
int quiet = 0;
setlocale(LC_MESSAGES, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
if (argc > 2) {
printf(_("unknown or incompatible options\n"));
print_help(argv[0]);
} else if (argc == 2) {
if (strcmp(argv[1], "--quiet") == 0 ||
strcmp(argv[1], "-q") == 0) {
quiet = 1;
} else if (strcmp(argv[1], "--help") == 0 ||
strcmp(argv[1], "-h") == 0) {
print_help(argv[0]);
} else {
printf(_("unknown option '%s'\n"), argv[1]);
print_help(argv[0]);
}
}
enabled = aa_is_enabled();
if (!enabled)
exit_with_error(errno, quiet);
if (!quiet)
printf(_("Yes\n"));
exit(0);
}

View File

@@ -1,218 +0,0 @@
/*
* Copyright (c) 2015
* Canonical, Ltd. (All rights reserved)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
* License published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, contact Novell, Inc. or Canonical
* Ltd.
*/
#include <errno.h>
#include <getopt.h>
#include <libintl.h>
#include <limits.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <sys/apparmor.h>
#include <unistd.h>
#define _(s) gettext(s)
static const char *opt_profile = NULL;
static const char *opt_namespace = NULL;
static bool opt_debug = false;
static bool opt_immediate = false;
static bool opt_verbose = false;
static void usage(const char *name, bool error)
{
FILE *stream = stdout;
int status = EXIT_SUCCESS;
if (error) {
stream = stderr;
status = EXIT_FAILURE;
}
fprintf(stream,
_("USAGE: %s [OPTIONS] <prog> <args>\n"
"\n"
"Confine <prog> with the specified PROFILE.\n"
"\n"
"OPTIONS:\n"
" -p PROFILE, --profile=PROFILE PROFILE to confine <prog> with\n"
" -n NAMESPACE, --namespace=NAMESPACE NAMESPACE to confine <prog> in\n"
" -d, --debug show messages with debugging information\n"
" -i, --immediate change profile immediately instead of at exec\n"
" -v, --verbose show messages with stats\n"
" -h, --help display this help\n"
"\n"), name);
exit(status);
}
#define error(fmt, args...) _error(_("aa-exec: ERROR: " fmt "\n"), ## args)
static void _error(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
exit(EXIT_FAILURE);
}
#define debug(fmt, args...) _debug(_("aa-exec: DEBUG: " fmt "\n"), ## args)
static void _debug(const char *fmt, ...)
{
va_list args;
if (!opt_debug)
return;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
}
#define verbose(fmt, args...) _verbose(_(fmt "\n"), ## args)
static void _verbose(const char *fmt, ...)
{
va_list args;
if (!opt_verbose)
return;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
}
static void verbose_print_argv(char **argv)
{
if (!opt_verbose)
return;
fprintf(stderr, _("exec"));
for (; *argv; argv++)
fprintf(stderr, " %s", *argv);
fprintf(stderr, "\n");
}
static char **parse_args(int argc, char **argv)
{
int opt;
struct option long_opts[] = {
{"debug", no_argument, 0, 'd'},
{"help", no_argument, 0, 'h'},
{"profile", required_argument, 0, 'p'},
{"namespace", required_argument, 0, 'n'},
{"immediate", no_argument, 0, 'i'},
{"verbose", no_argument, 0, 'v'},
};
while ((opt = getopt_long(argc, argv, "+dhp:n:iv", long_opts, NULL)) != -1) {
switch (opt) {
case 'd':
opt_debug = true;
break;
case 'h':
usage(argv[0], false);
break;
case 'p':
opt_profile = optarg;
break;
case 'n':
opt_namespace = optarg;
break;
case 'i':
opt_immediate = true;
break;
case 'v':
opt_verbose = true;
break;
default:
usage(argv[0], true);
break;
}
}
if (optind >= argc)
usage(argv[0], true);
return argv + optind;
}
static void build_name(char *name, size_t name_len,
const char *namespace, const char *profile)
{
size_t required_len = 1; /* reserve 1 byte for NUL-terminator */
if (namespace)
required_len += 1 + strlen(namespace) + 3; /* :<NAMESPACE>:// */
if (profile)
required_len += strlen(profile);
if (required_len > name_len)
error("name too long (%zu > %zu)", required_len, name_len);
name[0] = '\0';
if (namespace) {
strcat(name, ":");
strcat(name, namespace);
strcat(name, "://");
}
if (profile)
strcat(name, profile);
}
int main(int argc, char **argv)
{
char name[PATH_MAX];
int rc = 0;
argv = parse_args(argc, argv);
if (opt_namespace || opt_profile)
build_name(name, sizeof(name), opt_namespace, opt_profile);
else
goto exec;
if (opt_immediate) {
verbose("aa_change_profile(\"%s\")", name);
rc = aa_change_profile(name);
debug("%d = aa_change_profile(\"%s\")", rc, name);
} else {
verbose("aa_change_onexec(\"%s\")", name);
rc = aa_change_onexec(name);
debug("%d = aa_change_onexec(\"%s\")", rc, name);
}
if (rc) {
if (errno == ENOENT || errno == EACCES) {
error("%s '%s' does not exist\n",
opt_profile ? "profile" : "namespace", name);
} else if (errno == EINVAL) {
error("AppArmor interface not available");
} else {
error("%m");
}
}
exec:
verbose_print_argv(argv);
execvp(argv[0], argv);
error("Failed to execute \"%s\": %m", argv[0]);
}

View File

@@ -1,19 +0,0 @@
# ----------------------------------------------------------------------
# Copyright (C) 2015 Canonical Ltd.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of version 2 of the GNU General Public
# License published by the Free Software Foundation.
# ----------------------------------------------------------------------
all:
# As translations get added, they will automatically be included, unless
# the lang is explicitly added to DISABLED_LANGS; e.g. DISABLED_LANGS=en es
DISABLED_LANGS=
COMMONDIR=../../common
include $(COMMONDIR)/Make-po.rules
XGETTEXT_ARGS+=--language=C --keyword=_ $(shell if [ -f ${NAME}.pot ] ; then echo -n -j ; fi)

View File

@@ -1,66 +0,0 @@
# Copyright (C) 2015 Canonical Ltd
# This file is distributed under the same license as the AppArmor package.
# John Johansen <john.johansen@canonical.com>, 2015.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: apparmor@lists.ubuntu.com\n"
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
#: ../aa_enabled.c:26
#, c-format
msgid ""
"%s: [options]\n"
" options:\n"
" -q | --quiet Don't print out any messages\n"
" -h | --help Print help\n"
msgstr ""
#: ../aa_enabled.c:45
#, c-format
msgid "unknown or incompatible options\n"
msgstr ""
#: ../aa_enabled.c:55
#, c-format
msgid "unknown option '%s'\n"
msgstr ""
#: ../aa_enabled.c:64
#, c-format
msgid "Yes\n"
msgstr ""
#: ../aa_enabled.c:71
#, c-format
msgid "No - not available on this system.\n"
msgstr ""
#: ../aa_enabled.c:74
#, c-format
msgid "No - disabled at boot.\n"
msgstr ""
#: ../aa_enabled.c:77
#, c-format
msgid "Maybe - policy interface not available.\n"
msgstr ""
#: ../aa_enabled.c:81
#, c-format
msgid "Maybe - insufficient permissions to determine availability.\n"
msgstr ""
#: ../aa_enabled.c:84
#, c-format
msgid "Error - '%s'\n"
msgstr ""

View File

@@ -1,68 +0,0 @@
# German translation for apparmor
# Copyright (c) 2016 Rosetta Contributors and Canonical Ltd 2016
# This file is distributed under the same license as the apparmor package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2016.
#
msgid ""
msgstr ""
"Project-Id-Version: apparmor\n"
"Report-Msgid-Bugs-To: AppArmor list <apparmor@lists.ubuntu.com>\n"
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
"PO-Revision-Date: 2017-03-31 10:44+0000\n"
"Last-Translator: Tobias Bannert <tobannert@gmail.com>\n"
"Language-Team: German <de@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2017-04-05 05:23+0000\n"
"X-Generator: Launchpad (build 18335)\n"
"Language: de\n"
#: ../aa_enabled.c:26
#, c-format
msgid ""
"%s: [options]\n"
" options:\n"
" -q | --quiet Don't print out any messages\n"
" -h | --help Print help\n"
msgstr ""
#: ../aa_enabled.c:45
#, c-format
msgid "unknown or incompatible options\n"
msgstr "unbekannte oder nicht kompatible Optionen\n"
#: ../aa_enabled.c:55
#, c-format
msgid "unknown option '%s'\n"
msgstr "unbekannte Option »%s«\n"
#: ../aa_enabled.c:64
#, c-format
msgid "Yes\n"
msgstr "Ja\n"
#: ../aa_enabled.c:71
#, c-format
msgid "No - not available on this system.\n"
msgstr "Nein auf diesem System nicht verfügbar.\n"
#: ../aa_enabled.c:74
#, c-format
msgid "No - disabled at boot.\n"
msgstr "Nein beim Start deaktiviert.\n"
#: ../aa_enabled.c:77
#, c-format
msgid "Maybe - policy interface not available.\n"
msgstr ""
#: ../aa_enabled.c:81
#, c-format
msgid "Maybe - insufficient permissions to determine availability.\n"
msgstr ""
#: ../aa_enabled.c:84
#, c-format
msgid "Error - '%s'\n"
msgstr "Fehler - »%s«\n"

View File

@@ -1,72 +0,0 @@
# English (United Kingdom) translation for apparmor
# Copyright (c) 2016 Rosetta Contributors and Canonical Ltd 2016
# This file is distributed under the same license as the apparmor package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2016.
#
msgid ""
msgstr ""
"Project-Id-Version: apparmor\n"
"Report-Msgid-Bugs-To: AppArmor list <apparmor@lists.ubuntu.com>\n"
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
"PO-Revision-Date: 2016-02-18 06:22+0000\n"
"Last-Translator: Andi Chandler <Unknown>\n"
"Language-Team: English (United Kingdom) <en_GB@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2016-06-01 05:15+0000\n"
"X-Generator: Launchpad (build 18053)\n"
"Language: en_GB\n"
#: ../aa_enabled.c:26
#, c-format
msgid ""
"%s: [options]\n"
" options:\n"
" -q | --quiet Don't print out any messages\n"
" -h | --help Print help\n"
msgstr ""
"%s: [options]\n"
" options:\n"
" -q | --quiet Don't print out any messages\n"
" -h | --help Print help\n"
#: ../aa_enabled.c:45
#, c-format
msgid "unknown or incompatible options\n"
msgstr "unknown or incompatible options\n"
#: ../aa_enabled.c:55
#, c-format
msgid "unknown option '%s'\n"
msgstr "unknown option '%s'\n"
#: ../aa_enabled.c:64
#, c-format
msgid "Yes\n"
msgstr "Yes\n"
#: ../aa_enabled.c:71
#, c-format
msgid "No - not available on this system.\n"
msgstr "No - not available on this system.\n"
#: ../aa_enabled.c:74
#, c-format
msgid "No - disabled at boot.\n"
msgstr "No - disabled at boot.\n"
#: ../aa_enabled.c:77
#, c-format
msgid "Maybe - policy interface not available.\n"
msgstr "Maybe - policy interface not available.\n"
#: ../aa_enabled.c:81
#, c-format
msgid "Maybe - insufficient permissions to determine availability.\n"
msgstr "Maybe - insufficient permissions to determine availability.\n"
#: ../aa_enabled.c:84
#, c-format
msgid "Error - '%s'\n"
msgstr "Error - '%s'\n"

View File

@@ -1,72 +0,0 @@
# Indonesian translation for apparmor
# Copyright (c) 2016 Rosetta Contributors and Canonical Ltd 2016
# This file is distributed under the same license as the apparmor package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2016.
#
msgid ""
msgstr ""
"Project-Id-Version: apparmor\n"
"Report-Msgid-Bugs-To: AppArmor list <apparmor@lists.ubuntu.com>\n"
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
"PO-Revision-Date: 2016-01-20 08:59+0000\n"
"Last-Translator: Ari Setyo Wibowo <mr.a.contact@gmail.com>\n"
"Language-Team: Indonesian <id@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2016-06-01 05:15+0000\n"
"X-Generator: Launchpad (build 18053)\n"
"Language: id\n"
#: ../aa_enabled.c:26
#, c-format
msgid ""
"%s: [options]\n"
" options:\n"
" -q | --quiet Don't print out any messages\n"
" -h | --help Print help\n"
msgstr ""
"%s: [options]\n"
" pilihan:\n"
" -q | --quiet Jangan tampilkan pesan apapun\n"
" -h | --help Tampilkan bantuan\n"
#: ../aa_enabled.c:45
#, c-format
msgid "unknown or incompatible options\n"
msgstr "pilihan yang tidak dikenali atau tidak kompatibel\n"
#: ../aa_enabled.c:55
#, c-format
msgid "unknown option '%s'\n"
msgstr "pilihan tidak dikenali '%s'\n"
#: ../aa_enabled.c:64
#, c-format
msgid "Yes\n"
msgstr "Ya\n"
#: ../aa_enabled.c:71
#, c-format
msgid "No - not available on this system.\n"
msgstr "Tidak - tidak tersedia di sistem ini.\n"
#: ../aa_enabled.c:74
#, c-format
msgid "No - disabled at boot.\n"
msgstr "Tidak - nonaktifkan saat boot.\n"
#: ../aa_enabled.c:77
#, c-format
msgid "Maybe - policy interface not available.\n"
msgstr "Mungkin - kebijakan antarmuka tidak tersedia.\n"
#: ../aa_enabled.c:81
#, c-format
msgid "Maybe - insufficient permissions to determine availability.\n"
msgstr "Mungkin - izin tidak memadai untuk menentukan ketersediaan.\n"
#: ../aa_enabled.c:84
#, c-format
msgid "Error - '%s'\n"
msgstr "Kesalahan - '%s'\n"

View File

@@ -1,72 +0,0 @@
# Portuguese translation for apparmor
# Copyright (c) 2016 Rosetta Contributors and Canonical Ltd 2016
# This file is distributed under the same license as the apparmor package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2016.
#
msgid ""
msgstr ""
"Project-Id-Version: apparmor\n"
"Report-Msgid-Bugs-To: AppArmor list <apparmor@lists.ubuntu.com>\n"
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
"PO-Revision-Date: 2016-03-03 08:34+0000\n"
"Last-Translator: Ivo Xavier <ivoxavier.8@gmail.com>\n"
"Language-Team: Portuguese <pt@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2016-06-01 05:15+0000\n"
"X-Generator: Launchpad (build 18053)\n"
"Language: pt\n"
#: ../aa_enabled.c:26
#, c-format
msgid ""
"%s: [options]\n"
" options:\n"
" -q | --quiet Don't print out any messages\n"
" -h | --help Print help\n"
msgstr ""
"%s: [opções]\n"
" opções:\n"
" -q | --silencioso Não mostrar mensagens\n"
" -h | --ajuda Mostar ajuda\n"
#: ../aa_enabled.c:45
#, c-format
msgid "unknown or incompatible options\n"
msgstr "opções desconhecidas ou incompatíveis\n"
#: ../aa_enabled.c:55
#, c-format
msgid "unknown option '%s'\n"
msgstr "opção desconhecida '%s'\n"
#: ../aa_enabled.c:64
#, c-format
msgid "Yes\n"
msgstr "Sim\n"
#: ../aa_enabled.c:71
#, c-format
msgid "No - not available on this system.\n"
msgstr "Não - não disponível neste sistema.\n"
#: ../aa_enabled.c:74
#, c-format
msgid "No - disabled at boot.\n"
msgstr "Não - desligado ao iniciar.\n"
#: ../aa_enabled.c:77
#, c-format
msgid "Maybe - policy interface not available.\n"
msgstr "Talvez - política de interface não disponível.\n"
#: ../aa_enabled.c:81
#, c-format
msgid "Maybe - insufficient permissions to determine availability.\n"
msgstr "Talvez - permissões insuficientes para determinar disponibilidade.\n"
#: ../aa_enabled.c:84
#, c-format
msgid "Error - '%s'\n"
msgstr "Erro - '%s'\n"

View File

@@ -1,72 +0,0 @@
# Russian translation for apparmor
# Copyright (c) 2016 Rosetta Contributors and Canonical Ltd 2016
# This file is distributed under the same license as the apparmor package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2016.
#
msgid ""
msgstr ""
"Project-Id-Version: apparmor\n"
"Report-Msgid-Bugs-To: AppArmor list <apparmor@lists.ubuntu.com>\n"
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
"PO-Revision-Date: 2016-03-29 14:46+0000\n"
"Last-Translator: Eugene Marshal <Unknown>\n"
"Language-Team: Russian <ru@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2016-06-01 05:15+0000\n"
"X-Generator: Launchpad (build 18053)\n"
"Language: ru\n"
#: ../aa_enabled.c:26
#, c-format
msgid ""
"%s: [options]\n"
" options:\n"
" -q | --quiet Don't print out any messages\n"
" -h | --help Print help\n"
msgstr ""
"%s: [параметры]\n"
" параметры:\n"
" -q | --quiet не выводить никакие сообщения\n"
" -h | --help вывести справку\n"
#: ../aa_enabled.c:45
#, c-format
msgid "unknown or incompatible options\n"
msgstr "неизвестные или несовместимые параметры\n"
#: ../aa_enabled.c:55
#, c-format
msgid "unknown option '%s'\n"
msgstr "неизвестный параметр '%s'\n"
#: ../aa_enabled.c:64
#, c-format
msgid "Yes\n"
msgstr "Да\n"
#: ../aa_enabled.c:71
#, c-format
msgid "No - not available on this system.\n"
msgstr "Нет - недоступно на этой системе.\n"
#: ../aa_enabled.c:74
#, c-format
msgid "No - disabled at boot.\n"
msgstr "Нет - выключено при загрузке.\n"
#: ../aa_enabled.c:77
#, c-format
msgid "Maybe - policy interface not available.\n"
msgstr "Возможно - интерфейс политики недоступен.\n"
#: ../aa_enabled.c:81
#, c-format
msgid "Maybe - insufficient permissions to determine availability.\n"
msgstr "Возможно - недостаточно разрешений для определения доступности.\n"
#: ../aa_enabled.c:84
#, c-format
msgid "Error - '%s'\n"
msgstr "Ошибка - '%s'\n"

View File

@@ -1,6 +1,5 @@
# ----------------------------------------------------------------------
# Copyright (c) 2004, 2005 NOVELL (All rights reserved)
# Copyright (c) 2016 Canonical, Ltd.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of version 2 of the GNU General Public
@@ -18,7 +17,13 @@ NAME:=apache2-mod_apparmor
all:
COMMONDIR=../../common/
include $(COMMONDIR)/Make.rules
include common/Make.rules
COMMONDIR_EXISTS=$(strip $(shell [ -d ${COMMONDIR} ] && echo true))
ifeq ($(COMMONDIR_EXISTS), true)
common/Make.rules: $(COMMONDIR)/Make.rules
ln -sf $(COMMONDIR) .
endif
TARGET:=mod_apparmor.so
MANPAGES=mod_apparmor.8
@@ -36,48 +41,12 @@ APXS:=$(shell if [ -x "/usr/sbin/apxs2" ] ; then \
fi )
APXS_INSTALL_DIR=$(shell ${APXS} -q LIBEXECDIR)
DESTDIR=
ifdef USE_SYSTEM
LIBAPPARMOR = $(shell if pkg-config --exists libapparmor ; then \
pkg-config --silence-errors --libs libapparmor ; \
elif ldconfig -p | grep -q libapparmor\.so$$ ; then \
echo -lapparmor ; \
fi )
ifeq ($(strip $(LIBAPPARMOR)),)
ERROR_MESSAGE = $(error ${nl}\
************************************************************************${nl}\
Unable to find libapparmor installed on this system; either${nl}\
install libapparmor devel packages, set the LIBAPPARMOR variable${nl}\
manually, or build against in-tree libapparmor.${nl}\
************************************************************************${nl})
endif # LIBAPPARMOR not set
LDLIBS += $(LIBAPPARMOR)
else
LIBAPPARMOR_SRC := ../../libraries/libapparmor/
LIBAPPARMOR_INCLUDE = $(LIBAPPARMOR_SRC)/include
LIBAPPARMOR_PATH := $(LIBAPPARMOR_SRC)/src/.libs/
ifeq ($(realpath $(LIBAPPARMOR_PATH)/libapparmor.a),)
ERROR_MESSAGE = $(error ${nl}\
************************************************************************${nl}\
$(LIBAPPARMOR_PATH)/libapparmor.a is missing; either build against${nl}\
the in-tree libapparmor by building it first and then trying again${nl}\
(see the top-level README for help) or build against the system${nl}\
libapparmor by adding USE_SYSTEM=1 to your make command.${nl}\
************************************************************************${nl})
endif
# Need to pass -Wl twice here to get past both apxs2 and libtool, as
# libtool will add the path to the RPATH of the library if passed -L/some/path
LIBAPPARMOR_FLAGS = -I$(LIBAPPARMOR_INCLUDE) -Wl,-Wl,-L$(LIBAPPARMOR_PATH)
LDLIBS = -lapparmor
endif
# Need to pass -Wl twice here to get past both apxs2 and libtool, as
# libtool will add the path to the RPATH of the library if passed -L/some/path
LIBAPPARMOR_FLAGS=-I../../libraries/libapparmor/src -Wl,-Wl,-L../../libraries/libapparmor/src/.libs
LDLIBS=-lapparmor
.PHONY: libapparmor_check
.SILENT: libapparmor_check
libapparmor_check: ; $(ERROR_MESSAGE)
all: libapparmor_check $(TARGET) docs
.PHONY: docs
docs: ${MANPAGES} ${HTMLMANPAGES}
all: $(TARGET) ${MANPAGES} ${HTMLMANPAGES}
%.so: %.c
${APXS} ${LIBAPPARMOR_FLAGS} -c $< ${LDLIBS}
@@ -90,9 +59,6 @@ install: ${TARGET} ${MANPAGES}
make install_manpages DESTDIR=${DESTDIR}
.PHONY: clean
clean: pod_clean
clean: _clean
rm -rf .libs
rm -f *.la *.lo *.so *.o *.slo
.PHONY: check
check: check_pod_files
rm -f *.la *.lo *.so *.o *.slo Make.rules

View File

@@ -0,0 +1,215 @@
# ----------------------------------------------------------------------
# Copyright (c) 2004, 2005 NOVELL (All rights reserved)
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of version 2 of the GNU General Public
# License published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, contact Novell, Inc.
# ----------------------------------------------------------------------
# norootforbuild
# Check first to see if distro is already defined.
# I hate rpm macros
%if ! %{?distro:1}0
%if %{?suse_version:1}0
%define distro suse
%endif
%if %{?fedora_version:1}0
%define distro redhat
%endif
%endif
%if ! %{?distro:1}0
%define distro suse
%endif
# this is required to be underscore
%define module_name mod_apparmor
Summary: AppArmor module for apache2.
Name: apache2-mod_apparmor
Version: @@immunix_version@@
Release: @@repo_version@@
Group: Applications/System
Source0: %{name}-%{version}-@@repo_version@@.tar.gz
License: LGPL
BuildRoot: %{?_tmppath:}%{!?_tmppath:/var/tmp}/%{name}-%{version}-build
Url: http://forge.novell.com/modules/xfmod/project/?apparmor
Obsoletes: mod_change_hat mod-change-hat mod-apparmor apache2-mod-apparmor
Provides: mod_change_hat mod-change-hat mod-apparmor apache2-mod-apparmor
%if %{distro} == "suse"
%if 0%{?suse_version} < 1010
BuildRequires: libimmunix
%else
%if 0%{?suse_version} < 1030
BuildRequires: libapparmor
%else
BuildRequires: libapparmor-devel
%endif
%endif
%else
BuildRequires: libapparmor-devel
%endif
%if %{distro} == "suse"
%define apxs /usr/sbin/apxs2
%define apache_mmn %(MMN=$(%{apxs} -q LIBEXECDIR)_MMN; test -x $MMN && $MMN)
Prereq: apache2-prefork
Prereq: apparmor-parser
BuildRequires: apache2-devel
Requires: apache2 %{apache_mmn}
%else
%if %{distro} == "redhat" || %{distro} == "rhel4"
%define apxs /usr/sbin/apxs
Prereq: httpd
BuildRequires: httpd-devel
%endif
%endif
%define module_path %(%{apxs} -q LIBEXECDIR)
%define apache_sysconfdir %(%{apxs} -q SYSCONFDIR)
%description
apache2-mod_apparmor adds support to apache2 to provide AppArmor confinement
to individual cgi scripts handled by apache modules like mod_php and
mod_perl.
This package is part of a suite of tools that used to be named SubDomain.
%prep
%setup -q
%build
make APXS=%{apxs}
%install
make install DESTDIR=${RPM_BUILD_ROOT} DISTRO=%{distro} MANDIR=%{_mandir}
%if %{distro} == "suse"
mkdir -p ${RPM_BUILD_ROOT}%{_libdir}/apache2-prefork/
ln -s %{module_path}/%{module_name}.so ${RPM_BUILD_ROOT}%{_libdir}/apache2-prefork/%{module_name}.so
%else
%if %{distro} == "redhat" || %{distro} == "rhel4"
mkdir -p ${RPM_BUILD_ROOT}/%{apache_sysconfdir}.d/
install -m 644 %{module_name}.conf ${RPM_BUILD_ROOT}/%{apache_sysconfdir}.d/
%endif
%endif
%clean
[ "$RPM_BUILD_ROOT" != "/" ] && rm -rf $RPM_BUILD_ROOT
%files
%defattr(-,root,root)
%{module_path}
%if %{distro} == "suse"
%{_libdir}/apache2-prefork/%{module_name}.so
%else
%if %{distro} == "redhat" || %{distro} == "rhel4"
%{apache_sysconfdir}.d/%{module_name}.conf
%endif
%endif
%doc COPYING.LGPL
%{_mandir}/man*/*
%doc *.[0-9].html
%doc common/apparmor.css
%post
%if %{distro} == "suse"
/usr/sbin/a2enmod apparmor
%endif
%preun
%if %{distro} == "suse"
if [ $1 = 0 ] ; then
/usr/sbin/a2dismod apparmor
fi
%endif
%triggerpostun -- mod_change_hat mod-change-hat
%if %{distro} == "suse"
/usr/sbin/a2enmod apparmor
%endif
%changelog
* Sun Jul 29 2007 - sbeattie@suse.de
- Convert builddep on libapparmor to libapparmor-devel
* Tue Apr 3 2007 - sbeattie@suse.de
- Add mod_apparmor manpage to package
* Wed Sep 06 2006 - poeml@suse.de
- rename to apache2-mod_apparmor
- use a2enmod instead of frob_sysconfig
- remove SuSEconfig calls
* Fri May 26 2006 - schwab@suse.de
- Don't strip binaries.
* Wed Apr 12 2006 - Steve Beattie <sbeattie@suse.de>
- Move to novell forge svn repo; fix build issue with new layout
* Thu Mar 30 2006 - Seth Arnold <seth.arnold@suse.de> 2.0-7.2
- Relicense to LGPL
* Mon Jan 30 2006 - Steve Beattie <sbeattie@suse.de> 2.0-7.1
- Renamed apache config options:
ImmhatName -> AAHatName
ImmDefaultHatName -> AADefaultHatName
* Mon Jan 30 2006 - poeml@suse.de
- removed libapr-util1-devel from BuildRequires (apache2-devel does
require it)
* Fri Jan 27 2006 Steve Beattie <sbeattie@suse.de> 2.0-6.1
- No more neededforbuild in STABLE
* Wed Jan 25 2006 Steve Beattie <sbeattie@suse.de> 2.0-6
- Fix linking against libapparmor.so
* Sun Jan 8 2006 Steve Beattie <sbeattie@suse.de> 2.0-5
- More SUSE autobuild fixups.
* Wed Jan 4 2006 Steve Beattie <sbeattie@suse.de> 2.0-4
- Fixup SUSE autobuild require on apache-devel-packages
- Add svn revision to the source tarball
* Sun Dec 18 2005 Steve Beattie <sbeattie@novell.com> 2.0-3
- Include symlink in %{_libdir}/apache2-prefork/
* Thu Dec 8 2005 Steve Beattie <sbeattie@novell.com> 2.0-2
- Rename to apache2-mod-apparmor for consistency w/SUSE packages
- Rename module to mod_apparmor.so
* Wed Dec 7 2005 Steve Beattie <sbeattie@novell.com> 2.0-1
- Reset version for inclusion in SUSE autobuild
* Mon Dec 5 2005 Steve Beattie <sbeattie@novell.com> 1.99-9
- Rename package to mod-apparmor
* Wed Nov 30 2005 Steve Beattie <sbeattie@novell.com> 1.99-8
- Minor packaging cleanups
* Wed Nov 30 2005 Steve Beattie <sbeattie@novell.com> 1.99-7_imnx
- Convert license to GPL
* Thu Jun 23 2005 Steve Beattie <sbeattie@novell.com> 1.99-6_imnx
- Add trigger for mod_change_hat => mod-change-hat upgrades
- Don't run SuSEconfig on SuSE 9.3 or newer
* Mon May 23 2005 Steve Beattie <sbeattie@novell.com> 1.99-5_imnx
- Fix package uninstall on RHEL4.
* Fri Mar 11 2005 Steve Beattie <steve@immunix.com> 1.99-4_imnx
- Rename to be consistent with other packages
* Fri Feb 18 2005 Steve Beattie <steve@immunix.com> 1.99-3_imnx
- Cleanup some non-64bit clean code, sigh.
- Fix install locations on 64-bit platform.
* Fri Feb 4 2005 Seth Arnold <sarnold@immunix.coM> 1.99-1_imnx
- Reversion to 1.99
* Fri Nov 12 2004 Steve Beattie <steve@immunix.com> 1.2-2_imnx
- Add configuration file for redhat build
* Tue Oct 12 2004 Steve Beattie <steve@immunix.com> 1.2-1_imnx
- Bump version after shass-1.1 branched off
* Mon Sep 20 2004 Dominic Reynolds <dominic@immunix.com> 1.0-7_imnx_(redhat|suse)
- Modified to build separate versions for suse/redhat (EL3).
- Note:RH version does not currently setup the module configuraiton
- in apache.
* Tue Aug 31 2004 Steve Beattie <steve@immunix.com> 1.0-6_imnx
- Got location and per server config directives working somewhat
correctly :-)
- copyright fixups.
* Fri Aug 20 2004 Steve Beattie <steve@immunix.com> 1.0-5_imnx
- added support for <Location> hatname </Location>
* Wed Jul 21 2004 Steve Beattie <steve@immunix.com> 1.0-4_imnx
- reduced loglevel of some debug messages
- add change_hat to list of apache modules
* Tue Jul 20 2004 Steve Beattie <steve@immunix.com> 1.0-2_imnx
- got module actually working, at least in simple cases.
* Thu Jul 15 2004 Steve Beattie <steve@immunix.com> 1.0-1_imnx
- Initial package creation.

View File

@@ -1,13 +1,12 @@
/*
* Copyright (c) 2004, 2005, 2006 NOVELL (All rights reserved)
* Copyright (c) 2014 Canonical, Ltd. (All rights reserved)
*
* The mod_apparmor module is licensed under the terms of the GNU
* Lesser General Public License, version 2.1. Please see the file
* COPYING.LGPL.
*
* mod_apparmor - (apache 2.0.x)
* Author: Steve Beattie <steve@nxnw.org>
* Author: Steve Beattie <sbeattie@suse.de>
*
* This currently only implements change_hat functionality, but could be
* extended for other stuff we decide to do.
@@ -25,10 +24,13 @@
#include "apr_strings.h"
#include "apr_lib.h"
#include <sys/apparmor.h>
#include <apparmor.h>
#include <unistd.h>
/* #define DEBUG */
#ifndef __unused
#define __unused __attribute__((unused))
#endif
/* should the following be configurable? */
#define DEFAULT_HAT "HANDLING_UNTRUSTED_INPUT"
@@ -49,209 +51,165 @@ static unsigned long magic_token = 0;
static int inside_default_hat = 0;
typedef struct {
const char *hat_name;
char *path;
} apparmor_dir_cfg;
const char * hat_name;
char * path;
} immunix_dir_cfg;
typedef struct {
const char *hat_name;
int is_initialized;
} apparmor_srv_cfg;
const char * hat_name;
int is_initialized;
} immunix_srv_cfg;
/* aa_init() gets invoked in the post_config stage of apache.
/* immunix_init() gets invoked in the post_config stage of apache.
* Unfortunately, apache reads its config once when it starts up, then
* it re-reads it when goes into its restart loop, where it starts it's
* children. This means we cannot call change_hat here, as the modules
* memory will be wiped out, and the magic_token will be lost, so apache
* wouldn't be able to change_hat back out. */
static int
aa_init(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
static int
immunix_init (apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
{
apr_file_t *file;
apr_size_t size = sizeof(magic_token);
apr_file_t * file;
apr_size_t size = sizeof (magic_token);
int ret;
ret = apr_file_open (&file, "/dev/urandom", APR_READ, APR_OS_DEFAULT, p);
if (!ret) {
apr_file_read(file, (void *) &magic_token, &size);
apr_file_close(file);
apr_file_read (file, (void *) &magic_token, &size);
apr_file_close (file);
} else {
ap_log_error(APLOG_MARK, APLOG_ERR, errno, ap_server_conf,
"Failed to open /dev/urandom");
"Failed to open /dev/urandom");
}
ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, ap_server_conf,
"Opened /dev/urandom successfully");
ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, ap_server_conf, "Opened /dev/urandom successfully");
return OK;
}
/* As each child starts up, we'll change_hat into a default hat, mostly
* to protect ourselves from bugs in parsing network input, but before
* we change_hat to the uri specific hat. */
static void
aa_child_init(apr_pool_t *p, server_rec *s)
static void
immunix_child_init (apr_pool_t *p, server_rec *s)
{
int ret;
ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, ap_server_conf,
"init: calling change_hat with '%s'", DEFAULT_HAT);
"init: calling change_hat with '%s'", DEFAULT_HAT);
ret = aa_change_hat(DEFAULT_HAT, magic_token);
if (ret < 0) {
aa_change_hat(NULL, magic_token);
ap_log_error(APLOG_MARK, APLOG_ERR, errno, ap_server_conf,
"Failed to change_hat to '%s'", DEFAULT_HAT);
"Failed to change_hat to '%s'", DEFAULT_HAT);
} else {
inside_default_hat = 1;
}
}
}
static void
debug_dump_uri(request_rec *r)
{
apr_uri_t *uri = &r->parsed_uri;
if (uri)
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, "Dumping uri info "
"scheme='%s' host='%s' path='%s' query='%s' fragment='%s'",
uri->scheme, uri->hostname, uri->path, uri->query,
uri->fragment);
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, "Dumping uri info "
"scheme='%s' host='%s' path='%s' query='%s' fragment='%s'",
uri->scheme, uri->hostname, uri->path, uri->query,
uri->fragment);
else
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, "Asked to dump NULL uri");
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, "Asked to dump NULL uri");
}
/*
aa_enter_hat will attempt to change_hat in the following order:
/*
immunix_enter_hat will attempt to change_hat in the following order:
(1) to a hatname in a location directive
(2) to the server name or a defined per-server default
(3) to the server name + "-" + uri
(4) to the uri
(5) to DEFAULT_URI
(6) back to the parent profile
(2) to the uri
(3) to a per-server default
(4) to DEFAULT_URI
(5) back to the parent profile
*/
static int
aa_enter_hat(request_rec *r)
static int
immunix_enter_hat (request_rec *r)
{
int aa_ret = -1;
apparmor_dir_cfg *dcfg = (apparmor_dir_cfg *)
ap_get_module_config(r->per_dir_config, &apparmor_module);
apparmor_srv_cfg *scfg = (apparmor_srv_cfg *)
ap_get_module_config(r->server->module_config, &apparmor_module);
const char *aa_hat_array[6] = { NULL, NULL, NULL, NULL, NULL, NULL };
int i = 0;
char *aa_label, *aa_mode, *aa_hat;
const char *vhost_uri;
int sd_ret = -1;
immunix_dir_cfg * dcfg = (immunix_dir_cfg *)
ap_get_module_config (r->per_dir_config, &apparmor_module);
immunix_srv_cfg * scfg = (immunix_srv_cfg *)
ap_get_module_config (r->server->module_config, &apparmor_module);
debug_dump_uri(r);
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, "aa_enter_hat (%s) n:0x%lx p:0x%lx main:0x%lx",
dcfg->path, (unsigned long) r->next, (unsigned long) r->prev,
(unsigned long) r->main);
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, "in immunix_enter_hat (%s) n:0x%lx p:0x%lx main:0x%lx",
dcfg->path, (unsigned long) r->next, (unsigned long) r->prev,
(unsigned long) r->main);
/* We only call change_hat for the main request, not subrequests */
if (r->main)
return OK;
if (r->main)
return OK;
if (inside_default_hat) {
aa_change_hat(NULL, magic_token);
inside_default_hat = 0;
inside_default_hat = 0;
}
if (dcfg != NULL && dcfg->hat_name != NULL) {
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
"[dcfg] adding hat '%s' to aa_change_hat vector", dcfg->hat_name);
aa_hat_array[i++] = dcfg->hat_name;
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "calling change_hat [dcfg] %s", dcfg->hat_name);
sd_ret = aa_change_hat(dcfg->hat_name, magic_token);
if (sd_ret < 0) {
aa_change_hat(NULL, magic_token);
} else {
return OK;
}
}
if (scfg) {
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, "Dumping scfg info: "
"scfg='0x%lx' scfg->hat_name='%s'",
(unsigned long) scfg, scfg->hat_name);
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, "Dumping scfg info: "
"scfg='0x%lx' scfg->hat_name='%s'",
(unsigned long) scfg, scfg->hat_name);
} else {
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, "scfg is null");
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, "scfg is null");
}
if (scfg != NULL) {
if (scfg->hat_name != NULL) {
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
"[scfg] adding hat '%s' to aa_change_hat vector", scfg->hat_name);
aa_hat_array[i++] = scfg->hat_name;
} else {
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
"[scfg] adding server_name '%s' to aa_change_hat vector",
r->server->server_hostname);
aa_hat_array[i++] = r->server->server_hostname;
}
vhost_uri = apr_pstrcat(r->pool, r->server->server_hostname, "-", r->uri, NULL);
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
"[vhost+uri] adding vhost+uri '%s' to aa_change_hat vector", vhost_uri);
aa_hat_array[i++] = vhost_uri;
if (scfg != NULL && scfg->hat_name != NULL) {
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "calling change_hat [scfg] %s", scfg->hat_name);
sd_ret = aa_change_hat(scfg->hat_name, magic_token);
if (sd_ret < 0) {
aa_change_hat(NULL, magic_token);
} else {
return OK;
}
}
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
"[uri] adding uri '%s' to aa_change_hat vector", r->uri);
aa_hat_array[i++] = r->uri;
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
"[default] adding '%s' to aa_change_hat vector", DEFAULT_URI_HAT);
aa_hat_array[i++] = DEFAULT_URI_HAT;
aa_ret = aa_change_hatv(aa_hat_array, magic_token);
if (aa_ret < 0) {
ap_log_rerror(APLOG_MARK, APLOG_WARNING, errno, r, "aa_change_hatv call failed");
}
/* Check to see if a defined AAHatName or AADefaultHatName would
* apply, but wasn't the hat we landed up in; report a warning if
* that's the case. */
aa_ret = aa_getcon(&aa_label, &aa_mode);
if (aa_ret < 0) {
ap_log_rerror(APLOG_MARK, APLOG_WARNING, errno, r, "aa_getcon call failed");
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "calling change_hat [uri] %s", r->uri);
sd_ret = aa_change_hat(r->uri, magic_token);
if (sd_ret < 0) {
aa_change_hat(NULL, magic_token);
} else {
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r,
"AA checks: aa_getcon result is '%s', mode '%s'", aa_label, aa_mode);
/* TODO: use libapparmor get hat_name fn here once it is implemented */
aa_hat = strstr(aa_label, "//");
if (aa_hat != NULL && strcmp(aa_mode, "enforce") == 0) {
aa_hat += 2; /* skip "//" */
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r,
"AA checks: apache is in hat '%s', mode '%s'", aa_hat, aa_mode);
if (dcfg != NULL && dcfg->hat_name != NULL) {
if (strcmp(aa_hat, dcfg->hat_name) != 0)
ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
"AAHatName '%s' applies, but does not appear to be a hat in the apache apparmor policy",
dcfg->hat_name);
} else if (scfg != NULL && scfg->hat_name != NULL) {
if (strcmp(aa_hat, scfg->hat_name) != 0 &&
strcmp(aa_hat, r->uri) != 0)
ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
"AADefaultHatName '%s' applies, but does not appear to be a hat in the apache apparmor policy",
scfg->hat_name);
}
}
free(aa_label);
return OK;
}
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "calling change_hat DEFAULT_URI");
sd_ret = aa_change_hat(DEFAULT_URI_HAT, magic_token);
if (sd_ret < 0) aa_change_hat(NULL, magic_token);
return OK;
}
static int
aa_exit_hat(request_rec *r)
static int
immunix_exit_hat (request_rec *r)
{
int aa_ret;
apparmor_dir_cfg *dcfg = (apparmor_dir_cfg *)
ap_get_module_config(r->per_dir_config, &apparmor_module);
/* apparmor_srv_cfg *scfg = (apparmor_srv_cfg *)
ap_get_module_config(r->server->module_config, &apparmor_module); */
int sd_ret;
immunix_dir_cfg * dcfg = (immunix_dir_cfg *)
ap_get_module_config (r->per_dir_config, &apparmor_module);
/* immunix_srv_cfg * scfg = (immunix_srv_cfg *)
ap_get_module_config (r->server->module_config, &apparmor_module); */
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, "exiting change_hat: dir hat %s dir path %s",
dcfg->hat_name, dcfg->path);
dcfg->hat_name, dcfg->path);
aa_change_hat(NULL, magic_token);
/* can convert the following back to aa_change_hat() when the
* aa_change_hat() bug addressed in trunk commit 2329 lands in most
* system libapparmors */
aa_change_hatv(NULL, magic_token);
aa_ret = aa_change_hat(DEFAULT_HAT, magic_token);
if (aa_ret < 0) {
sd_ret = aa_change_hat(DEFAULT_HAT, magic_token);
if (sd_ret < 0) {
aa_change_hat(NULL, magic_token);
ap_log_rerror(APLOG_MARK, APLOG_ERR, errno, r,
"Failed to change_hat to '%s'", DEFAULT_HAT);
"Failed to change_hat to '%s'", DEFAULT_HAT);
} else {
inside_default_hat = 1;
}
@@ -260,15 +218,15 @@ aa_exit_hat(request_rec *r)
}
static const char *
aa_cmd_ch_path(cmd_parms *cmd, void *mconfig, const char *parm1)
aa_cmd_ch_path (cmd_parms * cmd, void * mconfig, const char * parm1)
{
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, "directory config change hat %s",
parm1 ? parm1 : "DEFAULT");
apparmor_dir_cfg *dcfg = mconfig;
parm1 ? parm1 : "DEFAULT");
immunix_dir_cfg * dcfg = mconfig;
if (parm1 != NULL) {
dcfg->hat_name = parm1;
dcfg->hat_name = parm1;
} else {
dcfg->hat_name = "DEFAULT";
dcfg->hat_name = "DEFAULT";
}
return NULL;
}
@@ -276,27 +234,27 @@ aa_cmd_ch_path(cmd_parms *cmd, void *mconfig, const char *parm1)
static int path_warn_once;
static const char *
immunix_cmd_ch_path(cmd_parms *cmd, void *mconfig, const char *parm1)
immunix_cmd_ch_path (cmd_parms * cmd, void * mconfig, const char * parm1)
{
if (path_warn_once == 0) {
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, "ImmHatName is "
"deprecated, please use AAHatName instead");
path_warn_once = 1;
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, "ImmHatName is "
"deprecated, please use AAHatName instead");
path_warn_once = 1;
}
return aa_cmd_ch_path(cmd, mconfig, parm1);
}
static const char *
aa_cmd_ch_srv(cmd_parms *cmd, void *mconfig, const char *parm1)
aa_cmd_ch_srv (cmd_parms * cmd, void * mconfig, const char * parm1)
{
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, "server config change hat %s",
parm1 ? parm1 : "DEFAULT");
apparmor_srv_cfg *scfg = (apparmor_srv_cfg *)
ap_get_module_config(cmd->server->module_config, &apparmor_module);
parm1 ? parm1 : "DEFAULT");
immunix_srv_cfg * scfg = (immunix_srv_cfg *)
ap_get_module_config(cmd->server->module_config, &apparmor_module);
if (parm1 != NULL) {
scfg->hat_name = parm1;
scfg->hat_name = parm1;
} else {
scfg->hat_name = "DEFAULT";
scfg->hat_name = "DEFAULT";
}
return NULL;
}
@@ -304,29 +262,27 @@ aa_cmd_ch_srv(cmd_parms *cmd, void *mconfig, const char *parm1)
static int srv_warn_once;
static const char *
immunix_cmd_ch_srv(cmd_parms *cmd, void *mconfig, const char *parm1)
immunix_cmd_ch_srv (cmd_parms * cmd, void * mconfig, const char * parm1)
{
if (srv_warn_once == 0) {
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, "ImmDefaultHatName is "
"deprecated, please use AADefaultHatName instead");
srv_warn_once = 1;
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, "ImmDefaultHatName is "
"deprecated, please use AADefaultHatName instead");
srv_warn_once = 1;
}
return aa_cmd_ch_srv(cmd, mconfig, parm1);
}
static void *
aa_create_dir_config(apr_pool_t *p, char *path)
immunix_create_dir_config (apr_pool_t * p, char * path)
{
apparmor_dir_cfg *newcfg = (apparmor_dir_cfg *) apr_pcalloc(p, sizeof(*newcfg));
immunix_dir_cfg * newcfg = (immunix_dir_cfg *) apr_pcalloc(p, sizeof(* newcfg));
ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, ap_server_conf,
"aa_create_dir_cfg (%s)", path ? path : ":no path:");
ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, ap_server_conf, "in immunix_create_dir (%s)", path ? path : ":no path:");
if (newcfg == NULL) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf,
"aa_create_dir_config: couldn't alloc dir config");
return NULL;
ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, "immunix_create_dir: couldn't alloc dir config");
return NULL;
}
newcfg->path = apr_pstrdup(p, path ? path : ":no path:");
newcfg->path = apr_pstrdup (p, path ? path : ":no path:");
return newcfg;
}
@@ -334,85 +290,83 @@ aa_create_dir_config(apr_pool_t *p, char *path)
/* XXX: Should figure out an appropriate action to take here, if any
static void *
aa_merge_dir_config(apr_pool_t *p, void *parent, void *child)
immunix_merge_dir_config (apr_pool_t * p, void * parent, void * child)
{
apparmor_dir_cfg *newcfg = (apparmor_dir_cfg *) apr_pcalloc(p, sizeof(*newcfg));
immunix_dir_cfg * newcfg = (immunix_dir_cfg *) apr_pcalloc(p, sizeof(* newcfg));
ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, ap_server_conf, "in immunix_merge_dir ()");
if (newcfg == NULL)
return NULL;
return NULL;
return newcfg;
}
*/
static void *
aa_create_srv_config(apr_pool_t *p, server_rec *srv)
immunix_create_srv_config (apr_pool_t * p, server_rec * srv)
{
apparmor_srv_cfg *newcfg = (apparmor_srv_cfg *) apr_pcalloc(p, sizeof(*newcfg));
immunix_srv_cfg * newcfg = (immunix_srv_cfg *) apr_pcalloc(p, sizeof(* newcfg));
ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, ap_server_conf,
"in aa_create_srv_config");
ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, ap_server_conf, "in immunix_create_srv");
if (newcfg == NULL) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf,
"aa_create_srv_config: couldn't alloc srv config");
return NULL;
ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, "immunix_create_srv: couldn't alloc srv config");
return NULL;
}
return newcfg;
}
static const command_rec mod_apparmor_cmds[] = {
static const command_rec immunix_cmds[] = {
AP_INIT_TAKE1(
AP_INIT_TAKE1 (
"ImmHatName",
immunix_cmd_ch_path,
NULL,
ACCESS_CONF,
""
immunix_cmd_ch_path,
NULL,
ACCESS_CONF,
""
),
AP_INIT_TAKE1(
AP_INIT_TAKE1 (
"ImmDefaultHatName",
immunix_cmd_ch_srv,
NULL,
RSRC_CONF,
""
immunix_cmd_ch_srv,
NULL,
RSRC_CONF,
""
),
AP_INIT_TAKE1(
AP_INIT_TAKE1 (
"AAHatName",
aa_cmd_ch_path,
NULL,
ACCESS_CONF,
""
aa_cmd_ch_path,
NULL,
ACCESS_CONF,
""
),
AP_INIT_TAKE1(
AP_INIT_TAKE1 (
"AADefaultHatName",
aa_cmd_ch_srv,
NULL,
RSRC_CONF,
""
aa_cmd_ch_srv,
NULL,
RSRC_CONF,
""
),
{ NULL }
};
static void
register_hooks(apr_pool_t *p)
static void
register_hooks (apr_pool_t *p)
{
ap_hook_post_config(aa_init, NULL, NULL, APR_HOOK_MIDDLE);
ap_hook_child_init(aa_child_init, NULL, NULL, APR_HOOK_MIDDLE);
ap_hook_access_checker(aa_enter_hat, NULL, NULL, APR_HOOK_FIRST);
/* ap_hook_post_read_request(aa_enter_hat, NULL, NULL, APR_HOOK_FIRST); */
ap_hook_log_transaction(aa_exit_hat, NULL, NULL, APR_HOOK_LAST);
ap_hook_post_config (immunix_init, NULL, NULL, APR_HOOK_MIDDLE);
ap_hook_child_init (immunix_child_init, NULL, NULL, APR_HOOK_MIDDLE);
ap_hook_access_checker(immunix_enter_hat, NULL, NULL, APR_HOOK_FIRST);
/* ap_hook_post_read_request(immunix_enter_hat, NULL, NULL, APR_HOOK_FIRST); */
ap_hook_log_transaction(immunix_exit_hat, NULL, NULL, APR_HOOK_LAST);
}
module AP_MODULE_DECLARE_DATA apparmor_module = {
STANDARD20_MODULE_STUFF,
aa_create_dir_config, /* dir config creater */
NULL, /* dir merger --- default is to override */
/* immunix_merge_dir_config, */ /* dir merger --- default is to override */
aa_create_srv_config, /* server config */
NULL, /* merge server config */
mod_apparmor_cmds, /* command table */
register_hooks /* register hooks */
immunix_create_dir_config, /* dir config creater */
NULL, /* dir merger --- default is to override */
/* immunix_merge_dir_config, */ /* dir merger --- default is to override */
immunix_create_srv_config, /* server config */
NULL, /* merge server config */
immunix_cmds, /* command table */
register_hooks /* register hooks */
};

View File

@@ -40,15 +40,11 @@ apache2(8)/httpd(8) configuration files, and restart Apache. Make sure that
apparmor is also functioning.
Once mod_apparmor is loaded within Apache, all requests to Apache will
cause mod_apparmor to attempt to change into a hat that matches the
ServerName for the server/vhost. If no such hat is found, it will
first fall back by attempting to change into a hat composed of the
ServerName-URI (e.g. "www.example.com-/app/some.cgi"). If that hat
is not found, it will fall back to attempting to use the hat named
by the URI (e.g. "/app/some.cgi"). If that hat is not found, it will
fall back to attempting to use the hat DEFAULT_URI; if that also does
not exist, it will fall back to using the global Apache profile. Most
static web pages can simply make use of the DEFAULT_URI hat.
cause mod_apparmor to attempt to change into a hat named by the URI
(e.g. /app/some.cgi). If no such hat is found, it will fall back to
attempting to use the hat DEFAULT_URI; if that also does not exist,
it will fall back to using the global Apache profile. Most static web
pages can simply make use of the DEFAULT_URI hat.
Additionally, before any requests come in to Apache, mod_apparmor
will attempt to change hat into the HANDLING_UNTRUSTED_INPUT hat.
@@ -64,8 +60,8 @@ provides the AAHatName and AADefaultHatName Apache configuration options.
=item B<AAHatName>
AAHatName allows you to specify a hat to be used for a given Apache
E<lt>DirectoryE<gt>, E<lt>DirectoryMatchE<gt>, E<lt>LocationE<gt> or
E<lt>LocationMatchE<gt> directive (see the Apache documentation for more
E<lt>DirectoryE<gt>, E<lt>DirectoryMatch>, E<lt>LocationE<gt> or
E<lt>LocationMatchE<gt> directive (see the Apache documenation for more
details). Note that mod_apparmor behavior can become confused if
E<lt>Directory*E<gt> and E<lt>Location*E<gt> directives are intermingled
and it is recommended to use one type of directive. If the hat specified by
@@ -78,9 +74,8 @@ AADefaultHatName allows you to specify a default hat to be used for
virtual hosts and other Apache server directives, so that you can have
different defaults for different virtual hosts. This can be overridden
by the AAHatName directive and is checked for only if there isn't
a matching AAHatName. The default value of AADefaultHatName is the
ServerName for the server/vhost configuration. If the AADefaultHatName
hat does not exist, then it falls back to the behavior described above.
a matching AAHatName. If the AADefaultHatName hat does not exist,
then it falls back to the behavior described above.
=back
@@ -95,35 +90,20 @@ On each URI request, mod_apparmor will first aa_change_hat(2) into
Then, after performing the initial parsing of the request, mod_apparmor
will:
=over 4
=over 2
=item 1
try to aa_change_hat(2) into a matching AAHatName hat if it exists and
1. try to aa_change_hat(2) into a matching AAHatName hat if it exists and
applies, otherwise it will
=item 2
2. try to aa_change_hat(2) into an AADefaultHatName hat if it has been defined
for the server/vhost, otherwise it will
try to aa_change_hat(2) into an AADefaultHatName hat, either the
ServerName (the default) or the configuration value specified by the
AADefaultHatName directive, for the server/vhost, otherwise it will
3. try to aa_change_hat(2) into the URI itself, otherwise it will
=item 3
try to aa_change_hat(2) into the ServerName-URI, otherwise it will
=item 4
try to aa_change_hat(2) into the URI itself, otherwise it will
=item 5
try to aa_change_hat(2) into the DEFAULT_URI hat, if it exists, otherwise it
4. try to aa_change_hat(2) into the DEFAULT_URI hat, if it exists, otherwise it
will
=item 6
fall back to the global Apache policy
5. fall back to the global Apache policy
=back
@@ -131,8 +111,7 @@ fall back to the global Apache policy
mod_apparmor() currently only supports apache2, and has only been tested
with the prefork MPM configuration -- threaded configurations of Apache
may not work correctly. For Apache 2.4 users, you should enable the mpm_prefork
module.
may not work correctly.
There are likely other bugs lurking about; if you find any, please report
them at L<https://bugs.launchpad.net/apparmor/+filebug>.

View File

@@ -1,6 +1,5 @@
# ----------------------------------------------------------------------
# Copyright (c) 1999, 2004, 2005 NOVELL (All rights reserved)
# Copyright (c) 2016 Canonical, Ltd.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of version 2 of the GNU General Public
@@ -17,57 +16,22 @@
NAME=pam_apparmor
all:
COMMONDIR=../../common/
MAKE_RULES=common/Make.rules
include $(COMMONDIR)/Make.rules
include ${MAKE_RULES}
ifdef USE_SYSTEM
LIBAPPARMOR = $(shell if pkg-config --exists libapparmor ; then \
pkg-config --silence-errors --libs libapparmor ; \
elif ldconfig -p | grep -q libapparmor\.so$$ ; then \
echo -lapparmor ; \
fi )
ifeq ($(strip $(LIBAPPARMOR)),)
ERROR_MESSAGE = $(error ${nl}\
************************************************************************${nl}\
Unable to find libapparmor installed on this system; either${nl}\
install libapparmor devel packages, set the LIBAPPARMOR variable${nl}\
manually, or build against in-tree libapparmor.${nl}\
************************************************************************${nl})
endif
LIBAPPARMOR_INCLUDE =
AA_LDLIBS = $(LIBAPPARMOR)
AA_LINK_FLAGS =
else
LIBAPPARMOR_SRC := ../../libraries/libapparmor/
LIBAPPARMOR_INCLUDE_PATH = $(LIBAPPARMOR_SRC)/include
LIBAPPARMOR_PATH := $(LIBAPPARMOR_SRC)/src/.libs/
ifeq ($(realpath $(LIBAPPARMOR_PATH)/libapparmor.a),)
ERROR_MESSAGE = $(error ${nl}\
************************************************************************${nl}\
$(LIBAPPARMOR_PATH)/libapparmor.a is missing; either build against${nl}\
the in-tree libapparmor by building it first and then trying again${nl}\
(see the top-level README for help) or build against the system${nl}\
libapparmor by adding USE_SYSTEM=1 to your make command.${nl}\
************************************************************************${nl})
endif
LIBAPPARMOR_INCLUDE = -I$(LIBAPPARMOR_INCLUDE_PATH)
AA_LINK_FLAGS = -L$(LIBAPPARMOR_PATH)
AA_LDLIBS = -lapparmor
COMMONDIR_EXISTS=$(strip $(shell [ -d ${COMMONDIR} ] && echo true))
ifeq ($(COMMONDIR_EXISTS), true)
common/Make.rules: $(COMMONDIR)/Make.rules
ln -sf $(COMMONDIR) .
endif
EXTRA_CFLAGS=$(CFLAGS) $(CPPFLAGS) -fPIC -shared -Wall $(LIBAPPARMOR_INCLUDE)
LINK_FLAGS=-Xlinker -x $(AA_LINK_FLAGS) $(LDFLAGS)
LIBS=-lpam $(AA_LDLIBS)
EXTRA_CFLAGS=$(CFLAGS) -fPIC -shared -Wall -I../../libraries/libapparmor/src/
LINK_FLAGS=-Xlinker -x -L../../libraries/libapparmor/src/.libs
LIBS=-lpam -lapparmor
OBJECTS=${NAME}.o get_options.o
.PHONY: libapparmor_check
.SILENT: libapparmor_check
libapparmor_check: ; $(ERROR_MESSAGE)
all: libapparmor_check $(NAME).so docs
.PHONY: docs
# docs: we should have some
docs:
all: $(NAME).so
$(NAME).so: ${OBJECTS}
$(CC) $(EXTRA_CFLAGS) $(LINK_FLAGS) -o $@ ${OBJECTS} $(LIBS)
@@ -85,5 +49,7 @@ install: $(NAME).so
install -m 555 $(NAME).so $(SECDIR)/
.PHONY: clean
clean:
clean: ${MAKE_RULES}
rm -f core core.* *.so *.o *.s *.a *~
rm -f ${NAME}-*.tar.gz Make.rules

View File

@@ -27,7 +27,7 @@
#include <grp.h>
#include <syslog.h>
#include <errno.h>
#include <sys/apparmor.h>
#include <apparmor.h>
#include <security/pam_ext.h>
#include <security/pam_modutil.h>
@@ -111,7 +111,6 @@ int pam_sm_open_session(pam_handle_t *pamh, int flags,
sizeof(magic_token));
if (retval < 0) {
pam_syslog(pamh, LOG_ERR, "Can't read from /dev/urandom\n");
close(fd);
return PAM_PERM_DENIED;
}
} while ((magic_token == 0) || (retval != sizeof(magic_token)));

View File

@@ -0,0 +1,83 @@
#
# spec file for package pam_apparmor (Version 2)
#
# Copyright (c) 2005 SUSE LINUX Products GmbH, Nuernberg, Germany.
# This file and all modifications and additions to the pristine
# package are under the same license as the package itself.
#
# Please submit bugfixes or comments via http://www.suse.de/feedback/
#
# norootforbuild
Name: pam_apparmor
License: GPL
Group: Productivity/Security
Autoreqprov: on
Version: @@immunix_version@@
Release: @@repo_version@@
Summary: Pam module to add AppArmor change_hat functionality
URL: http://forge.novell.com/modules/xfmod/project/?apparmor
Source: pam_apparmor-%{version}-@@repo_version@@.tar.gz
BuildRoot: %{_tmppath}/%{name}-%{version}-build
BuildRequires: pam-devel
Requires: pam
Prereq: pam
%if %{?suse_version:1}0
%if 0%{?suse_version} < 1030
BuildRequires: libapparmor
%else
BuildRequires: libapparmor-devel
%endif
%else
BuildRequires: libapparmor-devel
%endif
%description
The pam_apparmor module provides the means for any pam applications that
call pam_open_session() to automatically perform an AppArmor change_hat
operation in order to switch to a user-specific security policy.
Authors:
--------
Jesse Michael jmichael@suse.de
%prep
%setup -q
%build
make CFLAGS="${RPM_OPT_FLAGS}"
%install
[ "$RPM_BUILD_ROOT" != "/" ] && rm -rf $RPM_BUILD_ROOT
make install DESTDIR=${RPM_BUILD_ROOT} SECDIR=${RPM_BUILD_ROOT}/%{_lib}/security
%clean
[ "${RPM_BUILD_ROOT}" != "/" ] && rm -rf ${RPM_BUILD_ROOT}
%files
%defattr(444,root,root,755)
%doc README COPYING
%attr(555,root,root) /%{_lib}/security/pam_apparmor.so
%changelog -n pam_apparmor
* Tue Oct 31 2006 Jesse Michael <jmichael@suse.de>
- Add debug option
* Tue Oct 31 2006 Steve Beattie <sbeattie@suse.de>
- Add configuration options to order attempted hat changes
* Wed Oct 25 2006 Steve Beattie <sbeattie@suse.de>
- remove auto-editing of pam's common-session
- honor RPM's CFLAGS when building
- add license (same as Linux PAM package).
* Thu Sep 14 2006 Jesse Michael <jmichael@suse.de>
- header comment was incorrect
- use pam_get_user() instead of pam_get_item()
- fix read from urandom if 0
* Fri Jan 13 2006 Steve Beattie <sbeattie@suse.de>
- Add svn repo number to tarball
* Fri Jan 13 2006 Jesse Michael <jmichael@suse.de>
- Make magic tokens harder to guess by pulling them from /dev/urandom
* Wed Dec 21 2005 - jmichael@suse.de
- initial

View File

@@ -17,7 +17,13 @@ NAME = tomcat_apparmor
all:
COMMONDIR=../../../common/
include $(COMMONDIR)/Make.rules
include common/Make.rules
COMMONDIR_EXISTS=$(strip $(shell [ -d ${COMMONDIR} ] && echo true))
ifeq ($(COMMONDIR_EXISTS), true)
common/Make.rules: $(COMMONDIR)/Make.rules
ln -sf $(COMMONDIR) .
endif
LIB = lib
CATALINA_HOME = /usr/share/tomcat5
@@ -28,6 +34,7 @@ all:
clean:
ant clean
rm -f tomcat_apparmor.spec ${NAME}-*.tar.gz Make.rules
install:
install: $(SPECFILE)
ant -Dversion=$(VERSION) -Drelease=$(MAN_RELEASE) -Dcatalina_home=${CATALINA_HOME} -Dinstall_lib=${LIB} install_jar install_jni

View File

@@ -13,7 +13,7 @@
#include "jni.h"
#include <errno.h>
#include <sys/apparmor.h>
#include "sys/apparmor.h"
#include "com_novell_apparmor_JNIChangeHat.h"
/* c intermediate lib call for Java -> JNI -> c library execution of the change_hat call */

View File

@@ -0,0 +1,85 @@
# ----------------------------------------------------------------------
# Copyright (c) 2006 NOVELL (All rights reserved)
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of version 2 of the GNU General Public
# License published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, contact Novell, Inc.
# ----------------------------------------------------------------------
# norootforbuild
# Check first to see if distro is already defined.
%if ! %{?distro:1}0
%define distro suse
%endif
%if %{distro} == "suse"
%define CATALINA_HOME /usr/share/tomcat5
%endif
%define APPARMOR_DOC_DIR /usr/share/doc/packages/apparmor-docs/
%define JNI_SO libJNIChangeHat.so
%define JAR_FILE changeHatValve.jar
Summary: Tomcat 5 plugin for AppArmor change_hat
Name: tomcat_apparmor
Version: @@immunix_version@@
Release: @@repo_version@@
Group: System/Libraries
Source0: %{name}-%{version}-@@repo_version@@.tar.gz
License: LGPL
BuildRoot: %{?_tmppath:}%{!?_tmppath:/var/tmp}/%{name}-%{version}-build
Url: http://developer.novell.com/wiki/index.php/Novell_AppArmor
Prereq: tomcat5, servletapi5, libapparmor
BuildRequires: tomcat5, servletapi5 ant, java, libapparmor, java2-devel-packages, apparmor-docs
Provides: tomcat_apparmor
%description
tomcat_apparmor - is a plugin for Apache Tomcat version 5.x that provides
support for AppArmor change_hat for creating AppArmor containers that are
bound to discrete elements of processing within the Tomcat servlet
container. The AppArmor containers, or "hats", can be created for invidual
URL processing or per servlet.
%prep
%setup -q
%build
[ "${RPM_BUILD_ROOT}" != "/" ] && rm -rf ${RPM_BUILD_ROOT}
ant -Ddist=${RPM_BUILD_DIR}/%{name}-%{version} -Dtarget=1.4 jar jni_so
%install
ant -Ddist=${RPM_BUILD_DIR}/%{name}-%{version} -Dversion=%{version} -Drelease=%{release} -Dcatalina_home=%{CATALINA_HOME} -Dinstall_root=${RPM_BUILD_ROOT} -Dinstall_lib=%{_lib} install_jar install_jni
mkdir -p ${RPM_BUILD_ROOT}%{APPARMOR_DOC_DIR}
install ${RPM_BUILD_DIR}/%{name}-%{version}/README.tomcat_apparmor ${RPM_BUILD_ROOT}%{APPARMOR_DOC_DIR}
%clean
[ "$RPM_BUILD_ROOT" != "/" ] && rm -rf $RPM_BUILD_ROOT
%files
%defattr(-,root,root)
%{CATALINA_HOME}/server/lib/%{JAR_FILE}
/%{_lib}/lib*
/%{_libdir}/lib*
%{APPARMOR_DOC_DIR}/README.tomcat_apparmor
%post
ldconfig
%postun
ldconfig
%changelog
* Mon Oct 9 2006 - dreynolds@suse.de
- Initial package creation.

View File

@@ -17,7 +17,13 @@ NAME = tomcat_apparmor
all:
COMMONDIR=../../../common/
include $(COMMONDIR)/Make.rules
include common/Make.rules
COMMONDIR_EXISTS=$(strip $(shell [ -d ${COMMONDIR} ] && echo true))
ifeq ($(COMMONDIR_EXISTS), true)
common/Make.rules: $(COMMONDIR)/Make.rules
ln -sf $(COMMONDIR) .
endif
LIB = lib
CATALINA_HOME = /usr/share/tomcat55
@@ -28,6 +34,7 @@ all:
clean:
ant clean
rm -f tomcat_apparmor.spec ${NAME}-*.tar.gz Make.rules
install:
install: $(SPECFILE)
ant -Dversion=$(VERSION) -Drelease=$(MAN_RELEASE) -Dcatalina_home=${CATALINA_HOME} -Dinstall_lib=${LIB} install_jar install_jni

View File

@@ -13,7 +13,7 @@
#include "jni.h"
#include <errno.h>
#include <sys/apparmor.h>
#include <apparmor.h>
#include "com_novell_apparmor_JNIChangeHat.h"
/* c intermediate lib call for Java -> JNI -> c library execution of the change_hat call */

View File

@@ -0,0 +1,86 @@
# ----------------------------------------------------------------------
# Copyright (c) 2006 NOVELL (All rights reserved)
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of version 2 of the GNU General Public
# License published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, contact Novell, Inc.
# ----------------------------------------------------------------------
# norootforbuild
# Check first to see if distro is already defined.
%if ! %{?distro:1}0
%define distro suse
%endif
%if %{distro} == "suse"
%define CATALINA_HOME /usr/share/tomcat55
%endif
%define APPARMOR_DOC_DIR /usr/share/doc/packages/apparmor-docs/
%define JNI_SO libJNIChangeHat.so
%define JAR_FILE changeHatValve.jar
Summary: Tomcat 5 plugin for AppArmor change_hat
Name: tomcat_apparmor
Version: @@immunix_version@@
Release: @@repo_version@@
Group: System/Libraries
Source0: %{name}-%{version}-@@repo_version@@.tar.gz
License: LGPL
BuildRoot: %{?_tmppath:}%{!?_tmppath:/var/tmp}/%{name}-%{version}-build
Url: http://developer.novell.com/wiki/index.php/Novell_AppArmor
Prereq: tomcat55, servletapi5
BuildRequires: tomcat55, servletapi5, ant, java, libapparmor-devel, java2-devel-packages, apparmor-docs
%description
tomcat_apparmor - is a plugin for Apache Tomcat version 5.x that provides
support for AppArmor change_hat for creating AppArmor containers that are
bound to discrete elements of processing within the Tomcat servlet
container. The AppArmor containers, or "hats", can be created for invidual
URL processing or per servlet.
%prep
%setup -q
%build
[ "${RPM_BUILD_ROOT}" != "/" ] && rm -rf ${RPM_BUILD_ROOT}
ant -Dinstall_lib=%{_lib} -Dcatalina_home=%{CATALINA_HOME} -Ddist=${RPM_BUILD_DIR}/%{name}-%{version} -Dtarget=1.4 jar jni_so
%install
ant -Ddist=${RPM_BUILD_DIR}/%{name}-%{version} -Dversion=%{version} -Drelease=%{release} -Dcatalina_home=%{CATALINA_HOME} -Dinstall_root=${RPM_BUILD_ROOT} -Dinstall_lib=%{_lib} install_jar install_jni
mkdir -p ${RPM_BUILD_ROOT}%{APPARMOR_DOC_DIR}
install ${RPM_BUILD_DIR}/%{name}-%{version}/README.tomcat_apparmor ${RPM_BUILD_ROOT}%{APPARMOR_DOC_DIR}
%clean
[ "$RPM_BUILD_ROOT" != "/" ] && rm -rf $RPM_BUILD_ROOT
%files
%defattr(-,root,root)
%{CATALINA_HOME}/server/lib/%{JAR_FILE}
/%{_lib}/lib*
/%{_libdir}/lib*
doc %attr(0644,root,root) %{APPARMOR_DOC_DIR}/README.tomcat_apparmor
%post
ldconfig
%postun
ldconfig
%changelog
* Mon Jul 20 2007 - sbeattie@suse.de
- Convert builddep on libapparmor to libapparmor-devel
* Mon Oct 9 2006 - dreynolds@suse.de
- Initial package creation.

View File

@@ -1,7 +1,7 @@
# ------------------------------------------------------------------
#
# Copyright (c) 1999-2008 NOVELL (All rights reserved)
# Copyright 2009-2015 Canonical Ltd.
# Copyright 2009-2010 Canonical Ltd.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of version 2 of the GNU General Public
@@ -21,7 +21,7 @@
# exist
LOCALEDIR=/usr/share/locale
XGETTEXT_ARGS=--copyright-holder="Canonical Ltd" --msgid-bugs-address=apparmor@lists.ubuntu.com -d ${NAME}
XGETTEXT_ARGS=--copyright-holder="NOVELL, Inc." --msgid-bugs-address=apparmor@lists.ubuntu.com -d ${NAME}
# When making the .pot file, it's expected that the parent Makefile will
# pass in the list of sources in the SOURCES variable

View File

@@ -1,7 +1,7 @@
# ------------------------------------------------------------------
#
# Copyright (C) 2002-2005 Novell/SUSE
# Copyright (C) 2010-2015 Canonical, Ltd.
# Copyright (C) 2010 Canonical, Ltd.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of version 2 of the GNU General Public
@@ -15,37 +15,126 @@
# You should have received a copy of the GNU General Public License
# along with this program; if not, contact Novell, Inc.
# ------------------------------------------------------------------
# Make.rules - common make targets and variables for building AppArmor
# Make.rules - common make targets and variables for building the SHASS
# product.
#
# NOTES:
# Before including this file in your Makefile, you should
# - define COMMONDIR (the location of the common/ directory)
# - define the default rule (usually 'all:'). (Note: you can redefine
# it later in your Makefile)
.PHONY: common_Make.rules_is_a_bad_target
common_Make.rules_is_a_bad_target:
@echo "*** default target in common/Make.rules hit - either you did something strange, or something is broken... ***"
exit 1
# - must define the package NAME before including this file.
# - After checking in to cvs, you'll need to delele the hardlinked
# Make.rules files that already exist in the individual application
# directories
DISTRIBUTION=AppArmor
VERSION=$(shell cat $(COMMONDIR)/Version)
# Convenience functions
pathsearch = $(firstword $(wildcard $(addsuffix /$(1),$(subst :, ,$(PATH)))))
map = $(foreach a,$(2),$(call $(1),$(a)))
VERSION=$(shell cat common/Version)
AWK:=$(shell which awk)
ifndef AWK
$(error awk utility required for build but not available)
endif
define nl
# Convenience functions
pathsearch = $(firstword $(wildcard $(addsuffix /$(1),$(subst :, ,$(PATH)))))
map = $(foreach a,$(2),$(call $(1),$(a)))
# OVERRIDABLE variables
# Set these variables before including Make.rules to change its behavior
# SPECFILE - for packages that have a non-standard specfile name
# EXTERNAL_PACKAGE - for packages that have upstream versions that
# we're locally modifying (e.g. imnxcerttool/gnutls).
#
# use 'make BUILDIR=/some/where/else/' to override the /usr/src/redhat
# location -- it *should* pick out the right thing to do based on the
# .rpmmacros file, but you can still use BUILDDIR to override that.
TESTBUILDDIR=$(shell [ -f ${HOME}/.rpmmacros ] && awk '/^%_topdir/ {print $$2}' ${HOME}/.rpmmacros)
ifndef BUILDDIR
BUILDDIR=$(shell if [ -d "${TESTBUILDDIR}" ] ; then \
echo ${TESTBUILDDIR} | sed "s^/$$^^" ; \
elif [ -d "/usr/src/redhat" ] ; then \
echo "/usr/src/redhat" ; \
elif [ -d "/usr/src/packages" ] ; then \
echo "/usr/src/packages" ; \
else \
echo "/tmp/${NAME}" ; \
fi ;)
endif
ifndef DISTRO
DISTRO=$(shell if [ -f /etc/slackware-version ] ; then \
echo slackware ; \
elif [ -f /etc/debian_version ] ; then \
echo debian ;\
elif which rpm > /dev/null ; then \
if [ "$(rpm --eval '0%{?suse_version}')" != "0" ] ; then \
echo suse ;\
elif [ "$(rpm --eval '%{_host_vendor}')" = redhat ] ; then \
echo rhel4 ;\
elif [ "$(rpm --eval '0%{?fedora}')" != "0" ] ; then \
echo rhel4 ;\
else \
echo unknown ;\
fi ;\
else \
echo unknown ;\
fi)
endif
RPMARG=--define "_topdir $(BUILDDIR:/=)" \
--define "vendor NOVELL, Inc." \
--define "distribution ${DISTRIBUTION}" \
--define "debug_package %{nil}" \
--define "immunix_version ${VERSION}" \
$(shell [ -d ${BUILDDIR}/BUILDROOT ] && echo --define \"buildroot $(BUILDDIR:/=)/BUILDROOT\") \
$(shell [ -n "${DISTRO}" ] && echo --define \"distro ${DISTRO}\")
endef
REPO_VERSION_CMD=([ -x /usr/bin/bzr ] && /usr/bin/bzr version-info . 2> /dev/null || awk '{ print "revno: "$2 }' common/.stamp_rev) | awk '/^revno:/ { print $2 }'
REPO_VERSION_CMD=[ -x /usr/bin/bzr ] && /usr/bin/bzr version-info --custom --template="{revno}" . 2> /dev/null || awk '{ print $2 }' common/.stamp_rev
ifdef EXTERNAL_PACKAGE
RPMARG+=--define "_sourcedir $(shell pwd)"
endif
ifndef SPECFILE
SPECFILE = $(NAME).spec
endif
RELEASE_DIR = $(NAME)-$(VERSION)
TAR = /bin/tar czvp -h --exclude .svn --exclude .bzr --exclude .bzrignore --exclude ${RELEASE_DIR}/${RELEASE_DIR} $(shell test -f ${NAME}.exclude && echo "-X ${NAME}.exclude")
LDCONFIG = /sbin/ldconfig
RPMSUBDIRS=SOURCES SPECS BUILD BUILDROOT SRPMS RPMS/i386 RPMS/i586 \
RPMS/i686 RPMS/athlon RPMS/noarch RPMS/x86_64
BUILDRPMSUBDIRS=$(foreach subdir, $(RPMSUBDIRS), $(BUILDDIR:/=)/$(subdir))
ifdef EXTERNAL_PACKAGE
.PHONY: rpm
rpm: clean $(BUILDRPMSUBDIRS)
rpmbuild -ba ${RPMARG} ${SPECFILE}
else
.PHONY: rpm
rpm: clean $(BUILDRPMSUBDIRS)
__REPO_VERSION=`$(value REPO_VERSION_CMD)` ; \
__TARBALL=$(NAME)-$(VERSION)-$${__REPO_VERSION}.tar.gz ; \
make $${__TARBALL} ; \
cp $${__TARBALL} $(BUILDDIR)/SOURCES/
cp ${SPECFILE} $(BUILDDIR)/SPECS/
rpmbuild -ba ${RPMARG} ${SPECFILE}
.PHONY: ${SPECFILE}
${SPECFILE}: ${SPECFILE}.in
__REPO_VERSION=`$(value REPO_VERSION_CMD)` ; \
sed -e "s/@@immunix_version@@/${VERSION}/g" \
-e "s/@@repo_version@@/$${__REPO_VERSION}/g" $< > $@
%.tar.gz: clean ${SPECFILE}
-rm -rf $(RELEASE_DIR)
mkdir $(RELEASE_DIR)
$(TAR) --exclude $@ . | tar xz -C $(RELEASE_DIR)
$(TAR) --exclude $@ -f $@ $(RELEASE_DIR)
rm -rf $(RELEASE_DIR)
ifndef OVERRIDE_TARBALL
.PHONY: tarball
tarball: clean $(TARBALL)
endif
endif
ifndef PYTHON_VERSIONS
PYTHON_VERSIONS = $(call map, pathsearch, python2 python3)
@@ -61,18 +150,24 @@ pyalldo=set -e; $(foreach py, $(PYTHON_VERSIONS), $(py) $(1);)
.PHONY: version
.SILENT: version
version:
echo $(VERSION)
rpm -q --define "_sourcedir ." ${RPMARG} --specfile ${SPECFILE}
.PHONY: repo_version
.SILENT: repo_version
repo_version:
echo $(shell $(value REPO_VERSION_CMD))
$(value REPO_VERSION_CMD)
.PHONY: pod_clean
ifndef VERBOSE
.SILENT: pod_clean
endif
pod_clean:
.PHONY: build_dir
build_dir: $(BUILDRPMSUBDIRS)
$(BUILDRPMSUBDIRS):
mkdir -p $(BUILDRPMSUBDIRS)
.PHONY: _clean
.SILENT: _clean
_clean:
-rm -f ${NAME}-${VERSION}-*.tar.gz
-rm -f ${MANPAGES} *.[0-9].gz ${HTMLMANPAGES} pod2htm*.tmp
# =====================
@@ -82,7 +177,7 @@ pod_clean:
# =====================
# emits defined capabilities in a simple list, e.g. "CAP_NAME CAP_NAME2"
CAPABILITIES=$(shell echo "\#include <linux/capability.h>" | cpp -dM | LC_ALL=C sed -n -e '/CAP_EMPTY_SET/d' -e 's/^\#define[ \t]\+CAP_\([A-Z0-9_]\+\)[ \t]\+\([0-9xa-f]\+\)\(.*\)$$/CAP_\1/p' | LC_ALL=C sort)
CAPABILITIES=$(shell echo "\#include <linux/capability.h>" | cpp -dM | LC_ALL=C sed -n -e '/CAP_EMPTY_SET/d' -e 's/^\#define[ \t]\+CAP_\([A-Z0-9_]\+\)[ \t]\+\([0-9xa-f]\+\)\(.*\)$$/CAP_\1/p' | sort)
.PHONY: list_capabilities
list_capabilities: /usr/include/linux/capability.h
@@ -98,12 +193,12 @@ list_capabilities: /usr/include/linux/capability.h
# to mediate. We use PF_ here since that is what is required in
# bits/socket.h, but we will rewrite these as AF_.
FILTER_FAMILIES=PF_UNIX
FILTER_FAMILIES=PF_UNSPEC PF_UNIX PF_LOCAL PF_NETLINK
__FILTER=$(shell echo $(strip $(FILTER_FAMILIES)) | sed -e 's/ /\\\|/g')
# emits the AF names in a "AF_NAME NUMBER," pattern
AF_NAMES=$(shell echo "\#include <sys/socket.h>" | cpp -dM | LC_ALL=C sed -n -e '/$(__FILTER)/d' -e 's/PF_LOCAL/PF_UNIX/' -e 's/^\#define[ \t]\+PF_\([A-Z0-9_]\+\)[ \t]\+\([0-9]\+\).*$$/AF_\1 \2,/p' | sort -n -k2)
AF_NAMES=$(shell echo "\#include <sys/socket.h>" | cpp -dM | LC_ALL=C sed -n -e '/$(__FILTER)/d' -e 's/^\#define[ \t]\+PF_\([A-Z0-9_]\+\)[ \t]\+\([0-9]\+\).*$$/AF_\1 \2,/p' | sort -n -k2)
.PHONY: list_af_names
list_af_names:
@@ -166,7 +261,3 @@ ENSCRIPT_ARGS=-C -2jGr -f Courier6 -E
%.pm.ps: %.pm
enscript ${ENSCRIPT_ARGS} -o $@ $<
.PHONY: check_pod_files
check_pod_files:
LANG=C podchecker -warning -warning *.pod

View File

@@ -1 +1 @@
2.11.95
2.8.5

View File

@@ -0,0 +1 @@
Matt Barringer <mbarringer@suse.de>

View File

@@ -0,0 +1,340 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

View File

@@ -0,0 +1,167 @@
Basic Installation
==================
These are generic installation instructions.
The `configure' shell script attempts to guess correct values for
various system-dependent variables used during compilation. It uses
those values to create a `Makefile' in each directory of the package.
It may also create one or more `.h' files containing system-dependent
definitions. Finally, it creates a shell script `config.status' that
you can run in the future to recreate the current configuration, a file
`config.cache' that saves the results of its tests to speed up
reconfiguring, and a file `config.log' containing compiler output
(useful mainly for debugging `configure').
If you need to do unusual things to compile the package, please try
to figure out how `configure' could check whether to do them, and mail
diffs or instructions to the address given in the `README' so they can
be considered for the next release. If at some point `config.cache'
contains results you don't want to keep, you may remove or edit it.
The file `configure.in' is used to create `configure' by a program
called `autoconf'. You only need `configure.in' if you want to change
it or regenerate `configure' using a newer version of `autoconf'.
The simplest way to compile this package is:
1. `cd' to the directory containing the package's source code and type
`./configure' to configure the package for your system. If you're
using `csh' on an old version of System V, you might need to type
`sh ./configure' instead to prevent `csh' from trying to execute
`configure' itself.
Running `configure' takes a while. While running, it prints some
messages telling which features it is checking for.
2. Type `make' to compile the package.
3. Type `make install' to install the programs and any data files and
documentation.
4. You can remove the program binaries and object files from the
source code directory by typing `make clean'.
Compilers and Options
=====================
Some systems require unusual options for compilation or linking that
the `configure' script does not know about. You can give `configure'
initial values for variables by setting them in the environment. Using
a Bourne-compatible shell, you can do that on the command line like
this:
CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
Or on systems that have the `env' program, you can do it like this:
env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
Compiling For Multiple Architectures
====================================
You can compile the package for more than one kind of computer at the
same time, by placing the object files for each architecture in their
own directory. To do this, you must use a version of `make' that
supports the `VPATH' variable, such as GNU `make'. `cd' to the
directory where you want the object files and executables to go and run
the `configure' script. `configure' automatically checks for the
source code in the directory that `configure' is in and in `..'.
If you have to use a `make' that does not supports the `VPATH'
variable, you have to compile the package for one architecture at a time
in the source code directory. After you have installed the package for
one architecture, use `make distclean' before reconfiguring for another
architecture.
Installation Names
==================
By default, `make install' will install the package's files in
`/usr/local/bin', `/usr/local/man', etc. You can specify an
installation prefix other than `/usr/local' by giving `configure' the
option `--prefix=PATH'.
You can specify separate installation prefixes for
architecture-specific files and architecture-independent files. If you
give `configure' the option `--exec-prefix=PATH', the package will use
PATH as the prefix for installing programs and libraries.
Documentation and other data files will still use the regular prefix.
If the package supports it, you can cause programs to be installed
with an extra prefix or suffix on their names by giving `configure' the
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
Optional Features
=================
Some packages pay attention to `--enable-FEATURE' options to
`configure', where FEATURE indicates an optional part of the package.
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
is something like `gnu-as' or `x' (for the X Window System). The
`README' should mention any `--enable-' and `--with-' options that the
package recognizes.
For packages that use the X Window System, `configure' can usually
find the X include and library files automatically, but if it doesn't,
you can use the `configure' options `--x-includes=DIR' and
`--x-libraries=DIR' to specify their locations.
Specifying the System Type
==========================
There may be some features `configure' can not figure out
automatically, but needs to determine by the type of host the package
will run on. Usually `configure' can figure that out, but if it prints
a message saying it can not guess the host type, give it the
`--host=TYPE' option. TYPE can either be a short name for the system
type, such as `sun4', or a canonical name with three fields:
CPU-COMPANY-SYSTEM
See the file `config.sub' for the possible values of each field. If
`config.sub' isn't included in this package, then this package doesn't
need to know the host type.
If you are building compiler tools for cross-compiling, you can also
use the `--target=TYPE' option to select the type of system they will
produce code for and the `--build=TYPE' option to select the type of
system on which you are compiling the package.
Sharing Defaults
================
If you want to set default values for `configure' scripts to share,
you can create a site shell script called `config.site' that gives
default values for variables like `CC', `cache_file', and `prefix'.
`configure' looks for `PREFIX/share/config.site' if it exists, then
`PREFIX/etc/config.site' if it exists. Or, you can set the
`CONFIG_SITE' environment variable to the location of the site script.
A warning: not all `configure' scripts look for a site script.
Operation Controls
==================
`configure' recognizes the following options to control how it
operates.
`--cache-file=FILE'
Use and save the results of the tests in FILE instead of
`./config.cache'. Set FILE to `/dev/null' to disable caching, for
debugging `configure'.
`--help'
Print a summary of the options to `configure', and exit.
`--quiet'
`--silent'
`-q'
Do not print messages saying which checks are being made.
`--srcdir=DIR'
Look for the package's source code in directory DIR. Usually
`configure' can determine that directory automatically.
`--version'
Print the version of Autoconf used to generate the `configure'
script, and exit.
`configure' also accepts some other, not widely useful, options.

View File

@@ -0,0 +1,5 @@
# not a GNU package. You can remove this line, if
# have all needed files, that a GNU package needs
AUTOMAKE_OPTIONS = foreign 1.4
SUBDIRS = src

View File

@@ -0,0 +1,8 @@
In order to actually use aadbus, you need to tell auditd to use it as a dispatcher. It's simple:
* As root, edit /etc/auditd.conf
* Add the following line (using the correct path, of course):
dispatcher=/usr/local/bin/apparmor-dbus
* Restart auditd

View File

@@ -0,0 +1,43 @@
#
# spec file for package apparmor-dbus
#
# norootforbuild
Name: apparmor-dbus
BuildRequires: audit-devel dbus-1-devel pkgconfig libapparmor-devel
Requires: libapparmor
Version: 2.3
Release: 0
License: GPL
Group: System/Management
BuildRoot: %{_tmppath}/%{name}-%{version}-build
Source0: %{name}-%{version}.tar.bz2
Summary: -
%description
-
%prep
%setup -n %{name}-%{version}
%build
autoreconf --force --install
export CFLAGS="$RPM_OPT_FLAGS"
%{?suse_update_config:%{suse_update_config -f}}
./configure --prefix=%{_prefix}
make
%install
rm -rf %{buildroot}
%makeinstall
%clean
rm -rf %{buildroot}
%files
%defattr(-, root, root)
%{_prefix}/bin/apparmor-dbus
%changelog
* Thu Sep 13 2007 - sbeattie@suse.de
- Bump to revision 1.2

View File

@@ -0,0 +1,31 @@
#!/bin/sh
DIE=0
(autoconf --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "You must have autoconf installed to compile $package."
echo "Download the appropriate package for your distribution,"
echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/"
DIE=1
}
(automake --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "You must have automake installed to compile $package."
echo "Download the appropriate package for your system,"
echo "or get the source from one of the GNU ftp sites"
echo "listed in http://www.gnu.org/order/ftp.html"
DIE=1
}
if test "$DIE" -eq 1; then
exit 1
fi
echo "Running aclocal"
aclocal
echo "Running autoconf"
autoconf --force
echo "Running automake -ac"
automake -ac

View File

@@ -0,0 +1,16 @@
AC_INIT(configure.in)
AM_INIT_AUTOMAKE(apparmor-dbus, 2.3)
AC_LANG_C
AC_PROG_CC
AC_CHECK_HEADERS(libaudit.h,,AC_MSG_ERROR([libaudit header file not found!]))
AC_CHECK_LIB(audit, audit_open)
AC_CHECK_HEADERS(aalogparse/aalogparse.h)
AC_CHECK_LIB(apparmor, parse_record)
PKG_CHECK_MODULES(DBUS, dbus-1 >= 0.60)
CFLAGS="${CFLAGS} ${DBUS_CFLAGS}"
AC_CHECK_LIB(dbus-1, exit,,AC_MSG_ERROR([dbus-1 not found!]))
AC_OUTPUT(Makefile src/Makefile)

View File

@@ -0,0 +1,2 @@
bin_PROGRAMS = apparmor-dbus
apparmor_dbus_SOURCES = aadbus.c

View File

@@ -0,0 +1,322 @@
#define DBUS_API_SUBJECT_TO_CHANGE
#include <stdio.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <locale.h>
#include <libaudit.h>
#include <dbus/dbus.h>
#include <aalogparse/aalogparse.h>
#define NULLSPACE(x) (x == NULL) ? &empty_string : &x
#define NULLSTRLEN(x) (x == NULL) ? 1 : (strlen(x) + 1)
// Local data
static volatile int signaled = 0;
static int pipe_fd;
// Local functions
static int event_loop(void);
static int is_reject(char *data);
// SIGTERM handler
static void term_handler( int sig )
{
signaled = 1;
}
/*
* main is started by auditd. See dispatcher in auditd.conf
*/
int main(int argc, char *argv[])
{
struct sigaction sa;
setlocale (LC_ALL, "");
#ifndef DEBUG
/* Make sure we are root */
if (getuid() != 0) {
printf("You must be root to run this program.\n");
return 4;
}
#endif
// register sighandlers
sa.sa_flags = 0 ;
sa.sa_handler = term_handler;
sigemptyset( &sa.sa_mask ) ;
sigaction( SIGTERM, &sa, NULL );
sa.sa_handler = term_handler;
sigemptyset( &sa.sa_mask ) ;
sigaction( SIGCHLD, &sa, NULL );
sa.sa_handler = SIG_IGN;
sigaction( SIGHUP, &sa, NULL );
(void)chdir("/");
// change over to pipe_fd
pipe_fd = dup(0);
close(0);
open("/dev/null", O_RDONLY);
fcntl(pipe_fd, F_SETFD, FD_CLOEXEC);
// Start the program
return event_loop();
}
/* This function is needed for "old" messages which lumped
* everything together under one audit ID.
*/
static int is_reject (char *data)
{
int ret = -1;
/* Look for the first space */
char *start = strchr(data, ' ');
if ((start != NULL) && (strlen(start) > 9))
{
if (strncmp(start + 1, "REJECTING", 9) == 0)
{
ret = 0;
}
}
return ret;
}
static int event_loop(void)
{
void* data;
char *empty_string = " "; /* This is a quick way to indicate a 'null' value in our DBUS message */
struct iovec vec[2];
struct audit_dispatcher_header hdr;
DBusError error; /* Error, if any */
DBusMessage *message; /* Message to send */
static DBusConnection *con = NULL; /* Connection to DBUS server */
DBusMessageIter iter, /* The main message iterator */
profileIter,
nameIter,
name2Iter,
parentIter,
activeIter,
dataIter;
char *line = NULL, *parsable_line = NULL;
int real_data_size;
aa_log_record *record;
int is_rejection = 0;
if (con && !dbus_connection_get_is_connected(con))
{
dbus_connection_unref(con);
con = NULL;
}
if (!con)
{
dbus_error_init(&error);
con = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
if (!con)
{
dbus_error_free(&error);
return 1;
}
}
//message = dbus_message_new_signal("/com/Novell/AppArmor","com.novell.apparmor", "Reject");
/* allocate data structures */
data = malloc(MAX_AUDIT_MESSAGE_LENGTH);
if (data == NULL)
{
printf("Cannot allocate buffer\n");
return 1;
}
memset(data, 0, MAX_AUDIT_MESSAGE_LENGTH);
memset(&hdr, 0, sizeof(hdr));
do
{
int rc;
parsable_line = NULL;
is_rejection = 0;
struct timeval tv;
fd_set fd;
tv.tv_sec = 1;
tv.tv_usec = 0;
FD_ZERO(&fd);
FD_SET(pipe_fd, &fd);
rc = select(pipe_fd+1, &fd, NULL, NULL, &tv);
if (rc == 0)
continue;
else if (rc == -1)
break;
/* Get header first. it is fixed size */
vec[0].iov_base = (void*)&hdr;
vec[0].iov_len = sizeof(hdr);
memset(data, 0, MAX_AUDIT_MESSAGE_LENGTH);
// Next payload
vec[1].iov_base = data;
vec[1].iov_len = MAX_AUDIT_MESSAGE_LENGTH;
rc = readv(pipe_fd, vec, 2);
if (rc == 0 || rc == -1) {
printf("rc == %d(%s)\n", rc, strerror(errno));
break;
}
/* Handle the AppArmor events.
* 1500 is used for "old" style messages.
* 1503 is used for APPARMOR_DENIED messages.
*/
if ((hdr.type == 1500) || (hdr.type == 1503))
{
line = (char *) data;
record = NULL;
if (hdr.type == 1503)
is_rejection = 1;
if ((hdr.type == 1500) && (is_reject(line) == 0))
is_rejection = 1;
/* We only care about REJECTING messages */
if (is_rejection == 1)
{
/* parse_record expects things like they appear in audit.log -
* which means we need to prepend TYPE=APPARMOR (if hdr.type is 1500)
* or type=APPARMOR_DENIED (if hdr.type is 1503). This is not ideal.
*/
real_data_size = strlen(line);
if (hdr.type == 1500)
{
parsable_line = (char *) malloc(real_data_size + 20);
snprintf(parsable_line, real_data_size + 19, "type=APPARMOR msg=%s", line);
}
else
{
parsable_line = (char *) malloc(real_data_size + 27);
snprintf(parsable_line, real_data_size + 26, "type=APPARMOR_DENIED msg=%s", line);
}
record = parse_record(parsable_line);
message = dbus_message_new_signal("/com/Novell/AppArmor","com.novell.apparmor", "REJECT");
dbus_message_iter_init_append(message, &iter);
/*
* The message has a number of fields appended to it,
* all of which map to the aa_log_record struct that we get back from
* parse_record(). If an entry in the struct is NULL or otherwise invalid,
* the field is still appended as a single blank space (in the case of strings), or a
* 0 in case of integers (which are all PIDs and unlikely to ever be 0).
*
* TODO: Pass a bitmask int along for the denied & requested masks
*
* 1 - The full string - BYTE ARRAY
* 2 - The PID (record->pid) - DBUS_TYPE_INT64
* 3 - The task (record->task) - DBUS_TYPE_INT64
* 4 - The audit ID (record->audit_id) - DBUS_TYPE_STRING
* 5 - The operation (record->operation: "Exec" "ptrace" etc) - DBUS_TYPE_STRING
* 6 - The denied mask (record->denied_mask: "rwx" etc) - DBUS_TYPE_STRING
* 7 - The requested mask (record->requested_mask) - DBUS_TYPE_STRING
* 8 - The name of the profile (record->profile) - BYTE ARRAY
* 9 - The first name field (record->name) - BYTE ARRAY
* 10- The second name field (record->name2) - BYTE ARRAY
* 11- The attribute (record->attribute) - DBUS_TYPE_STRING
* 12- The parent task (record->parent) - BYTE ARRAY
* 13- The magic token (record->magic_token) - DBUS_TYPE_INT64
* 14- The info field (record->info) - BYTE ARRAY
* 15- The active hat (record->active_hat) - BYTE ARRAY
*/
if (record != NULL)
{
/* Please note: NULLSPACE is defined at the top of this file, and will expand to
a ternary conditional:
(record->audit_id == NULL) ? &empty_string : &record->audit_id
for example.
The way we handle strings is ugly - some of the characters we allow (0x80, for example) are invalid Unicode,
which will cause our DBus connection to be dropped if we send them as a DBUS_TYPE_STRING.
Instead, we send a bunch of containers, each with a byte array. Perhaps a struct would be better?
*/
dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE_AS_STRING, &dataIter);
dbus_message_iter_append_fixed_array(&dataIter, DBUS_TYPE_BYTE, &data, strlen(data) + 1);
dbus_message_iter_close_container(&iter, &dataIter);
dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT64, &record->pid);
dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT64, &record->task);
dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, NULLSPACE(record->audit_id));
dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, NULLSPACE(record->operation));
dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, NULLSPACE(record->denied_mask));
dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, NULLSPACE(record->requested_mask));
dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE_AS_STRING, &profileIter);
dbus_message_iter_append_fixed_array(&profileIter,
DBUS_TYPE_BYTE,
NULLSPACE(record->profile),
NULLSTRLEN(record->profile));
dbus_message_iter_close_container(&iter, &profileIter);
dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE_AS_STRING, &nameIter);
dbus_message_iter_append_fixed_array(&nameIter,
DBUS_TYPE_BYTE,
NULLSPACE(record->name),
NULLSTRLEN(record->name));
dbus_message_iter_close_container(&iter, &nameIter);
dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE_AS_STRING, &name2Iter);
dbus_message_iter_append_fixed_array(&name2Iter,
DBUS_TYPE_BYTE,
NULLSPACE(record->name2),
NULLSTRLEN(record->name2));
dbus_message_iter_close_container(&iter, &name2Iter);
dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, NULLSPACE(record->attribute));
dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE_AS_STRING, &parentIter);
dbus_message_iter_append_fixed_array(&parentIter,
DBUS_TYPE_BYTE,
NULLSPACE(record->parent),
NULLSTRLEN(record->parent));
dbus_message_iter_close_container(&iter, &parentIter);
dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT64, &record->magic_token);
dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, NULLSPACE(record->info));
dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE_AS_STRING, &activeIter);
dbus_message_iter_append_fixed_array(&activeIter,
DBUS_TYPE_BYTE,
NULLSPACE(record->active_hat),
NULLSTRLEN(record->active_hat));
dbus_message_iter_close_container(&iter, &activeIter);
}
dbus_connection_send(con, message, NULL);
dbus_connection_flush(con);
dbus_message_unref(message);
free_record(record);
if (parsable_line != NULL)
free(parsable_line);
}
}
} while(!signaled);
if (con)
dbus_connection_unref(con);
free(data);
return 0;
}

View File

@@ -0,0 +1 @@
Matt Barringer <mbarringer@suse.de>

View File

@@ -0,0 +1,340 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

View File

@@ -0,0 +1,167 @@
Basic Installation
==================
These are generic installation instructions.
The `configure' shell script attempts to guess correct values for
various system-dependent variables used during compilation. It uses
those values to create a `Makefile' in each directory of the package.
It may also create one or more `.h' files containing system-dependent
definitions. Finally, it creates a shell script `config.status' that
you can run in the future to recreate the current configuration, a file
`config.cache' that saves the results of its tests to speed up
reconfiguring, and a file `config.log' containing compiler output
(useful mainly for debugging `configure').
If you need to do unusual things to compile the package, please try
to figure out how `configure' could check whether to do them, and mail
diffs or instructions to the address given in the `README' so they can
be considered for the next release. If at some point `config.cache'
contains results you don't want to keep, you may remove or edit it.
The file `configure.in' is used to create `configure' by a program
called `autoconf'. You only need `configure.in' if you want to change
it or regenerate `configure' using a newer version of `autoconf'.
The simplest way to compile this package is:
1. `cd' to the directory containing the package's source code and type
`./configure' to configure the package for your system. If you're
using `csh' on an old version of System V, you might need to type
`sh ./configure' instead to prevent `csh' from trying to execute
`configure' itself.
Running `configure' takes a while. While running, it prints some
messages telling which features it is checking for.
2. Type `make' to compile the package.
3. Type `make install' to install the programs and any data files and
documentation.
4. You can remove the program binaries and object files from the
source code directory by typing `make clean'.
Compilers and Options
=====================
Some systems require unusual options for compilation or linking that
the `configure' script does not know about. You can give `configure'
initial values for variables by setting them in the environment. Using
a Bourne-compatible shell, you can do that on the command line like
this:
CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
Or on systems that have the `env' program, you can do it like this:
env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
Compiling For Multiple Architectures
====================================
You can compile the package for more than one kind of computer at the
same time, by placing the object files for each architecture in their
own directory. To do this, you must use a version of `make' that
supports the `VPATH' variable, such as GNU `make'. `cd' to the
directory where you want the object files and executables to go and run
the `configure' script. `configure' automatically checks for the
source code in the directory that `configure' is in and in `..'.
If you have to use a `make' that does not supports the `VPATH'
variable, you have to compile the package for one architecture at a time
in the source code directory. After you have installed the package for
one architecture, use `make distclean' before reconfiguring for another
architecture.
Installation Names
==================
By default, `make install' will install the package's files in
`/usr/local/bin', `/usr/local/man', etc. You can specify an
installation prefix other than `/usr/local' by giving `configure' the
option `--prefix=PATH'.
You can specify separate installation prefixes for
architecture-specific files and architecture-independent files. If you
give `configure' the option `--exec-prefix=PATH', the package will use
PATH as the prefix for installing programs and libraries.
Documentation and other data files will still use the regular prefix.
If the package supports it, you can cause programs to be installed
with an extra prefix or suffix on their names by giving `configure' the
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
Optional Features
=================
Some packages pay attention to `--enable-FEATURE' options to
`configure', where FEATURE indicates an optional part of the package.
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
is something like `gnu-as' or `x' (for the X Window System). The
`README' should mention any `--enable-' and `--with-' options that the
package recognizes.
For packages that use the X Window System, `configure' can usually
find the X include and library files automatically, but if it doesn't,
you can use the `configure' options `--x-includes=DIR' and
`--x-libraries=DIR' to specify their locations.
Specifying the System Type
==========================
There may be some features `configure' can not figure out
automatically, but needs to determine by the type of host the package
will run on. Usually `configure' can figure that out, but if it prints
a message saying it can not guess the host type, give it the
`--host=TYPE' option. TYPE can either be a short name for the system
type, such as `sun4', or a canonical name with three fields:
CPU-COMPANY-SYSTEM
See the file `config.sub' for the possible values of each field. If
`config.sub' isn't included in this package, then this package doesn't
need to know the host type.
If you are building compiler tools for cross-compiling, you can also
use the `--target=TYPE' option to select the type of system they will
produce code for and the `--build=TYPE' option to select the type of
system on which you are compiling the package.
Sharing Defaults
================
If you want to set default values for `configure' scripts to share,
you can create a site shell script called `config.site' that gives
default values for variables like `CC', `cache_file', and `prefix'.
`configure' looks for `PREFIX/share/config.site' if it exists, then
`PREFIX/etc/config.site' if it exists. Or, you can set the
`CONFIG_SITE' environment variable to the location of the site script.
A warning: not all `configure' scripts look for a site script.
Operation Controls
==================
`configure' recognizes the following options to control how it
operates.
`--cache-file=FILE'
Use and save the results of the tests in FILE instead of
`./config.cache'. Set FILE to `/dev/null' to disable caching, for
debugging `configure'.
`--help'
Print a summary of the options to `configure', and exit.
`--quiet'
`--silent'
`-q'
Do not print messages saying which checks are being made.
`--srcdir=DIR'
Look for the package's source code in directory DIR. Usually
`configure' can determine that directory automatically.
`--version'
Print the version of Autoconf used to generate the `configure'
script, and exit.
`configure' also accepts some other, not widely useful, options.

View File

@@ -0,0 +1,2 @@
SUBDIRS = src doc

View File

@@ -0,0 +1,5 @@
default: all
all:
srcdir=`pwd` sh macros/autogen.sh

View File

@@ -0,0 +1,6 @@
The profile editor requires wxWidgets 2.6 or higher. Your distro probably has a
binary package you could install, or you can install from a source distribution
from http://www.wxwidgets.org
This program is released under the GPL, except for all source files under
the src/wxStyledTextCtrl directory. Check there for license details for those files.

View File

@@ -0,0 +1,55 @@
AC_INIT(src/profileeditor.cpp)
AM_INIT_AUTOMAKE(profileeditor, 0.9)
AC_PROG_CXX
AC_PROG_INSTALL
AC_LIBTOOL_DLOPEN
AC_PROG_LIBTOOL
CPPFLAGS="$CPPFLAGS -Wall -g -fexceptions"
CXXFLAGS="$CPPFLAGS -Wall -g -fexceptions"
WXCONFIG=wx-config
AC_ARG_WITH(wx-config,
[[ --with-wx-config=FILE Use the given path to wx-config when determining
wxWidgets configuration; defaults to "wx-config"]],
[
if test "$withval" != "yes" -a "$withval" != ""; then
WXCONFIG=$withval
fi
])
wxversion=0
AC_DEFUN([WXTEST],
[
AC_REQUIRE([AC_PROG_AWK])
AC_MSG_CHECKING([wxWidgets version])
if wxversion=`$WXCONFIG --version`; then
AC_MSG_RESULT([$wxversion])
else
AC_MSG_RESULT([not found])
AC_MSG_ERROR([wxWidgets is required. Try --with-wx-config.])
fi])
# Call WXTEST func
WXTEST
# Verify minimus requires
vers=`echo $wxversion | $AWK 'BEGIN { FS = "."; } { printf "% d", ($1 * 1000 + $2) * 1000 + $3;}'`
if test -n "$vers" && test "$vers" -ge 2006000; then
WX_CPPFLAGS="`$WXCONFIG --cppflags`"
WX_CXXFLAGS="`$WXCONFIG --cxxflags | sed -e 's/-fno-exceptions//'`"
WX_LIBS="`$WXCONFIG --libs`"
else
AC_MSG_ERROR([wxWidgets 2.6.0 or newer is required])
fi
CPPFLAGS="$CPPFLAGS $WX_CPPFLAGS"
CXXFLAGS="$CXXFLAGS $WX_CPPFLAGS"
AC_SUBST(WX_LIBS)
AC_OUTPUT(Makefile src/Makefile src/wxStyledTextCtrl/Makefile doc/Makefile)

View File

@@ -0,0 +1,4 @@
docdir = $(datadir)/doc/@PACKAGE@
doc_DATA = \
en/AppArmorProfileEditor.htb

View File

@@ -0,0 +1,342 @@
# Makefile.in generated by automake 1.9.6 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
# 2003, 2004, 2005 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = ..
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
INSTALL = @INSTALL@
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
subdir = doc
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/configure.in
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
CONFIG_CLEAN_FILES =
SOURCES =
DIST_SOURCES =
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
am__vpath_adj = case $$p in \
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
*) f=$$p;; \
esac;
am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
am__installdirs = "$(DESTDIR)$(docdir)"
docDATA_INSTALL = $(INSTALL_DATA)
DATA = $(doc_DATA)
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AMDEP_FALSE = @AMDEP_FALSE@
AMDEP_TRUE = @AMDEP_TRUE@
AMTAR = @AMTAR@
AR = @AR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CXX = @CXX@
CXXCPP = @CXXCPP@
CXXDEPMODE = @CXXDEPMODE@
CXXFLAGS = @CXXFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
ECHO = @ECHO@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
F77 = @F77@
FFLAGS = @FFLAGS@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
MAKEINFO = @MAKEINFO@
OBJEXT = @OBJEXT@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
RANLIB = @RANLIB@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
VERSION = @VERSION@
WX_LIBS = @WX_LIBS@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_CXX = @ac_ct_CXX@
ac_ct_F77 = @ac_ct_F77@
ac_ct_RANLIB = @ac_ct_RANLIB@
ac_ct_STRIP = @ac_ct_STRIP@
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
datadir = @datadir@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
prefix = @prefix@
program_transform_name = @program_transform_name@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
docdir = $(datadir)/doc/@PACKAGE@
doc_DATA = \
en/AppArmorProfileEditor.htb
all: all-am
.SUFFIXES:
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
&& exit 0; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu doc/Makefile'; \
cd $(top_srcdir) && \
$(AUTOMAKE) --gnu doc/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(top_srcdir)/configure: $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
distclean-libtool:
-rm -f libtool
uninstall-info-am:
install-docDATA: $(doc_DATA)
@$(NORMAL_INSTALL)
test -z "$(docdir)" || $(mkdir_p) "$(DESTDIR)$(docdir)"
@list='$(doc_DATA)'; for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
f=$(am__strip_dir) \
echo " $(docDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(docdir)/$$f'"; \
$(docDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(docdir)/$$f"; \
done
uninstall-docDATA:
@$(NORMAL_UNINSTALL)
@list='$(doc_DATA)'; for p in $$list; do \
f=$(am__strip_dir) \
echo " rm -f '$(DESTDIR)$(docdir)/$$f'"; \
rm -f "$(DESTDIR)$(docdir)/$$f"; \
done
tags: TAGS
TAGS:
ctags: CTAGS
CTAGS:
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
list='$(DISTFILES)'; for file in $$list; do \
case $$file in \
$(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
$(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
esac; \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
if test "$$dir" != "$$file" && test "$$dir" != "."; then \
dir="/$$dir"; \
$(mkdir_p) "$(distdir)$$dir"; \
else \
dir=''; \
fi; \
if test -d $$d/$$file; then \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
fi; \
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
else \
test -f $(distdir)/$$file \
|| cp -p $$d/$$file $(distdir)/$$file \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
all-am: Makefile $(DATA)
installdirs:
for dir in "$(DESTDIR)$(docdir)"; do \
test -z "$$dir" || $(mkdir_p) "$$dir"; \
done
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-generic clean-libtool mostlyclean-am
distclean: distclean-am
-rm -f Makefile
distclean-am: clean-am distclean-generic distclean-libtool
dvi: dvi-am
dvi-am:
html: html-am
info: info-am
info-am:
install-data-am: install-docDATA
install-exec-am:
install-info: install-info-am
install-man:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-generic mostlyclean-libtool
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am: uninstall-docDATA uninstall-info-am
.PHONY: all all-am check check-am clean clean-generic clean-libtool \
distclean distclean-generic distclean-libtool distdir dvi \
dvi-am html html-am info info-am install install-am \
install-data install-data-am install-docDATA install-exec \
install-exec-am install-info install-info-am install-man \
install-strip installcheck installcheck-am installdirs \
maintainer-clean maintainer-clean-generic mostlyclean \
mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
uninstall uninstall-am uninstall-docDATA uninstall-info-am
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

View File

@@ -0,0 +1,2 @@
KDE_DOCS = profileeditor
KDE_LANG = en

View File

@@ -0,0 +1,6 @@
#!/bin/sh
aclocal
libtoolize --automake --force --copy
automake -a -c
autoconf

View File

@@ -0,0 +1,44 @@
# norootforbuild
Name: apparmor-profile-editor
BuildRequires: wxGTK-devel gcc-c++
Version: 0.9
Release: 1
Vendor: Novell
Copyright: GPL
Summary: AppArmor profile editor
Group: Application/Editors
Packager: mbarringer@suse.de
BuildRoot: %{_tmppath}/%{name}-root
Source: apparmor-profile-editor-0.9.tar.gz
%description
AppArmor profile editor
%prep
%setup -q -n %{name}-%{version}
%build
autoreconf --force --install
export CFLAGS="$RPM_OPT_FLAGS -DSCI_LEXER -DLINK_LEXERS -fPIC -DPIC -DWX_PRECOMP -DNO_GCC_PRAGMA -D__WX"
export CXXFLAGS="$RPM_OPT_FLAGS -DSCI_LEXER -DLINK_LEXERS -fPIC -DPIC -DWX_PRECOMP -DNO_GCC_PRAGMA -D__WX"
%{?suse_update_config:%{suse_update_config -f}}
./configure --prefix=%{_prefix} --disable-debug --enable-debug=no
make
%install
strip $RPM_BUILD_ROOT%{_prefix}/bin/* || :
rm -rf %{buildroot}
%makeinstall
%clean
rm -rf %{buildroot}
%post -p /sbin/ldconfig
%postun -p /sbin/ldconfig
%files
%defattr(-, root, root)
%{_prefix}/bin/profileeditor
%{_prefix}/share/doc/profileeditor/AppArmorProfileEditor.htb
%dir %{_prefix}/share/doc/profileeditor
%doc AUTHORS COPYING ChangeLog NEWS README TODO
%changelog

View File

@@ -0,0 +1,114 @@
/* AppArmor Profile Editor (C) 2006 Novell, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
*/
#include "wx/wxprec.h"
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
#include <wx/wfstream.h>
#include "AboutDialog.h"
#include "opensuse_logo.xpm"
IMPLEMENT_DYNAMIC_CLASS(AboutDialog, wxDialog)
BEGIN_EVENT_TABLE(AboutDialog, wxDialog)
END_EVENT_TABLE()
AboutDialog::AboutDialog()
{
}
AboutDialog::AboutDialog(wxWindow* parent,
wxWindowID id,
const wxString& caption,
const wxPoint& pos,
const wxSize& size,
long style)
{
Create(parent, id, caption, pos, size, style);
}
bool AboutDialog::Create(wxWindow* parent,
wxWindowID id,
const wxString& caption,
const wxPoint& pos,
const wxSize& size,
long style)
{
mpLogoBitmap = NULL;
mpVersionStaticText = NULL;
mpCopyrightStaticText = NULL;
mpOkButtonSizer = NULL;
mpOkButton = NULL;
SetExtraStyle(GetExtraStyle() | wxWS_EX_BLOCK_EVENTS);
wxDialog::Create(parent, id, caption, pos, size, style);
CreateControls();
GetSizer()->Fit(this);
GetSizer()->SetSizeHints(this);
Centre();
return true;
}
void AboutDialog::CreateControls()
{
SetBackgroundColour(wxColour(255, 255, 255));
wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);
SetSizer(mainSizer);
wxBitmap mpLogoBitmapBitmap(opensuse_logo_xpm);
mpLogoBitmap = new wxStaticBitmap(this,
wxID_ANY,
mpLogoBitmapBitmap,
wxDefaultPosition,
wxSize(223, 137),
0);
mainSizer->Add(mpLogoBitmap, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5);
mpVersionStaticText = new wxStaticText(this,
wxID_ANY,
VERSION_STRING,
wxDefaultPosition,
wxDefaultSize,
0);
mainSizer->Add(mpVersionStaticText, 0, wxALIGN_CENTER_HORIZONTAL|wxALL|wxADJUST_MINSIZE, 5);
mpCopyrightStaticText = new wxStaticText(this,
wxID_ANY,
_("(C) 2006 Novell, Inc\n"),
wxDefaultPosition,
wxDefaultSize,
0);
mainSizer->Add(mpCopyrightStaticText, 0, wxALIGN_CENTER_HORIZONTAL|wxALL|wxADJUST_MINSIZE, 5);
mpLicenseTextCtrl = new wxTextCtrl(this,
wxID_ANY,
_T(""),
wxDefaultPosition,
wxSize(400, -1),
wxTE_MULTILINE|wxTE_READONLY);
mpLicenseTextCtrl->SetValue(GPL_STRING);
mainSizer->Add(mpLicenseTextCtrl, 0, wxGROW|wxALL, 5);
mpOkButtonSizer = new wxStdDialogButtonSizer;
mainSizer->Add(mpOkButtonSizer, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5);
mpOkButton = new wxButton(this,
wxID_OK,
_("&OK"),
wxDefaultPosition,
wxDefaultSize,
0);
mpOkButtonSizer->AddButton(mpOkButton);
mpOkButtonSizer->Realize();
}

View File

@@ -0,0 +1,56 @@
#ifndef _ABOUTDIALOG_H_
#define _ABOUTDIALOG_H_
#define VERSION_STRING _("AppArmor Profile Editor version 0.9")
#define GPL_STRING _(" \
Portions of this software (C) 1998-2003 by Neil Hodgson <neilh@scintilla.org>\n\n \
This rest of this program is free software; you can redistribute it and/or modify \
it under the terms of the GNU General Public License as published by \
the Free Software Foundation; either version 2 of the License, or \
(at your option) any later version. \
\n\n \
This program is distributed in the hope that it will be useful, \
but WITHOUT ANY WARRANTY; without even the implied warranty of \
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the \
GNU General Public License for more details. \
\n\n \
You should have received a copy of the GNU General Public License \
along with this program; if not, write to the Free Software \
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA \
")
/**
* The "About" dialog
*/
class AboutDialog: public wxDialog
{
DECLARE_DYNAMIC_CLASS(AboutDialog)
DECLARE_EVENT_TABLE()
public:
AboutDialog();
AboutDialog(wxWindow* parent,
wxWindowID id = wxID_ANY,
const wxString& caption = _T("About"),
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxSize(400, 300),
long style = wxCAPTION|wxRESIZE_BORDER|wxSYSTEM_MENU|wxCLOSE_BOX);
bool Create(wxWindow* parent,
wxWindowID id = wxID_ANY,
const wxString& caption = _T("About"),
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxSize(400, 300),
long style = wxCAPTION|wxRESIZE_BORDER|wxSYSTEM_MENU|wxCLOSE_BOX);
void CreateControls();
private:
wxStaticBitmap* mpLogoBitmap;
wxStaticText* mpVersionStaticText;
wxStaticText* mpCopyrightStaticText;
wxStdDialogButtonSizer* mpOkButtonSizer;
wxTextCtrl* mpLicenseTextCtrl;
wxButton* mpOkButton;
};
#endif
// _ABOUTDIALOG_H_

View File

@@ -0,0 +1,185 @@
/* AppArmor Profile Editor (C) 2006 Novell, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
*/
#include "wx/wxprec.h"
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
#include <wx/config.h>
#include "Configuration.h"
// Initialize all of the static variables
wxString Configuration::mProfileDirectory = wxEmptyString;
wxString Configuration::mProfileEditorExecutable = wxEmptyString;
wxString Configuration::mParserCommand = wxEmptyString;
wxString Configuration::mTemplateText = wxEmptyString;
wxColour Configuration::mCommentColour = wxColour(DEFAULT_COMMENT_COLOUR);
wxColour Configuration::mIncludeColour = wxColour(DEFAULT_INCLUDE_COLOUR);
wxColour Configuration::mCapColour = wxColour(DEFAULT_CAP_COLOUR);
wxColour Configuration::mPathColour = wxColour(DEFAULT_PATH_COLOUR);
wxColour Configuration::mPermColour = wxColour(DEFAULT_PERM_COLOUR);
wxFont Configuration::mCapabilityFont(10, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
wxFont Configuration::mCommentFont(10, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_ITALIC, wxFONTWEIGHT_NORMAL);
wxFont Configuration::mIncludeFont(10, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
wxFont Configuration::mPathFont(10, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD);
wxFont Configuration::mPermsFont(10, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL,wxFONTWEIGHT_NORMAL);
int Configuration::mWindowX;
int Configuration::mWindowY;
int Configuration::mWindowHeight;
int Configuration::mWindowWidth;
/**
* Reads in the initial variables
*/
void Configuration::Initialize()
{
// Read in all of the values
mProfileEditorExecutable = wxTheApp->argv[0];
mWindowX = wxConfig::Get()->Read(_("WindowX"), 50);
mWindowY = wxConfig::Get()->Read(_("WindowY"), 50);
mWindowWidth = wxConfig::Get()->Read(_("WindowWidth"), 800);
mWindowHeight = wxConfig::Get()->Read(_("WindowHeight"), 600);
mProfileDirectory = wxConfig::Get()->Read(_("ProfileDirectory"), Configuration::BestGuessProfileDirectory());
mParserCommand = wxConfig::Get()->Read(_("Parser"), BestGuessParserCommand());
mTemplateText = wxConfig::Get()->Read(_("ProfileTemplate"), wxEmptyString);
mCommentColour = _ReadColour(_("CommentColour"), mCommentColour);
mIncludeColour = _ReadColour(_("IncludeColour"), mIncludeColour);
mCapColour = _ReadColour(_("CapabilityColour"), mCapColour);
mPathColour = _ReadColour(_("PathColour"), mPathColour);
mPermColour = _ReadColour(_("PermissionColour"), mPermColour);
_ReadFont(_("CommentFont"), mCommentFont);
_ReadFont(_("IncludeFont"), mIncludeFont);
_ReadFont(_("CapabilityFont"), mCapabilityFont);
_ReadFont(_("PathFont"), mPathFont);
_ReadFont(_("PermsFont"), mPermsFont);
}
/**
* Profiles are most likely stored in either /etc/subdomain.d or
* /etc/apparmor.d. Stat each to see which.
* @param void
* @return profile directory
*/
wxString Configuration::BestGuessProfileDirectory(void)
{
if (wxDirExists(_("/etc/apparmor.d")))
return (_("/etc/apparmor.d"));
else if (wxDirExists(_("/etc/subdomain.d")))
return (_("/etc/subdomain.d"));
else
return (_("/"));
}
/**
* The parser is probably apparmor_parser or
* subdomain_parser. If it's neither, the user
* will need to set it manually, so return /bin/false
* @return the path to the parser
*/
wxString Configuration::BestGuessParserCommand()
{
if (wxFileExists(_("/sbin/apparmor_parser")))
return _("/sbin/apparmor_parser");
else if (wxFileExists(_("/sbin/subdomain_parser")))
return _("/sbin/subdomain_parser");
else
return _("/bin/false");
}
/**
* Writes all of the values to disk
* @return only true for now
*/
bool Configuration::CommitChanges()
{
wxConfig::Get()->Write(_("ProfileDirectory"), mProfileDirectory);
wxConfig::Get()->Write(_("Parser"), mParserCommand);
wxConfig::Get()->Write(_("ProfileTemplate"), mTemplateText);
_WriteColour(_("CommentColour"), mCommentColour);
_WriteColour(_("IncludeColour"), mIncludeColour);
_WriteColour(_("CapabilityColour"), mCapColour);
_WriteColour(_("PathColour"), mPathColour);
_WriteColour(_("PermissionColour"), mPermColour);
wxConfig::Get()->Write(_("CommentFont"), mCommentFont.GetNativeFontInfoDesc());
wxConfig::Get()->Write(_("IncludeFont"), mIncludeFont.GetNativeFontInfoDesc());
wxConfig::Get()->Write(_("CapabilityFont"), mCapabilityFont.GetNativeFontInfoDesc());
wxConfig::Get()->Write(_("PathFont"), mPathFont.GetNativeFontInfoDesc());
wxConfig::Get()->Write(_("PermsFont"), mPermsFont.GetNativeFontInfoDesc());
wxConfig::Get()->Flush();
return true;
}
/**
* Writes the given window settings to the configuration file.
* This is kept separately from CommitChanges() because:
* a) There's no reason to re-write all configuration changes on exit and
* b) There's no reason to update the window position and size on every OnSize() event
*/
void Configuration::WriteWindowSettings(const wxPoint &pos, const wxSize& size)
{
wxConfig::Get()->Write(_("WindowX"), pos.x);
wxConfig::Get()->Write(_("WindowY"), pos.y);
wxConfig::Get()->Write(_("WindowWidth"), size.GetWidth());
wxConfig::Get()->Write(_("WindowHeight"), size.GetHeight());
wxConfig::Get()->Flush();
}
/**
* Reads a colour setting from the config file and translates it into
* a wxColour. If it can't convert the stored value, or the stored value
* does not exist, it will return whatever is passed as defaultColour.
* @param key the configuration key
* @param defaultColour a colour to return
* @return a colour
*/
wxColour Configuration::_ReadColour(const wxString& key, const wxColour& defaultColour)
{
wxColour ret;
wxString tmpStr = wxConfig::Get()->Read(key, wxEmptyString);
if (tmpStr.Length() == 6)
{
ret.Set(wxHexToDec(tmpStr.Mid(0,2)), // Red
wxHexToDec(tmpStr.Mid(2,2)), // Green
wxHexToDec(tmpStr.Mid(4,2)) // Blue
);
}
if (ret.Ok())
return ret;
else
return defaultColour;
}
/**
* Reads a font from the configuration file, and sets it as the 'font'
* @param key configuration key
* @param font the font to set
*/
void Configuration::_ReadFont(const wxString& key, wxFont& font)
{
wxString tmpStr;
if (wxConfig::Get()->Read(key, &tmpStr))
font.SetNativeFontInfo(tmpStr);
}
/**
* Takes a wxColour and converts it to a hex string for writing to disk.
* @param key configuration key
* @param colour the colour to convert
*/
void Configuration::_WriteColour(const wxString& key, const wxColour& colour)
{
wxConfig::Get()->Write(key, wxString::Format(_T("%02x%02x%02x"),
colour.Red(),
colour.Green(),
colour.Blue()));
}

View File

@@ -0,0 +1,84 @@
#ifndef CONFIGURATION_H
#define CONFIGURATION_H
#define DEFAULT_COMMENT_COLOUR 31, 31, 210
#define DEFAULT_INCLUDE_COLOUR 56, 136, 31
#define DEFAULT_CAP_COLOUR 229, 33, 204
#define DEFAULT_PATH_COLOUR 1, 1, 1
#define DEFAULT_PERM_COLOUR 160, 32, 240
class wxConfig;
/**
* The configuration details class
*/
class Configuration
{
public:
static void Initialize();
static wxString BestGuessProfileDirectory();
static wxString BestGuessParserCommand();
static bool CommitChanges();
static wxString GetProfileDirectory() { return mProfileDirectory; }
static wxString GetEditorExecutable() { return mProfileEditorExecutable; }
static wxString GetTemplateText() { return mTemplateText; }
static wxString GetParserCommand() { return mParserCommand; }
static wxColour GetCommentColour() { return mCommentColour; }
static wxColour GetIncludeColour() { return mIncludeColour; }
static wxColour GetCapColour() { return mCapColour; }
static wxColour GetPathColour() { return mPathColour; }
static wxColour GetPermColour() { return mPermColour; }
static wxFont GetCapabilityFont() { return mCapabilityFont; }
static wxFont GetCommentFont() { return mCommentFont; }
static wxFont GetIncludeFont() { return mIncludeFont; }
static wxFont GetPathFont() { return mPathFont; }
static wxFont GetPermFont() { return mPermsFont; }
static wxSize GetWindowSize() { return wxSize(mWindowWidth, mWindowHeight); }
static wxPoint GetWindowPos() { return wxPoint(mWindowX, mWindowY); }
static void WriteWindowSettings(const wxPoint &pos, const wxSize& size);
static void SetProfileDirectory(const wxString& profileDirectory)
{ mProfileDirectory = profileDirectory; }
static void SetEditorExecutable(const wxString& executable) { mProfileEditorExecutable = executable; }
static void SetParserCommand(const wxString& parserCommand) { mParserCommand = parserCommand; }
static void SetTemplateText(const wxString& templateText) { mTemplateText = templateText; }
static void SetCommentColour(const wxColour& commentColour) { mCommentColour = commentColour; }
static void SetIncludeColour(const wxColour& includeColour) { mIncludeColour = includeColour; }
static void SetCapColour(const wxColour& capColour) { mCapColour = capColour; }
static void SetPathColour(const wxColour& pathColour) { mPathColour = pathColour; }
static void SetPermColour(const wxColour& permColour) { mPermColour = permColour; }
static void SetCapabilityFont(const wxFont& capabilityFont) { mCapabilityFont = capabilityFont; }
static void SetCommentFont(const wxFont& commentFont) { mCommentFont = commentFont; }
static void SetIncludeFont(const wxFont& includeFont) { mIncludeFont = includeFont; }
static void SetPathFont(const wxFont& pathFont) { mPathFont = pathFont; }
static void SetPermFont(const wxFont& permsFont) { mPermsFont = permsFont; }
private:
static void _WriteColour(const wxString& key, const wxColour& colour);
static wxColour _ReadColour(const wxString& key, const wxColour& defaultColour);
static void _ReadFont(const wxString& key, wxFont& font);
static wxString mProfileDirectory;
static wxString mProfileEditorExecutable;
static wxString mParserCommand;
static wxString mTemplateText;
static wxColour mCommentColour;
static wxColour mIncludeColour;
static wxColour mCapColour;
static wxColour mPathColour;
static wxColour mPermColour;
static wxFont mCapabilityFont;
static wxFont mCommentFont;
static wxFont mIncludeFont;
static wxFont mPathFont;
static wxFont mPermsFont;
static int mWindowX; // These are just the settings from the
static int mWindowY; // config file, they are *NOT* updated
static int mWindowWidth; // in any size events
static int mWindowHeight;
};
#endif

View File

@@ -0,0 +1,24 @@
# these are the headers for your project
noinst_HEADERS = ProfileDirectoryTraverser.h ProfileTextCtrl.h Preferences.h \
AboutDialog.h opensuse_logo.xpm SearchAllProfiles.h Configuration.h
#########################################################################
# APPLICATION SECTION
#########################################################################
# this is the program that gets installed. it's name is used for all
# of the other Makefile.am variables
bin_PROGRAMS = profileeditor
# the application source, library search path, and link libraries
profileeditor_SOURCES = ProfileTextCtrl.cpp Preferences.cpp AboutDialog.cpp \
SearchAllProfiles.cpp Configuration.cpp profileeditor.cpp
profileeditor_LDFLAGS = $(WX_LIBS)
SUBDIRS = wxStyledTextCtrl
profileeditor_LDADD =\
$(top_builddir)/src/wxStyledTextCtrl/libAppArmorStyledTextCtrl.a
AM_CXXFLAGS = \
-DHELP_FILE_LOCATION=\"$(datadir)/doc/@PACKAGE@/AppArmorProfileEditor.htb\"

View File

@@ -0,0 +1,322 @@
/* AppArmor Profile Editor (C) 2006 Novell, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
*/
#include "wx/wxprec.h"
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
#include <wx/propdlg.h>
#include <wx/config.h>
#include <wx/colordlg.h>
#include <wx/fontdlg.h>
#include "Configuration.h"
#include "ProfileTextCtrl.h"
#include "Preferences.h"
IMPLEMENT_DYNAMIC_CLASS(PreferencesDialog, wxDialog)
BEGIN_EVENT_TABLE(PreferencesDialog, wxDialog)
EVT_BUTTON(ID_COMMENT_COLOUR_BUTTON, PreferencesDialog::OnColourButton)
EVT_BUTTON(ID_INCLUDES_COLOUR_BUTTON, PreferencesDialog::OnColourButton)
EVT_BUTTON(ID_PERMS_COLOUR_BUTTON, PreferencesDialog::OnColourButton)
EVT_BUTTON(ID_CAPABILITIES_COLOUR_BUTTON, PreferencesDialog::OnColourButton)
EVT_BUTTON(ID_PATHS_COLOUR_BUTTON, PreferencesDialog::OnColourButton)
EVT_BUTTON(ID_COMMENT_FONT_BUTTON, PreferencesDialog::OnFontButton)
EVT_BUTTON(ID_INCLUDES_FONT_BUTTON, PreferencesDialog::OnFontButton)
EVT_BUTTON(ID_CAPABILITIES_FONT_BUTTON, PreferencesDialog::OnFontButton)
EVT_BUTTON(ID_PATHS_FONT_BUTTON, PreferencesDialog::OnFontButton)
EVT_BUTTON(ID_PERMS_FONT_BUTTON, PreferencesDialog::OnFontButton)
END_EVENT_TABLE()
PreferencesDialog::PreferencesDialog( )
{
}
PreferencesDialog::PreferencesDialog(wxWindow* parent,
wxWindowID id,
const wxString& caption,
const wxPoint& pos,
const wxSize& size,
long style)
{
Create(parent, id, caption, pos, size, style);
}
bool PreferencesDialog::Create(wxWindow* parent,
wxWindowID id,
const wxString& caption,
const wxPoint& pos,
const wxSize& size,
long style)
{
mpPrefsNotebook = NULL;
mpProfileDir = NULL;
mpParserCommand = NULL;
mpTemplateTextCtrl = NULL;
mpCommentsButton = NULL;
mpIncludesButton = NULL;
mpPermsButton = NULL;
mpCapabilitiesButton = NULL;
mpPathsButton = NULL;
mpCommentsFontButton = NULL;
mpIncludesFontButton = NULL;
mpCapabilitiesFontButton = NULL;
mpPathsFontButton = NULL;
SetExtraStyle(GetExtraStyle()|wxWS_EX_BLOCK_EVENTS);
wxDialog::Create( parent, id, caption, pos, size, style );
CreateControls();
GetSizer()->Fit(this);
GetSizer()->SetSizeHints(this);
Centre();
return true;
}
void PreferencesDialog::CreateControls()
{
wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);
SetSizer(mainSizer);
mpPrefsNotebook = new wxNotebook(this, ID_PREFERENCES_NOTEBOOK, wxDefaultPosition, wxDefaultSize, wxNB_TOP );
// The paths pane
wxPanel* pathsPanel = new wxPanel( mpPrefsNotebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER|wxTAB_TRAVERSAL );
wxGridSizer* prefsGridSizer = new wxGridSizer(2, 2, 0, 0);
pathsPanel->SetSizer(prefsGridSizer);
wxStaticText* profileDirectoryText = new wxStaticText( pathsPanel, wxID_ANY, _("Profile Directory:"), wxDefaultPosition, wxDefaultSize, 0 );
prefsGridSizer->Add(profileDirectoryText, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE, 5);
mpProfileDir = new wxTextCtrl( pathsPanel, wxID_ANY, Configuration::GetProfileDirectory(), wxDefaultPosition, wxSize(200, -1), 0 );
prefsGridSizer->Add(mpProfileDir, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5);
wxStaticText* parserCommandText = new wxStaticText( pathsPanel, wxID_ANY, _("Path to apparmor_parser:"), wxDefaultPosition, wxDefaultSize, 0 );
prefsGridSizer->Add(parserCommandText, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE, 5);
mpParserCommand = new wxTextCtrl( pathsPanel, wxID_ANY, Configuration::GetParserCommand(), wxDefaultPosition, wxSize(200, -1), 0 );
prefsGridSizer->Add(mpParserCommand, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5);
mpPrefsNotebook->AddPage(pathsPanel, _("Paths"));
// The colours pane //
wxPanel* coloursPanel = new wxPanel( mpPrefsNotebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER|wxTAB_TRAVERSAL );
wxBoxSizer* colorFontBoxSizer = new wxBoxSizer(wxHORIZONTAL);
coloursPanel->SetSizer(colorFontBoxSizer);
wxStaticBox* colourBoxSizer = new wxStaticBox(coloursPanel, wxID_ANY, _("Colours"));
wxStaticBoxSizer* colourStaticBoxSizer = new wxStaticBoxSizer(colourBoxSizer, wxVERTICAL);
colorFontBoxSizer->Add(colourStaticBoxSizer, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
wxGridSizer* colourSubSizer = new wxGridSizer(4, 2, 0, 0);
colourStaticBoxSizer->Add(colourSubSizer, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5);
wxStaticText* commentsText = new wxStaticText( coloursPanel, wxID_STATIC, _("Comments"), wxDefaultPosition, wxDefaultSize, 0 );
colourSubSizer->Add(commentsText, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE, 5);
mpCommentsButton = new wxButton( coloursPanel, ID_COMMENT_COLOUR_BUTTON, _T(""), wxDefaultPosition, wxDefaultSize, 0 );
mpCommentsButton->SetBackgroundColour(Configuration::GetCommentColour());
colourSubSizer->Add(mpCommentsButton, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5);
wxStaticText* includesText = new wxStaticText( coloursPanel, wxID_STATIC, _("Includes"), wxDefaultPosition, wxDefaultSize, 0 );
colourSubSizer->Add(includesText, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE, 5);
mpIncludesButton = new wxButton( coloursPanel, ID_INCLUDES_COLOUR_BUTTON, _T(""), wxDefaultPosition, wxDefaultSize, 0 );
colourSubSizer->Add(mpIncludesButton, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5);
mpIncludesButton->SetBackgroundColour(Configuration::GetIncludeColour());
wxStaticText* capabilitiesText = new wxStaticText( coloursPanel, wxID_STATIC, _("Capabilities"), wxDefaultPosition, wxDefaultSize, 0 );
colourSubSizer->Add(capabilitiesText, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE, 5);
mpCapabilitiesButton = new wxButton( coloursPanel, ID_CAPABILITIES_COLOUR_BUTTON, _T(""), wxDefaultPosition, wxDefaultSize, 0 );
colourSubSizer->Add(mpCapabilitiesButton, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5);
mpCapabilitiesButton->SetBackgroundColour(Configuration::GetCapColour());
wxStaticText* pathsText = new wxStaticText( coloursPanel, wxID_STATIC, _("Paths"), wxDefaultPosition, wxDefaultSize, 0 );
colourSubSizer->Add(pathsText, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE, 5);
mpPathsButton = new wxButton( coloursPanel, ID_PATHS_COLOUR_BUTTON, _T(""), wxDefaultPosition, wxDefaultSize, 0 );
mpPathsButton->SetBackgroundColour(Configuration::GetPathColour());
colourSubSizer->Add(mpPathsButton, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5);
wxStaticText* permsText = new wxStaticText( coloursPanel, wxID_STATIC, _("Permissions"), wxDefaultPosition, wxDefaultSize, 0 );
colourSubSizer->Add(permsText, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE, 5);
mpPermsButton = new wxButton( coloursPanel, ID_PERMS_COLOUR_BUTTON, _T(""), wxDefaultPosition, wxDefaultSize, 0 );
mpPermsButton->SetBackgroundColour(Configuration::GetPermColour());
colourSubSizer->Add(mpPermsButton, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5);
// Fonts pane //
wxStaticBox* fontSubSizer = new wxStaticBox(coloursPanel, wxID_ANY, _("Fonts"));
wxStaticBoxSizer* fontBoxSizer = new wxStaticBoxSizer(fontSubSizer, wxVERTICAL);
colorFontBoxSizer->Add(fontBoxSizer, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
wxGridSizer* fontsGridSizer = new wxGridSizer(4, 2, 0, 0);
fontBoxSizer->Add(fontsGridSizer, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5);
wxStaticText* commentFontText = new wxStaticText( coloursPanel, wxID_STATIC, _("Comments"), wxDefaultPosition, wxDefaultSize, 0 );
fontsGridSizer->Add(commentFontText, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE, 5);
mpCommentsFontButton = new wxButton( coloursPanel, ID_COMMENT_FONT_BUTTON, _("ABCdef"), wxDefaultPosition, wxDefaultSize, 0 );
mpCommentsFontButton->SetFont(Configuration::GetCommentFont());
fontsGridSizer->Add(mpCommentsFontButton, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5);
wxStaticText* includesFontText = new wxStaticText( coloursPanel, wxID_STATIC, _("Includes"), wxDefaultPosition, wxDefaultSize, 0 );
fontsGridSizer->Add(includesFontText, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE, 5);
mpIncludesFontButton = new wxButton( coloursPanel, ID_INCLUDES_FONT_BUTTON, _("ABCdef"), wxDefaultPosition, wxDefaultSize, 0 );
mpIncludesFontButton->SetFont(Configuration::GetIncludeFont());
fontsGridSizer->Add(mpIncludesFontButton, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5);
wxStaticText* capabilitiesFontText = new wxStaticText( coloursPanel, wxID_STATIC, _("Capabilities"), wxDefaultPosition, wxDefaultSize, 0 );
fontsGridSizer->Add(capabilitiesFontText, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE, 5);
mpCapabilitiesFontButton = new wxButton( coloursPanel, ID_CAPABILITIES_FONT_BUTTON, _("ABCdef"), wxDefaultPosition, wxDefaultSize, 0 );
mpCapabilitiesFontButton->SetFont(Configuration::GetCapabilityFont());
fontsGridSizer->Add(mpCapabilitiesFontButton, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5);
wxStaticText* pathsFontText = new wxStaticText( coloursPanel, wxID_STATIC, _("Paths"), wxDefaultPosition, wxDefaultSize, 0 );
fontsGridSizer->Add(pathsFontText, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE, 5);
mpPathsFontButton = new wxButton( coloursPanel, ID_PATHS_FONT_BUTTON, _("ABCdef"), wxDefaultPosition, wxDefaultSize, 0 );
mpPathsFontButton->SetFont(Configuration::GetPathFont());
fontsGridSizer->Add(mpPathsFontButton, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5);
wxStaticText* permsFontText = new wxStaticText( coloursPanel, wxID_STATIC, _("Permissions"), wxDefaultPosition, wxDefaultSize, 0 );
fontsGridSizer->Add(permsFontText, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE, 5);
mpPermsFontButton = new wxButton( coloursPanel, ID_PERMS_FONT_BUTTON, _("ABCdef"), wxDefaultPosition, wxDefaultSize, 0 );
mpPermsFontButton->SetFont(Configuration::GetPermFont());
fontsGridSizer->Add(mpPermsFontButton, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5);
mpPrefsNotebook->AddPage(coloursPanel, _("Colours & Fonts"));
// Templates pane //
mpTemplateTextCtrl = new ProfileTextCtrl (mpPrefsNotebook, wxID_ANY, wxDefaultPosition, wxDefaultSize);
mpTemplateTextCtrl->SetText(Configuration::GetTemplateText());
mpPrefsNotebook->AddPage(mpTemplateTextCtrl, _("New Profile Template"));
mainSizer->Add(mpPrefsNotebook, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5);
wxBoxSizer* buttonBoxSizer = new wxBoxSizer(wxHORIZONTAL);
mainSizer->Add(buttonBoxSizer, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5);
wxStdDialogButtonSizer* buttonSizer = new wxStdDialogButtonSizer;
buttonBoxSizer->Add(buttonSizer, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
wxButton* okButton = new wxButton( this, wxID_OK, _("&OK"), wxDefaultPosition, wxDefaultSize, 0 );
buttonSizer->AddButton(okButton);
wxButton* cancelButton = new wxButton( this, wxID_CANCEL, _("&Cancel"), wxDefaultPosition, wxDefaultSize, 0 );
buttonSizer->AddButton(cancelButton);
buttonSizer->Realize();
}
void PreferencesDialog::OnColourButton(wxCommandEvent &event)
{
wxColourData currentData;
switch (event.GetId())
{
case ID_COMMENT_COLOUR_BUTTON:
currentData.SetColour(mpCommentsButton->GetBackgroundColour());
break;
case ID_INCLUDES_COLOUR_BUTTON:
currentData.SetColour(mpIncludesButton->GetBackgroundColour());
break;
case ID_CAPABILITIES_COLOUR_BUTTON:
currentData.SetColour(mpCapabilitiesButton->GetBackgroundColour());
break;
case ID_PATHS_COLOUR_BUTTON:
currentData.SetColour(mpPathsButton->GetBackgroundColour());
break;
case ID_PERMS_COLOUR_BUTTON:
currentData.SetColour(mpPermsButton->GetBackgroundColour());
break;
default:
currentData.SetColour(*wxWHITE);
break;
}
wxColourDialog *colourPicker = new wxColourDialog(this, &currentData);
if (colourPicker->ShowModal() == wxID_OK)
{
currentData = colourPicker->GetColourData();
wxColour currentColour = currentData.GetColour();
switch (event.GetId())
{
case ID_COMMENT_COLOUR_BUTTON:
mpCommentsButton->SetBackgroundColour(currentColour);
break;
case ID_INCLUDES_COLOUR_BUTTON:
mpIncludesButton->SetBackgroundColour(currentColour);
break;
case ID_CAPABILITIES_COLOUR_BUTTON:
mpCapabilitiesButton->SetBackgroundColour(currentColour);
break;
case ID_PATHS_COLOUR_BUTTON:
mpPathsButton->SetBackgroundColour(currentColour);
break;
case ID_PERMS_COLOUR_BUTTON:
mpPermsButton->SetBackgroundColour(currentColour);
break;
default:
break;
}
}
colourPicker->Destroy();
}
void PreferencesDialog::OnFontButton(wxCommandEvent &event)
{
wxFontData fontData;
switch (event.GetId())
{
case ID_COMMENT_FONT_BUTTON:
fontData.SetInitialFont(mpCommentsFontButton->GetFont());
break;
case ID_INCLUDES_FONT_BUTTON:
fontData.SetInitialFont(mpIncludesFontButton->GetFont());
break;
case ID_CAPABILITIES_FONT_BUTTON:
fontData.SetInitialFont(mpCapabilitiesFontButton->GetFont());
break;
case ID_PATHS_FONT_BUTTON:
fontData.SetInitialFont(mpPathsFontButton->GetFont());
break;
case ID_PERMS_FONT_BUTTON:
fontData.SetInitialFont(mpPermsFontButton->GetFont());
break;
default:
break;
}
wxFontDialog *fontDialog = new wxFontDialog(this, fontData);
if (fontDialog->ShowModal() == wxID_OK)
{
fontData = fontDialog->GetFontData();
wxFont newFont = fontData.GetChosenFont();
// Write it back to disk
switch (event.GetId())
{
case ID_COMMENT_FONT_BUTTON:
mpCommentsFontButton->SetFont(newFont);
break;
case ID_INCLUDES_FONT_BUTTON:
mpIncludesFontButton->SetFont(newFont);
break;
case ID_CAPABILITIES_FONT_BUTTON:
mpCapabilitiesFontButton->SetFont(newFont);
break;
case ID_PATHS_FONT_BUTTON:
mpPathsFontButton->SetFont(newFont);
break;
case ID_PERMS_FONT_BUTTON:
mpPermsFontButton->SetFont(newFont);
break;
default:
break;
}
}
fontDialog->Destroy();
}

View File

@@ -0,0 +1,102 @@
#ifndef PREFERENCES_H
#define PREFERENCES_H
#include <wx/notebook.h>
#define CONFIG_NAME "AppArmorProfileEditor"
#define DEFAULT_COMMENT_COLOUR_R 31
#define DEFAULT_COMMENT_COLOUR_G 31
#define DEFAULT_COMMENT_COLOUR_B 210
#define DEFAULT_INCLUDE_COLOUR_R 56
#define DEFAULT_INCLUDE_COLOUR_G 136
#define DEFAULT_INCLUDE_COLOUR_B 31
#define DEFAULT_CAP_COLOUR_R 229
#define DEFAULT_CAP_COLOUR_G 33
#define DEFAULT_CAP_COLOUR_B 204
#define DEFAULT_PATH_COLOUR_R 1
#define DEFAULT_PATH_COLOUR_G 1
#define DEFAULT_PATH_COLOUR_B 1
#define DEFAULT_PERM_COLOUR_R 160
#define DEFAULT_PERM_COLOUR_G 32
#define DEFAULT_PERM_COLOUR_B 240
enum
{
ID_COMMENT_COLOUR_BUTTON,
ID_PERMS_COLOUR_BUTTON,
ID_INCLUDES_COLOUR_BUTTON,
ID_CAPABILITIES_COLOUR_BUTTON,
ID_PATHS_COLOUR_BUTTON,
ID_COMMENT_FONT_BUTTON,
ID_PERMS_FONT_BUTTON,
ID_INCLUDES_FONT_BUTTON,
ID_CAPABILITIES_FONT_BUTTON,
ID_PATHS_FONT_BUTTON,
ID_PREFERENCES_NOTEBOOK,
};
/**
* The preferences dialog
*/
class PreferencesDialog: public wxDialog
{
DECLARE_DYNAMIC_CLASS( PreferencesDialog )
DECLARE_EVENT_TABLE()
public:
PreferencesDialog();
PreferencesDialog(wxWindow* parent,
wxWindowID id,
const wxString& caption = _("Preferences"),
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxSize(400, 300),
long style = wxCAPTION|wxRESIZE_BORDER|wxSYSTEM_MENU|wxCLOSE_BOX);
bool Create(wxWindow* parent,
wxWindowID,
const wxString& caption = _("Preferences"),
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxSize(400, 300),
long style = wxCAPTION|wxRESIZE_BORDER|wxSYSTEM_MENU|wxCLOSE_BOX );
void CreateControls();
wxString BestGuessProfileDirectory ();
wxString BestGuessParserCommand ();
// Event handlers
void OnColourButton(wxCommandEvent &event);
void OnFontButton (wxCommandEvent &event);
// Various accessor functions so we can save the data
wxColour GetCommentButtonColour(void) { return mpCommentsButton->GetBackgroundColour(); }
wxColour GetIncludeButtonColour(void) { return mpIncludesButton->GetBackgroundColour(); }
wxColour GetCapabilityButtonColour(void) { return mpCapabilitiesButton->GetBackgroundColour(); }
wxColour GetPathButtonColour(void) { return mpPathsButton->GetBackgroundColour(); }
wxColour GetPermButtonColour(void) { return mpPermsButton->GetBackgroundColour(); }
wxFont GetCommentButtonFont(void) { return mpCommentsFontButton->GetFont(); }
wxFont GetIncludeButtonFont(void) { return mpIncludesFontButton->GetFont(); }
wxFont GetPathButtonFont(void) { return mpPathsFontButton->GetFont(); }
wxFont GetCapabilityButtonFont(void) { return mpCapabilitiesFontButton->GetFont(); }
wxFont GetPermButtonFont(void) { return mpPermsFontButton->GetFont(); }
wxString GetProfileDir(void) { return mpProfileDir->GetValue(); }
wxString GetParser(void) { return mpParserCommand->GetValue(); }
wxString GetTemplateText(void) { return mpTemplateTextCtrl->GetText(); }
private:
wxNotebook* mpPrefsNotebook;
wxTextCtrl* mpProfileDir;
wxTextCtrl* mpParserCommand;
ProfileTextCtrl* mpTemplateTextCtrl;
wxButton* mpCommentsButton;
wxButton* mpIncludesButton;
wxButton* mpPermsButton;
wxButton* mpCapabilitiesButton;
wxButton* mpPathsButton;
wxButton* mpCommentsFontButton;
wxButton* mpIncludesFontButton;
wxButton* mpCapabilitiesFontButton;
wxButton* mpPathsFontButton;
wxButton* mpPermsFontButton;
};
#endif

View File

@@ -0,0 +1,43 @@
#ifndef PROFILE_DIRECTORY_TRAVERSER
#define PROFILE_DIRECTORY_TRAVERSER
/**
* The wxDirTraverser that searches through the profile directory
*/
class ProfileDirectoryTraverser : public wxDirTraverser
{
public:
ProfileDirectoryTraverser(wxTreeCtrl* profileTree,
const wxTreeItemId& startNode,
const wxString& profileDirectory)
: mpProfileTree(profileTree),
mCurNode(startNode),
mOriginalNode(startNode),
mProfileDirectory(profileDirectory) {}
virtual wxDirTraverseResult OnFile(const wxString& filename)
{
ProfileTreeData* data = new ProfileTreeData(filename);
// OnDir isn't called when the traverser starts
// going through the files in the top level directory,
// so we do this to keep the profiles in the right place
if (wxFileName(filename).GetPath() == mProfileDirectory)
mCurNode = mOriginalNode;
mpProfileTree->AppendItem(mCurNode, wxFileName(filename).GetFullName(), -1, -1, data);
return wxDIR_CONTINUE;
}
virtual wxDirTraverseResult OnDir(const wxString& dirname)
{
mCurNode = mpProfileTree->AppendItem(mOriginalNode, wxFileName(dirname).GetName());
return wxDIR_CONTINUE;
}
private:
wxTreeCtrl* mpProfileTree;
wxTreeItemId mCurNode, mOriginalNode;
wxString mProfileDirectory;
};
#endif

View File

@@ -0,0 +1,115 @@
/* AppArmor Profile Editor (C) 2006 Novell, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
*/
#include "wx/wxprec.h"
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
#include <wx/textctrl.h>
#include <wx/textfile.h>
#include <wx/config.h>
#include "ProfileTextCtrl.h"
#include "Preferences.h"
#include "Configuration.h"
BEGIN_EVENT_TABLE(ProfileTextCtrl, wxStyledTextCtrl)
EVT_STC_CHANGE(ID_STYLED_PROFILE_WINDOW, ProfileTextCtrl::OnModified)
END_EVENT_TABLE()
ProfileTextCtrl::ProfileTextCtrl(wxWindow *parent, wxWindowID id,
const wxPoint &pos,
const wxSize &size,
long style)
: wxStyledTextCtrl (parent, id, pos, size, style|wxTE_WORDWRAP|wxTE_MULTILINE|wxTE_PROCESS_ENTER)
{
mpParentWindow = parent;
SetLexer(wxSTC_LEX_APPARMOR);
StyleClearAll();
RefreshColoursAndFonts();
mNeedSaving = false;
mIsNew = false;
}
/**
* Loads a file from disk
* @param filename The file to load
* @return true on success, false on failure
*/
bool ProfileTextCtrl::LoadFile(const wxString& filename)
{
wxTextFile file;
wxString currentLine;
if (!file.Open(filename))
return false;
mIgnoreChanges = true; // Have OnModified ignore the events from loading the file
Clear();
mFilename = filename;
wxStyledTextCtrl::LoadFile(filename);
mIgnoreChanges = false;
mNeedSaving = false;
mIsNew = false;
return true;
}
/**
* Event handler triggered by any change in the window
* @param event
*/
void ProfileTextCtrl::OnModified(wxStyledTextEvent &event)
{
if (!mIgnoreChanges)
{
mNeedSaving = true;
wxPostEvent(mpParentWindow, event);
}
}
/**
* Reloads the syntax colouring and fonts
* @param
*/
void ProfileTextCtrl::RefreshColoursAndFonts(void)
{
wxColour yellowColour(252,253,127);
wxFont defaultFont (10, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
wxFont commentFont = Configuration::GetCommentFont();
wxFont includeFont = Configuration::GetIncludeFont();
wxFont capabilityFont = Configuration::GetCapabilityFont();
wxFont permFont = Configuration::GetPermFont();
wxFont pathFont = Configuration::GetPathFont();
StyleSetFont (wxSTC_STYLE_DEFAULT, defaultFont);
StyleSetForeground (wxSTC_STYLE_DEFAULT, *wxBLACK);
StyleSetBackground (wxSTC_STYLE_DEFAULT, *wxWHITE);
StyleSetFont (wxSTC_APPARMOR_COMMENT, commentFont);
StyleSetForeground (wxSTC_APPARMOR_COMMENT, Configuration::GetCommentColour());
StyleSetBackground (wxSTC_APPARMOR_COMMENT, *wxWHITE);
StyleSetFont (wxSTC_APPARMOR_INCLUDE, includeFont);
StyleSetForeground (wxSTC_APPARMOR_INCLUDE, Configuration::GetIncludeColour());
StyleSetBackground (wxSTC_APPARMOR_INCLUDE, *wxWHITE);
StyleSetFont (wxSTC_APPARMOR_CAPABILITY, capabilityFont);
StyleSetForeground (wxSTC_APPARMOR_CAPABILITY, Configuration::GetCapColour());
StyleSetBackground (wxSTC_APPARMOR_CAPABILITY, *wxWHITE);
StyleSetFont (wxSTC_APPARMOR_PATH, pathFont);
StyleSetForeground (wxSTC_APPARMOR_PATH, Configuration::GetPathColour());
StyleSetBackground (wxSTC_APPARMOR_PATH, *wxWHITE);
StyleSetFont (wxSTC_APPARMOR_PERMS, permFont);
StyleSetForeground (wxSTC_APPARMOR_PERMS, Configuration::GetPermColour());
StyleSetBackground (wxSTC_APPARMOR_PERMS, *wxWHITE);
StyleSetForeground (wxSTC_STYLE_BRACELIGHT, *wxBLACK);
StyleSetBackground (wxSTC_STYLE_BRACELIGHT, yellowColour);
StyleSetForeground (wxSTC_STYLE_BRACEBAD, *wxBLACK);
StyleSetBackground (wxSTC_STYLE_BRACEBAD, *wxRED);
SetCaretWidth(2);
}

View File

@@ -0,0 +1,44 @@
#ifndef PROFILE_TEXT_CTRL_H
#define PROFILE_TEXT_CTRL_H
#include "wxStyledTextCtrl/stc.h"
#define ID_STYLED_PROFILE_WINDOW 13082
/**
* The syntax highlighting text control
*/
class ProfileTextCtrl : public wxStyledTextCtrl
{
public:
ProfileTextCtrl (wxWindow *parent,
wxWindowID id = wxID_ANY,
const wxPoint &pos = wxDefaultPosition,
const wxSize &size = wxDefaultSize,
long style = wxSUNKEN_BORDER | wxVSCROLL);
bool LoadFile(const wxString &filename);
void ProcessLine(const wxString &currentLine);
void RefreshColoursAndFonts();
void OnModified(wxStyledTextEvent &event);
void OnReturnKey(wxCommandEvent& event);
bool GetNeedSaving() { return mNeedSaving; }
void SetNeedSaving(bool status) { mNeedSaving = status; }
wxString GetFileName() { return mFilename; }
void SetFileName(wxString fileName) { mFilename = fileName; }
void SetIsNew(bool status) { mIsNew = status; }
bool GetIsNew() { return mIsNew; }
void SetIgnoreChanges(bool value) { mIgnoreChanges = value; }
private:
wxWindow *mpParentWindow;
wxString mFilename;
bool mNeedSaving;
bool mIsNew;
bool mIgnoreChanges;
DECLARE_EVENT_TABLE()
};
#endif

View File

@@ -0,0 +1,179 @@
/* AppArmor Profile Editor (C) 2006 Novell, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
*/
#include "wx/wxprec.h"
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
#include <wx/dir.h>
#include <wx/ffile.h>
#include <wx/busyinfo.h>
#include <wx/process.h>
#include "SearchAllProfiles.h"
IMPLEMENT_DYNAMIC_CLASS(SearchAllProfilesDialog, wxDialog)
BEGIN_EVENT_TABLE(SearchAllProfilesDialog, wxDialog)
EVT_BUTTON(ID_SEARCH_ALL_PROFILES_BUTTON, SearchAllProfilesDialog::OnSearch)
EVT_LISTBOX_DCLICK(ID_SEARCH_ALL_PROFILES_LIST_BOX, SearchAllProfilesDialog::OnListBoxDClick)
END_EVENT_TABLE()
SearchAllProfilesDialog::SearchAllProfilesDialog( )
{
}
SearchAllProfilesDialog::SearchAllProfilesDialog(wxWindow* parent,
wxWindowID id,
const wxString& caption,
const wxPoint& pos,
const wxSize& size,
long style)
{
Create(parent, id, caption, pos, size, style);
}
bool SearchAllProfilesDialog::Create(wxWindow* parent,
wxWindowID id,
const wxString& caption,
const wxPoint& pos,
const wxSize& size,
long style )
{
mpSearchPhraseSizer = NULL;
mpSearchStaticText = NULL;
mpSearchPhraseTextCtrl = NULL;
mpSearchButton = NULL;
mpSearchResultsListBox = NULL;
mpOKButtonSizer = NULL;
mProfileDirectory = wxEmptyString;
mEditorExecutable = wxEmptyString;
mSearchedPhrase = wxEmptyString;
SetExtraStyle(GetExtraStyle() | wxWS_EX_BLOCK_EVENTS);
wxDialog::Create(parent, id, caption, pos, size, style);
CreateControls();
GetSizer()->Fit(this);
GetSizer()->SetSizeHints(this);
Centre();
return true;
}
void SearchAllProfilesDialog::CreateControls()
{
wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);
SetSizer(mainSizer);
mpSearchPhraseSizer = new wxFlexGridSizer(1, 3, 0, 0);
mainSizer->Add(mpSearchPhraseSizer, 0, wxGROW|wxALL, 5);
mpSearchStaticText = new wxStaticText(this,
wxID_ANY,
_T("Search phrase:"),
wxDefaultPosition,
wxDefaultSize,
0);
mpSearchPhraseSizer->Add(mpSearchStaticText, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE, 5);
mpSearchPhraseTextCtrl = new wxTextCtrl(this,
wxID_ANY,
_T(""),
wxDefaultPosition,
wxSize(300, -1),
0);
mpSearchPhraseSizer->Add(mpSearchPhraseTextCtrl, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5);
mpSearchButton = new wxButton(this,
ID_SEARCH_ALL_PROFILES_BUTTON,
_("Search"),
wxDefaultPosition,
wxDefaultSize,
0);
mpSearchPhraseSizer->Add(mpSearchButton, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL, 5);
mpSearchResultsListBox = new wxListBox(this,
ID_SEARCH_ALL_PROFILES_LIST_BOX,
wxDefaultPosition,
wxSize(-1, 200),
0,
NULL,
wxLB_SINGLE);
mainSizer->Add(mpSearchResultsListBox, 0, wxGROW|wxALL, 5);
mpOKButtonSizer = new wxStdDialogButtonSizer;
mainSizer->Add(mpOKButtonSizer, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5);
wxButton* okButton = new wxButton(this,
wxID_CANCEL,
_("&Cancel"),
wxDefaultPosition,
wxDefaultSize, 0);
mpOKButtonSizer->AddButton(okButton);
mpOKButtonSizer->Realize();
}
/**
* Event handler triggered by the Search button
* @param WXUNUSED( event )
*/
void SearchAllProfilesDialog::OnSearch(wxCommandEvent& WXUNUSED(event))
{
mpSearchButton->Disable();
mpSearchResultsListBox->Clear();
mSearchedPhrase = mpSearchPhraseTextCtrl->GetValue();
DoSearch(mSearchedPhrase);
mpSearchButton->Enable();
}
/**
* Calls the directory traverser
* @param searchString
*/
void SearchAllProfilesDialog::DoSearch(const wxString& searchString)
{
if (mProfileDirectory != wxEmptyString)
{
wxBusyInfo wait(_("Searching..."));
wxTheApp->Yield(); // Needed to repaint the busy window
SearchAllProfilesTraverser traverser(searchString, mpSearchResultsListBox);
wxDir dir (mProfileDirectory);
dir.Traverse(traverser,wxEmptyString);
}
}
/**
* A user has double clicked on a search result
* @param event
*/
void SearchAllProfilesDialog::OnListBoxDClick (wxCommandEvent& event)
{
wxString execString = mEditorExecutable;
execString.Append(_T(" "));
execString.Append(event.GetString());
execString.Append(_T(" \""));
execString.Append(mSearchedPhrase);
execString.Append(_T("\""));
wxProcess *proc = wxProcess::Open(execString);
if (proc == NULL)
{
wxMessageDialog *dlg = new wxMessageDialog(this, _("Could not exec!"), _("Error"),
wxOK|wxICON_ERROR);
dlg->ShowModal();
dlg->Destroy();
}
else
{
proc->Detach();
}
}

View File

@@ -0,0 +1,95 @@
#ifndef _SEARCHALLPROFILESDIALOG_H_
#define _SEARCHALLPROFILESDIALOG_H_
class wxFlexGridSizer;
class wxStdDialogButtonSizer;
/**
* A "Search All Profiles" dialog
*/
class SearchAllProfilesDialog: public wxDialog
{
DECLARE_DYNAMIC_CLASS(SearchAllProfilesDialog)
DECLARE_EVENT_TABLE()
public:
SearchAllProfilesDialog();
SearchAllProfilesDialog(wxWindow* parent,
wxWindowID id = wxID_ANY,
const wxString& caption = _("Search All Profiles"),
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxSize(400, 300),
long style = wxCAPTION|wxRESIZE_BORDER|wxSYSTEM_MENU|wxCLOSE_BOX);
/// Creation
bool Create(wxWindow* parent,
wxWindowID id = wxID_ANY,
const wxString& caption = _("Search All Profiles"),
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxSize(400, 300),
long style = wxCAPTION|wxRESIZE_BORDER|wxSYSTEM_MENU|wxCLOSE_BOX );
void CreateControls();
void OnSearch(wxCommandEvent& event);
void OnListBoxDClick (wxCommandEvent& event);
void DoSearch(const wxString& searchString);
void SetProfileDirectory (const wxString& dir) { mProfileDirectory = dir; }
void SetEditorExecutable (const wxString& exec) { mEditorExecutable = exec; }
void SetSearchText (const wxString& searchString) { mpSearchPhraseTextCtrl->SetValue(searchString); }
private:
wxFlexGridSizer* mpSearchPhraseSizer;
wxStaticText* mpSearchStaticText;
wxTextCtrl* mpSearchPhraseTextCtrl;
wxButton* mpSearchButton;
wxListBox* mpSearchResultsListBox;
wxStdDialogButtonSizer* mpOKButtonSizer;
wxString mProfileDirectory;
wxString mEditorExecutable;
wxString mSearchedPhrase;
};
/**
* The "Search All" traverser
*/
class SearchAllProfilesTraverser : public wxDirTraverser
{
public:
SearchAllProfilesTraverser (const wxString& search, wxListBox *rBox)
: searchString(search),
resultsBox(rBox) {}
virtual wxDirTraverseResult OnFile(const wxString& filename)
{
if (!tmpFile.Open(filename))
return wxDIR_CONTINUE;
if (!tmpFile.ReadAll(&tmpString))
return wxDIR_CONTINUE;
if (tmpString.Find(searchString) != -1)
resultsBox->Append(filename);
tmpFile.Close();
return wxDIR_CONTINUE;
}
virtual wxDirTraverseResult OnDir(const wxString& dirname)
{
return wxDIR_CONTINUE;
}
private:
wxString searchString;
wxListBox *resultsBox;
wxString tmpString;
wxFFile tmpFile;
};
enum
{
ID_SEARCH_ALL_PROFILES_BUTTON = 15599,
ID_SEARCH_ALL_PROFILES_LIST_BOX
};
#endif

View File

@@ -0,0 +1,173 @@
/* XPM */
static char * opensuse_logo_xpm[] = {
"223 137 33 1",
" c #FFFFFF",
". c #EBF4E6",
"+ c #E4F0DD",
"@ c #CDE5C1",
"# c #C5E1B7",
"$ c #B5D9A1",
"% c #A3D088",
"& c #7ABF48",
"* c #8FC86C",
"= c #F8FBF7",
"- c #BDDDAC",
"; c #85C35B",
"> c #F2F8EF",
", c #D5E9CB",
"' c #99CC7B",
") c #ACD495",
"! c #DCECD4",
"~ c #EDF1F0",
"{ c #D9E2E1",
"] c #E3EAE9",
"^ c #F6F8F8",
"/ c #A1BAB6",
"( c #357D74",
"_ c #007167",
": c #4F8881",
"< c #759E98",
"[ c #C4D3D1",
"} c #85A7A3",
"| c #93B1AD",
"1 c #64938D",
"2 c #B9CBC8",
"3 c #ADC2BF",
"4 c #CFDBD9",
" ",
" ",
" ",
" ",
" ",
" ",
" .+@#$%%%&&&&&&&&&&&&&&&&&&*%%%%%$##@++= ",
" +@-%;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*%-#+. >+= ",
" .,$'&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&')#+= #&&;%$#+> ",
" >,$;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*)#+= #&&&&&&&&;%-,+ ",
" .-'&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&'$,> #&&&&&&&&&&&&&&'$@. ",
" .-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*$,> #&&&&&&&&&&&&&&&&&&&%#!= ",
" >-*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*$!= #&&&&&&&&&&&&&&&&&&&&&&&'-!= ",
" =,'&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&%@$&&&&&&&&&&&&&&&&&&&&&&&&&&&'#. ",
" >$;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*$! ",
" +%&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&;-. ",
" ,'&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&', ",
" ,*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&;#= ",
" ,*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*%&&&&&&&&&;! ",
" ,*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*@. =!$&&&&&&&, ",
" +%&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*! =$&&&&&&, ",
" >)&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&$= .+= +;&&&&&! ",
" =#&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&$ ,%&&&&;$> .;&&&&;= ",
" !*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&% >'&&&&&&&&&# +&&&&&# ",
" =)&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&> .;&&&&&&&&&&&$ -&&&&&> ",
" @;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&$ '&&&&&&&&&&&&&@ =&&&&&- ",
" =)&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&. ,&&&&&&$> .)&&;= $&&&&;= ",
" +;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&* %&&&&&$ %&&, ,&&&&&@ ",
" -&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&% &&&&&&- %&&# +&&&&&* ",
" ='&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&% &&&&&&&@ =#&&&) &&&&&&+ ",
" .;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&% &&&&&&&&&%'&&&&&# >&&&&&&$ ",
" ,;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&' '&&&&&&&&&&&&&&&@ +&&&&&&&= ",
" @&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&= @&&&&&&&&&&&&&&&> #&&&&&&&, ",
" $&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&, =;&&&&&&&&&&&&&- *&&&&&&&) ",
" $&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&$&&&&&&&&&&&&&* +&&&&&&&&&&&&'= ,&&&&&&&&&= ",
" $&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&#.%&&&&&&&&&&&&# !;&&&&&&&&&'= =*&&&&&&&&&, ",
" $&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&;= ,*&&&&&&&&&&&+ =$;&&&&&*, )&&&&&&&&&&) ",
" $&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&, #;&&&&&&&&&;! +@#!. $&&&&&&&&&&&; ",
" #&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&* =#;&&&&&&&&&# .'&&&&&&&&&&&&&+ ",
" ,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&, =$;&&&&&&&&*,= .$&&&&&&&&&&&&&&;. ",
" .&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&% =#;&&&&&&&&&%####$*&&&&&&&&&&&&&&&)= ",
" =;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&$+ =@*&&&&&&&&&&&&&&&&&&&&&&&&&&&*+ ",
" '&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&%! !)&&&&&&&&&&&&&&&&&&&&&&&*, ",
" #&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*@= =,)&&&&&&&&&&&&&&&&&&', ",
" +&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&;$. =!$'&&&&&&&&&&&'-. .> ",
" =*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&',= +,#####@+= +%&# ",
" #&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&$! =,'&&&, ",
" >&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&;$!= !$;&&&&&= ",
" %&&&&&&&&&&&&&&&&&&&&&&&&;%##!++++##$%;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&%#+ +@)&&&&&&&&) ",
" +&&&&&&&&&&&&&&&&&&&&&&),> >,)&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*%%-%%*&&&&&&&&&&&&+ ",
" %&&&&&&&&&&&&&&&&&&&;#> =,'&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&$ ",
" !&&&&&&&&&&&&&&&&&&&#= +%&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&- ",
" %&&&&&&&&&&&&&&&&&'. +%&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&%. ",
" +&&&&&&&&&&&&&&&&&$ !*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&$. ",
" $&&&&&&&&&&&&&&&&# =-&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*#= ",
" =&&&&&&&&&&&&&&&&- >,-%%&&;%%-,> !;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&;$! ",
" ,&&&&&&&&&&&&&&&$ =@'&&&&&&&&&&&&&'@> >'&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&'-! ",
" $&&&&&&&&&&&&&&'= #;&&&&&&&&&&&&&&&&&&$> =$&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*%%&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*%#!= ",
" *&&&&&&&&&&&&&&. >'&&&&&&&&&&&&&&&&&&&&&&#= $&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&%,> .+!##%%'&&&&&&&&&&&'%%##!+ ",
" >&&&&&&&&&&&&&&# .;&&&&&&&&&&&&&&&&&&&&&&&&*. $&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&;! ",
" !&&&&&&&&&&&&&;= .;&&&&&&&&&&&&&&&&&&&&&&&&&&&, $&&&&&&&&&&&&&&&&&&&&&&&&&&&&&'$@+. ++#);&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&+ ",
" #&&&&&&&&&&&&&# =;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&, $&&&&&&&&&&&&&&&&&&&&&&&&&&$> !$&&&&&&&&&&&&&&&&&&&&&&&&&&&&$ ",
" )&&&&&&&&&&&&&> )&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&, '&&&&&&&&&&&&&&&&&&&&&&&%> =#;&&&&&&&&&&&&&&&&&&&&&&&&&. ",
" %&&&&&&&&&&&&' +&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&! =;&&&&&&&&&&&&&&&&&&&&&@ =-&&&&&&&&&&&&&&&&&&&&&&&; ",
" '&&&&&&&&&&&&- )&&&&&&&&&&&*$@++@-'&&&&&&&&&&&&&&;= +&&&&&&&&&&&&&&&&&&&&, +*&&&&&&&&&&&&&&&&&&&&&% ",
" &&&&&&&&&&&&&@ =&&&&&&&&&&;, >#;&&&&&&&&&&&&) -&&&&&&&&&&&&&&&&&&- =$&&&&&&&&&&&&&&&&&&&&- ",
" &&&&&&&&&&&&&+ !&&&&&&&&&;. >'&&&&&&&&&&&&+ =*&&&&&&&&&&&&&&&&;= @&&&&&&&&&&&&&&&&&&&# ",
" &&&&&&&&&&&&&+ #&&&&&&&&&# $&&&&&&&&&&&% ,&&&&&&&&&&&&&&&&- ,&&&&&&&&&&&&&&&&&&$ ",
" &&&&&&&&&&&&&+ #&&&&&&&&&> )&&&&&&&&&&&+ %&&&&&&&&&&&&&&&. ,&&&&&&&&&&&&&&&&&% ",
" ;&&&&&&&&&&&&+ #&&&&&&&&& =*&&&&&&&&&&$ !&&&&&&&&&&&&&&* ,&&&&&&&&&&&&&&&&; ",
" %&&&&&&&&&&&&@ #&&&&&&&&&! !&&&&&&&&&&; *&&&&&&&&&&&&&) ,&&&&&&&&&&&&&&&&> ",
" %&&&&&&&&&&&&- ,&&&&&&&&&'= %&&&&&&&&&&. #&&&&&&&&&&&&&# ,&&&&&&&&&&&&&&&, ",
" #&&&&&&&&&&&&' .&&&&&&&&&&'+ =,##@> ,&&&&&&&&&&@ >&&&&&&&&&&&&&@ @&&&&&&&&&&&&&&) ",
" ,&&&&&&&&&&&&&> *&&&&&&&&&&&&&&&&&&;, =&&&&&&&&&&$ *&&&&&&&&&&&&+ $&&&&&&&&&&&&&&= ",
" >&&&&&&&&&&&&&@ ,&&&&&&&&&&&&&&&&&&&&> '&&&&&&&&&% -&&&&&&&&&&&&+ $&&&&&&&&&&&&&# ",
" *&&&&&&&&&&&&* *&&&&&&&&&&&&&&&&&&&# %&&&&&&&&&% !&&&&&&&&&&&&+ $&&&&&&&&&&&&* ",
" -&&&&&&&&&&&&&, .&&&&&&&&&&&&&&&&&&&% %&&&&&&&&&% =;&&&&&&&&&&&+ $&&&&&&&&&&&&, ",
" >&&&&&&&&&&&&&* ,&&&&&&&&&&&&&&&&&&$ %&&&&&&&&&% =@*&&&&&&&&&, $&&&&&&&&&&&* ",
" %&&&&&&&&&&&&&# ,&&&&&&&&&&&&&&&&&+ &&&&&&&&&&% ,*&&&&&&&# @;&&&&&&&&&&@ ",
" ,&&&&&&&&&&&&&&. .'&&&&&&&&&&&&&&$ !&&&&&&&&&&) +%&&&&&# ,'&&&&&&&&;= ",
" *&&&&&&&&&&&&&;= ,*&&&&&&&&&&%+ $&&&&&&&&&&# .$&&&% +$&&&&&&&) ",
" +&&&&&&&&&&&&&&'= .#%*&;%$@> >&&&&&&&&&&&+ >-;* >-;&&&&&+ ",
" %&&&&&&&&&&&&&&'. %&&&&&&&&&&; =@ =,*&&&;= ",
" >;&&&&&&&&&&&&&&;! $&&&&&&&&&&&$ +)&&) ",
" @&&&&&&&&&&&&&&&&$= $&&&&&&&&&&&&. >-;, ",
" )&&&&&&&&&&&&&&&&;#= >%&&&&&&&&&&&&% => ",
" ='&&&&&&&&&&&&&&&&&&$!= !$&&&&&&&&&&&&&&+ ",
" >;&&&&&&&&&&&&&&&&&&&&'$#!++++,#%;&&&&&&&&&&&&&&&- ",
" .;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*= ",
" .'&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&;. ",
" ='&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&, ",
" -&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&, ",
" +*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&;! ~{{{{{{{{{{{{{{{{ ]{{^ ~{{^ {{{{{{{{{{{{{{{{~ {{{{{{{{{{{{{{{{{{{{{] ",
" =#;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&'> ~/(_________________:] <___(] /___([ {}__________________| ](______________________1^ 2333{^[ ",
" >$&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&;# [(____________________} 2_____: 4_____(^ ^|_____________________[ :________________________3 3:|<(1< ",
" >#*&&&&&&&&&&&&&&&&&&&&&&&&&;#= [______________________< 3______ 3______{ <______________________3 _________________________< <{31<< ",
" !$;&&&&&&&&&&&&&&&&&&&&',= ~(______________________< 3______ 3______{ 3_______________________2 _________________________| <{33{< ",
" .@)'&&&&&&&&&&&&'$,> |_______________________[ 3______ 3______{ ^(______________________(~ _________________________] ~ ^^ ~ ",
" >++++++++> (______(|33333333333333{ 3______ 3______{ [_______1/33333333333333~ ______:33333333333333333~ ",
" ______:^ 3______ 3______{ 3______/ ______< ",
" ______3 3______ 3______{ 3______{ ______< ",
" ______3 3______ 3______{ 3______{ ______< ",
" ______3 3______ 3______{ 3______{ ______< ",
" ______< 3______ 3______{ 3______2 ______< ",
" >#########,= =#, =,$%%%#> ,#########+ .#+ >@)%%)@= _______}4{{{{{{{{{{{{{^ 3______ 3______{ 2_______3{{{{{{{{{{{{{] ______1{{{{{{{{{{{{{^ ",
" -&&&&&&&&&&&;. )&&-!$;&&&&&&&- .'&&&&&&&&&&&)= >;&&+,%&&&&&&&;! 1______________________<{ 3______ 3______{ ]______________________(|^ ____________________(] ",
" @&&&&&&&&&&&&&;> %&&&&&&&&&&&&&&, =*&&&&&&&&&&&&&) +&&&&&&&&&&&&&&;> [________________________[ 3______ 3______{ <_______________________(] _____________________: ",
" ;&&&%#####-;&&&# %&&&;-#####*&&&' ,&&&;-#####$&&&&> +&&&&%#####-;&&&# 1________________________{ 3______ 3______{ ](_______________________:^ ______________________ ",
" &&&% .&&&% %&&;= =*&&& #&&&+ #&&&+ +&&&% .&&&% ^<_______________________1 3______ 3______{ ](_______________________[ _____________________( ",
" &&&# &&&% %&&% -&&& #&&& +&&&+ +&&&# &&&% [:______________________ 3______ 3______{ ^|(_____________________} _____________________3 ",
" &&&# &&&% %&&% #&&& #&&& +&&&+ +&&&# &&&% ~{{{{{{{{{{{{{[(______{ 3______ 3______{ {{{{{{{{{{{{{{}______< ______:3333333333333{ ",
" &&&# &&&% %&&% #&&& #&&&++++++++@&&&+ +&&&# &&&% /______{ 3______ 3______{ (_____< ______< ",
" &&&# &&&% %&&% #&&& #&&&&&&&&&&&&&&&+ +&&&# &&&% 3______{ 3______ 3______{ <_____< ______< ",
" &&&# &&&% %&&% #&&& #&&&&&&&&&&&&&&&> +&&&# &&&% 3______{ 3______ 3______{ <_____< ______< ",
" &&&# &&&% %&&% #&&& #&&&%%%%%%%%%%%! +&&&# &&&% 3______{ 3______~ /______{ :_____< ______< ",
" &&&# &&&% %&&% #&&& #&&& +&&&# &&&% 1______{ 3______} ](______] ~______< ______< ",
" &&&# &&&% %&&% #&&& #&&& +&&&# &&&% {33333333333333333}_______ [_______:3333333333/(_______ ^[33333333333333333:______} ______:33333333333333333[^ ",
" &&&# &&&% %&&% $&&& #&&& +&&&# &&&% |_________________________1 ~__________________________} ~(_________________________2 _________________________:^ ",
" &&&*= ,&&&) %&&&+ .;&&& #&&&@ +&&&# &&&% ~__________________________2 |_________________________{ 3__________________________~ __________________________2 ",
" '&&&;%%%%%%&&&&@ %&&&&'%%%%%&&&&) +&&&&*%%%%%%. +&&&# &&&% {_________________________1^ ^1_______________________3 3_________________________3 __________________________3 ",
" +&&&&&&&&&&&&&'= %&&&&&&&&&&&&&&+ %&&&&&&&&&&;> +&&&# &&&% ~________________________:] ^1_____________________3 2________________________| :_________________________2 ",
" !;&&&&&&&&&&%= %&&'>,'&&&&&&;! =$&&&&&&&&&)= $&'. ,&;+ 3_____________________(/^ [:_________________}] ^1_____________________:[ [________________________1^ ",
" +@######,. %&&% >,###+ >!######@ @= !. ]{{{{{{{{{{{{{{{{{{{{ ][33333333333334^ {{{{{{{{{{{{{{{{{{{{~ ~{{{{{{{{{{{{{{{{{{{{{{{ ",
" %&&% ",
" %&&% ",
" %&&% ",
" %&&% ",
" %&&% ",
" %&&% ",
" ,&&, ",
" !! ",
" ",
" ",
" ",
" ",
" ",
" "};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,136 @@
#ifndef _PROFILETOOL_H_
#define _PROFILETOOL_H_
#ifndef HELP_FILE_LOCATION
#define HELP_FILE_LOCATION ""
#endif
/**
* @short AppArmor Profile Tool
* @author Matt Barringer <mbarringer@suse.de>
* @version 1.0
*/
class ProfileToolFrame;
class ProfileTreeData;
/**
* The wxApp class
**/
class AppArmorProfileTool : public wxApp
{
public:
virtual bool OnInit();
virtual int OnExit();
private:
ProfileToolFrame *frame;
};
/**
* The main frame
**/
class ProfileToolFrame : public wxFrame
{
public:
ProfileToolFrame(const wxString& title,
const wxPoint& pos,
const wxSize& size,
const wxString& startingProfile,
const wxString& startingHighlight);
~ProfileToolFrame();
void CreateControls(const wxString &startingProfile,
const wxString &startingHighlight);
void ClearProfile();
bool DeleteProfile(wxString& profile);
void EnableSaveMenu(bool toggle);
int FindTreeNodeAndHighlight(wxTreeItemId startingNode, wxString path);
void LoadProfile(const wxString& profile, const wxString& highlight);
void PopulateControls();
void ProfileHasBeenModified();
int ProfileNeedSaving();
void ReloadProfile(const wxString &filePath);
void ReplaceAll(const wxString searchText,
const wxString replaceText,
int matchCase,
int wholeWord);
void RepopulateControl();
int SaveCurrentProfile();
// Event handlers
void OnQuit(wxCommandEvent& event);
void OnClose(wxCloseEvent &event);
void OnAbout(wxCommandEvent& event);
void OnSave(wxCommandEvent& event);
void OnFind(wxCommandEvent& event);
void OnSearchAllProfiles(wxCommandEvent& event);
void OnReplace(wxCommandEvent& event);
void OnSaveAs(wxCommandEvent& event);
void OnHelp(wxCommandEvent& event );
void OnDeleteProfile(wxCommandEvent &event);
void OnReloadProfile(wxCommandEvent &event);
void OnCheckSyntax(wxCommandEvent &event);
void OnEditMenu(wxCommandEvent& event);
void OnPreferences(wxCommandEvent& event);
void OnNewProfile(wxCommandEvent& event);
void OnProfileModified(wxStyledTextEvent &event);
void OnTreeSelection(wxTreeEvent& event);
void OnTreeContextMenu(wxTreeEvent& event);
void OnOpenInclude(wxCommandEvent &event);
void OnInsertInclude(wxCommandEvent &event);
void OnUpdateUI(wxStyledTextEvent &event);
void OnSize(wxSizeEvent& event);
void OnFindButton(wxFindDialogEvent& event);
void OnEndOfProfileReload(wxProcessEvent &event);
private:
wxTreeCtrl *mpProfileTree;
wxFindReplaceDialog *mpFindDialog, *mpReplaceDialog;
wxHtmlHelpController *mpHelpController;
ProfileTextCtrl *mpProfileView;
wxMenuBar *mpMenuBar;
wxFindReplaceData mFindData, mReplaceData;
wxTreeItemId mRootNode;
wxTreeItemId mCurrentNode;
wxSplitterWindow *mpSplitterWindow;
DECLARE_EVENT_TABLE()
};
/**
* This class is used to keep track of what path goes with
* what profile entry in the tree.
*/
class ProfileTreeData : public wxTreeItemData
{
public:
ProfileTreeData(const wxString& path) : mPath(path) {}
wxString GetPath(void) { return mPath; }
private:
wxString mPath;
};
enum
{
ID_MENU_FILE_NEW=1048,
ID_MENU_FILE_PREFERENCES,
ID_MENU_FILE_SAVE,
ID_MENU_FILE_SAVE_AS,
ID_MENU_HELP_ABOUT,
ID_MENU_HELP_PROFILES,
ID_MENU_EDIT_COPY,
ID_MENU_EDIT_CUT,
ID_MENU_EDIT_PASTE,
ID_MENU_EDIT_UNDO,
ID_MENU_EDIT_REDO,
ID_MENU_EDIT_FIND,
ID_MENU_EDIT_REPLACE,
ID_MENU_EDIT_FIND_NEXT,
ID_MENU_EDIT_SEARCH_ALL_PROFILES,
ID_PREFERENCES_DIALOG,
ID_TREE_CONTEXT_DELETE,
ID_TREE_CONTEXT_RELOAD,
ID_RELOAD_PROFILE_PROCESS,
ID_PROFILE_TREE
};
#endif // _PROFILETOOL_H_

View File

@@ -0,0 +1,78 @@
// Scintilla source code edit control
/** @file Accessor.h
** Rapid easy access to contents of a Scintilla.
**/
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.
enum { wsSpace = 1, wsTab = 2, wsSpaceTab = 4, wsInconsistent=8};
class Accessor;
typedef bool (*PFNIsCommentLeader)(Accessor &styler, int pos, int len);
/**
* Interface to data in a Scintilla.
*/
class Accessor {
protected:
enum {extremePosition=0x7FFFFFFF};
/** @a bufferSize is a trade off between time taken to copy the characters
* and retrieval overhead.
* @a slopSize positions the buffer before the desired position
* in case there is some backtracking. */
enum {bufferSize=4000, slopSize=bufferSize/8};
char buf[bufferSize+1];
int startPos;
int endPos;
int codePage;
virtual bool InternalIsLeadByte(char ch)=0;
virtual void Fill(int position)=0;
public:
Accessor() : startPos(extremePosition), endPos(0), codePage(0) {}
virtual ~Accessor() {}
char operator[](int position) {
if (position < startPos || position >= endPos) {
Fill(position);
}
return buf[position - startPos];
}
/** Safe version of operator[], returning a defined value for invalid position. */
char SafeGetCharAt(int position, char chDefault=' ') {
if (position < startPos || position >= endPos) {
Fill(position);
if (position < startPos || position >= endPos) {
// Position is outside range of document
return chDefault;
}
}
return buf[position - startPos];
}
bool IsLeadByte(char ch) {
return codePage && InternalIsLeadByte(ch);
}
void SetCodePage(int codePage_) { codePage = codePage_; }
virtual bool Match(int pos, const char *s)=0;
virtual char StyleAt(int position)=0;
virtual int GetLine(int position)=0;
virtual int LineStart(int line)=0;
virtual int LevelAt(int line)=0;
virtual int Length()=0;
virtual void Flush()=0;
virtual int GetLineState(int line)=0;
virtual int SetLineState(int line, int state)=0;
virtual int GetPropertyInt(const char *key, int defaultValue=0)=0;
virtual char *GetProperties()=0;
// Style setting
virtual void StartAt(unsigned int start, char chMask=31)=0;
virtual void SetFlags(char chFlags_, char chWhile_)=0;
virtual unsigned int GetStartSegment()=0;
virtual void StartSegment(unsigned int pos)=0;
virtual void ColourTo(unsigned int pos, int chAttr)=0;
virtual void SetLevel(int line, int level)=0;
virtual int IndentAmount(int line, int *flags, PFNIsCommentLeader pfnIsCommentLeader = 0)=0;
};

View File

@@ -0,0 +1,174 @@
// Scintilla source code edit control
/** @file AutoComplete.cxx
** Defines the auto completion list box.
**/
// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "Platform.h"
#include "PropSet.h"
#include "AutoComplete.h"
AutoComplete::AutoComplete() :
active(false),
separator(' '),
typesep('?'),
ignoreCase(false),
chooseSingle(false),
lb(0),
posStart(0),
startLen(0),
cancelAtStartPos(true),
autoHide(true),
dropRestOfWord(false) {
lb = ListBox::Allocate();
stopChars[0] = '\0';
fillUpChars[0] = '\0';
}
AutoComplete::~AutoComplete() {
if (lb) {
lb->Destroy();
delete lb;
lb = 0;
}
}
bool AutoComplete::Active() {
return active;
}
void AutoComplete::Start(Window &parent, int ctrlID,
int position, Point location, int startLen_,
int lineHeight, bool unicodeMode) {
if (active) {
Cancel();
}
lb->Create(parent, ctrlID, location, lineHeight, unicodeMode);
lb->Clear();
active = true;
startLen = startLen_;
posStart = position;
}
void AutoComplete::SetStopChars(const char *stopChars_) {
strncpy(stopChars, stopChars_, sizeof(stopChars));
stopChars[sizeof(stopChars) - 1] = '\0';
}
bool AutoComplete::IsStopChar(char ch) {
return ch && strchr(stopChars, ch);
}
void AutoComplete::SetFillUpChars(const char *fillUpChars_) {
strncpy(fillUpChars, fillUpChars_, sizeof(fillUpChars));
fillUpChars[sizeof(fillUpChars) - 1] = '\0';
}
bool AutoComplete::IsFillUpChar(char ch) {
return ch && strchr(fillUpChars, ch);
}
void AutoComplete::SetSeparator(char separator_) {
separator = separator_;
}
char AutoComplete::GetSeparator() {
return separator;
}
void AutoComplete::SetTypesep(char separator_) {
typesep = separator_;
}
char AutoComplete::GetTypesep() {
return typesep;
}
void AutoComplete::SetList(const char *list) {
lb->SetList(list, separator, typesep);
}
void AutoComplete::Show(bool show) {
lb->Show(show);
if (show)
lb->Select(0);
}
void AutoComplete::Cancel() {
if (lb->Created()) {
lb->Clear();
lb->Destroy();
active = false;
}
}
void AutoComplete::Move(int delta) {
int count = lb->Length();
int current = lb->GetSelection();
current += delta;
if (current >= count)
current = count - 1;
if (current < 0)
current = 0;
lb->Select(current);
}
void AutoComplete::Select(const char *word) {
size_t lenWord = strlen(word);
int location = -1;
const int maxItemLen=1000;
char item[maxItemLen];
int start = 0; // lower bound of the api array block to search
int end = lb->Length() - 1; // upper bound of the api array block to search
while ((start <= end) && (location == -1)) { // Binary searching loop
int pivot = (start + end) / 2;
lb->GetValue(pivot, item, maxItemLen);
int cond;
if (ignoreCase)
cond = CompareNCaseInsensitive(word, item, lenWord);
else
cond = strncmp(word, item, lenWord);
if (!cond) {
// Find first match
while (pivot > start) {
lb->GetValue(pivot-1, item, maxItemLen);
if (ignoreCase)
cond = CompareNCaseInsensitive(word, item, lenWord);
else
cond = strncmp(word, item, lenWord);
if (0 != cond)
break;
--pivot;
}
location = pivot;
if (ignoreCase) {
// Check for exact-case match
for (; pivot <= end; pivot++) {
lb->GetValue(pivot, item, maxItemLen);
if (!strncmp(word, item, lenWord)) {
location = pivot;
break;
}
if (CompareNCaseInsensitive(word, item, lenWord))
break;
}
}
} else if (cond < 0) {
end = pivot - 1;
} else if (cond > 0) {
start = pivot + 1;
}
}
if (location == -1 && autoHide)
Cancel();
else
lb->Select(location);
}

View File

@@ -0,0 +1,70 @@
// Scintilla source code edit control
/** @file AutoComplete.h
** Defines the auto completion list box.
**/
// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.
#ifndef AUTOCOMPLETE_H
#define AUTOCOMPLETE_H
/**
*/
class AutoComplete {
bool active;
char stopChars[256];
char fillUpChars[256];
char separator;
char typesep; // Type seperator
public:
bool ignoreCase;
bool chooseSingle;
ListBox *lb;
int posStart;
int startLen;
/// Should autocompletion be canceled if editor's currentPos <= startPos?
bool cancelAtStartPos;
bool autoHide;
bool dropRestOfWord;
AutoComplete();
~AutoComplete();
/// Is the auto completion list displayed?
bool Active();
/// Display the auto completion list positioned to be near a character position
void Start(Window &parent, int ctrlID, int position, Point location,
int startLen_, int lineHeight, bool unicodeMode);
/// The stop chars are characters which, when typed, cause the auto completion list to disappear
void SetStopChars(const char *stopChars_);
bool IsStopChar(char ch);
/// The fillup chars are characters which, when typed, fill up the selected word
void SetFillUpChars(const char *fillUpChars_);
bool IsFillUpChar(char ch);
/// The separator character is used when interpreting the list in SetList
void SetSeparator(char separator_);
char GetSeparator();
/// The typesep character is used for seperating the word from the type
void SetTypesep(char separator_);
char GetTypesep();
/// The list string contains a sequence of words separated by the separator character
void SetList(const char *list);
void Show(bool show);
void Cancel();
/// Move the current list element by delta, scrolling appropriately
void Move(int delta);
/// Select a list element that starts with word as the current element
void Select(const char *word);
};
#endif

View File

@@ -0,0 +1,270 @@
// Scintilla source code edit control
/** @file CallTip.cxx
** Code for displaying call tips.
**/
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.
#include <stdlib.h>
#include <string.h>
#include "Platform.h"
#include "Scintilla.h"
#include "CallTip.h"
CallTip::CallTip() {
wCallTip = 0;
inCallTipMode = false;
posStartCallTip = 0;
val = 0;
rectUp = PRectangle(0,0,0,0);
rectDown = PRectangle(0,0,0,0);
lineHeight = 1;
startHighlight = 0;
endHighlight = 0;
colourBG.desired = ColourDesired(0xff, 0xff, 0xff);
colourUnSel.desired = ColourDesired(0x80, 0x80, 0x80);
colourSel.desired = ColourDesired(0, 0, 0x80);
colourShade.desired = ColourDesired(0, 0, 0);
colourLight.desired = ColourDesired(0xc0, 0xc0, 0xc0);
}
CallTip::~CallTip() {
font.Release();
wCallTip.Destroy();
delete []val;
val = 0;
}
const int widthArrow = 14;
void CallTip::RefreshColourPalette(Palette &pal, bool want) {
pal.WantFind(colourBG, want);
pal.WantFind(colourUnSel, want);
pal.WantFind(colourSel, want);
pal.WantFind(colourShade, want);
pal.WantFind(colourLight, want);
}
static bool IsArrowCharacter(char ch) {
return (ch == 0) || (ch == '\001') || (ch == '\002');
}
void CallTip::DrawChunk(Surface *surface, int &x, const char *s,
int posStart, int posEnd, int ytext, PRectangle rcClient,
bool highlight, bool draw) {
s += posStart;
int len = posEnd - posStart;
int maxEnd = 0;
int ends[10];
for (int i=0;i<len;i++) {
if (IsArrowCharacter(s[i])) {
if (i > 0)
ends[maxEnd++] = i;
ends[maxEnd++] = i+1;
}
}
ends[maxEnd++] = len;
int startSeg = 0;
int xEnd;
for (int seg = 0; seg<maxEnd; seg++) {
int endSeg = ends[seg];
if (endSeg > startSeg) {
if (IsArrowCharacter(s[startSeg])) {
xEnd = x + widthArrow;
offsetMain = xEnd;
rcClient.left = x;
rcClient.right = xEnd;
if (draw) {
const int halfWidth = widthArrow / 2 - 3;
const int centreX = x + widthArrow / 2 - 1;
const int centreY = (rcClient.top + rcClient.bottom) / 2;
surface->FillRectangle(rcClient, colourBG.allocated);
PRectangle rcClientInner(rcClient.left+1, rcClient.top+1, rcClient.right-2, rcClient.bottom-1);
surface->FillRectangle(rcClientInner, colourUnSel.allocated);
if (s[startSeg] == '\001') {
// Up arrow
Point pts[] = {
Point(centreX - halfWidth, centreY + halfWidth / 2),
Point(centreX + halfWidth, centreY + halfWidth / 2),
Point(centreX, centreY - halfWidth + halfWidth / 2),
};
surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]),
colourBG.allocated, colourBG.allocated);
} else {
// Down arrow
Point pts[] = {
Point(centreX - halfWidth, centreY - halfWidth / 2),
Point(centreX + halfWidth, centreY - halfWidth / 2),
Point(centreX, centreY + halfWidth - halfWidth / 2),
};
surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]),
colourBG.allocated, colourBG.allocated);
}
}
if (s[startSeg] == '\001') {
rectUp = rcClient;
} else if (s[startSeg] == '\002') {
rectDown = rcClient;
}
} else {
xEnd = x + surface->WidthText(font, s+startSeg, endSeg - startSeg);
if (draw) {
rcClient.left = x;
rcClient.right = xEnd;
surface->DrawTextNoClip(rcClient, font, ytext,
s+startSeg, endSeg - startSeg,
highlight ? colourSel.allocated : colourUnSel.allocated,
colourBG.allocated);
}
}
x = xEnd;
startSeg = endSeg;
}
}
}
int CallTip::PaintContents(Surface *surfaceWindow, bool draw) {
PRectangle rcClientPos = wCallTip.GetClientPosition();
PRectangle rcClientSize(0, 0, rcClientPos.right - rcClientPos.left,
rcClientPos.bottom - rcClientPos.top);
PRectangle rcClient(1, 1, rcClientSize.right - 1, rcClientSize.bottom - 1);
// To make a nice small call tip window, it is only sized to fit most normal characters without accents
int ascent = surfaceWindow->Ascent(font) - surfaceWindow->InternalLeading(font);
// For each line...
// Draw the definition in three parts: before highlight, highlighted, after highlight
int ytext = rcClient.top + ascent + 1;
rcClient.bottom = ytext + surfaceWindow->Descent(font) + 1;
char *chunkVal = val;
bool moreChunks = true;
int maxWidth = 0;
while (moreChunks) {
char *chunkEnd = strchr(chunkVal, '\n');
if (chunkEnd == NULL) {
chunkEnd = chunkVal + strlen(chunkVal);
moreChunks = false;
}
int chunkOffset = chunkVal - val;
int chunkLength = chunkEnd - chunkVal;
int chunkEndOffset = chunkOffset + chunkLength;
int thisStartHighlight = Platform::Maximum(startHighlight, chunkOffset);
thisStartHighlight = Platform::Minimum(thisStartHighlight, chunkEndOffset);
thisStartHighlight -= chunkOffset;
int thisEndHighlight = Platform::Maximum(endHighlight, chunkOffset);
thisEndHighlight = Platform::Minimum(thisEndHighlight, chunkEndOffset);
thisEndHighlight -= chunkOffset;
rcClient.top = ytext - ascent - 1;
int x = 5;
DrawChunk(surfaceWindow, x, chunkVal, 0, thisStartHighlight,
ytext, rcClient, false, draw);
DrawChunk(surfaceWindow, x, chunkVal, thisStartHighlight, thisEndHighlight,
ytext, rcClient, true, draw);
DrawChunk(surfaceWindow, x, chunkVal, thisEndHighlight, chunkLength,
ytext, rcClient, false, draw);
chunkVal = chunkEnd + 1;
ytext += lineHeight;
rcClient.bottom += lineHeight;
maxWidth = Platform::Maximum(maxWidth, x);
}
return maxWidth;
}
void CallTip::PaintCT(Surface *surfaceWindow) {
if (!val)
return;
PRectangle rcClientPos = wCallTip.GetClientPosition();
PRectangle rcClientSize(0, 0, rcClientPos.right - rcClientPos.left,
rcClientPos.bottom - rcClientPos.top);
PRectangle rcClient(1, 1, rcClientSize.right - 1, rcClientSize.bottom - 1);
surfaceWindow->FillRectangle(rcClient, colourBG.allocated);
offsetMain = 5;
PaintContents(surfaceWindow, true);
// Draw a raised border around the edges of the window
surfaceWindow->MoveTo(0, rcClientSize.bottom - 1);
surfaceWindow->PenColour(colourShade.allocated);
surfaceWindow->LineTo(rcClientSize.right - 1, rcClientSize.bottom - 1);
surfaceWindow->LineTo(rcClientSize.right - 1, 0);
surfaceWindow->PenColour(colourLight.allocated);
surfaceWindow->LineTo(0, 0);
surfaceWindow->LineTo(0, rcClientSize.bottom - 1);
}
void CallTip::MouseClick(Point pt) {
clickPlace = 0;
if (rectUp.Contains(pt))
clickPlace = 1;
if (rectDown.Contains(pt))
clickPlace = 2;
}
PRectangle CallTip::CallTipStart(int pos, Point pt, const char *defn,
const char *faceName, int size,
int codePage_, int characterSet, Window &wParent) {
clickPlace = 0;
if (val)
delete []val;
val = new char[strlen(defn) + 1];
if (!val)
return PRectangle();
strcpy(val, defn);
codePage = codePage_;
Surface *surfaceMeasure = Surface::Allocate();
if (!surfaceMeasure)
return PRectangle();
surfaceMeasure->Init(wParent.GetID());
surfaceMeasure->SetUnicodeMode(SC_CP_UTF8 == codePage);
surfaceMeasure->SetDBCSMode(codePage);
startHighlight = 0;
endHighlight = 0;
inCallTipMode = true;
posStartCallTip = pos;
int deviceHeight = surfaceMeasure->DeviceHeightFont(size);
font.Create(faceName, characterSet, deviceHeight, false, false);
// Look for multiple lines in the text
// Only support \n here - simply means container must avoid \r!
int numLines = 1;
const char *newline;
const char *look = val;
rectUp = PRectangle(0,0,0,0);
rectDown = PRectangle(0,0,0,0);
offsetMain = 5;
int width = PaintContents(surfaceMeasure, false) + 5;
while ((newline = strchr(look, '\n')) != NULL) {
look = newline + 1;
numLines++;
}
lineHeight = surfaceMeasure->Height(font);
// Extra line for border and an empty line at top and bottom
int height = lineHeight * numLines - surfaceMeasure->InternalLeading(font) + 2 + 2;
delete surfaceMeasure;
return PRectangle(pt.x - offsetMain, pt.y + 1, pt.x + width - offsetMain, pt.y + 1 + height);
}
void CallTip::CallTipCancel() {
inCallTipMode = false;
if (wCallTip.Created()) {
wCallTip.Destroy();
}
}
void CallTip::SetHighlight(int start, int end) {
// Avoid flashing by checking something has really changed
if ((start != startHighlight) || (end != endHighlight)) {
startHighlight = start;
endHighlight = end;
if (wCallTip.Created()) {
wCallTip.InvalidateAll();
}
}
}

View File

@@ -0,0 +1,65 @@
// Scintilla source code edit control
/** @file CallTip.h
** Interface to the call tip control.
**/
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.
#ifndef CALLTIP_H
#define CALLTIP_H
/**
*/
class CallTip {
int startHighlight;
int endHighlight;
char *val;
Font font;
PRectangle rectUp;
PRectangle rectDown;
int lineHeight;
int offsetMain;
// Private so CallTip objects can not be copied
CallTip(const CallTip &) {}
CallTip &operator=(const CallTip &) { return *this; }
void DrawChunk(Surface *surface, int &x, const char *s,
int posStart, int posEnd, int ytext, PRectangle rcClient,
bool highlight, bool draw);
int PaintContents(Surface *surfaceWindow, bool draw);
public:
Window wCallTip;
Window wDraw;
bool inCallTipMode;
int posStartCallTip;
ColourPair colourBG;
ColourPair colourUnSel;
ColourPair colourSel;
ColourPair colourShade;
ColourPair colourLight;
int codePage;
int clickPlace;
CallTip();
~CallTip();
/// Claim or accept palette entries for the colours required to paint a calltip.
void RefreshColourPalette(Palette &pal, bool want);
void PaintCT(Surface *surfaceWindow);
void MouseClick(Point pt);
/// Setup the calltip and return a rectangle of the area required.
PRectangle CallTipStart(int pos, Point pt, const char *defn,
const char *faceName, int size, int codePage_,
int characterSet, Window &wParent);
void CallTipCancel();
/// Set a range of characters to be displayed in a highlight style.
/// Commonly used to highlight the current parameter.
void SetHighlight(int start, int end);
};
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,250 @@
// Scintilla source code edit control
/** @file CellBuffer.h
** Manages the text of the document.
**/
// Copyright 1998-2004 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.
#ifndef CELLBUFFER_H
#define CELLBUFFER_H
/**
* This holds the marker identifier and the marker type to display.
* MarkerHandleNumbers are members of lists.
*/
struct MarkerHandleNumber {
int handle;
int number;
MarkerHandleNumber *next;
};
/**
* A marker handle set contains any number of MarkerHandleNumbers.
*/
class MarkerHandleSet {
MarkerHandleNumber *root;
public:
MarkerHandleSet();
~MarkerHandleSet();
int Length();
int NumberFromHandle(int handle);
int MarkValue(); ///< Bit set of marker numbers.
bool Contains(int handle);
bool InsertHandle(int handle, int markerNum);
void RemoveHandle(int handle);
bool RemoveNumber(int markerNum);
void CombineWith(MarkerHandleSet *other);
};
/**
* Each line stores the starting position of the first character of the line in the cell buffer
* and potentially a marker handle set. Often a line will not have any attached markers.
*/
struct LineData {
int startPosition;
MarkerHandleSet *handleSet;
LineData() : startPosition(0), handleSet(0) {
}
};
/**
* The line vector contains information about each of the lines in a cell buffer.
*/
class LineVector {
public:
int growSize;
int lines;
LineData *linesData;
int size;
int *levels;
int sizeLevels;
/// Handles are allocated sequentially and should never have to be reused as 32 bit ints are very big.
int handleCurrent;
LineVector();
~LineVector();
void Init();
void Expand(int sizeNew);
void ExpandLevels(int sizeNew=-1);
void ClearLevels();
void InsertValue(int pos, int value);
void SetValue(int pos, int value);
void Remove(int pos);
int LineFromPosition(int pos);
int AddMark(int line, int marker);
void MergeMarkers(int pos);
void DeleteMark(int line, int markerNum, bool all);
void DeleteMarkFromHandle(int markerHandle);
int LineFromHandle(int markerHandle);
};
enum actionType { insertAction, removeAction, startAction };
/**
* Actions are used to store all the information required to perform one undo/redo step.
*/
class Action {
public:
actionType at;
int position;
char *data;
int lenData;
bool mayCoalesce;
Action();
~Action();
void Create(actionType at_, int position_=0, char *data_=0, int lenData_=0, bool mayCoalesce_=true);
void Destroy();
void Grab(Action *source);
};
/**
*
*/
class UndoHistory {
Action *actions;
int lenActions;
int maxAction;
int currentAction;
int undoSequenceDepth;
int savePoint;
void EnsureUndoRoom();
public:
UndoHistory();
~UndoHistory();
void AppendAction(actionType at, int position, char *data, int length);
void BeginUndoAction();
void EndUndoAction();
void DropUndoSequence();
void DeleteUndoHistory();
/// The save point is a marker in the undo stack where the container has stated that
/// the buffer was saved. Undo and redo can move over the save point.
void SetSavePoint();
bool IsSavePoint() const;
/// To perform an undo, StartUndo is called to retrieve the number of steps, then UndoStep is
/// called that many times. Similarly for redo.
bool CanUndo() const;
int StartUndo();
const Action &GetUndoStep() const;
void CompletedUndoStep();
bool CanRedo() const;
int StartRedo();
const Action &GetRedoStep() const;
void CompletedRedoStep();
};
/**
* Holder for an expandable array of characters that supports undo and line markers.
* Based on article "Data Structures in a Bit-Mapped Text Editor"
* by Wilfred J. Hansen, Byte January 1987, page 183.
*/
class CellBuffer {
private:
char *body; ///< The cell buffer itself.
int size; ///< Allocated size of the buffer.
int length; ///< Total length of the data.
int part1len; ///< Length of the first part.
int gaplen; ///< Length of the gap between the two parts.
char *part2body; ///< The second part of the cell buffer.
///< Doesn't point after the gap but set so that
///< part2body[position] is consistent with body[position].
bool readOnly;
int growSize;
bool collectingUndo;
UndoHistory uh;
LineVector lv;
SVector lineStates;
void GapTo(int position);
void RoomFor(int insertionLength);
inline char ByteAt(int position);
void SetByteAt(int position, char ch);
public:
CellBuffer(int initialLength = 4000);
~CellBuffer();
/// Retrieving positions outside the range of the buffer works and returns 0
char CharAt(int position);
void GetCharRange(char *buffer, int position, int lengthRetrieve);
char StyleAt(int position);
int ByteLength();
int Length();
void Allocate(int newSize);
int Lines();
int LineStart(int line);
int LineFromPosition(int pos) { return lv.LineFromPosition(pos); }
const char *InsertString(int position, char *s, int insertLength);
/// Setting styles for positions outside the range of the buffer is safe and has no effect.
/// @return true if the style of a character is changed.
bool SetStyleAt(int position, char style, char mask='\377');
bool SetStyleFor(int position, int length, char style, char mask);
const char *DeleteChars(int position, int deleteLength);
bool IsReadOnly();
void SetReadOnly(bool set);
/// The save point is a marker in the undo stack where the container has stated that
/// the buffer was saved. Undo and redo can move over the save point.
void SetSavePoint();
bool IsSavePoint();
/// Line marker functions
int AddMark(int line, int markerNum);
void DeleteMark(int line, int markerNum);
void DeleteMarkFromHandle(int markerHandle);
int GetMark(int line);
void DeleteAllMarks(int markerNum);
int LineFromHandle(int markerHandle);
/// Actions without undo
void BasicInsertString(int position, char *s, int insertLength);
void BasicDeleteChars(int position, int deleteLength);
bool SetUndoCollection(bool collectUndo);
bool IsCollectingUndo();
void BeginUndoAction();
void EndUndoAction();
void DeleteUndoHistory();
/// To perform an undo, StartUndo is called to retrieve the number of steps, then UndoStep is
/// called that many times. Similarly for redo.
bool CanUndo();
int StartUndo();
const Action &GetUndoStep() const;
void PerformUndoStep();
bool CanRedo();
int StartRedo();
const Action &GetRedoStep() const;
void PerformRedoStep();
int SetLineState(int line, int state);
int GetLineState(int line);
int GetMaxLineState();
int SetLevel(int line, int level);
int GetLevel(int line);
void ClearLevels();
};
#define CELL_SIZE 2
#endif

View File

@@ -0,0 +1,283 @@
// Scintilla source code edit control
/** @file ContractionState.cxx
** Manages visibility of lines for folding.
**/
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.
#include "Platform.h"
#include "ContractionState.h"
OneLine::OneLine() {
displayLine = 0;
//docLine = 0;
visible = true;
height = 1;
expanded = true;
}
ContractionState::ContractionState() {
lines = 0;
size = 0;
linesInDoc = 1;
linesInDisplay = 1;
valid = false;
docLines = 0;
sizeDocLines = 0;
}
ContractionState::~ContractionState() {
Clear();
}
void ContractionState::MakeValid() const {
if (!valid) {
// Could be cleverer by keeping the index of the last still valid entry
// rather than invalidating all.
linesInDisplay = 0;
for (int lineInDoc=0; lineInDoc<linesInDoc; lineInDoc++) {
lines[lineInDoc].displayLine = linesInDisplay;
if (lines[lineInDoc].visible) {
linesInDisplay += lines[lineInDoc].height;
}
}
if (sizeDocLines < linesInDisplay) {
delete []docLines;
int *docLinesNew = new int[linesInDisplay + growSize];
if (!docLinesNew) {
docLines = 0;
sizeDocLines = 0;
return;
}
docLines = docLinesNew;
sizeDocLines = linesInDisplay + growSize;
}
int lineInDisplay=0;
for (int line=0; line<linesInDoc; line++) {
if (lines[line].visible) {
for (int linePiece=0; linePiece<lines[line].height; linePiece++) {
docLines[lineInDisplay] = line;
lineInDisplay++;
}
}
}
valid = true;
}
}
void ContractionState::Clear() {
delete []lines;
lines = 0;
size = 0;
linesInDoc = 1;
linesInDisplay = 1;
delete []docLines;
docLines = 0;
sizeDocLines = 0;
}
int ContractionState::LinesInDoc() const {
return linesInDoc;
}
int ContractionState::LinesDisplayed() const {
if (size != 0) {
MakeValid();
}
return linesInDisplay;
}
int ContractionState::DisplayFromDoc(int lineDoc) const {
if (size == 0) {
return lineDoc;
}
MakeValid();
if ((lineDoc >= 0) && (lineDoc < linesInDoc)) {
return lines[lineDoc].displayLine;
}
return -1;
}
int ContractionState::DocFromDisplay(int lineDisplay) const {
if (lineDisplay <= 0)
return 0;
if (lineDisplay >= linesInDisplay)
return linesInDoc;
if (size == 0)
return lineDisplay;
MakeValid();
if (docLines) { // Valid allocation
return docLines[lineDisplay];
} else {
return 0;
}
}
void ContractionState::Grow(int sizeNew) {
OneLine *linesNew = new OneLine[sizeNew];
if (linesNew) {
int i = 0;
for (; i < size; i++) {
linesNew[i] = lines[i];
}
for (; i < sizeNew; i++) {
linesNew[i].displayLine = i;
}
delete []lines;
lines = linesNew;
size = sizeNew;
valid = false;
} else {
Platform::DebugPrintf("No memory available\n");
// TODO: Blow up
}
}
void ContractionState::InsertLines(int lineDoc, int lineCount) {
if (size == 0) {
linesInDoc += lineCount;
linesInDisplay += lineCount;
return;
}
//Platform::DebugPrintf("InsertLine[%d] = %d\n", lineDoc);
if ((linesInDoc + lineCount + 2) >= size) {
Grow(linesInDoc + lineCount + growSize);
}
linesInDoc += lineCount;
for (int i = linesInDoc; i >= lineDoc + lineCount; i--) {
lines[i].visible = lines[i - lineCount].visible;
lines[i].height = lines[i - lineCount].height;
linesInDisplay += lines[i].height;
lines[i].expanded = lines[i - lineCount].expanded;
}
for (int d=0;d<lineCount;d++) {
lines[lineDoc+d].visible = true; // Should inherit visibility from context ?
lines[lineDoc+d].height = 1;
lines[lineDoc+d].expanded = true;
}
valid = false;
}
void ContractionState::DeleteLines(int lineDoc, int lineCount) {
if (size == 0) {
linesInDoc -= lineCount;
linesInDisplay -= lineCount;
return;
}
int deltaDisplayed = 0;
for (int d=0;d<lineCount;d++) {
if (lines[lineDoc+d].visible)
deltaDisplayed -= lines[lineDoc+d].height;
}
for (int i = lineDoc; i < linesInDoc-lineCount; i++) {
if (i != 0) // Line zero is always visible
lines[i].visible = lines[i + lineCount].visible;
lines[i].expanded = lines[i + lineCount].expanded;
lines[i].height = lines[i + lineCount].height;
}
linesInDoc -= lineCount;
linesInDisplay += deltaDisplayed;
valid = false;
}
bool ContractionState::GetVisible(int lineDoc) const {
if (size == 0)
return true;
if ((lineDoc >= 0) && (lineDoc < linesInDoc)) {
return lines[lineDoc].visible;
} else {
return false;
}
}
bool ContractionState::SetVisible(int lineDocStart, int lineDocEnd, bool visible) {
if (lineDocStart == 0)
lineDocStart++;
if (lineDocStart > lineDocEnd)
return false;
if (size == 0) {
Grow(linesInDoc + growSize);
}
// TODO: modify docLine members to mirror displayLine
int delta = 0;
// Change lineDocs
if ((lineDocStart <= lineDocEnd) && (lineDocStart >= 0) && (lineDocEnd < linesInDoc)) {
for (int line=lineDocStart; line <= lineDocEnd; line++) {
if (lines[line].visible != visible) {
delta += visible ? lines[line].height : -lines[line].height;
lines[line].visible = visible;
}
}
}
linesInDisplay += delta;
valid = false;
return delta != 0;
}
bool ContractionState::GetExpanded(int lineDoc) const {
if (size == 0)
return true;
if ((lineDoc >= 0) && (lineDoc < linesInDoc)) {
return lines[lineDoc].expanded;
} else {
return false;
}
}
bool ContractionState::SetExpanded(int lineDoc, bool expanded) {
if (size == 0) {
if (expanded) {
// If in completely expanded state then setting
// one line to expanded has no effect.
return false;
}
Grow(linesInDoc + growSize);
}
if ((lineDoc >= 0) && (lineDoc < linesInDoc)) {
if (lines[lineDoc].expanded != expanded) {
lines[lineDoc].expanded = expanded;
return true;
}
}
return false;
}
int ContractionState::GetHeight(int lineDoc) const {
if (size == 0)
return 1;
if ((lineDoc >= 0) && (lineDoc < linesInDoc)) {
return lines[lineDoc].height;
} else {
return 1;
}
}
// Set the number of display lines needed for this line.
// Return true if this is a change.
bool ContractionState::SetHeight(int lineDoc, int height) {
if (lineDoc > linesInDoc)
return false;
if (size == 0) {
if (height == 1) {
// If in completely expanded state then all lines
// assumed to have height of one so no effect here.
return false;
}
Grow(linesInDoc + growSize);
}
if (lines[lineDoc].height != height) {
lines[lineDoc].height = height;
valid = false;
return true;
} else {
return false;
}
}
void ContractionState::ShowAll() {
delete []lines;
lines = 0;
size = 0;
}

View File

@@ -0,0 +1,65 @@
// Scintilla source code edit control
/** @file ContractionState.h
** Manages visibility of lines for folding.
**/
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.
#ifndef CONTRACTIONSTATE_H
#define CONTRACTIONSTATE_H
/**
*/
class OneLine {
public:
int displayLine; ///< Position within set of visible lines
//int docLine; ///< Inverse of @a displayLine
int height; ///< Number of display lines needed to show all of the line
bool visible;
bool expanded;
OneLine();
virtual ~OneLine() {}
};
/**
*/
class ContractionState {
void Grow(int sizeNew);
enum { growSize = 4000 };
int linesInDoc;
mutable int linesInDisplay;
mutable OneLine *lines;
int size;
mutable int *docLines;
mutable int sizeDocLines;
mutable bool valid;
void MakeValid() const;
public:
ContractionState();
virtual ~ContractionState();
void Clear();
int LinesInDoc() const;
int LinesDisplayed() const;
int DisplayFromDoc(int lineDoc) const;
int DocFromDisplay(int lineDisplay) const;
void InsertLines(int lineDoc, int lineCount);
void DeleteLines(int lineDoc, int lineCount);
bool GetVisible(int lineDoc) const;
bool SetVisible(int lineDocStart, int lineDocEnd, bool visible);
bool GetExpanded(int lineDoc) const;
bool SetExpanded(int lineDoc, bool expanded);
int GetHeight(int lineDoc) const;
bool SetHeight(int lineDoc, int height);
void ShowAll();
};
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,305 @@
// Scintilla source code edit control
/** @file Document.h
** Text document that handles notifications, DBCS, styling, words and end of line.
**/
// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.
#ifndef DOCUMENT_H
#define DOCUMENT_H
/**
* A Position is a position within a document between two characters or at the beginning or end.
* Sometimes used as a character index where it identifies the character after the position.
*/
typedef int Position;
const Position invalidPosition = -1;
/**
* The range class represents a range of text in a document.
* The two values are not sorted as one end may be more significant than the other
* as is the case for the selection where the end position is the position of the caret.
* If either position is invalidPosition then the range is invalid and most operations will fail.
*/
class Range {
public:
Position start;
Position end;
Range(Position pos=0) :
start(pos), end(pos) {
};
Range(Position start_, Position end_) :
start(start_), end(end_) {
};
bool Valid() const {
return (start != invalidPosition) && (end != invalidPosition);
}
// Is the position within the range?
bool Contains(Position pos) const {
if (start < end) {
return (pos >= start && pos <= end);
} else {
return (pos <= start && pos >= end);
}
}
// Is the character after pos within the range?
bool ContainsCharacter(Position pos) const {
if (start < end) {
return (pos >= start && pos < end);
} else {
return (pos < start && pos >= end);
}
}
bool Contains(Range other) const {
return Contains(other.start) && Contains(other.end);
}
bool Overlaps(Range other) const {
return
Contains(other.start) ||
Contains(other.end) ||
other.Contains(start) ||
other.Contains(end);
}
};
class DocWatcher;
class DocModification;
class RESearch;
/**
*/
class Document {
public:
/** Used to pair watcher pointer with user data. */
class WatcherWithUserData {
public:
DocWatcher *watcher;
void *userData;
WatcherWithUserData() {
watcher = 0;
userData = 0;
}
};
enum charClassification { ccSpace, ccNewLine, ccWord, ccPunctuation };
private:
int refCount;
CellBuffer cb;
charClassification charClass[256];
char stylingMask;
int endStyled;
int styleClock;
int enteredCount;
int enteredReadOnlyCount;
WatcherWithUserData *watchers;
int lenWatchers;
bool matchesValid;
RESearch *pre;
char *substituted;
public:
int stylingBits;
int stylingBitsMask;
int eolMode;
/// Can also be SC_CP_UTF8 to enable UTF-8 mode
int dbcsCodePage;
int tabInChars;
int indentInChars;
int actualIndentInChars;
bool useTabs;
bool tabIndents;
bool backspaceUnindents;
Document();
virtual ~Document();
int AddRef();
int Release();
int LineFromPosition(int pos);
int ClampPositionIntoDocument(int pos);
bool IsCrLf(int pos);
int LenChar(int pos);
int MovePositionOutsideChar(int pos, int moveDir, bool checkLineEnd=true);
// Gateways to modifying document
void ModifiedAt(int pos);
bool DeleteChars(int pos, int len);
bool InsertStyledString(int position, char *s, int insertLength);
int Undo();
int Redo();
bool CanUndo() { return cb.CanUndo(); }
bool CanRedo() { return cb.CanRedo(); }
void DeleteUndoHistory() { cb.DeleteUndoHistory(); }
bool SetUndoCollection(bool collectUndo) {
return cb.SetUndoCollection(collectUndo);
}
bool IsCollectingUndo() { return cb.IsCollectingUndo(); }
void BeginUndoAction() { cb.BeginUndoAction(); }
void EndUndoAction() { cb.EndUndoAction(); }
void SetSavePoint();
bool IsSavePoint() { return cb.IsSavePoint(); }
int GetLineIndentation(int line);
void SetLineIndentation(int line, int indent);
int GetLineIndentPosition(int line);
int GetColumn(int position);
int FindColumn(int line, int column);
void Indent(bool forwards, int lineBottom, int lineTop);
static char *TransformLineEnds(int *pLenOut, const char *s, size_t len, int eolMode);
void ConvertLineEnds(int eolModeSet);
void SetReadOnly(bool set) { cb.SetReadOnly(set); }
bool IsReadOnly() { return cb.IsReadOnly(); }
bool InsertChar(int pos, char ch);
bool InsertString(int position, const char *s);
bool InsertString(int position, const char *s, size_t insertLength);
void ChangeChar(int pos, char ch);
void DelChar(int pos);
void DelCharBack(int pos);
char CharAt(int position) { return cb.CharAt(position); }
void GetCharRange(char *buffer, int position, int lengthRetrieve) {
cb.GetCharRange(buffer, position, lengthRetrieve);
}
char StyleAt(int position) { return cb.StyleAt(position); }
int GetMark(int line) { return cb.GetMark(line); }
int AddMark(int line, int markerNum);
void AddMarkSet(int line, int valueSet);
void DeleteMark(int line, int markerNum);
void DeleteMarkFromHandle(int markerHandle);
void DeleteAllMarks(int markerNum);
int LineFromHandle(int markerHandle) { return cb.LineFromHandle(markerHandle); }
int LineStart(int line);
int LineEnd(int line);
int LineEndPosition(int position);
int VCHomePosition(int position);
int SetLevel(int line, int level);
int GetLevel(int line) { return cb.GetLevel(line); }
void ClearLevels() { cb.ClearLevels(); }
int GetLastChild(int lineParent, int level=-1);
int GetFoldParent(int line);
void Indent(bool forwards);
int ExtendWordSelect(int pos, int delta, bool onlyWordCharacters=false);
int NextWordStart(int pos, int delta);
int NextWordEnd(int pos, int delta);
int Length() { return cb.Length(); }
void Allocate(int newSize) { cb.Allocate(newSize*2); }
long FindText(int minPos, int maxPos, const char *s,
bool caseSensitive, bool word, bool wordStart, bool regExp, bool posix, int *length);
long FindText(int iMessage, unsigned long wParam, long lParam);
const char *SubstituteByPosition(const char *text, int *length);
int LinesTotal();
void ChangeCase(Range r, bool makeUpperCase);
void SetDefaultCharClasses(bool includeWordClass);
void SetCharClasses(const unsigned char *chars, charClassification newCharClass);
void SetStylingBits(int bits);
void StartStyling(int position, char mask);
bool SetStyleFor(int length, char style);
bool SetStyles(int length, char *styles);
int GetEndStyled() { return endStyled; }
bool EnsureStyledTo(int pos);
int GetStyleClock() { return styleClock; }
void IncrementStyleClock();
int SetLineState(int line, int state) { return cb.SetLineState(line, state); }
int GetLineState(int line) { return cb.GetLineState(line); }
int GetMaxLineState() { return cb.GetMaxLineState(); }
bool AddWatcher(DocWatcher *watcher, void *userData);
bool RemoveWatcher(DocWatcher *watcher, void *userData);
const WatcherWithUserData *GetWatchers() const { return watchers; }
int GetLenWatchers() const { return lenWatchers; }
bool IsWordPartSeparator(char ch);
int WordPartLeft(int pos);
int WordPartRight(int pos);
int ExtendStyleRange(int pos, int delta, bool singleLine = false);
bool IsWhiteLine(int line);
int ParaUp(int pos);
int ParaDown(int pos);
int IndentSize() { return actualIndentInChars; }
int BraceMatch(int position, int maxReStyle);
private:
void CheckReadOnly();
charClassification WordCharClass(unsigned char ch);
bool IsWordStartAt(int pos);
bool IsWordEndAt(int pos);
bool IsWordAt(int start, int end);
void NotifyModifyAttempt();
void NotifySavePoint(bool atSavePoint);
void NotifyModified(DocModification mh);
};
/**
* To optimise processing of document modifications by DocWatchers, a hint is passed indicating the
* scope of the change.
* If the DocWatcher is a document view then this can be used to optimise screen updating.
*/
class DocModification {
public:
int modificationType;
int position;
int length;
int linesAdded; /**< Negative if lines deleted. */
const char *text; /**< Only valid for changes to text, not for changes to style. */
int line;
int foldLevelNow;
int foldLevelPrev;
DocModification(int modificationType_, int position_=0, int length_=0,
int linesAdded_=0, const char *text_=0, int line_=0) :
modificationType(modificationType_),
position(position_),
length(length_),
linesAdded(linesAdded_),
text(text_),
line(line_),
foldLevelNow(0),
foldLevelPrev(0) {}
DocModification(int modificationType_, const Action &act, int linesAdded_=0) :
modificationType(modificationType_),
position(act.position),
length(act.lenData),
linesAdded(linesAdded_),
text(act.data),
line(0),
foldLevelNow(0),
foldLevelPrev(0) {}
};
/**
* A class that wants to receive notifications from a Document must be derived from DocWatcher
* and implement the notification methods. It can then be added to the watcher list with AddWatcher.
*/
class DocWatcher {
public:
virtual ~DocWatcher() {}
virtual void NotifyModifyAttempt(Document *doc, void *userData) = 0;
virtual void NotifySavePoint(Document *doc, void *userData, bool atSavePoint) = 0;
virtual void NotifyModified(Document *doc, DocModification mh, void *userData) = 0;
virtual void NotifyDeleted(Document *doc, void *userData) = 0;
virtual void NotifyStyleNeeded(Document *doc, void *userData, int endPos) = 0;
};
#endif

View File

@@ -0,0 +1,186 @@
// Scintilla source code edit control
/** @file DocumentAccessor.cxx
** Rapid easy access to contents of a Scintilla.
**/
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include "Platform.h"
#include "PropSet.h"
#include "SVector.h"
#include "Accessor.h"
#include "DocumentAccessor.h"
#include "CellBuffer.h"
#include "Scintilla.h"
#include "Document.h"
DocumentAccessor::~DocumentAccessor() {
}
bool DocumentAccessor::InternalIsLeadByte(char ch) {
if (SC_CP_UTF8 == codePage)
// For lexing, all characters >= 0x80 are treated the
// same so none is considered a lead byte.
return false;
else
return Platform::IsDBCSLeadByte(codePage, ch);
}
void DocumentAccessor::Fill(int position) {
if (lenDoc == -1)
lenDoc = pdoc->Length();
startPos = position - slopSize;
if (startPos + bufferSize > lenDoc)
startPos = lenDoc - bufferSize;
if (startPos < 0)
startPos = 0;
endPos = startPos + bufferSize;
if (endPos > lenDoc)
endPos = lenDoc;
pdoc->GetCharRange(buf, startPos, endPos-startPos);
buf[endPos-startPos] = '\0';
}
bool DocumentAccessor::Match(int pos, const char *s) {
for (int i=0; *s; i++) {
if (*s != SafeGetCharAt(pos+i))
return false;
s++;
}
return true;
}
char DocumentAccessor::StyleAt(int position) {
// Mask off all bits which aren't in the 'mask'.
return static_cast<char>(pdoc->StyleAt(position) & mask);
}
int DocumentAccessor::GetLine(int position) {
return pdoc->LineFromPosition(position);
}
int DocumentAccessor::LineStart(int line) {
return pdoc->LineStart(line);
}
int DocumentAccessor::LevelAt(int line) {
return pdoc->GetLevel(line);
}
int DocumentAccessor::Length() {
if (lenDoc == -1)
lenDoc = pdoc->Length();
return lenDoc;
}
int DocumentAccessor::GetLineState(int line) {
return pdoc->GetLineState(line);
}
int DocumentAccessor::SetLineState(int line, int state) {
return pdoc->SetLineState(line, state);
}
void DocumentAccessor::StartAt(unsigned int start, char chMask) {
// Store the mask specified for use with StyleAt.
mask = chMask;
pdoc->StartStyling(start, chMask);
startPosStyling = start;
}
void DocumentAccessor::StartSegment(unsigned int pos) {
startSeg = pos;
}
void DocumentAccessor::ColourTo(unsigned int pos, int chAttr) {
// Only perform styling if non empty range
if (pos != startSeg - 1) {
if (pos < startSeg) {
Platform::DebugPrintf("Bad colour positions %d - %d\n", startSeg, pos);
}
if (validLen + (pos - startSeg + 1) >= bufferSize)
Flush();
if (validLen + (pos - startSeg + 1) >= bufferSize) {
// Too big for buffer so send directly
pdoc->SetStyleFor(pos - startSeg + 1, static_cast<char>(chAttr));
} else {
if (chAttr != chWhile)
chFlags = 0;
chAttr |= chFlags;
for (unsigned int i = startSeg; i <= pos; i++) {
PLATFORM_ASSERT((startPosStyling + validLen) < Length());
styleBuf[validLen++] = static_cast<char>(chAttr);
}
}
}
startSeg = pos+1;
}
void DocumentAccessor::SetLevel(int line, int level) {
pdoc->SetLevel(line, level);
}
void DocumentAccessor::Flush() {
startPos = extremePosition;
lenDoc = -1;
if (validLen > 0) {
pdoc->SetStyles(validLen, styleBuf);
startPosStyling += validLen;
validLen = 0;
}
}
int DocumentAccessor::IndentAmount(int line, int *flags, PFNIsCommentLeader pfnIsCommentLeader) {
int end = Length();
int spaceFlags = 0;
// Determines the indentation level of the current line and also checks for consistent
// indentation compared to the previous line.
// Indentation is judged consistent when the indentation whitespace of each line lines
// the same or the indentation of one line is a prefix of the other.
int pos = LineStart(line);
char ch = (*this)[pos];
int indent = 0;
bool inPrevPrefix = line > 0;
int posPrev = inPrevPrefix ? LineStart(line-1) : 0;
while ((ch == ' ' || ch == '\t') && (pos < end)) {
if (inPrevPrefix) {
char chPrev = (*this)[posPrev++];
if (chPrev == ' ' || chPrev == '\t') {
if (chPrev != ch)
spaceFlags |= wsInconsistent;
} else {
inPrevPrefix = false;
}
}
if (ch == ' ') {
spaceFlags |= wsSpace;
indent++;
} else { // Tab
spaceFlags |= wsTab;
if (spaceFlags & wsSpace)
spaceFlags |= wsSpaceTab;
indent = (indent / 8 + 1) * 8;
}
ch = (*this)[++pos];
}
*flags = spaceFlags;
indent += SC_FOLDLEVELBASE;
// if completely empty line or the start of a comment...
if ((ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r') ||
(pfnIsCommentLeader && (*pfnIsCommentLeader)(*this, pos, end-pos)) )
return indent | SC_FOLDLEVELWHITEFLAG;
else
return indent;
}

View File

@@ -0,0 +1,67 @@
// Scintilla source code edit control
/** @file DocumentAccessor.h
** Implementation of BufferAccess and StylingAccess on a Scintilla
** rapid easy access to contents of a Scintilla.
**/
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.
class Document;
/**
*/
class DocumentAccessor : public Accessor {
// Private so DocumentAccessor objects can not be copied
DocumentAccessor(const DocumentAccessor &source) : Accessor(), props(source.props) {}
DocumentAccessor &operator=(const DocumentAccessor &) { return *this; }
protected:
Document *pdoc;
PropSet &props;
WindowID id;
int lenDoc;
char styleBuf[bufferSize];
int validLen;
char chFlags;
char chWhile;
unsigned int startSeg;
int startPosStyling;
int mask;
bool InternalIsLeadByte(char ch);
void Fill(int position);
public:
DocumentAccessor(Document *pdoc_, PropSet &props_, WindowID id_=0) :
Accessor(), pdoc(pdoc_), props(props_), id(id_),
lenDoc(-1), validLen(0), chFlags(0), chWhile(0),
startSeg(0), startPosStyling(0),
mask(127) { // Initialize the mask to be big enough for any lexer.
}
~DocumentAccessor();
bool Match(int pos, const char *s);
char StyleAt(int position);
int GetLine(int position);
int LineStart(int line);
int LevelAt(int line);
int Length();
void Flush();
int GetLineState(int line);
int SetLineState(int line, int state);
int GetPropertyInt(const char *key, int defaultValue=0) {
return props.GetInt(key, defaultValue);
}
char *GetProperties() {
return props.ToString();
}
WindowID GetWindow() { return id; }
void StartAt(unsigned int start, char chMask=31);
void SetFlags(char chFlags_, char chWhile_) {chFlags = chFlags_; chWhile = chWhile_; };
unsigned int GetStartSegment() { return startSeg; }
void StartSegment(unsigned int pos);
void ColourTo(unsigned int pos, int chAttr);
void SetLevel(int line, int level);
int IndentAmount(int line, int *flags, PFNIsCommentLeader pfnIsCommentLeader = 0);
};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,581 @@
// Scintilla source code edit control
/** @file Editor.h
** Defines the main editor class.
**/
// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.
#ifndef EDITOR_H
#define EDITOR_H
/**
*/
class Caret {
public:
bool active;
bool on;
int period;
Caret();
};
/**
*/
class Timer {
public:
bool ticking;
int ticksToWait;
enum {tickSize = 100};
TickerID tickerID;
Timer();
};
/**
*/
class Idler {
public:
bool state;
IdlerID idlerID;
Idler();
};
/**
*/
class LineLayout {
private:
friend class LineLayoutCache;
int *lineStarts;
int lenLineStarts;
/// Drawing is only performed for @a maxLineLength characters on each line.
int lineNumber;
bool inCache;
public:
enum { wrapWidthInfinite = 0x7ffffff };
int maxLineLength;
int numCharsInLine;
enum validLevel { llInvalid, llCheckTextAndStyle, llPositions, llLines } validity;
int xHighlightGuide;
bool highlightColumn;
int selStart;
int selEnd;
bool containsCaret;
int edgeColumn;
char *chars;
unsigned char *styles;
int styleBitsSet;
char *indicators;
int *positions;
char bracePreviousStyles[2];
// Hotspot support
int hsStart;
int hsEnd;
// Wrapped line support
int widthLine;
int lines;
LineLayout(int maxLineLength_);
virtual ~LineLayout();
void Resize(int maxLineLength_);
void Free();
void Invalidate(validLevel validity_);
int LineStart(int line) {
if (line <= 0) {
return 0;
} else if ((line >= lines) || !lineStarts) {
return numCharsInLine;
} else {
return lineStarts[line];
}
}
void SetLineStart(int line, int start);
void SetBracesHighlight(Range rangeLine, Position braces[],
char bracesMatchStyle, int xHighlight);
void RestoreBracesHighlight(Range rangeLine, Position braces[]);
};
/**
*/
class LineLayoutCache {
int level;
int length;
int size;
LineLayout **cache;
bool allInvalidated;
int styleClock;
int useCount;
void Allocate(int length_);
void AllocateForLevel(int linesOnScreen, int linesInDoc);
public:
LineLayoutCache();
virtual ~LineLayoutCache();
void Deallocate();
enum {
llcNone=SC_CACHE_NONE,
llcCaret=SC_CACHE_CARET,
llcPage=SC_CACHE_PAGE,
llcDocument=SC_CACHE_DOCUMENT
};
void Invalidate(LineLayout::validLevel validity_);
void SetLevel(int level_);
int GetLevel() { return level; }
LineLayout *Retrieve(int lineNumber, int lineCaret, int maxChars, int styleClock_,
int linesOnScreen, int linesInDoc);
void Dispose(LineLayout *ll);
};
/**
* Hold a piece of text selected for copying or dragging.
* The text is expected to hold a terminating "\0" and this is counted in len.
*/
class SelectionText {
public:
char *s;
int len;
bool rectangular;
int codePage;
int characterSet;
SelectionText() : s(0), len(0), rectangular(false), codePage(0), characterSet(0) {}
~SelectionText() {
Free();
}
void Free() {
Set(0, 0, 0, 0, false);
}
void Set(char *s_, int len_, int codePage_, int characterSet_, bool rectangular_) {
delete []s;
s = s_;
if (s)
len = len_;
else
len = 0;
codePage = codePage_;
characterSet = characterSet_;
rectangular = rectangular_;
}
void Copy(const char *s_, int len_, int codePage_, int characterSet_, bool rectangular_) {
delete []s;
s = new char[len_];
if (s) {
len = len_;
for (int i = 0; i < len_; i++) {
s[i] = s_[i];
}
} else {
len = 0;
}
codePage = codePage_;
characterSet = characterSet_;
rectangular = rectangular_;
}
void Copy(const SelectionText &other) {
Copy(other.s, other.len, other.codePage, other.characterSet, other.rectangular);
}
};
/**
*/
class Editor : public DocWatcher {
// Private so Editor objects can not be copied
Editor(const Editor &) : DocWatcher() {}
Editor &operator=(const Editor &) { return *this; }
protected: // ScintillaBase subclass needs access to much of Editor
/** On GTK+, Scintilla is a container widget holding two scroll bars
* whereas on Windows there is just one window with both scroll bars turned on. */
Window wMain; ///< The Scintilla parent window
/** Style resources may be expensive to allocate so are cached between uses.
* When a style attribute is changed, this cache is flushed. */
bool stylesValid;
ViewStyle vs;
Palette palette;
int printMagnification;
int printColourMode;
int printWrapState;
int cursorMode;
int controlCharSymbol;
bool hasFocus;
bool hideSelection;
bool inOverstrike;
int errorStatus;
bool mouseDownCaptures;
/** In bufferedDraw mode, graphics operations are drawn to a pixmap and then copied to
* the screen. This avoids flashing but is about 30% slower. */
bool bufferedDraw;
/** In twoPhaseDraw mode, drawing is performed in two phases, first the background
* and then the foreground. This avoids chopping off characters that overlap the next run. */
bool twoPhaseDraw;
int xOffset; ///< Horizontal scrolled amount in pixels
int xCaretMargin; ///< Ensure this many pixels visible on both sides of caret
bool horizontalScrollBarVisible;
int scrollWidth;
bool verticalScrollBarVisible;
bool endAtLastLine;
bool caretSticky;
Surface *pixmapLine;
Surface *pixmapSelMargin;
Surface *pixmapSelPattern;
Surface *pixmapIndentGuide;
Surface *pixmapIndentGuideHighlight;
LineLayoutCache llc;
KeyMap kmap;
Caret caret;
Timer timer;
Timer autoScrollTimer;
enum { autoScrollDelay = 200 };
Idler idler;
Point lastClick;
unsigned int lastClickTime;
int dwellDelay;
int ticksToDwell;
bool dwelling;
enum { selChar, selWord, selLine } selectionType;
Point ptMouseLast;
bool inDragDrop;
bool dropWentOutside;
int posDrag;
int posDrop;
int lastXChosen;
int lineAnchor;
int originalAnchorPos;
int currentPos;
int anchor;
int targetStart;
int targetEnd;
int searchFlags;
int topLine;
int posTopLine;
int lengthForEncode;
bool needUpdateUI;
Position braces[2];
int bracesMatchStyle;
int highlightGuideColumn;
int theEdge;
enum { notPainting, painting, paintAbandoned } paintState;
PRectangle rcPaint;
bool paintingAllText;
int modEventMask;
SelectionText drag;
enum selTypes { noSel, selStream, selRectangle, selLines };
selTypes selType;
bool moveExtendsSelection;
int xStartSelect; ///< x position of start of rectangular selection
int xEndSelect; ///< x position of end of rectangular selection
bool primarySelection;
int caretXPolicy;
int caretXSlop; ///< Ensure this many pixels visible on both sides of caret
int caretYPolicy;
int caretYSlop; ///< Ensure this many lines visible on both sides of caret
int visiblePolicy;
int visibleSlop;
int searchAnchor;
bool recordingMacro;
int foldFlags;
ContractionState cs;
// Hotspot support
int hsStart;
int hsEnd;
// Wrapping support
enum { eWrapNone, eWrapWord, eWrapChar } wrapState;
bool backgroundWrapEnabled;
int wrapWidth;
int docLineLastWrapped;
int docLastLineToWrap;
int wrapVisualFlags;
int wrapVisualFlagsLocation;
int wrapVisualStartIndent;
int actualWrapVisualStartIndent;
bool convertPastes;
Document *pdoc;
Editor();
virtual ~Editor();
virtual void Initialise() = 0;
virtual void Finalise();
void InvalidateStyleData();
void InvalidateStyleRedraw();
virtual void RefreshColourPalette(Palette &pal, bool want);
void RefreshStyleData();
void DropGraphics();
virtual PRectangle GetClientRectangle();
PRectangle GetTextRectangle();
int LinesOnScreen();
int LinesToScroll();
int MaxScrollPos();
Point LocationFromPosition(int pos);
int XFromPosition(int pos);
int PositionFromLocation(Point pt);
int PositionFromLocationClose(Point pt);
int PositionFromLineX(int line, int x);
int LineFromLocation(Point pt);
void SetTopLine(int topLineNew);
bool AbandonPaint();
void RedrawRect(PRectangle rc);
void Redraw();
void RedrawSelMargin(int line=-1);
PRectangle RectangleFromRange(int start, int end);
void InvalidateRange(int start, int end);
int CurrentPosition();
bool SelectionEmpty();
int SelectionStart();
int SelectionEnd();
void SetRectangularRange();
void InvalidateSelection(int currentPos_, int anchor_);
void SetSelection(int currentPos_, int anchor_);
void SetSelection(int currentPos_);
void SetEmptySelection(int currentPos_);
bool RangeContainsProtected(int start, int end) const;
bool SelectionContainsProtected();
int MovePositionOutsideChar(int pos, int moveDir, bool checkLineEnd=true);
int MovePositionTo(int newPos, selTypes sel=noSel, bool ensureVisible=true);
int MovePositionSoVisible(int pos, int moveDir);
void SetLastXChosen();
void ScrollTo(int line, bool moveThumb=true);
virtual void ScrollText(int linesToMove);
void HorizontalScrollTo(int xPos);
void MoveCaretInsideView(bool ensureVisible=true);
int DisplayFromPosition(int pos);
void EnsureCaretVisible(bool useMargin=true, bool vert=true, bool horiz=true);
void ShowCaretAtCurrentPosition();
void DropCaret();
void InvalidateCaret();
virtual void UpdateSystemCaret();
void NeedWrapping(int docLineStartWrapping = 0, int docLineEndWrapping = 0x7ffffff);
bool WrapLines(bool fullWrap, int priorityWrapLineStart);
void LinesJoin();
void LinesSplit(int pixelWidth);
int SubstituteMarkerIfEmpty(int markerCheck, int markerDefault);
void PaintSelMargin(Surface *surface, PRectangle &rc);
LineLayout *RetrieveLineLayout(int lineNumber);
void LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayout *ll,
int width=LineLayout::wrapWidthInfinite);
ColourAllocated TextBackground(ViewStyle &vsDraw, bool overrideBackground, ColourAllocated background, bool inSelection, bool inHotspot, int styleMain, int i, LineLayout *ll);
void DrawIndentGuide(Surface *surface, int lineVisible, int lineHeight, int start, PRectangle rcSegment, bool highlight);
void DrawWrapMarker(Surface *surface, PRectangle rcPlace, bool isEndMarker, ColourAllocated wrapColour);
void DrawEOL(Surface *surface, ViewStyle &vsDraw, PRectangle rcLine, LineLayout *ll,
int line, int lineEnd, int xStart, int subLine, int subLineStart,
bool overrideBackground, ColourAllocated background,
bool drawWrapMark, ColourAllocated wrapColour);
void DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVisible, int xStart,
PRectangle rcLine, LineLayout *ll, int subLine=0);
void RefreshPixMaps(Surface *surfaceWindow);
void Paint(Surface *surfaceWindow, PRectangle rcArea);
long FormatRange(bool draw, RangeToFormat *pfr);
int TextWidth(int style, const char *text);
virtual void SetVerticalScrollPos() = 0;
virtual void SetHorizontalScrollPos() = 0;
virtual bool ModifyScrollBars(int nMax, int nPage) = 0;
virtual void ReconfigureScrollBars();
void SetScrollBars();
void ChangeSize();
void AddChar(char ch);
virtual void AddCharUTF(char *s, unsigned int len, bool treatAsDBCS=false);
void ClearSelection();
void ClearAll();
void ClearDocumentStyle();
void Cut();
void PasteRectangular(int pos, const char *ptr, int len);
virtual void Copy() = 0;
virtual bool CanPaste();
virtual void Paste() = 0;
void OpenAppArmorInclude();
void Clear();
void SelectAll();
void Undo();
void Redo();
void DelChar();
void DelCharBack(bool allowLineStartDeletion);
virtual void ClaimSelection() = 0;
virtual void NotifyChange() = 0;
virtual void NotifyFocus(bool focus);
virtual int GetCtrlID() { return ctrlID; }
virtual void NotifyParent(SCNotification scn) = 0;
virtual void NotifyStyleToNeeded(int endStyleNeeded);
void NotifyChar(int ch);
void NotifyMove(int position);
void NotifySavePoint(bool isSavePoint);
void NotifyModifyAttempt();
virtual void NotifyDoubleClick(Point pt, bool shift);
void NotifyHotSpotClicked(int position, bool shift, bool ctrl, bool alt);
void NotifyHotSpotDoubleClicked(int position, bool shift, bool ctrl, bool alt);
void NotifyUpdateUI();
void NotifyPainted();
bool NotifyMarginClick(Point pt, bool shift, bool ctrl, bool alt);
void NotifyNeedShown(int pos, int len);
void NotifyDwelling(Point pt, bool state);
void NotifyZoom();
void NotifyModifyAttempt(Document *document, void *userData);
void NotifySavePoint(Document *document, void *userData, bool atSavePoint);
void CheckModificationForWrap(DocModification mh);
void NotifyModified(Document *document, DocModification mh, void *userData);
void NotifyDeleted(Document *document, void *userData);
void NotifyStyleNeeded(Document *doc, void *userData, int endPos);
void NotifyMacroRecord(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
void PageMove(int direction, selTypes sel=noSel, bool stuttered = false);
void ChangeCaseOfSelection(bool makeUpperCase);
void LineTranspose();
void Duplicate(bool forLine);
virtual void CancelModes();
void NewLine();
void CursorUpOrDown(int direction, selTypes sel=noSel);
void ParaUpOrDown(int direction, selTypes sel=noSel);
int StartEndDisplayLine(int pos, bool start);
virtual int KeyCommand(unsigned int iMessage);
virtual int KeyDefault(int /* key */, int /*modifiers*/);
int KeyDown(int key, bool shift, bool ctrl, bool alt, bool *consumed=0);
int GetWhitespaceVisible();
void SetWhitespaceVisible(int view);
void Indent(bool forwards);
long FindText(uptr_t wParam, sptr_t lParam);
void SearchAnchor();
long SearchText(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
long SearchInTarget(const char *text, int length);
void GoToLine(int lineNo);
virtual void CopyToClipboard(const SelectionText &selectedText) = 0;
char *CopyRange(int start, int end);
void CopySelectionFromRange(SelectionText *ss, int start, int end);
void CopySelectionRange(SelectionText *ss);
void CopyRangeToClipboard(int start, int end);
void CopyText(int length, const char *text);
void SetDragPosition(int newPos);
virtual void DisplayCursor(Window::Cursor c);
virtual void StartDrag();
void DropAt(int position, const char *value, bool moving, bool rectangular);
/** PositionInSelection returns 0 if position in selection, -1 if position before selection, and 1 if after.
* Before means either before any line of selection or before selection on its line, with a similar meaning to after. */
int PositionInSelection(int pos);
bool PointInSelection(Point pt);
bool PointInSelMargin(Point pt);
void LineSelection(int lineCurrent_, int lineAnchor_);
void DwellEnd(bool mouseMoved);
virtual void ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, bool alt);
void ButtonMove(Point pt);
void ButtonUp(Point pt, unsigned int curTime, bool ctrl);
void Tick();
bool Idle();
virtual void SetTicking(bool on) = 0;
virtual bool SetIdle(bool) { return false; }
virtual void SetMouseCapture(bool on) = 0;
virtual bool HaveMouseCapture() = 0;
void SetFocusState(bool focusState);
virtual bool PaintContains(PRectangle rc);
bool PaintContainsMargin();
void CheckForChangeOutsidePaint(Range r);
void SetBraceHighlight(Position pos0, Position pos1, int matchStyle);
void SetDocPointer(Document *document);
void Expand(int &line, bool doExpand);
void ToggleContraction(int line);
void EnsureLineVisible(int lineDoc, bool enforcePolicy);
int ReplaceTarget(bool replacePatterns, const char *text, int length=-1);
bool PositionIsHotspot(int position);
bool PointIsHotspot(Point pt);
void SetHotSpotRange(Point *pt);
void GetHotSpotRange(int& hsStart, int& hsEnd);
int CodePage() const;
int WrapCount(int line);
virtual sptr_t DefWndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) = 0;
public:
// Public so the COM thunks can access it.
bool IsUnicodeMode() const;
// Public so scintilla_send_message can use it.
virtual sptr_t WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
// Public so scintilla_set_id can use it.
int ctrlID;
friend class AutoSurface;
friend class SelectionLineIterator;
};
/**
* A smart pointer class to ensure Surfaces are set up and deleted correctly.
*/
class AutoSurface {
private:
Surface *surf;
public:
AutoSurface(Editor *ed) : surf(0) {
if (ed->wMain.GetID()) {
surf = Surface::Allocate();
if (surf) {
surf->Init(ed->wMain.GetID());
surf->SetUnicodeMode(SC_CP_UTF8 == ed->CodePage());
surf->SetDBCSMode(ed->CodePage());
}
}
}
AutoSurface(SurfaceID sid, Editor *ed) : surf(0) {
if (ed->wMain.GetID()) {
surf = Surface::Allocate();
if (surf) {
surf->Init(sid, ed->wMain.GetID());
surf->SetUnicodeMode(SC_CP_UTF8 == ed->CodePage());
surf->SetDBCSMode(ed->CodePage());
}
}
}
~AutoSurface() {
delete surf;
}
Surface *operator->() const {
return surf;
}
operator Surface *() const {
return surf;
}
};
#endif

View File

@@ -0,0 +1,257 @@
// Scintilla source code edit control
/** @file ExternalLexer.cxx
** Support external lexers in DLLs.
**/
// Copyright 2001 Simon Steele <ss@pnotepad.org>, portions copyright Neil Hodgson.
// The License.txt file describes the conditions under which this software may be distributed.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "Platform.h"
#include "SciLexer.h"
#include "PropSet.h"
#include "Accessor.h"
#include "DocumentAccessor.h"
#include "KeyWords.h"
#include "ExternalLexer.h"
LexerManager *LexerManager::theInstance = NULL;
//------------------------------------------
//
// ExternalLexerModule
//
//------------------------------------------
char **WordListsToStrings(WordList *val[]) {
int dim = 0;
while (val[dim])
dim++;
char **wls = new char * [dim + 1];
for (int i = 0;i < dim;i++) {
SString words;
words = "";
for (int n = 0; n < val[i]->len; n++) {
words += val[i]->words[n];
if (n != val[i]->len - 1)
words += " ";
}
wls[i] = new char[words.length() + 1];
strcpy(wls[i], words.c_str());
}
wls[dim] = 0;
return wls;
}
void DeleteWLStrings(char *strs[]) {
int dim = 0;
while (strs[dim]) {
delete strs[dim];
dim++;
}
delete [] strs;
}
void ExternalLexerModule::Lex(unsigned int startPos, int lengthDoc, int initStyle,
WordList *keywordlists[], Accessor &styler) const {
if (!fneLexer)
return ;
char **kwds = WordListsToStrings(keywordlists);
char *ps = styler.GetProperties();
// The accessor passed in is always a DocumentAccessor so this cast and the subsequent
// access will work. Can not use the stricter dynamic_cast as that requires RTTI.
DocumentAccessor &da = static_cast<DocumentAccessor &>(styler);
WindowID wID = da.GetWindow();
fneLexer(externalLanguage, startPos, lengthDoc, initStyle, kwds, wID, ps);
delete ps;
DeleteWLStrings(kwds);
}
void ExternalLexerModule::Fold(unsigned int startPos, int lengthDoc, int initStyle,
WordList *keywordlists[], Accessor &styler) const {
if (!fneFolder)
return ;
char **kwds = WordListsToStrings(keywordlists);
char *ps = styler.GetProperties();
// The accessor passed in is always a DocumentAccessor so this cast and the subsequent
// access will work. Can not use the stricter dynamic_cast as that requires RTTI.
DocumentAccessor &da = static_cast<DocumentAccessor &>(styler);
WindowID wID = da.GetWindow();
fneFolder(externalLanguage, startPos, lengthDoc, initStyle, kwds, wID, ps);
delete ps;
DeleteWLStrings(kwds);
}
void ExternalLexerModule::SetExternal(ExtLexerFunction fLexer, ExtFoldFunction fFolder, int index) {
fneLexer = fLexer;
fneFolder = fFolder;
externalLanguage = index;
}
//------------------------------------------
//
// LexerLibrary
//
//------------------------------------------
LexerLibrary::LexerLibrary(const char* ModuleName) {
// Initialise some members...
first = NULL;
last = NULL;
// Load the DLL
lib = DynamicLibrary::Load(ModuleName);
if (lib->IsValid()) {
m_sModuleName = ModuleName;
//Cannot use reinterpret_cast because: ANSI C++ forbids casting between pointers to functions and objects
GetLexerCountFn GetLexerCount = (GetLexerCountFn)lib->FindFunction("GetLexerCount");
if (GetLexerCount) {
ExternalLexerModule *lex;
LexerMinder *lm;
// Find functions in the DLL
GetLexerNameFn GetLexerName = (GetLexerNameFn)lib->FindFunction("GetLexerName");
ExtLexerFunction Lexer = (ExtLexerFunction)lib->FindFunction("Lex");
ExtFoldFunction Folder = (ExtFoldFunction)lib->FindFunction("Fold");
// Assign a buffer for the lexer name.
char lexname[100];
strcpy(lexname, "");
int nl = GetLexerCount();
for (int i = 0; i < nl; i++) {
GetLexerName(i, lexname, 100);
lex = new ExternalLexerModule(SCLEX_AUTOMATIC, NULL, lexname, NULL);
// Create a LexerMinder so we don't leak the ExternalLexerModule...
lm = new LexerMinder;
lm->self = lex;
lm->next = NULL;
if (first != NULL) {
last->next = lm;
last = lm;
} else {
first = lm;
last = lm;
}
// The external lexer needs to know how to call into its DLL to
// do its lexing and folding, we tell it here. Folder may be null.
lex->SetExternal(Lexer, Folder, i);
}
}
}
next = NULL;
}
LexerLibrary::~LexerLibrary() {
Release();
delete lib;
}
void LexerLibrary::Release() {
//TODO maintain a list of lexers created, and delete them!
LexerMinder *lm;
LexerMinder *next;
lm = first;
while (NULL != lm) {
next = lm->next;
delete lm->self;
delete lm;
lm = next;
}
first = NULL;
last = NULL;
}
//------------------------------------------
//
// LexerManager
//
//------------------------------------------
/// Return the single LexerManager instance...
LexerManager *LexerManager::GetInstance() {
if(!theInstance)
theInstance = new LexerManager;
return theInstance;
}
/// Delete any LexerManager instance...
void LexerManager::DeleteInstance()
{
if(theInstance) {
delete theInstance;
theInstance = NULL;
}
}
/// protected constructor - this is a singleton...
LexerManager::LexerManager() {
first = NULL;
last = NULL;
}
LexerManager::~LexerManager() {
Clear();
}
void LexerManager::Load(const char* path)
{
LoadLexerLibrary(path);
}
void LexerManager::LoadLexerLibrary(const char* module)
{
LexerLibrary *lib = new LexerLibrary(module);
if (NULL != first) {
last->next = lib;
last = lib;
} else {
first = lib;
last = lib;
}
}
void LexerManager::Clear()
{
if (NULL != first) {
LexerLibrary *cur = first;
LexerLibrary *next;
while (cur) {
next = cur->next;
delete cur;
cur = next;
}
first = NULL;
last = NULL;
}
}
//------------------------------------------
//
// LexerManager
//
//------------------------------------------
LMMinder::~LMMinder()
{
LexerManager::DeleteInstance();
}
LMMinder minder;

View File

@@ -0,0 +1,91 @@
// Scintilla source code edit control
/** @file ExternalLexer.h
** Support external lexers in DLLs.
**/
// Copyright 2001 Simon Steele <ss@pnotepad.org>, portions copyright Neil Hodgson.
// The License.txt file describes the conditions under which this software may be distributed.
#ifndef EXTERNALLEXER_H
#define EXTERNALLEXER_H
#define EXT_LEXER_DECL
// External Lexer function definitions...
typedef void (EXT_LEXER_DECL *ExtLexerFunction)(unsigned int lexer, unsigned int startPos, int length, int initStyle,
char *words[], WindowID window, char *props);
typedef void (EXT_LEXER_DECL *ExtFoldFunction)(unsigned int lexer, unsigned int startPos, int length, int initStyle,
char *words[], WindowID window, char *props);
typedef void* (EXT_LEXER_DECL *GetLexerFunction)(unsigned int Index);
typedef int (EXT_LEXER_DECL *GetLexerCountFn)();
typedef void (EXT_LEXER_DECL *GetLexerNameFn)(unsigned int Index, char *name, int buflength);
//class DynamicLibrary;
/// Sub-class of LexerModule to use an external lexer.
class ExternalLexerModule : protected LexerModule {
protected:
ExtLexerFunction fneLexer;
ExtFoldFunction fneFolder;
int externalLanguage;
char name[100];
public:
ExternalLexerModule(int language_, LexerFunction fnLexer_,
const char *languageName_=0, LexerFunction fnFolder_=0) : LexerModule(language_, fnLexer_, 0, fnFolder_){
strncpy(name, languageName_, sizeof(name));
languageName = name;
};
virtual void Lex(unsigned int startPos, int lengthDoc, int initStyle,
WordList *keywordlists[], Accessor &styler) const;
virtual void Fold(unsigned int startPos, int lengthDoc, int initStyle,
WordList *keywordlists[], Accessor &styler) const;
virtual void SetExternal(ExtLexerFunction fLexer, ExtFoldFunction fFolder, int index);
};
/// LexerMinder points to an ExternalLexerModule - so we don't leak them.
class LexerMinder {
public:
ExternalLexerModule *self;
LexerMinder *next;
};
/// LexerLibrary exists for every External Lexer DLL, contains LexerMinders.
class LexerLibrary {
DynamicLibrary *lib;
LexerMinder *first;
LexerMinder *last;
public:
LexerLibrary(const char* ModuleName);
~LexerLibrary();
void Release();
LexerLibrary *next;
SString m_sModuleName;
};
/// LexerManager manages external lexers, contains LexerLibrarys.
class LexerManager {
public:
~LexerManager();
static LexerManager *GetInstance();
static void DeleteInstance();
void Load(const char* path);
void Clear();
private:
LexerManager();
static LexerManager *theInstance;
void LoadLexerLibrary(const char* module);
LexerLibrary *first;
LexerLibrary *last;
};
class LMMinder {
public:
~LMMinder();
};
#endif

View File

@@ -0,0 +1,71 @@
// Scintilla source code edit control
/** @file Indicator.cxx
** Defines the style of indicators which are text decorations such as underlining.
**/
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.
#include "Platform.h"
#include "Scintilla.h"
#include "Indicator.h"
void Indicator::Draw(Surface *surface, const PRectangle &rc, const PRectangle &rcLine) {
surface->PenColour(fore.allocated);
int ymid = (rc.bottom + rc.top) / 2;
if (style == INDIC_SQUIGGLE) {
surface->MoveTo(rc.left, rc.top);
int x = rc.left + 2;
int y = 2;
while (x < rc.right) {
surface->LineTo(x, rc.top + y);
x += 2;
y = 2 - y;
}
surface->LineTo(rc.right, rc.top + y); // Finish the line
} else if (style == INDIC_TT) {
surface->MoveTo(rc.left, ymid);
int x = rc.left + 5;
while (x < rc.right) {
surface->LineTo(x, ymid);
surface->MoveTo(x-3, ymid);
surface->LineTo(x-3, ymid+2);
x++;
surface->MoveTo(x, ymid);
x += 5;
}
surface->LineTo(rc.right, ymid); // Finish the line
if (x - 3 <= rc.right) {
surface->MoveTo(x-3, ymid);
surface->LineTo(x-3, ymid+2);
}
} else if (style == INDIC_DIAGONAL) {
int x = rc.left;
while (x < rc.right) {
surface->MoveTo(x, rc.top+2);
int endX = x+3;
int endY = rc.top - 1;
if (endX > rc.right) {
endY += endX - rc.right;
endX = rc.right;
}
surface->LineTo(endX, endY);
x += 4;
}
} else if (style == INDIC_STRIKE) {
surface->MoveTo(rc.left, rc.top - 4);
surface->LineTo(rc.right, rc.top - 4);
} else if (style == INDIC_HIDDEN) {
// Draw nothing
} else if (style == INDIC_BOX) {
surface->MoveTo(rc.left, ymid+1);
surface->LineTo(rc.right, ymid+1);
surface->LineTo(rc.right, rcLine.top+1);
surface->LineTo(rc.left, rcLine.top+1);
surface->LineTo(rc.left, ymid+1);
} else { // Either INDIC_PLAIN or unknown
surface->MoveTo(rc.left, ymid);
surface->LineTo(rc.right, ymid);
}
}

View File

@@ -0,0 +1,22 @@
// Scintilla source code edit control
/** @file Indicator.h
** Defines the style of indicators which are text decorations such as underlining.
**/
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.
#ifndef INDICATOR_H
#define INDICATOR_H
/**
*/
class Indicator {
public:
int style;
ColourPair fore;
Indicator() : style(INDIC_PLAIN), fore(ColourDesired(0,0,0)) {
}
void Draw(Surface *surface, const PRectangle &rc, const PRectangle &rcLine);
};
#endif

View File

@@ -0,0 +1,148 @@
// Scintilla source code edit control
/** @file KeyMap.cxx
** Defines a mapping between keystrokes and commands.
**/
// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.
#include "Platform.h"
#include "Scintilla.h"
#include "KeyMap.h"
KeyMap::KeyMap() : kmap(0), len(0), alloc(0) {
for (int i = 0; MapDefault[i].key; i++) {
AssignCmdKey(MapDefault[i].key,
MapDefault[i].modifiers,
MapDefault[i].msg);
}
}
KeyMap::~KeyMap() {
Clear();
}
void KeyMap::Clear() {
delete []kmap;
kmap = 0;
len = 0;
alloc = 0;
}
void KeyMap::AssignCmdKey(int key, int modifiers, unsigned int msg) {
if ((len+1) >= alloc) {
KeyToCommand *ktcNew = new KeyToCommand[alloc + 5];
if (!ktcNew)
return;
for (int k = 0; k < len; k++)
ktcNew[k] = kmap[k];
alloc += 5;
delete []kmap;
kmap = ktcNew;
}
for (int keyIndex = 0; keyIndex < len; keyIndex++) {
if ((key == kmap[keyIndex].key) && (modifiers == kmap[keyIndex].modifiers)) {
kmap[keyIndex].msg = msg;
return;
}
}
kmap[len].key = key;
kmap[len].modifiers = modifiers;
kmap[len].msg = msg;
len++;
}
unsigned int KeyMap::Find(int key, int modifiers) {
for (int i = 0; i < len; i++) {
if ((key == kmap[i].key) && (modifiers == kmap[i].modifiers)) {
return kmap[i].msg;
}
}
return 0;
}
const KeyToCommand KeyMap::MapDefault[] = {
{SCK_DOWN, SCI_NORM, SCI_LINEDOWN},
{SCK_DOWN, SCI_SHIFT, SCI_LINEDOWNEXTEND},
{SCK_DOWN, SCI_CTRL, SCI_LINESCROLLDOWN},
{SCK_DOWN, SCI_ASHIFT, SCI_LINEDOWNRECTEXTEND},
{SCK_UP, SCI_NORM, SCI_LINEUP},
{SCK_UP, SCI_SHIFT, SCI_LINEUPEXTEND},
{SCK_UP, SCI_CTRL, SCI_LINESCROLLUP},
{SCK_UP, SCI_ASHIFT, SCI_LINEUPRECTEXTEND},
{'[', SCI_CTRL, SCI_PARAUP},
{'[', SCI_CSHIFT, SCI_PARAUPEXTEND},
{']', SCI_CTRL, SCI_PARADOWN},
{']', SCI_CSHIFT, SCI_PARADOWNEXTEND},
{SCK_LEFT, SCI_NORM, SCI_CHARLEFT},
{SCK_LEFT, SCI_SHIFT, SCI_CHARLEFTEXTEND},
{SCK_LEFT, SCI_CTRL, SCI_WORDLEFT},
{SCK_LEFT, SCI_CSHIFT, SCI_WORDLEFTEXTEND},
{SCK_LEFT, SCI_ASHIFT, SCI_CHARLEFTRECTEXTEND},
{SCK_RIGHT, SCI_NORM, SCI_CHARRIGHT},
{SCK_RIGHT, SCI_SHIFT, SCI_CHARRIGHTEXTEND},
{SCK_RIGHT, SCI_CTRL, SCI_WORDRIGHT},
{SCK_RIGHT, SCI_CSHIFT, SCI_WORDRIGHTEXTEND},
{SCK_RIGHT, SCI_ASHIFT, SCI_CHARRIGHTRECTEXTEND},
{'/', SCI_CTRL, SCI_WORDPARTLEFT},
{'/', SCI_CSHIFT, SCI_WORDPARTLEFTEXTEND},
{'\\', SCI_CTRL, SCI_WORDPARTRIGHT},
{'\\', SCI_CSHIFT, SCI_WORDPARTRIGHTEXTEND},
{SCK_HOME, SCI_NORM, SCI_VCHOME},
{SCK_HOME, SCI_SHIFT, SCI_VCHOMEEXTEND},
{SCK_HOME, SCI_CTRL, SCI_DOCUMENTSTART},
{SCK_HOME, SCI_CSHIFT, SCI_DOCUMENTSTARTEXTEND},
{SCK_HOME, SCI_ALT, SCI_HOMEDISPLAY},
// {SCK_HOME, SCI_ASHIFT, SCI_HOMEDISPLAYEXTEND},
{SCK_HOME, SCI_ASHIFT, SCI_VCHOMERECTEXTEND},
{SCK_END, SCI_NORM, SCI_LINEEND},
{SCK_END, SCI_SHIFT, SCI_LINEENDEXTEND},
{SCK_END, SCI_CTRL, SCI_DOCUMENTEND},
{SCK_END, SCI_CSHIFT, SCI_DOCUMENTENDEXTEND},
{SCK_END, SCI_ALT, SCI_LINEENDDISPLAY},
// {SCK_END, SCI_ASHIFT, SCI_LINEENDDISPLAYEXTEND},
{SCK_END, SCI_ASHIFT, SCI_LINEENDRECTEXTEND},
{SCK_PRIOR, SCI_NORM, SCI_PAGEUP},
{SCK_PRIOR, SCI_SHIFT, SCI_PAGEUPEXTEND},
{SCK_PRIOR, SCI_ASHIFT, SCI_PAGEUPRECTEXTEND},
{SCK_NEXT, SCI_NORM, SCI_PAGEDOWN},
{SCK_NEXT, SCI_SHIFT, SCI_PAGEDOWNEXTEND},
{SCK_NEXT, SCI_ASHIFT, SCI_PAGEDOWNRECTEXTEND},
{SCK_DELETE, SCI_NORM, SCI_CLEAR},
{SCK_DELETE, SCI_SHIFT, SCI_CUT},
{SCK_DELETE, SCI_CTRL, SCI_DELWORDRIGHT},
{SCK_DELETE, SCI_CSHIFT, SCI_DELLINERIGHT},
{SCK_INSERT, SCI_NORM, SCI_EDITTOGGLEOVERTYPE},
{SCK_INSERT, SCI_SHIFT, SCI_PASTE},
{SCK_INSERT, SCI_CTRL, SCI_COPY},
{SCK_ESCAPE, SCI_NORM, SCI_CANCEL},
{SCK_BACK, SCI_NORM, SCI_DELETEBACK},
{SCK_BACK, SCI_SHIFT, SCI_DELETEBACK},
{SCK_BACK, SCI_CTRL, SCI_DELWORDLEFT},
{SCK_BACK, SCI_ALT, SCI_UNDO},
{SCK_BACK, SCI_CSHIFT, SCI_DELLINELEFT},
{'Z', SCI_CTRL, SCI_UNDO},
{'Y', SCI_CTRL, SCI_REDO},
{'X', SCI_CTRL, SCI_CUT},
{'C', SCI_CTRL, SCI_COPY},
{'V', SCI_CTRL, SCI_PASTE},
{'A', SCI_CTRL, SCI_SELECTALL},
{SCK_TAB, SCI_NORM, SCI_TAB},
{SCK_TAB, SCI_SHIFT, SCI_BACKTAB},
{SCK_RETURN, SCI_NORM, SCI_NEWLINE},
{SCK_RETURN, SCI_SHIFT, SCI_NEWLINE},
{SCK_ADD, SCI_CTRL, SCI_ZOOMIN},
{SCK_SUBTRACT, SCI_CTRL, SCI_ZOOMOUT},
{SCK_DIVIDE, SCI_CTRL, SCI_SETZOOM},
//'L', SCI_CTRL, SCI_FORMFEED,
{'L', SCI_CTRL, SCI_LINECUT},
{'L', SCI_CSHIFT, SCI_LINEDELETE},
{'T', SCI_CSHIFT, SCI_LINECOPY},
{'T', SCI_CTRL, SCI_LINETRANSPOSE},
{'D', SCI_CTRL, SCI_SELECTIONDUPLICATE},
{'U', SCI_CTRL, SCI_LOWERCASE},
{'U', SCI_CSHIFT, SCI_UPPERCASE},
{0,0,0},
};

View File

@@ -0,0 +1,43 @@
// Scintilla source code edit control
/** @file KeyMap.h
** Defines a mapping between keystrokes and commands.
**/
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.
#ifndef KEYTOCOMMAND_H
#define KEYTOCOMMAND_H
#define SCI_NORM 0
#define SCI_SHIFT SCMOD_SHIFT
#define SCI_CTRL SCMOD_CTRL
#define SCI_ALT SCMOD_ALT
#define SCI_CSHIFT (SCI_CTRL | SCI_SHIFT)
#define SCI_ASHIFT (SCI_ALT | SCI_SHIFT)
/**
*/
class KeyToCommand {
public:
int key;
int modifiers;
unsigned int msg;
};
/**
*/
class KeyMap {
KeyToCommand *kmap;
int len;
int alloc;
static const KeyToCommand MapDefault[];
public:
KeyMap();
~KeyMap();
void Clear();
void AssignCmdKey(int key, int modifiers, unsigned int msg);
unsigned int Find(int key, int modifiers); // 0 returned on failure
};
#endif

View File

@@ -0,0 +1,142 @@
// Scintilla source code edit control
/** @file KeyWords.cxx
** Colourise for particular languages.
**/
// Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdarg.h>
#include "Platform.h"
#include "PropSet.h"
#include "Accessor.h"
#include "KeyWords.h"
#include "Scintilla.h"
#include "SciLexer.h"
const LexerModule *LexerModule::base = 0;
int LexerModule::nextLanguage = SCLEX_AUTOMATIC+1;
LexerModule::LexerModule(int language_,
LexerFunction fnLexer_,
const char *languageName_,
LexerFunction fnFolder_,
const char * const wordListDescriptions_[],
int styleBits_) :
language(language_),
fnLexer(fnLexer_),
fnFolder(fnFolder_),
wordListDescriptions(wordListDescriptions_),
styleBits(styleBits_),
languageName(languageName_) {
next = base;
base = this;
if (language == SCLEX_AUTOMATIC) {
language = nextLanguage;
nextLanguage++;
}
}
int LexerModule::GetNumWordLists() const {
if (wordListDescriptions == NULL) {
return -1;
} else {
int numWordLists = 0;
while (wordListDescriptions[numWordLists]) {
++numWordLists;
}
return numWordLists;
}
}
const char *LexerModule::GetWordListDescription(int index) const {
static const char *emptyStr = "";
PLATFORM_ASSERT(index < GetNumWordLists());
if (index >= GetNumWordLists()) {
return emptyStr;
} else {
return wordListDescriptions[index];
}
}
int LexerModule::GetStyleBitsNeeded() const {
return styleBits;
}
const LexerModule *LexerModule::Find(int language) {
const LexerModule *lm = base;
while (lm) {
if (lm->language == language) {
return lm;
}
lm = lm->next;
}
return 0;
}
const LexerModule *LexerModule::Find(const char *languageName) {
if (languageName) {
const LexerModule *lm = base;
while (lm) {
if (lm->languageName && 0 == strcmp(lm->languageName, languageName)) {
return lm;
}
lm = lm->next;
}
}
return 0;
}
void LexerModule::Lex(unsigned int startPos, int lengthDoc, int initStyle,
WordList *keywordlists[], Accessor &styler) const {
if (fnLexer)
fnLexer(startPos, lengthDoc, initStyle, keywordlists, styler);
}
void LexerModule::Fold(unsigned int startPos, int lengthDoc, int initStyle,
WordList *keywordlists[], Accessor &styler) const {
if (fnFolder) {
int lineCurrent = styler.GetLine(startPos);
// Move back one line in case deletion wrecked current line fold state
if (lineCurrent > 0) {
lineCurrent--;
int newStartPos = styler.LineStart(lineCurrent);
lengthDoc += startPos - newStartPos;
startPos = newStartPos;
initStyle = 0;
if (startPos > 0) {
initStyle = styler.StyleAt(startPos - 1);
}
}
fnFolder(startPos, lengthDoc, initStyle, keywordlists, styler);
}
}
// Alternative historical name for Scintilla_LinkLexers
int wxForceScintillaLexers(void) {
return Scintilla_LinkLexers();
}
// To add or remove a lexer, add or remove its file and run LexGen.py.
// Force a reference to all of the Scintilla lexers so that the linker will
// not remove the code of the lexers.
int Scintilla_LinkLexers() {
static int forcer = 0;
// Shorten the code that declares a lexer and ensures it is linked in by calling a method.
#define LINK_LEXER(lexer) extern LexerModule lexer; forcer += lexer.GetLanguage();
//++Autogenerated -- run src/LexGen.py to regenerate
//**\(\tLINK_LEXER(\*);\n\)
LINK_LEXER(lmAppArmor);
return 1;
}

View File

@@ -0,0 +1,82 @@
// Scintilla source code edit control
/** @file KeyWords.h
** Colourise for particular languages.
**/
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.
typedef void (*LexerFunction)(unsigned int startPos, int lengthDoc, int initStyle,
WordList *keywordlists[], Accessor &styler);
/**
* A LexerModule is responsible for lexing and folding a particular language.
* The class maintains a list of LexerModules which can be searched to find a
* module appropriate to a particular language.
*/
class LexerModule {
protected:
const LexerModule *next;
int language;
LexerFunction fnLexer;
LexerFunction fnFolder;
const char * const * wordListDescriptions;
int styleBits;
static const LexerModule *base;
static int nextLanguage;
public:
const char *languageName;
LexerModule(int language_,
LexerFunction fnLexer_,
const char *languageName_=0,
LexerFunction fnFolder_=0,
const char * const wordListDescriptions_[] = NULL,
int styleBits_=5);
virtual ~LexerModule() {
}
int GetLanguage() const { return language; }
// -1 is returned if no WordList information is available
int GetNumWordLists() const;
const char *GetWordListDescription(int index) const;
int GetStyleBitsNeeded() const;
virtual void Lex(unsigned int startPos, int lengthDoc, int initStyle,
WordList *keywordlists[], Accessor &styler) const;
virtual void Fold(unsigned int startPos, int lengthDoc, int initStyle,
WordList *keywordlists[], Accessor &styler) const;
static const LexerModule *Find(int language);
static const LexerModule *Find(const char *languageName);
};
/**
* Check if a character is a space.
* This is ASCII specific but is safe with chars >= 0x80.
*/
inline bool isspacechar(unsigned char ch) {
return (ch == ' ') || ((ch >= 0x09) && (ch <= 0x0d));
}
inline bool iswordchar(char ch) {
return isascii(ch) && (isalnum(ch) || ch == '.' || ch == '_');
}
inline bool iswordstart(char ch) {
return isascii(ch) && (isalnum(ch) || ch == '_');
}
inline bool isoperator(char ch) {
if (isascii(ch) && isalnum(ch))
return false;
// '.' left out as it is used to make up numbers
if (ch == '%' || ch == '^' || ch == '&' || ch == '*' ||
ch == '(' || ch == ')' || ch == '-' || ch == '+' ||
ch == '=' || ch == '|' || ch == '{' || ch == '}' ||
ch == '[' || ch == ']' || ch == ':' || ch == ';' ||
ch == '<' || ch == '>' || ch == ',' || ch == '/' ||
ch == '?' || ch == '!' || ch == '.' || ch == '~')
return true;
return false;
}

Some files were not shown because too many files have changed in this diff Show More