Tuesday, November 9, 2004

Friday, October 8, 2004

PEAR::Auth and vpop-xmlrpc

You guessed, I've written a vpop-xmlrpc container for PEAR::Auth.


There's also a new version of the vpop-xmlrpc cgi, which is needed for the Auth container, because the method vpop.auth has recently been added.


Have fun ;)

Wednesday, October 6, 2004

ext/vpopmail? no thanks...

If you ever thought about administering vpopmail through PHP, you most probably already stumbled across the vpopmail extension living in PECL, and know that making use of it is rather kludgy...


In need of such a solution I've written a simple XML-RPC CGI service in C with help of the xmlrpc-c library. I really didn't think that it would be that easy, but it definitely was, considering that I'm a C novice ;)


The following source will show that it's quite as simple as writing this XML-RPC backend in PHP, and it's really fast.


Update:
There's now a source tarball available at: http://dev.iworks.at/vpop-xmlrpc/
<php>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <vauth.h>
#include <vpopmail.h>
#include <xmlrpc.h>
#include <xmlrpc_cgi.h>


static xmlrpc_value *vpop_adduser(xmlrpc_env *env, xmlrpc_value *param, void *data)
{

char *user, *domain, *password, *fullname;
xmlrpc_bool rs;


xmlrpc_parse_value(env, param, "({s:s,s:s,s:s,s:s,*})",
"user", &user,
"domain", &domain,
"password", &password,
"fullname", &fullname
);


if (env->fault_occurred) {
return NULL;
}


rs = vadduser(user, domain, password, fullname, 0) == 0 ? 1 : 0;


return xmlrpc_build_value(env, "b", rs);
}


static xmlrpc_value *vpop_deluser(xmlrpc_env *env, xmlrpc_value *param, void *data)
{

char *user, *domain;
xmlrpc_bool rs;


xmlrpc_parse_value(env, param, "({s:s,s:s,*})",
"user", &user,
"domain", &domain
);


if (env->fault_occurred) {
return NULL;
}


rs = vdeluser(user, domain) == 0 ? 1 : 0;


return xmlrpc_build_value(env, "b", rs);
}


static xmlrpc_value *vpop_passwd(xmlrpc_env *env, xmlrpc_value *param, void *data)
{

char *user, *domain, *password;
xmlrpc_bool rs;


xmlrpc_parse_value(env, param, "({s:s,s:s,s:s,*})",
"user", &user,
"domain", &domain,
"password", &password
);


if (env->fault_occurred) {
return NULL;
}


rs = vpasswd(user, domain, password, 0) == 0 ? 1 : 0;


return xmlrpc_build_value(env, "b", rs);
}


static xmlrpc_value *vpop_setquota(xmlrpc_env *env, xmlrpc_value *param, void *data)
{

char *user, *domain, *quota;
xmlrpc_bool rs;


xmlrpc_parse_value(env, param, "({s:s,s:s,s:s,*})",
"user", &user,
"domain", &domain,
"quota", &quota
);


if (env->fault_occurred) {
return NULL;
}


rs = vsetuserquota(user, domain, quota) == 0 ? 1 : 0;


return xmlrpc_build_value(env, "b", rs);
}


int main(int argc, char **argv)
{

xmlrpc_cgi_init(XMLRPC_CGI_NO_FLAGS);


xmlrpc_cgi_add_method_w_doc("vpop.adduser", &vpop_adduser, NULL,
"b:S", "Add a vpopmail user to a domain with password, fullname and quota.");
xmlrpc_cgi_add_method_w_doc("vpop.deluser", &vpop_deluser, NULL,
"b:S", "Delete a user from a domain.");
xmlrpc_cgi_add_method_w_doc("vpop.passwd", &vpop_passwd, NULL,
"b:S", "Change the password of a user in a domain.");
xmlrpc_cgi_add_method_w_doc("vpop.setquota", &vpop_setquota, NULL,
"b:S", "Set the quota of a user in a domain.");


xmlrpc_cgi_process_call();


xmlrpc_cgi_cleanup();
return 0;
}

</php>

Monday, September 13, 2004

Chora already fixed

Jan reported that Chora is already fixed for three months.


First of all, let me apologize, I didn't want to hurt Horde or anyone else, and if you found my posting confusing, then well, I was confused and not too little...


That weekend my server has been cracked again, and ctorrent has been installed to burn my traffic (from the same network 210.5.125.*).


I doubt that the announcement Jan posted helped much, because how comes that apparently every script-kiddy knew about the vulnaribility but not chora users (at least I didn't know, and I saw a lot of chora 1.2 installations out there).


If I would have found a note on Chora's homepage, I think, I wouldn't have posted such a panic reaction.


So, sorry once again and I hope that this was - at least - a lesson to everyone of us...

Sunday, September 12, 2004

HORDE::Chora major vulnaribility

If you're running Hordes Chora 1.2 you should immediately upgrade your Horde installation or temporarily disable CVS access through HTTP.


Unfiltered $_GET as shell argument
On a quick glance scripts like diff.php seem to use unfiltered $_GET parameters as shell command arguments, which will allow any remote user to execute any command as webserver user.


A request like http://cvs.your.host/... will reveal the process list of the machine.

Wednesday, August 25, 2004

ext/apr - exercise or joke?

Well yes, it started as an exercise (and others thought it is a joke) ;)


