EPIC4 maildir patch
Sunday, March 30. 2014
I'm in the IRC 24/7. For the "idling" on my favorite channel I have used EPIC4 for a very long time. Couple of decades, in fact. The project is in a bad shape. Anything IRC-related is. For the record: I'll be the last dinosaur to punch the clock for the last time and turn off the lights when I notice that I'll be idling there alone. It won't come for another couple of decades, though.
Based on epicsol.org website, there is actually nobody to contact about EPIC4 bugs, no mailing list anymore (last one died 2009) nor any contact e-mail or a form. So, there literally is nobody who I could notify about anything. Writing on my own blog about it is pretty much all I can do for the project.
Back to business... My Linux-box is a mail-host and whenever something new arrives, it is really nice to get notified about that while doing absolutely nothing on the channel. However, when I stopped using mbox for storing the mail in my box, my favorite IRC-client stopped doing the notifying. It didn't not have the code for the more effective Maildir format. It does now.
My stuff is at http://opensource.hqcodeshop.com/EPIC/4/
It contains 64-bit RPM for Fedora 20 and the .src.rpm if you want to do the build by yourself. Note that my version is the latest EPIC4 2.10.4, not the Fedora-boxed 2.10.2.
To start using the Maildir-mode, say:
set mail_type maildir
in your .ircrc-file. The thing relies on $MAIL-environment variable to know where your mail is stored at.
Update 31th March 2014:
I actually got hold of Mr. Jeremy Nelson, the author or EPIC4 and EPIC5. He took my patch and said that it will be released in 2.10.5. We had a brief conversation in #epic-channel and he also said, that he is about to publish the EPIC5 project in Github.
My patch (epic4-2.10.1-maildir.patch) is as follows:
diff -aur epic4-2.10.1/include/config.h epic4-2.10.1.JT/include/config.h
--- epic4-2.10.1/include/config.h 2006-06-18 20:33:51.000000000 +0300
+++ epic4-2.10.1.JT/include/config.h 2012-08-30 13:22:20.319515332 +0300
@@ -412,7 +412,7 @@
#define DEFAULT_LOGFILE "irc.log"
#define DEFAULT_MAIL 2
#define DEFAULT_MAIL_INTERVAL 60
-/ #define DEFAULT_MAIL_TYPE "mbox" /
+#define DEFAULT_MAIL_TYPE "mbox"
#define DEFAULT_MAX_RECONNECTS 4
#define DEFAULT_METRIC_TIME 0
#define DEFAULT_MODE_STRIPPER 0
diff -aur epic4-2.10.1/include/vars.h epic4-2.10.1.JT/include/vars.h
--- epic4-2.10.1/include/vars.h 2006-06-18 20:33:51.000000000 +0300
+++ epic4-2.10.1.JT/include/vars.h 2012-08-30 13:24:19.719723226 +0300
@@ -93,7 +93,7 @@
LOG_REWRITE_VAR,
MAIL_VAR,
MAIL_INTERVAL_VAR,
- / MAIL_TYPE_VAR, /
+ MAIL_TYPE_VAR,
MANGLE_INBOUND_VAR,
MANGLE_LOGFILES_VAR,
MANGLE_OUTBOUND_VAR,
diff -aur epic4-2.10.1/source/mail.c epic4-2.10.1.JT/source/mail.c
--- epic4-2.10.1/source/mail.c 2006-06-18 20:33:51.000000000 +0300
+++ epic4-2.10.1.JT/source/mail.c 2012-08-30 15:25:05.568641118 +0300
@@ -353,7 +353,7 @@
return 0;
}
- maildir_path = malloc_strdup(tmp_maildir_path);
+ maildir_path = malloc_strdup(maildir);
maildir_last_changed = -1;
return 1;
}
@@ -375,13 +375,29 @@
{
int count = 0;
DIR dir;
+ Filename tmp_maildir_path;
+ struct dirent* dir_data;
- if ((dir = opendir(maildir_path)))
+ strlcpy(tmp_maildir_path, maildir_path, sizeof(Filename));
+ strlcat(tmp_maildir_path, "/new", sizeof(Filename));
+ if ((dir = opendir(tmp_maildir_path)))
{
- while (readdir(dir) != NULL)
- count++;
+ while ((dir_data = readdir(dir)) != NULL) {
+ if (dir_data->d_name[0] != '.')
+ count++;
+ }
+ closedir(dir);
+ }
+
+ strlcpy(tmp_maildir_path, maildir_path, sizeof(Filename));
+ strlcat(tmp_maildir_path, "/cur", sizeof(Filename));
+ if ((dir = opendir(tmp_maildir_path)))
+ {
+ while ((dir_data = readdir(dir)) != NULL) {
+ if (dir_data->d_name[0] != '.')
+ count++;
+ }
closedir(dir);
- count -= 2; / Don't count . or .. /
}
return count;
@@ -398,6 +414,7 @@
{
Stat sb;
Stat stat_buf;
+ Filename tmp_maildir_path;
if (ptr)
stat_buf = (Stat )ptr;
@@ -408,8 +425,11 @@
if (!init_maildir_checking())
return 0; / Can't find maildir /
+ strlcpy(tmp_maildir_path, maildir_path, sizeof(Filename));
+ strlcat(tmp_maildir_path, "/new", sizeof(Filename));
+
/ If there is no mailbox, there is no mail! /
- if (stat(maildir_path, stat_buf) == -1)
+ if (stat(tmp_maildir_path, stat_buf) == -1)
return 0;
/
@@ -547,6 +567,10 @@
update_mail_level2_maildir();
if (status == 2)
{
+ Filename tmp_maildir_path;
+ strlcpy(tmp_maildir_path, maildir_path, sizeof(Filename));
+ strlcat(tmp_maildir_path, "/new", sizeof(Filename));
+
/ XXX Ew. Evil. Gross. /
ts.actime = stat_buf.st_atime;
ts.modtime = stat_buf.st_mtime;
@@ -642,6 +666,27 @@
void set_mail_type (const void stuff)
{
- / EPIC4 cannot switch mailbox types (yet) /
+ const char value;
+ struct mail_checker new_checker;
+ char old_mailval[16];
+
+ value = (const char )stuff;
+
+ if (value == NULL)
+ new_checker = NULL;
+ else if (!my_stricmp(value, "MBOX"))
+ new_checker = &mail_types[0];
+ else if (!my_stricmp(value, "MAILDIR"))
+ new_checker = &mail_types[1];
+ else
+ {
+ say("/SET MAIL_TYPE must be MBOX or MAILDIR.");
+ return;
+ }
+
+ snprintf(old_mailval, sizeof(old_mailval), "%d", get_int_var(MAIL_VAR));
+ set_var_value(MAIL_VAR, zero);
+ checkmail = new_checker;
+ set_var_value(MAIL_VAR, old_mailval);
}
diff -aur epic4-2.10.1/source/vars.c epic4-2.10.1.JT/source/vars.c
--- epic4-2.10.1/source/vars.c 2008-03-17 05:42:46.000000000 +0200
+++ epic4-2.10.1.JT/source/vars.c 2012-08-30 13:14:54.801014647 +0300
@@ -194,7 +194,7 @@
{ "LOG_REWRITE", STR_TYPE_VAR, 0, 0, NULL, NULL, 0, 0 },
{ "MAIL", INT_TYPE_VAR, DEFAULT_MAIL, 0, NULL, set_mail, 0, 0 },
{ "MAIL_INTERVAL", INT_TYPE_VAR, DEFAULT_MAIL_INTERVAL, 0, NULL, set_mail_interval, 0, 0 },
- / { "MAIL_TYPE", STR_TYPE_VAR, 0, 0, NULL, set_mail_type, 0, 0 }, /
+ { "MAIL_TYPE", STR_TYPE_VAR, 0, 0, NULL, set_mail_type, 0, 0 },
{ "MANGLE_INBOUND", STR_TYPE_VAR, 0, 0, NULL, set_mangle_inbound, 0, 0 },
{ "MANGLE_LOGFILES", STR_TYPE_VAR, 0, 0, NULL, set_mangle_logfiles, 0, 0 },
{ "MANGLE_OUTBOUND", STR_TYPE_VAR, 0, 0, NULL, set_mangle_outbound, 0, 0 },
@@ -350,7 +350,7 @@
set_string_var(HIGHLIGHT_CHAR_VAR, DEFAULT_HIGHLIGHT_CHAR);
set_string_var(LASTLOG_LEVEL_VAR, DEFAULT_LASTLOG_LEVEL);
set_string_var(LOG_REWRITE_VAR, NULL);
- / set_string_var(MAIL_TYPE_VAR, DEFAULT_MAIL_TYPE); /
+ set_string_var(MAIL_TYPE_VAR, DEFAULT_MAIL_TYPE);
set_string_var(MANGLE_INBOUND_VAR, NULL);
set_string_var(MANGLE_LOGFILES_VAR, NULL);
set_string_var(MANGLE_OUTBOUND_VAR, NULL);
Trivial mod_rewrite: Redirect to another file in the same directory
Wednesday, March 19. 2014
I found a funny quote at Htaccess Rewrites - Rewrite Tricks and Tips, it says:
``Despite the tons of examples and docs, mod_rewrite is voodoo. Damned cool voodoo, but still voodoo. ''
-- Brian Moore
bem@news.cmc.net
The quote is originally at http://httpd.apache.org/docs/2.0/rewrite/. Now obsoleted documentation for old Apache version.
I'll have to second Brian's opinion. I've touched the subject earlier at Advanced mod_rewrite: FastCGI Ruby on Rails /w HTTPS.
My YUM-repo definition RPM had a bug in it (see: CentOS 6 PHP 5.4 and 5.5 yum repository) and I had to release a new version of it. There exist already couple of links to the file. Why didn't I think of a situation where an update is released? Darn! So, let's keep the URL alive, even if a new version of the file with different name is released. That way everybody stays happy.
Attempt 1: Failure
An over enthusiastic "hey, that should be simple!" -type of naive solution. Create a .htaccess-file into the appropriate directory with content:
RedirectPermanent oldname.rpm newname.rpm
Well ... no. The result is a HTTP/500 and in the error log there was a:
/home/the/entire/path/here/.htaccess: Redirect to non-URL
Ok. It didn't work.
Attempt 2: Failure
Let's ramp this up. Forget the simple tools, hit it with mod_rewrite! Make .htaccess contain:
RewriteEngine on
RewriteRule ^oldname\.rpm$ newname.rpm [R=301]
Well ... no. The result is a HTTP/404, because the redirect goes really wrong. The result will be http://my.server.name/home/the/entire/path/here/newname.rpm, which is pretty far from being correct. There is a funny mix of URL and the actual filesystem storage.
The reason can be found from the Apache docs at RewriteRule PT-flag:
"The target (or substitution string) in a RewriteRule is assumed to be a file path, by default. The use of the [PT] flag causes it to be treated as a URI instead."
and
"Note that the PT flag is implied in per-directory contexts such as <Directory> sections or in .htaccess files."
That phrase can be translated as:
- Internally RewriteRule works with filesystem paths
- When using RewriteRule from a .htaccess-file it does not use filesystem paths, but URLs
- A .htaccess-file really messes things up
Something more elegant is obviously needed.
Attempt 3: Failure
I studied the Apache docs and found a perfect solution! What about if there was a way to discard the filesystem path entirely. Nice! Let's go that way, make .htaccess contain:
RewriteEngine on
RewriteRule ^oldname\.rpm$ newname.rpm [R=301,DPI]
Well ... no. I have the DiscardPathInfo-flag there, but it changes absolutely nothing. It is the same with or without the flag. It clearly says that "The DPI flag causes the PATH_INFO portion of the rewritten URI to be discarded" in the docs. Apparently the flag is used for completely different thing (which I'm having hard time to comprehend), but the thing is that I cannot use it to fix my redirect.
Attempt 4: Success!
After browsing the Apache-docs even more I struck gold. The docs for RewriteBase-directive say:
"This directive is required when you use a relative path in a substitution in per-directory (htaccess) context"
and
"This misconfiguration would normally cause the server to look for an "opt" directory under the document root."
That's exactly what I'm doing here. I have a relative path. I'm using a substitution in a .htaccess-file. It even mis-behaves precisely like in the example from the docs.
The solution is to make .htaccess contain:
RewriteEngine on
RewriteBase /path/here/
RewriteRule ^oldname\.rpm$ newname.rpm [R=301]
Now it works exactly as I want it to do! Nice!
When a request is done for the old filename, Apache will do an external redirect and notify browser about the new version. wget fails to save the file with the new name (it will use the old name), but for example Firefox does that correctly.
Conclusion
Darn that voodoo is hard.
The mod_rewrite's complexity simply laughs at any system administrator. I consider myself to be one of the experienced ones, but still ... I find myself struggling with the subject.
Java 1.7 update 51 breaking Cisco ASDM login
Monday, March 10. 2014
One day I needed to drill a hole to a Cisco firewall. I went to Adaptive Security Device Manager and could not log in. Whaat?!
It did work before, but apparently something changed. Sneak peek with Wireshark revealed that SSL handshake failed. Java console has something like this in it:
java.lang.SecurityException: Missing required Permissions manifest attribute in main jar: https://dm-launcher.jar
at com.sun.deploy.security.DeployManifestChecker.verifyMainJar(Unknown Source)
at com.sun.deploy.security.DeployManifestChecker.verifyMainJar(Unknown Source)
at com.sun.javaws.Launcher.doLaunchApp(Unknown Source)
at com.sun.javaws.Launcher.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
and:
javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: Java couldn't trust Server
at sun.security.ssl.Alerts.getSSLException(Unknown Source)
at sun.security.ssl.SSLSocketImpl.fatal(Unknown Source)
at sun.security.ssl.Handshaker.fatalSE(Unknown Source)
at sun.security.ssl.Handshaker.fatalSE(Unknown Source)
at sun.security.ssl.ClientHandshaker.serverCertificate(Unknown Source)
at sun.security.ssl.ClientHandshaker.processMessage(Unknown Source)
Little bit of googling revealed Issues Accessing ASDM at Cisco's learning network and Cisco ASDM blocked by Java? at spiceworks.com. So I wasn't alone with the problem. Oracle's release notes for update 51 revealed a number of changes to earlier versions. Java is still piece of shit, but they're trying to fix it. Too little, too late. It is very unfortunate that I have to have Java Runtime installed and use it for a number of important applications. Now Oracle is making radical changes to JRE to improve its flaky security and these customer companies like Cisco cannot keep up with the changes.
Anyway, enough rant, here is how to fix it. The idea is to take the self-signed certificate from the Cisco firewall and import it for Java. This is yet another nice feature of a Windows-computer. There needs to be separate a separate certificate store for operating system, browser and Java.
First go to web-interface of the Cisco appliance. Internet Explorer cannot export a certificate from a web site, so use a Firefox or Chrome or pretty much any other browser. Save the certificate to a file. Like this:
When you have the file, go to Control Panel on Windows:
Select Java and Security-tab:
From there you can find Manage Certificates. Import the certificate-file from there:
It is very, very important that you first select Certificate Type: Secure Site. Any other certificate type won't fix the problem.
On the security-tab there is an exception list for certificates. Adding an exception won't fix this, since the problem is with the fact that the certificate is self-signed.
Now login works again.
When I first encountered this issue, I asked help from couple of guys who are very familiar with Cisco IOS (not Apple iOS). The initial response was "What is ASDM?" Apparently the GUI is not the expert's way to go.
Firefox per dir save
Sunday, March 9. 2014
Once upon a time there was a Firefox version which remembered where something was saved from a website. I think the last download destination directory was stored per host. I clearly remember that when I downloaded something from SourceForge, it would remember the directory, but since there are number of projects I download from it didn't always be a correct one. But for websites, I use for only one piece of software, it was always correct.
Then something changed. My Firefox wouldn't remember my destinations anymore.
Now for some nostalgic reason I wanted the functionality back. My loyal/hated aide Google found me a solution for that. A Mozilla support forum discussion named Changing FF25 download location in Win7 - Browse will not get past /User folder. It clearly states that such a setting exists, but is now off by default. When I went to my about:config, it looked like this:
Like the support forum promised, the configuration directive is hidden. They say hidden, but actually it is not created at all. Luckily you can add it by yourself by right clicking on the Firefox configuration:
Just add a new boolean variable with name browser.download.lastDir.savePerSite and you're good to go. Remember to set the value into true. It is enabled immediately, no restarting or anything needed.
The last thing for me to do is keep wondering why it was enabled in a couple of versions when it was introduced and then turned off.