summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Wells <mark@freeside.biz>2015-10-30 11:24:47 -0700
committerMark Wells <mark@freeside.biz>2015-10-30 11:24:47 -0700
commitebf0fbf1e78dda4cba6ce0aa1420233375f3a0ee (patch)
tree1796a411f7f82e2f755ab09b36758956ce0e0822
parentb2787f77f842a16df069227e74a2da54b8b36efb (diff)
parentb8fc5d2178e7358661e37ef97b7619f7a9080f3a (diff)
Merge branch 'master' of git.freeside.biz:/home/git/freeside
-rw-r--r--FS/FS/ClientAPI/MyAccount.pm4
-rw-r--r--FS/FS/ClientAPI/Signup.pm4
-rw-r--r--FS/FS/log_context.pm2
-rw-r--r--FS/FS/msg_template/InitialData.pm17
-rwxr-xr-xFS/bin/freeside-paymentech-download42
-rwxr-xr-xFS/bin/freeside-paymentech-upload47
-rw-r--r--Makefile3
-rwxr-xr-xdebian/rules1
-rw-r--r--httemplate/elements/ckeditor/plugins/blockprotect/plugin.js139
-rw-r--r--httemplate/elements/popup_link-make_appointment.html2
-rw-r--r--httemplate/misc/make_appointment.html (renamed from httemplate/elements/make_appointment.html)2
-rw-r--r--httemplate/misc/schedule-appointment.html (renamed from httemplate/elements/schedule-appointment.html)0
-rw-r--r--httemplate/view/cust_main/menu.html2
-rw-r--r--httemplate/view/cust_main/payment_history/invoice.html4
-rw-r--r--rt/share/static/RichText/skins/kama/icons.pngbin0 -> 13244 bytes
-rw-r--r--rt/share/static/RichText/skins/kama/images/dialog_sides.gifbin0 -> 48 bytes
-rw-r--r--rt/share/static/RichText/skins/kama/images/dialog_sides.pngbin0 -> 178 bytes
-rw-r--r--rt/share/static/RichText/skins/kama/images/dialog_sides_rtl.pngbin0 -> 181 bytes
-rw-r--r--rt/share/static/RichText/skins/kama/images/mini.gifbin0 -> 183 bytes
-rw-r--r--rt/share/static/RichText/skins/kama/images/sprites.pngbin0 -> 7086 bytes
-rw-r--r--rt/share/static/RichText/skins/kama/images/sprites_ie6.pngbin0 -> 2724 bytes
-rw-r--r--rt/share/static/RichText/skins/kama/images/toolbar_start.gifbin0 -> 105 bytes
22 files changed, 232 insertions, 37 deletions
diff --git a/FS/FS/ClientAPI/MyAccount.pm b/FS/FS/ClientAPI/MyAccount.pm
index 89c70f75c..f272cd490 100644
--- a/FS/FS/ClientAPI/MyAccount.pm
+++ b/FS/FS/ClientAPI/MyAccount.pm
@@ -2521,8 +2521,8 @@ sub _do_bop_realtime {
#this used to apply a credit, but now we can void invoices...
foreach my $cust_bill (@cust_bill) {
- my $voiderror = $cust_bill->void();
- warn "Error voiding cust bill after decline: $voiderror";
+ my $voiderror = $cust_bill->void('automatic payment failed');
+ warn "Error voiding cust bill after decline: $voiderror" if $voiderror;
}
}
diff --git a/FS/FS/ClientAPI/Signup.pm b/FS/FS/ClientAPI/Signup.pm
index a4ea21b8f..e166d407e 100644
--- a/FS/FS/ClientAPI/Signup.pm
+++ b/FS/FS/ClientAPI/Signup.pm
@@ -824,8 +824,8 @@ sub new_customer {
#this used to apply a credit, but now we can void invoices...
foreach my $cust_bill (@cust_bill) {
- my $voiderror = $cust_bill->void();
- warn "Error voiding cust bill after decline: $voiderror";
+ my $voiderror = $cust_bill->void('automatic payment failed');
+ warn "Error voiding cust bill after decline: $voiderror" if $voiderror;
}
#should check list for errors...
diff --git a/FS/FS/log_context.pm b/FS/FS/log_context.pm
index bd142471c..ff3471760 100644
--- a/FS/FS/log_context.pm
+++ b/FS/FS/log_context.pm
@@ -18,6 +18,8 @@ my @contexts = ( qw(
queue
upgrade
upgrade_taxable_billpkgnum
+ freeside-paymentech-upload
+ freeside-paymentech-download
) );
=head1 NAME
diff --git a/FS/FS/msg_template/InitialData.pm b/FS/FS/msg_template/InitialData.pm
index dbb9f4037..baf145d8b 100644
--- a/FS/FS/msg_template/InitialData.pm
+++ b/FS/FS/msg_template/InitialData.pm
@@ -22,6 +22,23 @@ If you did not request this password reset, you may safely ignore and delete thi
END
],
},
+ { msgname => 'Refund receipt',
+ msgclass => 'email',
+ mime_type => 'text/html',
+ _conf => 'refund_receipt_msgnum',
+ _insert_args => [ subject => '{ $company_name } refund receipt',
+ body => <<'END',
+Dear {$first} {$last},<BR>
+<BR>
+The following refund has been applied to your account.<BR>
+<BR>
+Refund ID: {$refundnum}<BR>
+Date: {$date}<BR>
+Amount: {$refund}<BR>
+
+END
+ ],
+ },
];
}
diff --git a/FS/bin/freeside-paymentech-download b/FS/bin/freeside-paymentech-download
index 16ac3c23b..1b2f95175 100755
--- a/FS/bin/freeside-paymentech-download
+++ b/FS/bin/freeside-paymentech-download
@@ -11,11 +11,20 @@ use FS::Record qw(qsearch qsearchs);
use FS::pay_batch;
use FS::cust_pay_batch;
use FS::Conf;
+use FS::Log;
use vars qw( $opt_t $opt_v $opt_a );
getopts('vta:');
#$Net::SFTP::Foreign::debug = -1;
+
+sub log_and_die {
+ my $message = shift;
+ my $log = FS::Log->new('freeside-paymenttech-download');
+ $log->error($message);
+ die $message;
+}
+
sub usage { "
Usage:
freeside-paymentech-download [ -v ] [ -t ] [ -a archivedir ] user\n
@@ -25,13 +34,13 @@ my $user = shift or die &usage;
adminsuidsetup $user;
if ( $opt_a ) {
- die "no such directory: $opt_a\n"
+ log_and_die("no such directory: $opt_a\n")
unless -d $opt_a;
- die "archive directory $opt_a is not writable by the freeside user\n"
+ log_and_die("archive directory $opt_a is not writable by the freeside user\n")
unless -w $opt_a;
}
-my $unzip_check = `which unzip` or die "can't find unzip executable\n";
+my $unzip_check = `which unzip` or log_and_die("can't find unzip executable\n");
#my $tmpdir = File::Temp->newdir();
my $tmpdir = tempdir( CLEANUP => 1 ); #DIR=>somewhere?
@@ -39,22 +48,31 @@ my $tmpdir = tempdir( CLEANUP => 1 ); #DIR=>somewhere?
my $conf = new FS::Conf;
my @batchconf = $conf->config('batchconfig-paymentech');
# BIN, terminalID, merchantID, username, password
-my $username = $batchconf[3] or die "no Paymentech batch username configured\n";
-my $password = $batchconf[4] or die "no Paymentech batch password configured\n";
+my $username = $batchconf[3] or log_and_die("no Paymentech batch username configured\n");
+my $password = $batchconf[4] or log_and_die("no Paymentech batch password configured\n");
my $host = ($opt_t ? 'orbitalbatchvar.paymentech.net'
: 'orbitalbatch.paymentech.net');
print STDERR "Connecting to $username\@$host...\n" if $opt_v;
-my $sftp = Net::SFTP::Foreign->new( host => $host,
- user => $username,
- password => $password,
- timeout => 30,
- );
-die "failed to connect to '$username\@$host'\n(".$sftp->error.")\n" if $sftp->error;
+my $sftp;
+my $ssh_retry = 25; # number of times to try connection, needs to be >= 1
+my $ssh_retry_wait = 60*5; # seconds to wait between tries
+while ($ssh_retry > 0) {
+ $sftp = Net::SFTP::Foreign->new( host => $host,
+ user => $username,
+ password => $password,
+ timeout => 30,
+ );
+ last unless $sftp->error;
+ $ssh_retry -= 1;
+ sleep($ssh_retry_wait) if $ssh_retry > 0;
+}
+
+log_and_die("failed to connect to '$username\@$host'\n(".$sftp->error.")\n") if $sftp->error;
my @files = map { $_->{filename} } @{ $sftp->ls('.', wanted => qr/_resp\.zip$/) };
-die "no response files found\n" if !@files;
+log_and_die("no response files found\n") if !@files;
BATCH: foreach my $filename (@files) {
diff --git a/FS/bin/freeside-paymentech-upload b/FS/bin/freeside-paymentech-upload
index 609019eb2..a6e6a5d28 100755
--- a/FS/bin/freeside-paymentech-upload
+++ b/FS/bin/freeside-paymentech-upload
@@ -11,12 +11,20 @@ use FS::Record qw(qsearch qsearchs);
use FS::pay_batch;
use FS::cust_pay_batch;
use FS::Conf;
+use FS::Log;
use vars qw( $opt_a $opt_t $opt_v $opt_p );
getopts('avtp:');
#$Net::SFTP::Foreign::debug = -1;
+sub log_and_die {
+ my $message = shift;
+ my $log = FS::Log->new('freeside-paymenttech-upload');
+ $log->error($message);
+ die $message;
+}
+
sub usage { "
Usage:
freeside-paymentech-upload [ -v ] [ -t ] user batchnum
@@ -26,7 +34,7 @@ sub usage { "
my $user = shift or die &usage;
adminsuidsetup $user;
-my $zip_check = `which zip` or die "can't find zip executable\n";
+my $zip_check = `which zip` or log_and_die("can't find zip executable\n");
my @batches;
@@ -34,21 +42,21 @@ if($opt_a) {
my %criteria = (status => 'O');
$criteria{'payby'} = uc($opt_p) if $opt_p;
@batches = qsearch('pay_batch', \%criteria);
- die "No open batches found".($opt_p ? " of type '$opt_p'" : '').".\n"
+ log_and_die("No open batches found".($opt_p ? " of type '$opt_p'" : '').".\n")
if !@batches;
}
else {
my $batchnum = shift;
- die &usage if !$batchnum;
+ log_and_die("batchnum not passed\n".&usage) if !$batchnum;
@batches = qsearchs('pay_batch', { batchnum => $batchnum } );
- die "Can't find payment batch '$batchnum'\n" if !@batches;
+ log_and_die("Can't find payment batch '$batchnum'\n") if !@batches;
}
my $conf = new FS::Conf;
my @batchconf = $conf->config('batchconfig-paymentech');
# BIN, terminalID, merchantID, username, password
-my $username = $batchconf[3] or die "no Paymentech batch username configured\n";
-my $password = $batchconf[4] or die "no Paymentech batch password configured\n";
+my $username = $batchconf[3] or log_and_die("no Paymentech batch username configured\n");
+my $password = $batchconf[4] or log_and_die("no Paymentech batch password configured\n");
#my $tmpdir = File::Temp->newdir();
my $tmpdir = tempdir( CLEANUP => 1 ); #DIR=>somewhere?
@@ -61,7 +69,7 @@ foreach my $pay_batch (@batches) {
print STDERR "Exporting batch $batchnum to $filename...\n" if $opt_v;
my $text = $pay_batch->export_batch(format => 'paymentech');
$text =~ s!<fileID>FILEID</fileID>!<fileID>$filename</fileID>!
- or die "couldn't find FILEID tag\n";
+ or log_and_die("couldn't find FILEID tag\n");
open OUT, ">$tmpdir/$filename.xml";
print OUT $text;
close OUT;
@@ -69,7 +77,7 @@ foreach my $pay_batch (@batches) {
system('zip', '-P', $password, '-q', '-j',
"$tmpdir/$filename.zip", "$tmpdir/$filename.xml");
- die "failed to create zip file\n" if (! -f "$tmpdir/$filename.zip" );
+ log_and_die("failed to create zip file\n") if (! -f "$tmpdir/$filename.zip" );
push @filenames, $filename;
}
@@ -77,17 +85,26 @@ my $host = ($opt_t ? 'orbitalbatchvar.paymentech.net'
: 'orbitalbatch.paymentech.net');
print STDERR "Connecting to $username\@$host...\n" if $opt_v;
-my $sftp = Net::SFTP::Foreign->new( host => $host,
- user => $username,
- password => $password,
- timeout => 30,
- );
-die "failed to connect to '$username\@$host'\n(".$sftp->error.")\n"
+my $sftp;
+my $ssh_retry = 25; # number of times to try connection, needs to be >= 1
+my $ssh_retry_wait = 60*5; # seconds to wait between tries
+while ($ssh_retry > 0) {
+ $sftp = Net::SFTP::Foreign->new( host => $host,
+ user => $username,
+ password => $password,
+ timeout => 30,
+ );
+ last unless $sftp->error;
+ $ssh_retry -= 1;
+ sleep($ssh_retry_wait) if $ssh_retry > 0;
+}
+
+log_and_die("failed to connect to '$username\@$host'\n(".$sftp->error.")\n")
if $sftp->error;
foreach my $filename (@filenames) {
$sftp->put("$tmpdir/$filename.zip", "$filename.zip")
- or die "failed to upload file (".$sftp->error.")\n";
+ or log_and_die("failed to upload file (".$sftp->error.")\n");
}
print STDERR "Finished!\n" if $opt_v;
diff --git a/Makefile b/Makefile
index 3af5da812..91b14b8a8 100644
--- a/Makefile
+++ b/Makefile
@@ -117,7 +117,7 @@ FREESIDE_URL = "http://localhost/freeside/"
#for now, same db as specified in DATASOURCE... eventually, otherwise?
RT_DB_DATABASE = freeside
-TORRUS_ENABLED = 0
+TORRUS_ENABLED = 1
# for auto-version updates, so we can "make release" more things automatically
RPM_SPECFILE = rpm/freeside.spec
@@ -400,6 +400,7 @@ create-rt: configure-rt
install-rt:
if [ ${RT_ENABLED} -eq 1 ]; then ( cd rt; make install ); fi
+ if [ ${RT_ENABLED} -eq 1 ]; then cp -r ${RT_PATH}/share/static/images ${FREESIDE_DOCUMENT_ROOT}/rt/NoAuth/ ;fi
if [ ${RT_ENABLED} -eq 1 ]; then perl -p -i -e "\
s'%%%RT_DOMAIN%%%'${RT_DOMAIN}'g;\
s'%%%RT_TIMEZONE%%%'${RT_TIMEZONE}'g;\
diff --git a/debian/rules b/debian/rules
index a7f2b72d0..e7f5bd8a0 100755
--- a/debian/rules
+++ b/debian/rules
@@ -266,6 +266,7 @@ install-stamp: build-stamp
install -d $(RT_PATH)/share
( cd rt; $(MAKE) config-install dirs files-install fixperms instruct )
+ cp -r ${RT_PATH}/share/static/images ${FREESIDE_DOCUMENT_ROOT}/rt/NoAuth/
##hack the build dir out of RT. yeah, sucky.
diff --git a/httemplate/elements/ckeditor/plugins/blockprotect/plugin.js b/httemplate/elements/ckeditor/plugins/blockprotect/plugin.js
new file mode 100644
index 000000000..e4ef39167
--- /dev/null
+++ b/httemplate/elements/ckeditor/plugins/blockprotect/plugin.js
@@ -0,0 +1,139 @@
+/**
+ * The "blockprotect" plugin. Adapted from the "placeholder" plugin.
+ */
+
+(function() {
+ var delim_o = '{';
+ var delim_c = '}';
+
+ var create_block = function(content, inside) {
+ if (inside) return content;
+ // fix nbsp's
+ content = content.replace(/&nbsp;/gi, ' ');
+ // escape the content
+ var el = document.createElement('SPAN');
+ // IE8 compat
+ if( typeof(el.textContent) != 'undefined' ) {
+ el.textContent = content;
+ } else if( typeof(el.innerText) != 'undefined' ) {
+ el.innerText = content;
+ }
+ el.setAttribute('class', 'cke_blockprotect');
+ return el.outerHTML;
+ };
+ var block_writeHtml = function( element ) {
+ // to unescape the element contents, write it out as HTML,
+ // stick that into a SPAN element, and then extract the text
+ // content of that.
+ var inner_writer = new CKEDITOR.htmlParser.basicWriter;
+ element.writeChildrenHtml(inner_writer);
+
+ var el = document.createElement('SPAN');
+ el.innerHTML = inner_writer.getHtml();
+ if( typeof(el.textContent) != 'undefined' ) {
+ return el.textContent;
+ } else if( typeof(el.innerText) != 'undefined' ) {
+ return el.innerText;
+ }
+ };
+ var to_protected_html = function(data) {
+ var depth = 0;
+ var chunk = '';
+ var out = '';
+ var in_tag = false;
+ var p = 0; // position in the string
+ while( 1 ) {
+ // find the next delimiter of either kind
+ var i = data.indexOf(delim_o, p);
+ var j = data.indexOf(delim_c, p);
+ if (i == -1 && j == -1) {
+ // then there are no more delimiters
+ break;
+ } else if ((i < j || j == -1) && i != -1) {
+ // next delimiter is an open
+ // push everything from current position to
+ // the delimiter
+ if ( i > p ) chunk += data.substr(p, i - p);
+ p = i + 1;
+ if ( depth == 0 ) {
+ // we're in document text. find whether an HTML tag starts,
+ // or ends, before the next delimiter, so that we know whether
+ // to output the next block in a SPAN or just as escaped text
+ for(var q = 0; q < chunk.length; q++ ) {
+ if (chunk[q] == '<') in_tag = true;
+ if (chunk[q] == '>') in_tag = false;
+ }
+
+ // then output the chunk, and go to the start of the
+ // protected block
+ out += chunk;
+ chunk = '';
+ }
+ chunk += delim_o;
+ depth++;
+ } else if ((j < i || i == -1) && j != -1) {
+ // next delimiter is a close
+ if ( j > p ) chunk += data.substr(p, j - p);
+ p = j + 1;
+ depth--;
+ chunk += delim_c;
+ if ( depth == 0 ) {
+ // end of a protected block
+ out += create_block(chunk, in_tag);
+ chunk = '';
+ } else if ( depth < 0 ) {
+ depth = 0;
+ }
+ } else {
+ // can't happen
+ }
+ }
+ // append any text after the last delimiter
+ if ( depth ) {
+ out += create_block(data.substr(p), in_tag);
+ } else {
+ out += data.substr(p);
+ }
+ return out;
+ };
+
+ CKEDITOR.plugins.add( 'blockprotect', {
+ afterInit: function( editor ) {
+ CKEDITOR.addCss( '.cke_blockprotect' +
+ '{' +
+ 'background-color: #ffff88;' +
+ ( CKEDITOR.env.gecko ? 'cursor: default;' : '' ) +
+ '}'
+ );
+
+ // keep these from getting stripped out
+ editor.filter.allow('span(cke_blockprotect)',
+ 'blockprotect', true);
+
+ // add filter at the front of toHtml
+ editor.on( 'toHtml',
+ function( evt ) {
+ evt.data.dataValue =
+ to_protected_html(evt.data.dataValue);
+ return evt;
+ },
+ this, null, 0
+ );
+
+ editor.dataProcessor.htmlFilter.addRules({
+ elements: {
+ span: function( element ) {
+ if ( element.className = 'cke_blockprotect' ) {
+ // defeat HTML escaping
+ var content = block_writeHtml(element);
+ element.writeHtml = function(writer, filter) {
+ writer.text(content);
+ }
+ }
+ } // span function
+ } // elements
+ });
+ }
+ }); // plugins.add
+}) ();
+
diff --git a/httemplate/elements/popup_link-make_appointment.html b/httemplate/elements/popup_link-make_appointment.html
index 60a337c04..3a8d37a8c 100644
--- a/httemplate/elements/popup_link-make_appointment.html
+++ b/httemplate/elements/popup_link-make_appointment.html
@@ -26,6 +26,6 @@ $params->{'actionlabel'} ||= 'Schedule appointment';
#$params->{'width'} ||= 350;
#$params->{'height'} ||= 220;
-$params->{'action'} = $p. '/elements/make_appointment.html?custnum='. $params->{'custnum'};
+$params->{'action'} = $p. 'misc/make_appointment.html?custnum='. $params->{'custnum'};
</%init>
diff --git a/httemplate/elements/make_appointment.html b/httemplate/misc/make_appointment.html
index ddf377f54..6f308e0a8 100644
--- a/httemplate/elements/make_appointment.html
+++ b/httemplate/misc/make_appointment.html
@@ -2,7 +2,7 @@
% #XXX actually, the action needs to repace the top-level window with this
% #$params->{'action'} = $p. 'rt/Search/Schedule.html?'. $query;
-<FORM NAME="appointment_form" METHOD="POST" ACTION="<% $p %>elements/schedule-appointment.html">
+<FORM NAME="appointment_form" METHOD="POST" ACTION="<% $p %>misc/schedule-appointment.html">
<INPUT TYPE="hidden" NAME="custnum" VALUE="<% $cgi->param('custnum') |h %>">
diff --git a/httemplate/elements/schedule-appointment.html b/httemplate/misc/schedule-appointment.html
index 69b9f422b..69b9f422b 100644
--- a/httemplate/elements/schedule-appointment.html
+++ b/httemplate/misc/schedule-appointment.html
diff --git a/httemplate/view/cust_main/menu.html b/httemplate/view/cust_main/menu.html
index b8740635d..ab2d69d34 100644
--- a/httemplate/view/cust_main/menu.html
+++ b/httemplate/view/cust_main/menu.html
@@ -317,7 +317,7 @@ my @menu = (
label => 'Schedule new appointment',
confexists => 'ticket_system',
acl => 'Make appointment',
- popup => "elements/make_appointment.html?custnum=$custnum",
+ popup => "misc/make_appointment.html?custnum=$custnum",
actionlabel => 'Schedule appointment',
},
],
diff --git a/httemplate/view/cust_main/payment_history/invoice.html b/httemplate/view/cust_main/payment_history/invoice.html
index 058da5463..613936e00 100644
--- a/httemplate/view/cust_main/payment_history/invoice.html
+++ b/httemplate/view/cust_main/payment_history/invoice.html
@@ -35,12 +35,12 @@ if ( $cust_bill->closed !~ /^Y/i && $opt{'Void invoices'} ) {
}
my $email = ($opt{'has_email_address'} && $opt{'Resend invoices'}) ?
- q! (<A HREF="javascript:void(0)" ONCLICK="areyousure_popup('Send email receipt for invoice #!.
+ q! (<A HREF="javascript:void(0)" ONCLICK="areyousure_popup('Send email copy of invoice #!.
$cust_bill->invnum.
q! to customer?','!.
"${p}misc/send-invoice.cgi?method=email;notice_name=Invoice;popup=1;invnum=".
$cust_bill->invnum.
- q!','Email Invoice Receipt')" TITLE="Send email receipt">email&nbsp;receipt</A>)!
+ q!','Email Invoice Receipt')" TITLE="Send email invoice">email&nbsp;invoice</A>)!
: '';
my $events = '';
diff --git a/rt/share/static/RichText/skins/kama/icons.png b/rt/share/static/RichText/skins/kama/icons.png
new file mode 100644
index 000000000..a2a385773
--- /dev/null
+++ b/rt/share/static/RichText/skins/kama/icons.png
Binary files differ
diff --git a/rt/share/static/RichText/skins/kama/images/dialog_sides.gif b/rt/share/static/RichText/skins/kama/images/dialog_sides.gif
new file mode 100644
index 000000000..8f91b4753
--- /dev/null
+++ b/rt/share/static/RichText/skins/kama/images/dialog_sides.gif
Binary files differ
diff --git a/rt/share/static/RichText/skins/kama/images/dialog_sides.png b/rt/share/static/RichText/skins/kama/images/dialog_sides.png
new file mode 100644
index 000000000..1042a61cf
--- /dev/null
+++ b/rt/share/static/RichText/skins/kama/images/dialog_sides.png
Binary files differ
diff --git a/rt/share/static/RichText/skins/kama/images/dialog_sides_rtl.png b/rt/share/static/RichText/skins/kama/images/dialog_sides_rtl.png
new file mode 100644
index 000000000..d7f7b49fc
--- /dev/null
+++ b/rt/share/static/RichText/skins/kama/images/dialog_sides_rtl.png
Binary files differ
diff --git a/rt/share/static/RichText/skins/kama/images/mini.gif b/rt/share/static/RichText/skins/kama/images/mini.gif
new file mode 100644
index 000000000..54d910741
--- /dev/null
+++ b/rt/share/static/RichText/skins/kama/images/mini.gif
Binary files differ
diff --git a/rt/share/static/RichText/skins/kama/images/sprites.png b/rt/share/static/RichText/skins/kama/images/sprites.png
new file mode 100644
index 000000000..0cb4e1c6c
--- /dev/null
+++ b/rt/share/static/RichText/skins/kama/images/sprites.png
Binary files differ
diff --git a/rt/share/static/RichText/skins/kama/images/sprites_ie6.png b/rt/share/static/RichText/skins/kama/images/sprites_ie6.png
new file mode 100644
index 000000000..5bb305c8d
--- /dev/null
+++ b/rt/share/static/RichText/skins/kama/images/sprites_ie6.png
Binary files differ
diff --git a/rt/share/static/RichText/skins/kama/images/toolbar_start.gif b/rt/share/static/RichText/skins/kama/images/toolbar_start.gif
new file mode 100644
index 000000000..1774246c2
--- /dev/null
+++ b/rt/share/static/RichText/skins/kama/images/toolbar_start.gif
Binary files differ