My intention was to export apr_md5_encode() to php which generates MD5 password hashes similar to those found in .htpasswd files. PEARs File_Passwd already does that, but with plain vanilla PHP - generating one password takes about 0.2 seconds and more.


Currently I'm trying to make apr_threads usable - wouldn't threads in PHP be cool? Yes, they'd definitly be :) It's just a segfault away from working ;)



<?php

class Thread1 extends APR_Thread {
function
run() {
// do some work
}
}
class
Thread2 extends APR_Thread {
function
run() {
// do some concurrent work
}
}
new
Thread1;
new
Thread2;
?>

Thanks to Derick, Sara and the whole php.pecl gang - I wouldn't have managed to get that far without their tremendous help!

Thursday, August 5, 2004

Update: overflow:auto in Mozilla

If you want the page to scroll when the scrolling-enabled DIV has nothing to scroll you'll have to wrap the contents of the scrollMe function into the following if statement:



function scrollMe(event)
{
if (event.currentTarget.scrollHeight >
event.currentTarget.offsetHeight) {
// ...
}
}

Have fun!

Wednesday, August 4, 2004

Dropping server load with HTTP caching

Ever watched youself browsing e.g. a web forum?
Noticed that you viewed the same page several times?


Well, this means extraordinary and useless load for your server if there's no caching mechanism implemented in the web application. Even if there is some file or db cache you can still improve performance with implementing some http cache.


The easiest way is using PEARs HTTP::Header:



<?php

require_once 'HTTP/Header/Cache.php';
// only cache a few seconds for frequently
// changing pages like a forum;
// Header_Cache will exit automatically with
// "HTTP 304 Not Modified" if the page is
// requested twice within 3 seconds
$cache = &new HTTP_Header_Cache(3, 'seconds');
$cache->sendHeaders();

// ... load from file/db cache
// ... or rebuild page
?>

Probably the greatest caveat of using HTTP caching is, that our beloved Internet Explorer with standard settings doesn't even send an request to the server if it just notices a "Last-Modified" header (sic!), so one'd have to press the reload button (without CTRL) that a new page is displayed after the defined amount of time.


A dead end again? Decide yourself...


I finally managed to implement support for Internet Explorer in HTTP_Header 1.1.0 :D

Tuesday, August 3, 2004

Class inheritance or Containers?

While talking with Daniel and Lorenzo about "Tree Reincarnated" I regularly stumble across the question what approach to use to implement different backends: "Class inheritance or Containers?".


I personally feel that using the container approach leads to massive code duplication, while using class inheritance avoids the most (most, because there's no real multiple class inheritance in PHP).


Container



<?php

class PublicAPI
{
var
$container; // !SpecificAPI

function doSomething()
{
return
$this->container->doSomething();
}
}
?>

Class Inheritance



<?php

class SpecificAPI extends PublicAPI
{
function
doSomething()
{
// do something only this class needs to do
}
}
?>

So what do you feel about this topic and how you'd handle that?


UPDATE


While looking again at Daniel's nice diagram, I feel like we've already reached the point where solving this problem with class inheritence is impossible (despite using aggregate*() - you're right Lorenzo, again :) have nice holidays! ).


Tree_Admin_Simple_MDB2 would have to extend Tree_Simple_MDB2 and Tree_Admin_Simple_RDBMS...


Mike's arrived at the dead end, again ;)

Monday, August 2, 2004

Javascript & Flexy

If you ever used Flexy, which I consider a really great TE, you have most probably already stumbled across Flexy's inability to step into <script> blocks.


A really easy method to overcome this problem is to define scriptOpen and scriptClose properties in your base objects outputted by Flexy:



<?php

class FlexyObject {
var
$scriptOpen = "n<script type="text/javascript"> <!--n";
var
$scriptClose = "n//--> </script>n";
var
$scriptData = "var foo = 'bar';";
}
?>


Outputting above object with the following template wont work:



<html>
<script type="text/javascript">
{scriptData:h}
</script>
</html>


Instead:



<html>
{scriptOpen:h}
{scriptData:h}
{scriptClose:h}
</html>


...works like a charm... ;)

Alan said, Flexy wont step into Javascript blocks because that caused massive problems with the Smarty convertor...

Scrollable overflow:auto Elements in Mozilla

Doing some extensive Javascript work lately, I managed to make HTML elements styled with //overflow:auto// scrollable in Mozilla.


Just place this snippet at the bottom of your page with DIV elements that have scroll as classname:



<script type="text/javascript"> <!--
// enable scrolling for overflow:auto elements in Mozilla
function scrollMe(event)
{
var st = event.currentTarget.scrollTop;
st += (event.detail * 12);
event.currentTarget.scrollTop = st < 0 ? 0 : st;
event.preventDefault();
}
if (document.body.addEventListener) {
var divs = document.getElementsByTagName('DIV');
for (var d in divs) {
if (divs[d].className && divs[d].className == 'scroll') {
try {
divs[d].addEventListener(
'DOMMouseScroll', scrollMe, false);
} catch (ex) {}
}
}
}
// -->
</script>

I already posted a feature request to embed something similar in pearweb.