June 12, 2002, 10:02:08 pm
<--PreviousNext -->

PHP-GTK
<?php
/*

    Copyright (C) 2001 Richard D. Payne

     This file is part of Teak (http://teak.sourceforge.net).

    Teak 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.

    Teak 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 Teak; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

*/
    
dl ('php_gtk.so');

    Class 
Compose_Window extends GtkWindow {
        var 
$send_button;
        var 
$cancel_button;
        var 
$message_parts;
        var 
$itemf;
        var 
$imap_connection;

        function 
Compose_Window($to_string,$cc_array,$subject,$body,$conn) {
            global 
$host;
            global 
$user;
            global 
$passwd;

            
$this->GtkWindow();

            
$mailhost="{".$host.":143}";

            
$this->set_title("Teak - Compose Message");
            
$this->set_usize(640,480);

            
// Construct the mailbox name
            
$mailhost="{".$host.":143}$drafts";

            if ((
$conn == NULL) && ($passwd != NULL))
                
$this->get_imap_connection($mailhost,$passwd);
            else
                
$this->imap_connection=$conn;
            
            
$master_box = &new GtkVBox(false,5);
            
$master_box->set_border_width(5);
            
$top_box = &new GtkVBox(false,5);
            
$bottom_box = &new GtkVBox(false,5);
        
            list(
$pixmap$mask) = Gdk::pixmap_create_from_xpm(null,null,"images/envelope.xpm");
            
$this->send_button = new GtkButton();
    
// It seems Zend can't handle $this->send_button->function(), so we have to do this
            
$send_button=$this->send_button;
            
$send_image = &new GtkPixmap($pixmap,$mask);
            
$send_box = &new GtkHbox();
            
$send_label = &new GtkLabel("Send");
            
$send_box->pack_start($send_image);
            
$send_box->pack_start($send_label);
            
$send_button->add($send_box);

            
$attach_button =  &new GtkButton();
            list(
$pixmap$mask) = Gdk::pixmap_create_from_xpm(null,null,"images/attachment.xpm");
            
$attach_image = &new GtkPixmap($pixmap,$mask);
            
$attach_box = &new GtkHbox();
            
$attach_label = &new GtkLabel("Attach");
            
$attach_box->pack_start($attach_image);
            
$attach_box->pack_start($attach_label);
            
$attach_button->add($attach_box);

            
$cancel_button $this->cancel_button;
            
$cancel_button = &new GtkButton("Cancel");
            
$cancel_button->connect('clicked',array($this,destroy_window));

            list(
$pixmap$mask) = Gdk::pixmap_create_from_xpm(null,null,"images/cancel.xpm");
            
$cancel_image = &new GtkPixmap($pixmap,$mask);
            
$cancel_box = &new GtkHbox();
            
$cancel_label = &new GtkLabel("Cancel");
            
$cancel_box->pack_start($cancel_image);
            
$cancel_box->pack_start($cancel_label);
            
$this->cancel_button = new GtkButton();
            
$cancel_button=$this->cancel_button;
            
$cancel_button->add($cancel_box);
            
$cancel_button->connect('clicked',array($this,destroy_window)); 

            
$button_table = &new GtkToolbar(GTK_ORIENTATION_HORIZONTAL,GTK_TOOLBAR_BOTH);
            
$button_table->append_widget($this->send_button,"Send Message","");
            
$button_table->append_widget($attach_button,"Attach File(s)","");
            
$button_table->append_space();
            
$button_table->append_widget($this->cancel_button,"Cancel This Message","");
            
            
$address_box = &new GtkTable(3,2,false);
            
$address_box->set_row_spacings(5);
            
$address_box->set_col_spacings(5);
            
$to_button = &new GtkButton ("To");
            
$to_button->set_usize(60,25);
            
$cc_button = &new GtkButton ("Cc");
            
$cc_button->set_usize(60,25);
            
$bcc_button = &new GtkButton ("Bcc");
            
$bcc_button->set_usize(60,25);

            
$to_entry = &new GtkEntry();
            if (
$to_string != NULL)
                
$to_entry->set_text($to_string);
            
$cc_entry = &new GtkEntry();
            if (
count($cc_array) != 0) {
                
$cc_string=$cc_array[0]->mailbox."@".$cc_array[0]->host;
                if (
count($cc_array 1)) {
                    for (
$i=1;$i<count($cc_array);$i++) {
                        
$cc_string=$cc_string.";".$cc_array[$i]->mailbox."@".$cc_array[$i]->host;
                    }
                }
            
$cc_entry->set_text($cc_string);
            }
            
            
$bcc_entry = &new GtkEntry();

            
//Attach the signal handlers for the to/cc/bcc buttons
            
$to_button->connect('clicked',array($this,show_ldap_search_dialog),$to_entry);
            
$cc_button->connect('clicked',array($this,show_ldap_search_dialog),$cc_entry);
            
$bcc_button->connect('clicked',array($this,show_ldap_search_dialog),$bcc_entry);
            
$address_box->attach($to_button,1,2,1,2,GTK_SHRINK,GTK_SHRINK);
            
$address_box->attach($to_entry,2,3,1,2);
            
$address_box->attach($cc_button,1,2,2,3,GTK_SHRINK,GTK_SHRINK);
            
$address_box->attach($cc_entry,2,3,2,3);
            
$address_box->attach($bcc_button,1,2,3,4,GTK_SHRINK,GTK_SHRINK);
            
$address_box->attach($bcc_entry,2,3,3,4);

            
$text_scroll = &new GtkScrolledWindow();
            
$text_box = &new GtkText();
            if (
$body != NULL)
                
$text_box->insert(null,null,null,$body);
            
$text_box->set_editable(TRUE);
            
$text_scroll->add($text_box);

            
$subject_label = &new GtkLabel("Subject: ");
            
$subject_entry = &new GtkEntry();
            if (
$subject != NULL)
                
$subject_entry->set_text($subject);
            
$subject_box = &new GtkTable(1,2,false);
            
$subject_box->attach($subject_label,1,2,1,2,GTK_SHRINK,GTK_SHRINK);
            
$subject_box->attach($subject_entry,2,3,1,2);
            
            
$bottom_box->pack_start($subject_box,false,false,10);
            
$bottom_box->pack_start($text_scroll,true,true);

            
$master_box->pack_start($top_box,false,false);
            
$master_box->pack_start($bottom_box,true,true);

            
$message_parts=$this->message_parts;

            
// Create the menus, we need this down here because of the parameter for callback
            
$ag = &new GtkAccelGroup();
            
$itemf = &new GtkItemFactory(GtkMenuBar::get_type(), '<main>'$ag);
            
$this->add_accel_group($ag);
            
$itemf->create_items(array(
                array(
'/_Message','',null,0,'<Branch>'),
                array(
'/_Message/Se_nd',  '<alt>N', array($this,send_mail), 1'',array($to_entry,$cc_entry$bcc_entry$subject_entry,$text_box,&$message_parts)), 
                array(
'/_Message/_Save''<alt>S',array(&$this,save_message),2'',array($to_entry,$cc_entry$bcc_entry$subject_entry,$text_box,$mailhost)),
                array(
'/_Message/sep1','',null,3,'<Separator>'),
                array(
'/_Message/Exit','<alt>Q',null,4,''),
            
//Text menu    
                
array('/_Text','',null,5,'<Branch>'),
                array(
'/_Text/Cut','<alt>X',array($this,cut_text),6,'',array($text_box)),
                array(
'/_Text/_Copy','<alt>C',array($this,copy_text),7,'',array($text_box)),
                array(
'/_Text/_Paste','<alt>P',array($this,paste_text),8,'',array($text_box)),
                array(
'/_Text/sep2','',null,9,'<Separator>'),
                array(
'/_Text/Select A_ll','<alt>L',array($this,select_all_text),7,'',array($text_box))
            ));
            
//Set the class variable to be the local
            
$this->itemf=$itemf;    

            
$button_menu_box = &new GtkVBox();
            
$button_menu_box->pack_start($itemf->get_widget('<main>'),false,false,5);
            
$button_menu_box->pack_start($button_table,false,false);

            
$top_box->pack_start($button_menu_box,false,false);
            
$top_box->pack_start($address_box);


            
//Setup the event handlers
            
$send_button->connect('clicked',array($this,send_mail),null,$to_entry,$cc_entry$bcc_entry$subject_entry,$text_box,&$message_parts);
            
$attach_button->connect('clicked',array($this,get_file_name),&$message_parts);
            
$this->add($master_box);
            
$this->show_all();
        }
        
// End constructor

/* #################################################################################
    Function close out this window
*/ #################################################################################
    
function destroy_window($widget) {
        
$this->destroy();
    }



/* #################################################################################
    Function to check the spelling in $text
*/ #################################################################################
    
function check_spelling ($text_box) {

        return 
TRUE;

        
/* More important things to do for now than this......
        $text=$text_box->get_chars(0,-1);
        //FIXME, the language should really not be hard coded!

        $pspell_link = pspell_new("en","american","lrg","ISO8859-1",PSPELL_NORMAL);
        if ($pspell_link == NULL) {
            echo "Unable to make a connection to the spell checker\n";
            return;
        }

        if (!pspell_check ($pspell_link, $text)) {
                                $suggestions = pspell_suggest ($pspell_link, $text);

                                for ($i=0; $i < count ($suggestions); $i++)
                                    echo "Possible spelling: " . $suggestions[$i] . "\n";
                }
        */

    
}

/* #################################################################################
    save the message (for editing later) in the folder $drafts
    we don't save attachments with the message at this point

    We need an imap connection here to save the message
*/ #################################################################################
    
function save_message($widget$id$to$cc$bcc$subj$text,$mailhost) {
        global 
$drafts;
        global 
$host;

        if (
$this->imap_connection == NULL) {
            
$this->show_passwd_dialog($mailhost);
        }

        
// Construct the right mbox for the Drafts folder
        
if ($drafts != NULL)
            
$drafts_mbox "{".$host.":143}".$drafts;
        else {
            
$message "You have not listed a folder in which to save your draft messages.\n Please edit your config.php file and add a drafts folder\n Your message has not been saved!";
            
$ed = &new error_dialog($message);
            return;
        }
        

        
$env["to"]=$to->get_text();
        
$env["from"]=$return_address;
        
$env["cc"]=$cc->get_text();
        
$env["bcc"]=$bcc->get_text();
        
$env["subject"]=$subj->get_text();

        
$num_parts=(count($parts)+1);
        
$msg_text["type"]=TYPETEXT;
                
$msg_text["subtype"]="plain";
                
$msg_text["contents.data"]=$text->get_chars(0,-1);        
        
$body[0]=$msg_text;
        
$message=imap_mail_compose($env,$body);
        
$success=imap_append($this->imap_connection,$drafts_mbox,$message);
        if (
$success == 1) {
            
$this->destroy_window(null);
        }
        else { 
            
$message "Something went wrong on message save:\n ".imap_last_error()."\n";
            
$ed = &new error_dialog($message);
        }

    }

/* #################################################################################
    Create a password dialog for the user to put in their password
*/ #################################################################################
    
function show_passwd_dialog($mailhost) {
        global 
$user;

        
$pwd_dialog = &new password_dialog();
        
$pwd_ok_button $pwd_dialog->get_ok_button();
        
$pwd_cancel_button $pwd_dialog->get_cancel_button();
        
$pwd_ok_button->connect('clicked', array($this,destroy_dialog),$pwd_dialog);
        
$pwd_cancel_button->connect('clicked', array($this,destroy_dialog),$pwd_dialog);

        
//"Start" the dialog's main, it will exit when the user presses OK or Cancel
        
$pwd_dialog->start_main();
        
$pwd_entry $pwd_dialog->get_passwd_entry();
        
$passwd=$pwd_entry->get_chars(0,-1);
        
$return $this->get_imap_connection($mailhost,$passwd);
}    

    function 
destroy_dialog($widget$dialog) {
            
$dialog->destroy();
        }
    

/* #################################################################################
    Make a connection to the imap server
*/ #################################################################################
    
function get_imap_connection($mailhost,$passwd) {
        global 
$user;
        
$this->imap_connection imap_open ("$mailhost","$user""$passwd");
        if (
$this->imap_connection == NULL) {
            
$message="The connection to the IMAP server has failed\n".imap_last_error();
            
$error_dialog = &new error_dialog($message);

        }
        else
            return 
TRUE;
    }



/* #################################################################################
    Actually sends the mail and calls the spell checker, if desiired
*/ #################################################################################
    
function send_mail($widget$id$to$cc$bcc$subj$text,$parts)  {
        global 
$return_address;
        global 
$smtp_path;
        
        
//if ($spell_check == TRUE) {
            //$send=$this->check_spelling ($text);
            //if ($send != TRUE)
            //    return;
        //}

        
$env["to"]=$to->get_text();

        if (
$env["to"] == NULL) {
        echo 
"No recipient listed!\n";
            return;
        }

        
$env["from"]=$return_address;
        
$env["cc"]=$cc->get_text();
        
$env["bcc"]=$bcc->get_text();
        
$env["subject"]=$subj->get_text();

        
$num_parts=(count($parts)+1);
        
$msg_text["type"]=TYPETEXT;
                
$msg_text["subtype"]="plain";
                
$msg_text["contents.data"]=$text->get_chars(0,-1);        

        
/* If we only have one element in the array then the user hasn't attached
            any files, so we're not generating a multi-part message */
        
if ($num_parts == 
            
$body[0]=$msg_text;
        else {
            
$header["type"]=TYPEMULTIPART;
                
$header["subtype"]="mixed";
            
$body[0]=$header;
            
$body[1]=$msg_text;
            for (
$i=2;$i<($num_parts+1);$i++) {
                
$part_count=($i 1);
                
$body[$i]=$parts[$part_count];
            }
                }    

        
$result=imap_mail_compose($env,$body);
        
$mail_pipe=popen("$smtp_path","w");
        
fwrite($mail_pipe,$result);
        
pclose($mail_pipe);
        
$this->destroy();

    
    }

/* ##############################################################################################
    Create the file dialog for attachments
*/ ##############################################################################################

    
function get_file_name ($widget,$parts) {
            
$fs = &new GtkFileSelection('File Selection Example');
            
$ok_button $fs->ok_button;
            
$ok_button->connect('clicked', array($this,attach_file),$fs,&$parts);
            
$ok_button->connect_object('clicked', array($fs'destroy'));
            
$cancel_button $fs->cancel_button;
            
$cancel_button->connect_object('clicked', array($fs'destroy'));
            
$fs->show();
    }


    function 
attach_file ($widget,$fs,$parts) {

    
//This is REALLY basic and probably needs much more work, but it works for now!
            
$file=$fs->get_filename();
                        
$fp=fopen($file,"r");
                        
$contents=fread($fp,filesize($file));
                        
fclose($fp);

            
//Get just the name of the file, without the path
            
$pos=strrpos($file,'/');
            
$filename=substr($file,$pos+1,strlen($file));

            
$parts_size=(count($parts)+1);
            
$parts[$parts_size]["type"]=TYPEAPPLICATION;
                        
$parts[$parts_size]["encoding"]=ENCBINARY;
                        
$parts[$parts_size]["subtype"]="octet-stream";
                        
$parts[$parts_size]["description"]=basename($filename);
                        
$parts[$parts_size]["contents.data"]=$contents;
            
$parts[$parts_size]["disposition.type"] = "attachment";
            
$parts[$parts_size]["disposition"]["filename"] = $filename;
            
    }

/* ###############################################################################################
    Function to popup a search dialog to search for addresses in the ldap directory
*/ ###############################################################################################
    
function show_ldap_search_dialog($widget,$txt_box) {
        
$search_dialog = &new ldap_search_dialog($txt_box);
        
$search_dialog->show();

    }
/* ###############################################################################################
    Some general purpose functions for getting/returning components
*/ ###############################################################################################
    
    
function get_send_button() {
        return 
$this->send_button;
    }

    function 
cut_text ($widget$id$text_area) {
        
$text_area->cut_clipboard();
    }

    function 
copy_text ($widget$id$text_area) {
        
$text_area->copy_clipboard();
    }

    function 
paste_text ($widget$id$text_area) {
        
$text_area->paste_clipboard();
    }

    function 
select_all_text ($widget$id$text_area) {
        
$text_area->select_region(0,-1);
    }
    

    function 
get_exit_menu_item () {
        
$itemfact=$this->itemf;
        return (
$itemfact->get_widget_by_action(4));
    }

    function 
get_cancel_button() {
        return 
$this->cancel_button;
    }

    function 
get_send_menu_item () {
        
$itemfact=$this->itemf;
        return (
$itemfact->get_widget_by_action(1));
    }
}

// End Class

?>