Discussion: after a message delete or move is handled, this function redirect the browser back to the appropiate page, and puts some data in the URI which the mail_msg class translates into a report to the user recapping what actions just took place. ALSO, note with multiple accounts or with filtering, it may be possible this function is processing a batch of messages that may be from or going to different folders, accounts, and servers. Both here and at the mail_msg move and delete functions, some grouping of message numbers is attempted, but this could be improved upon.
Discussion: Uses the phpgw api browser class to generate the headers which preceed the actual attachment data. Note this is tricky because different browsers, especially the MSIE versions, require different headers to be present in order to handle the data effectively at the clients browser. Incorrect headers can cause things like the browser not getting the name of the attachment, or not starting the associated viewer for the attachment, or even several save_or_open dialogs in a row.
Discussion: Used in special cases when simply giving the client browser unprocessed html MIME part(s) is not a good idea or needs special attention. Not a good idea means that there is CSS in the html part which would totally b0rk the look of the clients browser, or certain unusual script. Special Handling means a MULTIPART RELATED message such as Outkrook stationary or Evolutions version of the same, where the html has IMG tags in it that are not real HREFs but rather a reference to another MIME part in the same message. To handle that this message display code swaps that IMG mime part reference with an actual URL used by "get_attach" function to retrieve that particular MIME part from the email server and send it to the browser, this the IMG appears in the HTML message as intended. In that case the processing is done before the message is dispayed, and the processed HTML part is stored as a form hiddenvar in base64 encoded format. The user sees a button saying "View HTML", if clicked this processed HTML part is submitted to this function which base64 decodes it and sends it to the browser as a simgle html page, not a part of a mail like is typical. In either case the user gets that button and the buttons associated form submits data to this function. If the part is not RELATED, i.e. did not require special IMG tag swapping, then this function gets submitted to is a reference to the particular HTML part of the message and it is sent to the browser as a page unto itself. In either case, the part is not displayed inline with other MIME parts, not displayed in the same browser window as the rest of the groupware template, instead this part will be viewed in its own page.
Discussion: UNDER DEVELOPMENT
Discussion: bocompose needs GLOBALS[phpgw]->msg_bootstrap which has function "ensure_mail_msg_exists". Its safe to repeatedly use create_object on it because the api is smart enough not to re-create it if it already exists. And that function "ensure_mail_msg_exists". will not re-create or re-login, so this is "safe".
Discussion: Used by this class and also exposes some usefull functionality, mail.spell uses this function, for example.
Access: publicDiscussion: ?
Access: public
Discussion: This is how we apply the logic of the "AND" and "OR" that relate the match criteria rows SIMPLE LOGIC: each "and" "or" is compared with the item before it * example: ROW-0: subject contains "you got a raise" ROW-1: AND sender contains "boss" ROW-2: OR sender contains "your brother" * translates to: // (ROW-0 "AND" ROW-1) "OR" ROW-2 if both row 0 and row 1 are not satified, then this particular "logic chain" ends, BUT with row 2, the possible match would be if sender contains "your brother", and this match ALONE triggers the filter action. REMEMBER THIS: *ROW-2 itself can cause a match* because with "(X1 and X2) or X3", X3 alone causes a match. thus satisfying that particular filtes's match criteria and triggering action note: this means this we do *not* have this: // ROW-0 "AND" (ROW-1 "OR" ROW-2) if the above is really what you want: I suggest putting the "OR"s first, which puts the openening and closing Parentheses around the "OR" statement * example: ROW-0: sender contains "boss" ROW-1: OR sender contains "your brother" ROW-0: AND subject contains "you got a raise" * translates to: // (sender contains "boss" -OR- sender contains "your brother") -AND- subject contains "you got a raise" this is how you get the results you want. This example is designed to illustrate the a mail from "boss" about getting a "raise" may be more important to you than a mail from "your brother" with the same subject, because it is possible your brother does not control your compensation and he is just making a joke. You manage this logic by remembering that if you use 3 rows of match criteria, rows one and two have a parentheses around them. Why do it this way? The Sieve concept is to make filters EASY TO UNDERSTAND, studies show people actually use them in such cases therefor the simple rule that ANDs and ORs are paired together in the first and second row, is consistent and hopefully easy enough for "Jane / Joe User" to understand
Author: Angles
Discussion: Different Layouts appear different but use mostly the same source data. Pass param $layout to specify a layout 1or layout 2 style stats appearance, default is "2" which means email layout 2 appearance.
Access: private, may be used publically if needed.Discussion: Not used anymore, if a remote clients wants processed email message list data, this would be the function to use. If necessary it can be updated to produce new data as required. but layout 1 is kinda lame looking, may be replaced.
Discussion: takes the complex mime data provided by php, turns it into a flat array with human understandable descriptions of what the parts do,
Discussion: NOTE: if prefs are submitted that alter anything relative to a cached data item, the that cached item MUST BE EXPIRED, for example GLOBALS[phpgw]->msg->expire_session_cache_item("mailserver_callstr")
Access: publicDiscussion: we need mail_msg fully initialized to set prefs, but we do not need class_dcom, nor do we need to login, this is how to do it:
Example:$GLOBALS["phpgw"]->msg_bootstrap = CreateObject("email.msg_bootstrap"); $GLOBALS["phpgw"]->msg_bootstrap->set_do_login(False); $GLOBALS["phpgw"]->msg_bootstrap->ensure_mail_msg_exists("name of this calling function", $this->debug_set_prefs);
Discussion: This function serves as a single place to establish and maintain all preferences available to the email class. Since the preferenced are stored in a dynamic database, the database schema is not present at the database level, so we define it here. Also, $this->std_prefs[] and $this->cust_prefs[] arrays can be used to build a UI for managing and showing these prefs, and those arrays can be looped through for the setting and storing of these preferences.
Access: public## sample usages of the "init_default" property [init_default] comma seperated, first word is an instructional token --possible tokens are-- string [any_string] ex. 'string,new_old' set_or_not [set|not_set] ex. 'set_or_not,not_set' function [string_will_be_eval'd] ex. 'function,$this->sub_default_userid($accountid)' init_no_fill we will not fill this item during initialization (ex. a password) varEVAL [string_to_eval] ex. "$GLOBALS['phpgw_info']['server']['mail_server']"
Discussion: email preferences, like many other phpGW preference items, do not have a Database table devoted only to email preferences. If there were such a Database table, its fields would describe a schema similar to the one we are about to study. Email prefs are stored in the phpGW preferences table, which is shared by many apps and has the charactoristics of a dynamic data store, i.e. we can add, remove, or change email preference details without having to alter the Database table itself. This can make programming easier, but it also can present a chalange if your app has many preferences, which may have a complicted tree-like hierarchy. Low level preference functiond are handled by the pgpGW api. The data itself is stored in the database as a serialized array using the php functions serialize and unserialize. We can gain the flexibility of a rich preference data handling system by doing some work up front. The work in question here is an array based schema hard coded in this function, yet similar schema definitions could exist in an XML file, as the concept is very similar. We use an associaltive array (i,e. not a simple numbered array) to hold our schema data,
Example:This is a how-to example for adding an email preference item, saving it to the prefs DB table, retieving the pref, and using it in code. This DocSubTopic deals with adding an email preference item, using pref item "icon theme" as an example. A Step-by-Step example is provided with explanation, (1) copy an existing preference item to use as a template for your new preference item. (2) replace in the schema with your information, as such: *id* The "Unique ID" of this pref item. The pref DB uses this like a UID. *type* [ exists| user_string | known_string ] *widget* [ checkbox | textbox | textarea | combobox | passwordbox ] *accts_usage* [ default, extra_accounts ] *write_props* [ empty_string_ok | password, hidden, encrypted, empty_no_delete | no_db_defang ] *lang_blurb* description displayed to the user on the preferences page. *init_default* --possible tokens are-- string [any_string] ex. 'string,new_old' set_or_not [set|not_set] ex. 'set_or_not,not_set' function [string_will_be_eval'd] ex. "function,$this->sub_default_userid($accountid)" init_no_fill we will not fill this item during initialization (ex. a password) varEVAL [string_to_eval] ex. "$GLOBALS['phpgw_info']['server']['mail_server']" *values* Array of values available to the user, "key" => "value" , used with combobox widgets. *long_desc* Long help, detained description of the option displayed to the user as "long help". (3) Your are done. The preference is now part of email preferences. It will bedisplayed on the preferences page, saved and read from the preferences DB, it will have the default value you specified unless the user chooses otherwise. All this happens automatically, without the developer having to write any more code.
Discussion: For abstraction from phpgw UI and from PHP's GPC data, put the submitted GPC data into a class var $this->args[] array. This array is then used to represent the submitted data, instead of $GLOBALS['HTTP_POST_VARS']. This serves to further seperate the mail functionality from php itself, this function will perform the variable handling of the traditional php page view Get Post Cookie (no cookie data used here though) The same data could be grabbed from any source, XML-RPC for example, insttead of php's GPC vars, so this function could (should) have an equivalent XML-RPC "to handle filling these class variables from an alternative source. These class vars are only relevant to setting email prefs.
Author: AnglesDiscussion: EXPIRE ANY CACHED ITEM THAT WAS DERIVED FROM A CHANGED PREF ITEM. We should be precise and only expire if necessary, but for now just expire any cached item that could be effected by a change in preferences. NOTE: default acctnum is always 0, the acctnum which these prefs apply to.
Discussion: EXPIRE ANY CACHED ITEM THAT WAS DERIVED FROM A CHANGED PREF ITEM. We should be precise and only expire if necessary, but for now just expire any cached item that could be effected by a change in preferences. NOTE: we locate this after we have obtained a reliable acctnum which these prefs apply to.
Discussion: functional relative to function "grab_set_prefs_args_gpc()", except this function grabs the data from an alternative, non-php-GPC, source NOT YET IMPLEMENTED
Author: AnglesDiscussion: Reusable function, any preference data structured as in "this->init_available_prefs()" can use this code to automate preference submissions.
Author: AnglesDiscussion: ?
Access: private
Discussion: Gets the value for the "X-Originating-IP" header. That header is used by hotmail, for example, it looked like a "good thing" and was a feature request, so we use it here too. Even if the IP private (such as on a LAN), this can still be useful for the admin.
Discussion: If a message has already been sent, and IF the user has set the pref enabling the use of the sent folder, only then should this function be used. If a message has not actually been sent, it should NOT be copied to the "Sent" folder because that misrepresents to the user the history of the message. Mostly this is an issue with automated messages sent from other apps. My .02 cents is that if a user did not send a message by pressing the "Send" button, then the message does not belong in the Sent messages folder. Other people may have a different opinion, so this function will not zap your keyboard if you think differently. Nonetheless, if the user has not enabled the preference "Sent mail copied to Sent Folder", then noting gets copied there no matter what. Note that we obtain these preference settings as shown in the example for this function. If the folder does not already exist, class mail_msg has code to make every reasonable attempt to create the folder automatically. Some servers just do things differently enough (unusual namespaces, sub folder trees) that the auto create may not work, but it is nost likly that it can be created, and even more likely that it already exists. NOTE: this particular class should be made availabllle to public use without the brain damage that is the current learning curve for this code. BUT for now, this is a private function unless you really know what you are doing. Even then, code in this class is subject to change.
Access: private - NEEDS TO BE MADE AVAILABLE FOR PUBLIC USEDiscussion: FUTURE CODE what follows is untested but should work to accomplish that. While we do need to login to the mail server, we can just select the INBOX because the IMAP APPEND command does not require you have "selected" the folder that is the target of the append. We should be able to simply bootstrap the msg objext and call login, because during initialization the msg object gathers all the data it can find on what account number we are dealing with here, it handles that for us automatically. We do not want to append to the sent folder of the wrong account.
Example:## this should work if a stream does not already exist (UNTESTED) $this->msg_bootstrap = CreateObject("email.msg_bootstrap"); $this->msg_bootstrap->ensure_mail_msg_exists('email.bosend.copy_to_sent_folder', $this->debug_send); ## now run the rest of the function as usual.
Discussion: Compose form submit action target is bosend, naturally, however the spell check button submit is identical EXCEPT "btn_spellcheck" POST var will be set, which requires we handoff the handling to the spell class.
Discussion: If needed, put the body through stripslashes_gpc() before handing it off to the mail_spell object. This function simply gathers the required information and hands it off to the mail_spell class,
Discussion: advanced function to send mail with all the complexities of modern MIME usage. Currently handles forwarding as an "encapsulated" MIME part, thus prewserving the original messages structure, including any attachments the original message had. Of course the user can attach files, this includes attaching additional files to a forwarded message which itself alsready has attachments.
Discussion: NOTE this is a vestigal way for phpgw apps to inter-operate, I *think* this is being obsoleted via n-tiering and xml-rpc / soap methods. RARELY USED, maybe NEVER used, most email code for this is now commented out "back in the day..." the "x-phpgw" header was specified by a phpgw app *other* than the email app which was used to include special phpgw related handling instructions in the message which to the message intentended to be noticed and processed by the phpgw email app when the user open the mail for viewing, at which time the phpgw email app would issue the special handling instructions contained in the "x-phpgw" header. even before n-tiering of the phpgw apps and api begain, I (angles) considered this a possible area of abuse and I commented out the code in the email app that would notice, process and issue those instructions.
Discussion: charset could take up a lot of notes here, suffice to say that email began life as a US-ASCII thing and still us-ascii chars are strictly required for some headers, while other headers and the body have various alternative ways to deal with other charsets, ways that are well documented in email and other RFC's and other literature. In the rare event that the phpgw api is unable to provide us with a charset value, we use the RFC specified default value of "US-ASCII"
Discussion: Generally this var does not need to be specified. When the mail is being sent from the user's default email account (or mail on behalf of the user, like automated email notifications), we generate the "from" header for the user, hence no custom "from" arg is necessary. This is the most common scenario, in which case we generate the "from" value as follows: (1) the user's "fullname" (a.k.a. the "personal" part of the address) is always picked up from the phpgw api's value that contains the users name, and (2) the user's email address is either (2a) the default value from the phpgw api which was passed into the user's preferences because the user specified no custom email address preference, or (2b) the user specified a custom email address in the email preferences in which case the aformentioned phpgw api default email address is not used in the user's preferences array, this user supplied value is used instead. Providing a "from" arg is usually for extra email accounts and/or alternative email profiles, where the user wants other than the "from" info otherwise defaultly associated with this email acccount. NOTE: from != sender from is who the mail came from assuming that person is also the mail's author. this is by far the most common scenario, "from" and "author" are usually one in the same (see below for info on when to *also* use "sender" - VERY rare)
Discussion: RFC2822 makes clear that the Sender header is ONLY used if some one NOT the author (ex. the author's secretary) is sending the author's email. RFC2822 considers that "From" = the author and the "Sender" = the person who clicked the send button. Generally they are one in the same and generally the Sender header (and hence this "sender" var) is NOT needed, not used, not included in the email's headers.
Discussion: According to RFC2822 the Date header *should* be the local time with the correct timezone offset relative to GMT, however this is problematic on many Linux boxen, and in general I have found that reliably extracting this data from the host OS can be tricky, so instead we use a fallback value which is simply GMT time, which is allowed under RFC2822 but not preferred. FUTURE: figure out a host independant way of getting the correct rfc time and TZ offset
Discussion: when class.msg_send conducts the handshake with the SMTP server, this will be the required domain value that we supply to the SMTP server. Phpgw is considered the client to the SMTP server. RFC2821 sect 4.1.1.1 specifies this value is almost always the Fully Qualified Domain Name of the SMTP client machine, but rarely, when said client machine has dynamic FQDN or no reverse mapping is available, this value *should* be "address leteral" (see sect 4.1.3). Refer to the documentation for BIND for further reading on reverse lookup issues.
Discussion: top level 7bit requires qprinting the body if the body has 8bit chars in it ISSUE 1: "it's unnecessary" nowdays, most all MTAs and IMAP/POP servers can handle 8bit by todays usage, 7bit is quite restrictive, when considering the variety of things that may be attached to or carried in a message (and growing) [begin digression] However, stuffing RFC822 email thru a X500 (?) gateway requires 7bit body, which we could do here, at the MUA level, and may possibly require other alterations of the message that occur at the gateway, some of which may actually drop portions of the message, indeed it's complicated, but rare in terms of total mail volume (?) [end digression] ISSUE 2: "risks violating RFCs and confusing MTAs" setting top level encoding to 7bit when the body actually has 8bit chars is "TOTALLY BAD" MTA's will be totally confused by that mis-match, and it violates RFCs **More Importantly** this is a coding and functionality issue involved in forwarding: in general, when you forward a message you should not alter that message if that forwarded message has 8bit chars, I don't think that can be altered even to quote-print that forwarded part (i.e. to convert it to 7bit) would be altering it I suppose you could base64 encode it, on the theory that it decodes exactly back into it's original form, but the practice of base64 encoding non-attachments (i.e. text parts) is EXTREMELY rare in my experience (Angles) and still problematic in coding for this. I suppose this assumes qprint is possible "lossy" in that the exact original may not be exactly the same as said pre-encoded forwarded part, and, after all, it's still altering the part. CONCLUSION: Set Top Level Header "Content-Transfer-Encoding" to "8bit" because it's easier to code for and less likely to violate RFCs. for now send out as 8bit and hope for the best.
Discussion: used in making select text, value items, such as in the combobox widget.
Access: privateDiscussion: ?
Access: privateDiscussion: OOP style class for producing common widgets in html pages, such as a combobox. Designed to reduce bain damage to the developer by hiding the details of the html tags and by treating these things as widgets which is what they are, more than just simple html markup.
Discussion: class html_widgets needs the special C-Style Include .h like file, class.spell_struct which holds data structure class correction_info used here for integration with the mail.spell spellchecking class.
Discussion: generate an a href item, includes link, target, text. CLEARS ITSELF after each "get_href"
Author: Angles$this->widgets->set_href_link('index.php'); $this->widgets->set_href_target('top'); $this->widgets->get_href_clickme(lang('click here for more info in a new window')); $my_href_tag = $this->widgets->get_href();
Discussion: href class vars for link, target, text. CLEARS ITSELF after each "get_href". This utilty function does that. It is RARE that you would ever need to call this directly.
Access: privateDiscussion: After you set "href_target", "href_clickme" and other optional properties ("href_target") this function generates an HREF tag from that data and returns it. NOTE after generating the HREF tag, and before returning it, this function CLEARS ALL PROPERTIES that it used to make that href tag, so this "widget" automatically is ready to new usage without having to explicitly call any "new" or "clear" function.
Access: publicDiscussion: not really a widget, does not use OOP style, but it gets the job done quickly. Somewhat Depreciated, use the OOP style href widget instead.
Example:this->href_maketag("index.jsp", "click here for home page", "new");Access: public
Discussion: not really a widget but it gets the job done. QUICK way to generate a typical A IMG html item in a single function call. Not OOP style, just a quick utilty function. ALL params must be passed in this function call.
Example:$my_img = widgets->img_maketag("poweredby.png", "powered by RedHat", "", "", "0");Access: public
Discussion: generate a combo box html widget.
Author: Angles$this->widgets->new_combobox(); $this->widgets->set_cbox_name("user_choice"); $this->widgets->set_cbox_item("yes"', "Customer is Right"); $this->widgets->set_cbox_item("no"', "Customer is Wrong"); $my_combobox_wirget = $this->widgets->get_combobox();
Discussion: This function makes use of structure "correction_info" which we expose by including file class.spell_struct in the constructor for this class. The combobox select item this function makes embeds array data in the items "value" by setting it to a string that resembles a URL get request, which we then can recover this array by applying php function parse_str to the value when the user submits the form. The idea is to provide enough data in the value that the spellcheck replacement code can accurately find and replace the desired word, or not change the word at all if special suggestion string "K_E_E_P" is present. The first suggestion should be en empty string with special value "K_E_E_P" which means no change to the misspelled word, this is indicated by passing an empty string for param $suggestion_num. The value for the suggestion item is a URL type string that contains as much informaion as we can preserve from the $this_bad_word_element object param, but specifying the individual suggestion provieded by the $suggestion_num arg which is the index to this particular suggestion in the $this_bad_word_element->suggestions[] numbered array of suggestions. Upon submit, we can apply php function parse_str() to this uri to recover the desired array structure. Parse_str will even urldecode the items for us.
Discussion: this function does not clear its properties, so if for some reason you want THE SAME comboboxes more then one time, calling "get_combobox" will return the same combobox until you clear it by calling "new_combobox", which you should ALWAYS do when starting a new combobox widget.
Access: publicDiscussion: generate a opening tag of a form including name, action, method, and hiddenvars
Author: Angles$this->widgets->new_form(); $this->widgets->set_form_name('spell_review'); $this->widgets->set_form_method('POST'); $this->widgets->set_form_action('index.php?email.targets.move'); $this->widgets->set_form_hiddenvar('subject', 'stock'); $this->widgets->set_form_hiddenvar('symbol', 'GM'); // OPTIONAL if you have set "preserve_vars" you can include them as hidden vars with this command $this->commit_preserve_vars_to_form(); $my_form_tag = $this->widgets->get_form();
Discussion: This seems dumb at first, but take the folders combobox as an example, when the user selects a folder from the combbox the OnChange submits the form associated with that combobox, i.e. the form OnChange and the form name should be the same name and the form age should surround the combobox, I think, Anyway, IMAP servers have folders but POP servers do now, so we will not show said folder combobox if viewing a POP3 mail server. Therefor, in our template we put a non-breaking-space in the place of the combobox html. BUT what about that those form tage that surround this combobox, we should leave them out too. In typical templaying this is ease to replace the form opening tag with a non-breaking-space. BUT the closing tag is such a simple thing we often hard code it into the template, not a template var. SO we can not leave out the form open tag but have the form close tag still be in the template. This no-brainer function just makes it easy to remember to leave out or include, as the case may be, the form closeing tag.
Access: publicDiscussion: Since a button is generally considered a "widget", I will call this a widget although it does not use "set_" property functions the other widgets do. All params must be passed in the function call.
Access: public$my_button = $this->widgets->make_button('submit', 'btn_send', lang('Send'));
Discussion: generate a toolbar for use in email pages NOTE: usually only one toolbar made per page view so there is no "new_toolbar" function because we should not need it. set_toolbar_msg is the only value that you might want to check if you make more then one toolbar.
Author: AnglesDiscussion: Usually after deleting or moving messages or creating, renaming, or deleting folders, the mail_msg generates some kind of message to report to the user what actions were just taken. Note a blank string will clear a msg if needed. Currently only the uiindex page and the uifolder page might provide a msg.
Access: publicDiscussion: generate a toolbar for use in email pages NOTE: WE NEED globals[phpge]->msg OBJECT and A LOGIN in order to make this toolbar, THEREFOR do not put this toolbar on a page where login may not be available.Currently, Preferencs pages DO NOT LOGIN, because if you are setting preferences you do not need a mailserver stream AND you may not even have enough data set to get a mailserver stream. Note: uses a private template object to assemple the toolbar, calling function is responsible for putting the result in the global template.
Access: publicDiscussion: The first item in this folder combo box tells the user to "pick a folder to change to", and has no "value", the value is an empty string, this is more like a label than a combobox item.
Access: private, maybe made publicDiscussion: the "values" are in the form of a URI request string, since a combobox can only submit a single string as its value. This way we put alot of information if the form of the URI request and use php function "parse_str" to "recover" all this data on the submit. Accounts have a "status" associated with them, can be "enabled", "disabled", or "empty". In this combobox we show "enabled" and "disabled" accounts, not "empty" accounts. NOTE "disabled" really has no use, and "empty" I am not sure if that is ever used anywhere at all. Also note that a "disabled" account should never be "pre-selected" in this combobox, which seems logical. Almost always there is an email account that can be considered "active" because the user is viewing its data (folders, messages, its preferences) or if the user is composing a message then the last "active" account is considered the account which this mail will be "from". Therefor, generally all mail activity have an account that it applies to. So when this combobox comes across the account that is currently "active", that account will be "pre-selected" in the combobox. This serves two purposes, ONE, the user can not swicth to an account that is currently the "active" account, the user can only switch do a different account, and TWO, this gives the user visual feedback about which account is currently "active", on some pages, such as the compose page, this remines the user who the mail will be "from", i.e. which account sent the mail. In making this thing we iterate thru the "extra_and_default_acounts list", which is an numbered array whose members are structured array data describing the account.
Discussion: php may or may not have IMAP extension built in. This class will AUTO-DETECT that and load either (a) a class which mostly wraps the available builtin functions, or (b) a TOTAL REPLACEMENT to PHPs builtin imap extension. Currently, the POP3 socket class is fully implemented, basically a re-write of the UWash c-client, because all the logic contained in an imap server had to be emulated locally here, since a pop server provides only the most basic information, the rest must be deduced. NOTE: the imap socket class is NOT COMPLETE!
Author: Angles and others, each function has an authors list
Discussion: see PHP function: IMAP_STATUS -- This function returns status information on a mailbox other than the current one SA_MESSAGES - set status->messages to the number of messages in the mailbox SA_RECENT - set status->recent to the number of recent messages in the mailbox SA_UNSEEN - set status->unseen to the number of unseen (new) messages in the mailbox SA_UIDNEXT - set status->uidnext to the next uid to be used in the mailbox SA_UIDVALIDITY - set status->uidvalidity to a constant that changes when uids for the mailbox may no longer be valid SA_ALL - set all of the above
Discussion: see PHP function: IMAP_MAILBOXMSGINFO -- Get information about the current mailbox
Syntax:structure returns this data Date date of last change Driver driver Mailbox name of the mailbox Nmsgs number of messages Recent number of recent messages Unread number of unread messages Deleted number of deleted messages Size mailbox size
Discussion: class mailbox_status is used by function IMAP_STATUS class mailbox_msg_info is used by function IMAP_MAILBOXMSGINFO These two functions / classes are similar, some notes on their usage is the example below
Example:Note 1) IMAP_MAILBOXMSGINFO is only used for the folder that the client is currently logged into, for pop3 this is always "INBOX", for imap this is the currently selected (opened) folder. Therefor, with imap the target folder must already be selected (via IMAP_OPEN or IMAP_REOPEN) Note 2) IMAP_STATUS is can be used to obtain data on a folder that is NOT currently selected (opened) by the client. For pop3 this difference means nothing, for imap this means the client need NOT select (i.e. open) the target folder before requesting status data. Still, IMAP_STATUS can be used on any folder wheter it is currently selected (opened) or not. Note 3) The main functional difference is that one function returns size data, and the other does not. imap_mailboxmsginfo returns size data, imap_status does NOT. This size data adds all the sizes of the messages in that folder together to get the total folder size. Some IMAP servers can take alot of time and CPU cycles to get this total, particularly with MAILDIR type imap servers such as Courier-imap, while other imap servers seem to return this size data with little difficulty.
Discussion: see PHP function: imap_fetchstructure -- Read the structure of a particular message
Syntax:structure of return data is this type Primary body type encoding Body transfer encoding ifsubtype TRUE if there is a subtype string subtype MIME subtype ifdescription TRUE if there is a description string description Content description string ifid TRUE if there is an identification string id Identification string lines Number of lines bytes Number of bytes ifdisposition TRUE if there is a disposition string disposition Disposition string ifdparameters TRUE if the dparameters array exists dparameters Disposition parameter array ifparameters TRUE if the parameters array exists parameters MIME parameters array parts Array of objects describing each message part
Discussion: see PHP function: imap_fetch_overview -- Read an overview of the information in the headers of the given message. NOT CURRENTY IMPLEMENTED
Discussion: see PHP function: imap_headerinfo -- Read the header of the message see PHP function: imap_header which is simply an alias to imap_headerinfo
Discussion: mail_dcom_base Extends phpgw api class network After mail_dcom_base is loaded, a top level class mail_dcom is created specifically for the necessary propocol, either POP3, IMAP, or NNTP
Syntax:CreateObject('email.mail_dcom');Author: Angles, Skeeter, Itzchak Rehberg, Joseph Engo
this is the array return struture result['folder'] : string is the folder (a.k.a. mailbox) name WITHOUT the bracketed result['svr_and_port'] string : for Internal Use result['server'] : string is the IP or NAME of the server result['port_with_junk'] string : for Internal Use result['port'] string is the port number
Discussion: $fq_folder name arrives as: FOLDERNAME OR some variation like this: FOLDERNAME FOLDERNAME this is how php passes around this data in its builtin IMAP extensions this function breaks down that string into it's parts
Author: AnglesDiscussion: POP3 servers data typically ends with special charactor(s), usually an empty line, i.e. a lone CRLF pair, or line that is a period "." followed br a CRLF pair thus we can direct this function to read the server's data until such special end flag is reached
Author: Angles, skeeterDiscussion: ?
Author: AnglesDiscussion: useful for debugging, CRLF pairs are CarrageReturn + LineFeed which is the standard way email client and servers end any line while communicating
Author: AnglesDiscussion: PHP `quoted_printable_decode` function does not work properly: it should convert '_' characters into ' '.
Discussion: Remove '=' at the end of the lines. `quoted_printable_decode` doesn't do it.
Discussion: uses ereg_replace and preg_replace in addition to php function base64_decode
Discussion: ?
Discussion: ?
Discussion: ?
Discussion: useable but depreciated
Discussion: ?
Discussion: ?
Discussion: ?
Discussion: usable but depreciated
Discussion: appears to implement UUDECODE without any special php functions.
Discussion: this is a NON-REGEX way to to so this, and is NOT case sensitive this *should* be faster then Regular expressions and *should* not be confused by regex special chars such as the period "." or the slashes "/" and "\" , etc...
Syntax:?Author: Angles
Discussion: IMAP servers send out data that is fairly well "typed", meaning RFC2060 is pretty strict about what the server may send out, allowing the client (us) to more easily interpet this data. The important indicator is the string at the beginning of each line of data from the server, it can be: "*" (astrisk) = "untagged" = means "this line contains server data and more data will follow" "+" (plus sign) means "you, the client, must now finish sending your data to the server" "tagged" is the command tag that the client used to initiate this command, such as "A001" IMAP server's final line of data for that command will contain that command's tag as sent from the client This tagged "command completion" signal is followed by either: "OK" = successful command completion "NO" = failure of some kind "BAD" = protocol error such as unrecognized command or syntax error, client should abort this command processing
Syntax:?Author: Angles, skeeter
Discussion: ?
Syntax:?Author: Angles
Discussion: implements the functionality of php function IMAP_OPEN note that php's IMAP_OPEN applies to IMAP, POP3 and NNTP servers
Syntax:?Author: Angles, skeeter
Discussion: ?
Author: AnglesDiscussion: implements the functionality of php function IMAP_STATUS
Syntax:?Author: Angles, skeeter
Discussion: mail_dcom Extends mail_dcom_base which Extends phpgw api class network This is a top level class mail_dcom is designed specifically POP3
Syntax:CreateObject('email.mail_dcom');Author: Angles, Skeeter, Itzchak Rehberg, Joseph Engo
Discussion: implements the functionality of php function IMAP_OPEN note that php IMAP_OPEN applies to IMAP, POP3 and NNTP servers
Author: Angles, skeeterDiscussion: implements the functionality of php function IMAP_CLOSE, note that with POP3, messages are marked "Deleted" and then automatically expunged on QUIT, aka IMAP_CLOSE.
Author: Angles, skeeterDiscussion: implements php function IMAP_MAILBOXMSGINFO
Author: Angles, skeeterDiscussion: needed
Author: Angles, skeeterDiscussion: actually usrs the function ->mailboxmsginfo to obtain the return data
Author: Angles, skeeterDiscussion: using SORTDATE can cause some messages to be displayed in the wrong cronologicall order, because the sender's MUA can be innaccurate in date stamping
Author: Angles, Skeeter, Itzchak Rehberg, Joseph Engoparam criteria is used like this SORTDATE 0 This is the Date that the senders email client stamps the message with SORTARRIVAL 1 This is the date the email arrives at your email server (MTA) SORTFROM 2 SORTSUBJECT 3 SORTSIZE 6
Discussion: basiclly a replacement for PHPs c-client logic which is missing if IMAP is not builtin
Author: Angles, calls functions with authors Skeeter, Itzchak Rehberg, Joseph EngoDiscussion: basiclly a replacement for PHP's c-client logic which is missing if IMAP is not builtin
Author: Angles, calls functions with authors Skeeter, Itzchak Rehberg, Joseph EngoDiscussion: as implemented, reference is to some part of class var $this->msg_structure
Author: AnglesDiscussion: as implemented, reference is to some part of class var $this->msg_structure
Author: Angles, Itzchak Rehberg, Joseph EngoDiscussion: as implemented, reference is to some part of class var $this->msg_structure unsets any unfilled elements of the referenced part in the fetchstructure object to mimic PHPs return structure
Author: AnglesDiscussion: as implemented, reference is to some part of class var $this->msg_structure parses "content-type:" header into fetchstructure data ->type and ->subtype
Author: Angles, Itzchak Rehberg, Joseph EngoDiscussion: as implemented, reference is to some part of class var $this->msg_structure parses "content-type:" header string into fetchstructure data info->parameters or "content-disposition:" header string into fetchstructure data info->dparameters
Author: Angles, Itzchak Rehberg, Joseph EngoDiscussion: none
Author: Angles, Skeeter, Itzchak Rehberg, Joseph EngoDiscussion: none
Author: Itzchak Rehberg, Joseph EngoDiscussion: Similar to an IMAP server, POP3 must be expunged to actually delete marked messages This is done (1) by immediately closing the connection after your done marking, this will cause POP3 to expunge or (2) by issuing PHPs buildin IMAP_EXPUNGE command which we DO NOT emulate here
Author: AnglesDiscussion: This function implements the FT_PREFETCHTEXT text option This function uses the helper function "get_header_raw"
Author: AnglesDiscussion: This function UN-FOLDS the headers as per RFC2822 "folding, so each element is in fact the intended complete header line, eliminates partial "folded" lines
Author: AnglesDiscussion: This function causes a fetch of the complete, unfiltered RFC2822 format header of the specified message as a text string and returns that text string (i.e. glob)
Author: AnglesDiscussion: NOTE: as of Oct 17, 2001, the $part_num used here is not always the same as the part number used for official imap servers. But because this same class produced the fetchstructure, and provided it to the client, and that client will again use this class to get that part, the part number is consistant internally and is MUCH easier to implement in the fetchbody code. However, in the future, the part numbering logic in fetchbody will be coded to exactly match what an official imap server would expect. In the mail_msg class I refer to this "inexact" part number as "mime number dumb" as it is based only on the part's position in the fetchstructure array, before the processing to convert to official imap part number, which mail_msg class refers to as "mime number smart", which is used to access mime parts when using PHP's builtin IMAP module.
Author: AnglesDiscussion: This function implements the IMAP_BODY and also includes a custom boolean param "phpgw_include_header" which also includes unfiltered headers in the return string NEEDED: code for flags: FT_UID; maybe FT_INTERNAL; FT_NOT; flag FT_PEEK has no effect on POP3
Author: Angles
Discussion: php3 limits POST arrays to one level of array key/value pairs thus complex filtering instructions are containded in special strings submitted as controls names action instructions willlook something like this: $filter_X ['action_1_judgement'] => 'fileinto' the "key" string "action_1_judgement" needs to be "decompressed" into an associative array the string means this: a: we are dealing with "action" instructions b: when this data is "decompressed" this would be action[1] data c: that this should be action[1] ["judgement"] where "judgement" is the key, and d: that value of this action[1] ["judgement"] = "fileinto"
Author: Angles
Discussion: In tests PHP3 could not handle having an object as a simple array item. Therefor we had to make this class to be the thing that holdes a class.dcom (DataCommunications) object. PHP4 had no problem with the previous code but it was changed to this for backwards compatibility with PHP3, otherwise the script exits with a parse error. Multiple account capability requires that any account can have a stream open to its server at any time, independant of any other DataCommunications object, simce one account may be IMAP while another account may be POP3. Using an array of these mail_dcom_holders, we can achieve this goal and still have PHP3 compatibility.
Example:$GLOBALS['phpgw_dcom_'.$acctnum] = new mail_dcom_holder; $GLOBALS['phpgw_dcom_'.$acctnum]->dcom = CreateObject("email.mail_dcom", $this_server_type); now we have an array based structure where each array key can have a DataCommunications object of its own, thereby allowing for multiple mail accounts of any type to be open simultaneously.
Discussion: The three files and classes inter relate in the following way to end up with the mail_msg object FIRST, include class mail_msg_base, then SECONDLY incluse mail_msg_wrappers extending mail_msg_base, then THIRDLY include mail_msg which extends mail_msg_wrappers and, by inheritance, mail_msg_base All functions that are at the heart of email functionality are in this class. This class is in the process of being further OOPd so programmers can more easily use it without having to know abou the internal details. When multiple accounts are in use, each active account can be accessed and controlled through this class. Each active account with a stream open to its maiul server has its own DataCommunications object which used to be a part of this class but had to be moved elsewhere for PHP3 compatibility, but still each DataCommunications object is in an array and is accessed via an account number which is comtrolled in this class. This class handles organizing the preferences for each of the multiple accounts. In general, a simple class var array keeps the multiple account information organized as a numbered array based on integer account number. There are already many OOP methods that hide complexities from the programmer, such as the preference and arg access functions. Many of those functions can optionally take an account number and foilder name, but if none is supplies the functions uses logic to obtain valid account number and folder name for whatever account you are dealing with. There is extensice debug output available by setting the various debug flags between 1 to 3, or to 0 if no debug is wanted. More documentation is provided for each function in this class.
Discussion: In a complex app such as email it becomes difficult to keep track of all the GET POST vars that the app is expected to know about. Therefor, all GPC vars this class is expected to be aware of are listed here with an explanation of what they do.
Param1: msgball (typed array) msgball "object" is a message-descriptive "object" or associative arrays that has all important message reference data as array data, passed via URI (real or embedded). With multiple accounts enabled most data such as a folder name or a message number, mean nothing by themselves because we do not know which account they are supposed to apply to. Msgball typed array combines all necessary data, the acctnum, folder, msgnum, and sometimes other data such as part_no, into one thing. Use msgball anytime you are dealing with messages, if you only you do not care about individual email messages, such as when switching from one folder to another, then you can use the fldball typed array, see below, which does not require such detailed information.Discussion: Simplified way to logout. Closes all open streams for all accounts. Usually closing selected streams only is an internal only thing used in special circumstances, so this function SHOULD BE CALLED AT THE END of your page view, for example, just before the last template "pfp" (or whatever output function you use). NOTE: IF THERE IS A WAY TO "HOOK" THIS so it happens AUTOMATICALLY after the last parse of the api template, that would be a "good thing"
Discussion: Streams are left open during any particular mail operation and are not closed until this function is called. If this function is not called then the stream becomes a zombie and the mail server will close it after a certain amount of time. Mail streams before PHP 4,2 are not persistent, they last only as long as the page view or mail operation. This function should be called so the streams are properly closed with the logout command to the mail server.
Discussion: Typically used for moving mail between seperate accounts, use this function to make sure the source or destination mail server stream is open and the required folder is selected. If not, this function will open the connection and select the desired folder.
Discussion: ?
Discussion: as of RedHat 7.3 there us a bug in php and UWash requiring unusual mailscr_callstr containing "novalidate-cert" even for NON-SSL connections. If possible, this function adjusts the mailsvr_callstr and continues execution of the script. As long as we "return" from this function, instead of exiting, we can continue the script from where the error occured, assuming we have fixed the error. This is a cool thing, the option to fix and continue just by using "return", or to exit with "phpgw_exit", which ends execution of the script.
Discussion: Mail servers ecpect the foldername to be in a particluar form. This function makes sure of this. If a foldername without a namespace is provided, this function will preform a lookup of all available folders for the given acount and get the closest match. The lookup may be nevessary because the namespace and delimiter can differ from server to server, although most typically the name space is "INBOX" and the delimiter is a period.
Discussion: Folder if not passed will be obtained from the class which keeps track od the folder currently selected, this allows us to call this with no args and the current folder is "prep-ed". Foldnames with spaces and other URL unfriendly chars are encoded here must be decoded on the next input (script session) to undo what we do here.
** note this has chars that will not show up in the inline doc parser ** ensure_no_brackets('INBOX') = 'INBOX'Example:
** same as syntax but can be viewed in the inline doc parser ** ensure_no_brackets('{mail.yourserver.com:143}INBOX') results in 'INBOX'
Discussion: After updating to RH73, a new bug popped up where PHP was checking the validity of the mail server certificate even for NON-SSL sessions, under certain circumstances. This has been handles in the login_error routine where this particular error is detected and fixes by adding "novalidate-cert" to the non-ssl imap or pop mailsvr_callstr, note this breaks good servers, so it's handled only after an error pops up and is determined to be a result of this bug. CACHE NOTE: this item is saved in the appsession cache, AND is bese64_encoded there, which encoding and decoding is handled in "save_session_cache_item" and "read_session_cache_item", respectively, where this dataname "mailsvr_namespace" has a special handler for this purpose. because this data has "database unfriendly" chars in it.
Syntax:Example:
{mail.yourserver.com:143}Access: PRIVATE - public access is object->get_arg_value("mailsvr_namespace")
Discussion: The preferences for email were designed to *someday* let the user specify a non standard port to use for the mail server. This preference never came to be. The user still can not actually set a port number to use for the mail server. However, in the preferences api there is still code initializing a preference item called "mail_port", with a note that some day it would be user settable, but since it is not currently, the api preferences class has a function to determine the port number based on what kind of server we are connecting to. THIS DOES NOT REALLY BELONG IN PREFS, it never because a user preference, so the api preferences should not be concerned with mail_port. THEREFOR we will SET IT HERE. For backwards compatibility we still set a pref value for mail_port after we are done here, until we replace any code that asks prefs for a port number. Then, port number should be exclusively treated as an "arg" accessable through the OOP style ->get_arg_value('mail_port') function. We do not have a seperate functin for this, we do it here, because the "mail_port" and the "mail_server_type" and the "mailsvr_callstr" are inextricibly linked, they exist only as a related group if data. CONCLUSION: we determine "mail_port" in this function "get_mailsvr_callstr" which is a private function anyway.
INBOX where INBOX is returned as the namespaceExample:
get_mailsvr_namespace({mail.servyou.com:143}INBOX) returns INBOX
Discussion: for more info see: see http://www.rfc-editor.org/rfc/rfc2342.txt CACHE NOTE: this item is saved in the appsession cache.
Access: PRIVATE - public access is object->get_arg_value("mailsvr_namespace")(a) typical imap "INBOX.Sent" returns the "." as the delimiter, (b) UWash imap (stock mbox) "email/Sent" returns the "/" as the delimiterAccess: PRIVATE - public access is object->get_arg_value("mailsvr_delimiter")
Discussion: Note that syntax "NAMESPACE_DELIMITER_FOLDER" is called a "fully qualified" folder name here. The param $feed_folder will be compared to the folder list supplied by the server to insure an accurate folder name is returned because a param $feed_folder LACKING a namespace or delimiter MUST have them added in order to become a "long" folder name, and just guessing is not good enough to ensure accuracy. Works with supported imap servers: UW-Maildir, Cyrus, Courier, UWash Example (Cyrus or Courier): INBOX.Templates Example (if subfolders a.k.a. "inferior folders" are enabled): INBOX.drafts.rfc ???? Example (UW-Maildir only): /home/James.Drafts ???? The above examle would suggext that UW-Maildir takes "~" as namespace and "/" as its pre-folder name delimiter, which as somewhat nonstandard because it appears the rest of the folder name uses "." as the delimiter.
Access: PublicDiscussion: Simply, this is the folder name without the nor the NAMESPACE nor the DELIMITER preceeding it. Inline docparser repeat: ... without the {serverName:port} nor the NAMESPACE nor the DELIMITER preceeding it. Works with supported imap servers UWash, UW-Maildir, Cyrus, Courier (old) Example (Cyrus or Courier): Templates (old) Example (Cyrus only): drafts.rfc
Discussion: returns a numbered array, each element has 2 properties, "folder_long" and "folder_short" so every available folder is in the structure in both long form [namespace][delimiter][foldername] and short form (does not have the [namespace][delimiter] prefix to the folder name) This function can cache data in 2 ways (1) caching as server data in the prefs DB cache department, and (2) in the class var $this->get_arg_value("folder_list") Data will be grabbed from cache when available and when allowed. CACHE NOTE: this item is saved in the appsession cache.
Access: private - public access is object->get_arg_value("folder_list") but may be called directly if you need to manually force_refresh any cached data, although this is still for private use as well.Discussion: uwash is file system based, so it requires a filesystem slash after the namespace.
Note that with uwash the delimiter is in fact the file system slash.
example: requesting list for "mail/*"
(NOTE this
Discussion: when handling handle non-UWash IMAP servers, i.e. typical IMAP servers that do not use a filesystem slash as the "delimiter", the last arg is typically "INBOX*" (no dot) which DOES include the inbox in the list of folders. Wheres adding the delimiter "INBOX.*" (has dot) will NOT include the INBOX in the list of folders. So - it's theoretically safe to include the delimiter here, but the INBOX will not be included in the list, this is typically the ONLY TIME you would ever *not* use the delimiter between the namespace and what comes after it. HOWEVER to get *shared* folders included in the return, better NOT include the "." delimiter. For example: Cyrus does not like anything but a "*" as the pattern IF you want shared folders returned. Return data is a list suck as this: INBOX INBOX.Trash (inline docparser repeat): {some.server.com:143}INBOX AND {some.server.com:143}INBOX.Trash
Discussion: uses "folder_list[folder_long]" as the "haystack" because it is the most unaltered folder information returned from the server that we have if TRUE, then the "official" folder_long name is returned - the one supplied by the server itself during the get_folder_list routine - "folder_list[folder_long]" if False, an empty string is returned.
Discussion: returns True if the given foldername is probable an IMAP folder. Uses some general criteria such as anything with a DOT_SLASH is probably not the name of an IMAP folder.
Discussion: DEPRECIATED function was used when the number of unseen messages in a folder was included in the dropdown folder list combobox HTML select widget.
Discussion: if mcrypt is not enabled, then the password data should be unmolested thru the crypto functions, i.e. do not alter the string if mcrypt will not be preformed on that string.
Discussion: if mcrypt is not enabled, then the password data should be unmolested thru the crypto functions, i.e. do not alter the string if mcrypt will not be preformed on that string.
Discussion: the phpgw versions prior to and including 0.9.12 *may* have double or even tripple serialized passwd strings stored in their preferences table. SO: (1) check for this (2) unserialize to the real string (3) feed the unserialized / fixed passwd in the prefs class and save the "upgraded" passwd
Discussion: will produce a string containing email addresses for (a) display a browser such as on the compose form, or (b) for use in an email mesage header, hence the standards compliance necessity, message headers must follow strict form.
Discussion: To adress(es) in a string as we would get from a submitted compose form hold alot of useful information that can be extracted by sperating out the individual elements of the email address and, if many addresses are present, making an array of this data. This is especially useful during the send procedure, when we feed each individual address to the MTA, because the MTA expects a SIMPLE email address in the RCPT TO: command arg, not an address that contains any of the other things that an email address can contain, such as a users name (personal part) which itself can contain chars outside of the ASCII range (whether ISO encoded or not) that the MTA does not need and does not want to see in the RCPT TO: commands.
Example:* * using html special chars so the inline doc parser will show the brackets and stuff * * ->make_rfc_addy_array('john@doe.com,"Php Group"<info@phpgroupware.org>,jerry@example.com,"joe john" <jj@example.com>') which will be decomposed into an array of individual email addresses where each numbered item will be like this this: array[x]['personal'] array[x]['plain'] the above example would return this structure: array[0]['personal'] = "" array[0]['plain'] = "john@doe.com" array[1]['personal'] = "Php Group" array[1]['plain'] = "info@phpgroupware.org" array[2]['personal'] = "" array[2]['plain'] = "jerry@example.com" array[3]['personal'] = "joe john" array[3]['plain'] = "jj@example.com"Syntax:
ASCII example, inline docs will not show correctly johnUnknown: #doe.com,"Php Group"
Discussion: this is the opposite of the function make_rfc_addy_array
Discussion: ?
Discussion: ?
Discussion: Users some randomization and RFC standards to make a MIME part seperator.
Discussion: Users some randomization and some datetime elements to produce an RFC compliant MessageID header string.
Discussion: for use in an IMAP_APPEND command, and anytime you need to give the IMAP server Flag information ina format that it understands, as opposed to the PHP object which is not understandable to an IMAP server. ALSO can be used in string matching functions to verify if a message has a certain flag.
Example:example of verifing a message has been replied to if (strisr('Answered'), $flags_str) then (show replied flag)
Discussion: ?
Access: privateDiscussion: ?
Access: privateDiscussion: alias function for backward compatibility only, useful only until the rest of the code calls the real function "fill_sort_order_start"
Discussion: if sort, order, and start are available in the GPC vars and are valid (values work, not out of range) then those GPC vars are used as source data. If not, then data is generated accourding to the users prefs for sort and order, abd start is assumed 0 if not otherwise provided in the GPC vars. NOTE: MSGNUM IS NO LONGER HANDLED IN THIS FUNCTION so it was renamed from "fill_sort_order_start_msgnum" to "fill_sort_order_start".
Syntax:These are the PHP Sorting definitions and what they do and what their int value is. SORTDATE: 0 //This is the Date that the senders email client stanp the message with SORTARRIVAL: 1 //This is the date your email server's MTA stamps the message with // using SORTDATE cause some messages to be displayed in the wrong cronologicall order SORTFROM: 2 SORTSUBJECT: 3 SORTTO: 4 // only used in the "Send" folder SORTSIZE: 6
Discussion: for use when displaying a list of messages, a quick way to determine if visual information (paperclip) is necessary
Discussion: NOTE: initially I wanted to treat base64 attachments with more "respect", but many other attachments are NOT base64 encoded and are still attachments. If param_value NAME has a value, pretend it's an attachment, however, a base64 part IS an attachment even if it has no name, just make one up. BEGIN UPDATE: an exception to this is that some insane MUAs base64 encode the BODY, meaning a one part email body can be base64 encoded, BUT this is mostly spammers or malicious mail TRYING TO HIDE SOMETHING, such as the old IFRAME trick, or perhaps a more complicated message wrapped as one part, which may contain BAD files ending in bat, exe, or inf. END UPDATE. Also, if "disposition" header = "attachment", same thing, it is an attachment, and if no name is in the params, make one up. NOTE: we do not use "elseif" in the following logic because an attachment may be detected in *any* of the following code blocks in no particular, nor predictable, order.
POSSIBLE VALUES FOR [ " m_description " ] ARE container packagelist presentable/image attachment presentableSyntax:
RULES for determining m_description are a) if no subpart(s) then we have either "presentable" or "attachment" b) if subpart(s) and a boundary param, then we have a "packagelist" (HeadersOnly) c) else we have a container
Discussion: This code inherited from previous maintainer, who said this - function make_clickable taken from text_to_links() in the SourceForge Snipplet Library http://sourceforge.net/snippet/detail.php?type=snippet&id=100004 modified to make mailto: addresses compose in phpGW (not by Angles)
Discussion: can take as input either a php structure or an anglemail flat part array. For example, an attribute could be "filename" and its value could be "image.png", this function looks for the attribute, if it exists or not. If it does exist, you may be interested in its associated value, but that another issue.
Discussion: uses the following class args ['args']['td'] "td" means "Total Deleted", if it's filled it contains the number of messages that were deleted ['args']['tm'] "tm" means "Total Moved", if it's filled it contains the number of messages that were moved ['args']['tf'] "tf" means "To Folder", if it's filled it contains the name of the folder that messages were moved to if the user requests a delete, then arg "td" SHOULD/MUST be filled with that information if the user requests a move, then BOTH args "tm" AND "tf" SHOULD/MUST be filled with that information "tm" is the number of messages moved, and it's most useful to know where they were moved to, hence "tf"
Discussion: total size of all emails in this folder added up, if its OK to get that data
Discussion: ?
Access: privateDiscussion: first some background on the terms used here * "plain address" means the "user
Unknown: #domain.com" part * "personal" means the name string that may be associated with that address in the headers that would look like this if present: "Joe Dough"Discussion: according to preferences, for the displayed "From" string the user wants to see the "personal" data AND the "plain address" data of the person who the message is from as the "From String" that is displated to the user. Additionally, we checked and made sure both those pieces of data are available.
Discussion: according to preferences, for the displayed "From" string the user wants to see the "personal" data AND the plain address of the "ReplyTo" header, if available. To visually indicate this is reply to address, we surround in in < > instead of ( ) which we use to surround the "from" plain address, as used above. Note: even though we use the "personal" name from the From header, we show with it the plain address from the ReplyTo header. This is how this preference works :) Of course, if no ReplyTo address is present, we can not fulfill this user perference
Discussion: The displayed "From String" the user will see is the "plain address" of the From person ONLY, no "personal" data is ahown. This happens as a fallback option when the user's assumed desire to see the "personal" data is unable to be fulfilled because that "personal" data for the From person was not available in the email headers.
Discussion: Hides the implementation details from the calling process Provides most args to the dcom class from variables which class msg processed and set Sometimes returns processed data ready to be used for display or information MORE DISCUSSION - Why Wrap Here? Answer: because once the msg class opens a mailsvr_stream, that will be the only stream that instance of the class will have, so WHY keep supplying it as an arg EVERY time? Also, same for the "msgnum", unless you are looping thru a message list, you are most likely concerned with only ONE message, and the variable would be the MIME part therein
Discussion: Wrapper supplies the needed mailsvr_stream arg to IMAP_FETSCSTRUCTURE The data communications object (class mail_dcom) is supplied by the class
Discussion: Wrapper supplies the needed mailsvr_stream arg to IMAP_HEADER The data communications object (class mail_dcom) is supplied by the class
Discussion: = = = = USELESS FUNCTION = = = = returns array of strings, each string is extremely truncated partial contents of date, from, and subject, also includes the msg size in chars
Discussion: Folder and Account Number SHOULD be obtained from the class vars which were set during begin_request(), where folder and acctnum were determined from GET POST data or data supplied to begin_request() in its arg array. This way the desired folder is known to be correctly named (it exists, not a bogus foldername) and associated with the correct acctnum. However, some of the filter functions do use these params, but using them is discouraged. The return is an array of "msgball" data, which contains acctnum, foldername, message UID, and some other info, such as a pre-prepared "fake URI" a.k.a. a GET URI string of type magball. Use this data and specifically these message numbers to request more detailed information about a message (headers, subject), or the request message itself from the server. Sort and Order is applied by the class, so the calling process does not need to specify sorting here The data communications object (class mail_dcom) is supplied by the class
Discussion: used only if the total size of a folder is desired, which takes time for the server to return The other data IMAP_MAILBOXMSGINFO returns (if size is NOT needed) is obtainable from "get_folder_status_info" more quickly and wth less load to the IMAP server The data communications object (class mail_dcom) and mailsvr_stream are supplied by the class
Author: Anglesthis is the return structure result['is_imap'] boolean - pop3 server do not know what is "new" or not, IMAP servers do result['folder_checked'] string - the folder checked, as processed by the msg class, which may have done a lookup on the folder name result['alert_string'] string - lang'd string to show the user about status of new messages in this folder result['number_new'] integer - for IMAP: the number "recent" and/or "unseen"messages; for POP3: the total number of messages result['number_all'] integer - for IMAP and POP3: the total number messages in the folder
Discussion: gives user friendly "alert_string" element to show the user, info is for what ever folder the msg class is currently logged into, you may want to apply PHP function "number_format()" to the integers after you have done any math code and befor eyou display them to the user, it adds the thousands comma
Author: AnglesDiscussion: HTML select "combobox"s can only return 1 "value" per item, to break that limitation you can use that 1 item like a "fake URI", meaning you make a single string store structured data by using the standard syntax of a HTTP GET URI, see the example
Example:HTTP GET URI, example < select name="fake_uri_data" > < option value="&item=phone&action=dial&touchtone=1" > ( ... etc ... ) In an HTTP POST event, this would appear as in the example $GLOBALS['HTTP_POST_VARS']['fake_uri_data'] => "&item=phone&action=dial&touchtone=1" Then you feed that string into this function and you get back an associave array like this return["item"] => "phone" return["action"] => "dial" return["touchtone"] => "1" NOTE: this differs from PHP's parse_str() because this function will NOT attempt to decode the urlencoded values. In this way you may store many data elements in a single HTML "option" value=" " tag.Author: Angles
Discussion: to further seperate the mail functionality from php itself, this function will perform the variable handling of the traditional php page view Get Post Cookie (no cookie data used here though) The same data could be grabbed from any source, XML-RPC for example, insttead of php's GPC vars, so this function could (should) have an equivalent XML-RPC "to handle filling these class variables from an alternative source.
Author: AnglesDiscussion: functional relative to function "grab_class_args_gpc()", except this function grabs the data from an alternative, non-php-GPC, source NOT YET IMPLEMENTED
Author: AnglesDiscussion: ?
Author: AnglesDiscussion: ?
Author: AnglesDiscussion: ?
Author: AnglesDiscussion: Data this class must generate includes preferences, mail server callstring, namespace, delimiter, (not a complete list). The first time a data element is generated, for example ->get_arg_value("mailsvr_namespace"), which is needed before we can login to the mailserver, the private function "get_mailsvr_namespace" determines this string, then places that value in what I refer to as the "Level1 cache" (L1 cache) which is simply a class variable that is filled with that value. Additionally, that data is saved in the appsession cache. The L1 cache only exists as long as the script is run, usually one pageview. The appsession cache exists as long as the user is logged in. When the user requests another page view, private function ""get_mailsvr_namespace" checks (always) the L1 cache for this value, if this is the first time this function has been called for this pageview, that L1 cache does not yet exist. Then the functions checks the appsession cache for this value. In this example, it will find it there, put that value in the L1 cache, then return the value and exit. For the rest of the pageview, any call to this function will return the L1 cache value, no logic in that function is actually encountered.
Discussion: CACHE FORM TWO is anything the mail server sends us that we want to cache. The IMAP rfc requires we cache as much as we can so we do not ask the server for the same information unnecessarily. Take function "get_msgball_list" as an example. This is a list of messages in a folder, the list we save is in the form of typed array "msgball" which means the list included message number, full folder name, and account number. BEGIN DIGRESSION Why is all this data cached? Traditionally, a mail message has a "ball and chain" association with a particular mail server, a particular account on that mail server, and a particular folder within that account. This is the traditional way to think of email. HOWEVER, this email app desires to completely seperate an individual mail message from any of those traditional associations. So what does a "msgball" list allow us to so? This way we can move messages between accounts without caring where that account is located, what type of server its on, or what folder its in. We can have exotic search results where the "msgball" list contains references to messages from different accounts on different servers of different types in different folders therein. Because every peice of data about the message we need is stored in the typed array "msgball", we have complete freedom of movement and manipulation of those messages. END DIGRESSION. So the function "get_msgball_list", the first time it is called for any particular folder, asks the mail server for a list of message UIDs (Unique Message ID good for as long as that message is in that folder), and assembles the "msgball" list by adding the associated account number and folder name to that message number. This list is then stored in the appsession cache. Being in the appsession cache means this data will persist for as long as the user is logged in. The data becomes STALE if 1. new mail arrives in the folder, or 2. messages are moved out of the folder. So the next pageview the user requests for that folder calls "get_msgball_list" which attempts to find the data stored in the appsession cache. If it is found cached there, the data is checked for VALIDITY during function "read_session_cache_item" which calls function "get_folder_status_info" and checks for 2 things, 1. that this "msgball" is in fact referring to the same server, account, and folder as the newly requested data, and (CRUCIAL ITEM) 2. checks for staleness using the data returned from "get_folder_status_info", especially "uidnext", "uidvalidity", and "number_all" to determine if the data is stale or not. MORE ON THIS LATER. If the data is not stale and correctly refers to the right account, the "msgball" list stored in the appsession cache is used as the return value of "get_msgball_list" and THE SERVER IS NOT ASKED FOR THE MESSAGE LIST UNNECESSARILY. This allows for folders with thousands of messages to reduce client - server xfers dramatically. HOWEVER - this is an area where additional speed could be achieved by NOT VALIDIATING EVERY TIME, meaning we could set X minutes where the "msgball" list is considered NOT STALE. This eliminates a server login just to get validity information via "get_folder_status_info". HOWEVER, even though we have the message list for that folder in cache, we still must request the envelope info (from, to, subject, date) in order to show the index page. THIS DATA COULD BE CACHED TOO. Conclusion - you have seen how a massage list is cached, validated, and reused. Additionally, we have discussed ways to gain further speed with X minutes of assumed "freshness" and by caching envelope data.
Discussion: used with appsession TEMPORARY DATA CACHING server-side caching of limited, ephermal data, such as a list of messages from an imap search, via appsession
Author: AnglesDiscussion: used with appsession TEMPORARY DATA CACHING server-side caching of limited, ephermal data, such as a list of messages from an imap search, via appsession. NOTE: to cache an item you must add it to list of data items that has a handler here, otherwise we skip it.
Author: AnglesDiscussion: used with appsession TEMPORARY DATA CACHING server-side caching of limited, ephermal data, such as a list of messages from an imap search, via appsession
Author: AnglesDiscussion: Folder List data does not change that often, as opposed to the data cached in appsession, which often changes with each page view. Refer to class var array $this->cachable_server_items[] to see supported cachable items. Currently the longer-term data we cache with this Perf-Based methodology are: (1) 'get_mailsvr_namespace', and (2) 'get_folder_list' Those items go hand-in-hand. The data cached is that data which is produced (returned) by the function of the same name (easier to remember this way :), i.e. function "get_mailsvr_namespace()" data is saved to an array item with base element called "get_mailsvr_namespace". Ditto for function "get_folder_list()". Both cached items are necessary to achieve a longer-lived caching of a list of folders available to the user for a particular emil account. This folder list does not change often, thus deserving of a longer-lived caching than the appsession caching methodology. Namespace is also cached because it is used to analyse the folder_list data (generating "folder_short" from cached "folder_long" names, so those data items need each other. SO: The Storage Object for this data is currently (Dec 26, 2001) the Email Preferences database, for this reason: it's the only data store available to the email class for which the data survives and spans sessions. Perhaps a dedicated table in the DB may be used in the future,
Discussion: DORMANT CODE, used with server-side session-spanning caching. currently not used but may be implemented again.
Author: AnglesDiscussion: DORMANT CODE, used with server-side session-spanning caching. currently not used but may be implemented again.
Author: AnglesDiscussion: DORMANT CODE, used with server-side session-spanning caching. currently not used but may be implemented again.
Author: AnglesDiscussion: When multiple email accounts are enables, they may even be active at the same time, thus the properties and preferences for any individual email account must be distinctly accessable for each email account with as little brain damage to the developer as possible. These access methods server two purposes: (1) centralize access to all params and oprefs into a common, standardized methodology, and (2) these access functions also transparently handly the dirty work of tracking which email account the data applies to, takes care of any special handling a param may require, and it's classic OOP style. With the exception of a few paramaters/arguments that are not specific to any individual email acount, such as for private, internal object core properties, the developer need only use these functions to access object params, arguments, and preferences.
Author: AnglesDiscussion: When multiple email accounts are enabled, all arg/param and preference access functions "pivot" off of this "object->acctnum" property, it serves essentially as the array key which maps the various access functions to the data of the intended account number. DEVELOPERS NOTE: The integer zero returned by this function can sometimes be mistaken as "empty" of "false", when using conditionals such as if ($my_acctnum) { then do this }; may incorrectly interper integer 0 as a "false" and this example conditional would not behave as expected, since there is infact a valid acount number of 0 in the variable. The preferred test for that type of condition is: if ((string)$my_acctnum != '') { then do this }; which produces a more desirable result.
Author: AnglesDiscussion: ?
Access: publicDiscussion: ?
Access: publicDiscussion: ?
Access: publicDiscussion: It is common the boolean preference items are simply not set if their value is supposed to be false. This function can be used for this discovery. Note that some string preferences items, such as the email sig, can be set yet have a value of an empty string, in this case this function follows strict logic and returns True because the preference exists. Similarly, uwash mail location is another example of a preference item where an empty string is a valid value.
Access: publicDiscussion: ?
Access: publicDiscussion: The result are not the raw preferences directly from the database, this function returns the preference array for an email account as explosed to the email app, that is these are preferences that have passed through some logic to process and normalize them,
Access: publicDiscussion: NOTE the first thing this function does is clear the existing preference array for the emal account. This happens no matter what. This effectively is a way to clear an accounts email preference array by passing an empty array, which can be useful in certain situations. More commonly this function is used to set the entire preference array for an account in one operation. In that case you better know what youre doing, $pref_array_data must be correctly formed emai pref array data. By clearing the existing preference array no matter what, this is why a return value of False indicates that, while no new preference data was set, still something did occur and that was the clearing of any pre-existing preference array.
Access: privateDiscussion: ?
Access: privateDiscussion: ?
Access: publicDiscussion: ?
Access: publicDiscussion: Some class variables, such as "mailsvr_namespace", have functions dedicated only to determining their value. In these cases this function will hand off the request directly to that specialized function. In other cases the class variable desired is a simple variable and its value is returned.
Access: publicDiscussion: Esoteric utility function for specialized private use.
Access: privateDiscussion: ?
Access: publicDiscussion: ?
Access: privateDiscussion: ?
Access: privateDiscussion: ?
Access: private
Discussion: class provides for complex SMTP transactions, bypassing need for php's builtin mail sending functions. Currently part of the email class group, when mature will be moved to standard phpgroupware api.
Author: (a) Itzchak Rehberg - initial implementation, SMTP communication and control flow, excellent work! and (b) Angelo Puglisi (Angles) - convert to multi-dimentional array driven architecture, expanded debugging, RFC2822 and 2821 compliance, retain a copy for archiving option, fake send debug, handshake retention, other stuff...
Discussion: only has one function which bootstraps the GLOBALS->msg (if necessary). It should be safe to call CreateObject on this class at any time for object $GLOBALS[phpgw]->msg_bootstrap because api is smart enough to not re-create it and theres nothing in the constructor, so this bootstrap capability should be available at any time to any code file. If there is a problem logging in, function GLOBALS["phpgw"]->msg->login_error() is called, giving an error message, and the script exits.
Example:$GLOBALS["phpgw"]->msg_bootstrap = CreateObject("email.msg_bootstrap"); $GLOBALS['phpgw']->msg_bootstrap->login(); ## OR, if you care about debug info, an alternative is to use this, does the same thing but gives debug info. $GLOBALS['phpgw']->msg_bootstrap->ensure_mail_msg_exists('name of my function');Access: public
Discussion: OPTONAL, most often it is desirable to establish a mail server stream, so the default assumed value for "do_login" is True for any call to "ensure_mail_msg_exists". However, set to False for situations where you want to set or get email preference data when a login is not required or when there may be no preference data set yet, such as the first time a user sets the preferences.
Access: publicDiscussion: ?
Access: publicDiscussion: Alias to "ensure_mail_msg_exists", if you want debugging output capability then use that function. If you just want to get email working quickly, use this function.
Example:## email quickstart: $GLOBALS["phpgw"]->msg_bootstrap = CreateObject("email.msg_bootstrap"); $GLOBALS['phpgw']->msg_bootstrap->login();
Discussion: This process os the same for any email related code that needs the mail_msg object and an open stream. This function calls msg->begin_request and thus all the complicated logic associated with multiple accounts is handled there.
Discussion: This is a utility function called by this-> ensure_mail_msg_exists. Email uses utility c lasses from both email and api utility objects, such as html_widgets, this function makes sure the most commonly used of these are available for global access throughout the email code. Right now this is private, used only by this class itself.
Access: private
Discussion: Provide this class with any of the above vars that you have. Subject and Body will be spellchecked, but the other data is needed because this class handles the rest of the logic from spell checking, to user review of spellcheck, to applying the users choices to the body, only then is the message handed off to another object, either class send for sending, or class compose if the user wants to edit the text some more. Calling process MUST set any vars it wants preserved through the spellcheck process, they will be put in the spellcheck page form.
Discussion: class spell needs the public shared C-Style Include .h file, which holds public data structure classes for class email spell
Discussion: This class must discover if its spell service module is real or dummy, and use this function to set that information and make it available publicly via "get_can_spell". Should be discovered and set in the constructor.
Access: privateDiscussion: If a real, working spell service is abailable, such as pspell support compiled into php, this will return True, if a dummy placeholder service is loaded, such as when the pspell extension is NOT compiled into php, this returns False. This class picks up this value in its constructor, when it loads a spell service backend, that the service object will report if it can do anything or not. Dummy placeholder class is loaded only so certain function names exists, so php will not complain anout undefined functions.
Access: publicDiscussion: This class must discover if its spell service module takes single words or lines (strings) of text, and use this function to set that information and make it available publicly via "get_sp_feed_type". Should be discovered and set in the constructor. Can be one of SP_FEED_UNKNOWN, SP_FEED_WORDS, or SP_FEED_LINES, as defined in file class.spell_struct
Access: privateDiscussion: Supporting more than one backend service means this class must report how the backend wants the input, single words or lines of text. Can be one of SP_FEED_UNKNOWN, SP_FEED_WORDS, or SP_FEED_LINES, as defined in file class.spell_struct.
Access: publicDiscussion: Spell check is called from class.bosend, where the compose form gets submitted. If the spellcheck button was pressed, then class.bosend creates an object of this class to handle the spell checking. When the user submits the spellcheck form, the desired misspelled words will be replaced and then this class invokes class.bocompose to take the user back to the compose form with the corrected body text. From there the user may click send which submits the form to class.bosend. Therefor any send related GPC vars that the compose form had when it was submitted for spellchecking must be put back in the compose form after spellchecking so that class.bosend gets the information it needs, the same information it would have gotten had a spell check not occurred. Certain vars will be passed in the URL, these are sort, order, start, the msgball or fldball, and fwd_proc are all passed in the URL that is the form "action". Other vars have their own special requirements, these are body and subject vars, because they will be spellchecked. All other vars that need to be preserved use this function to set their data. These var names are enumerated in $this->preserve_tokens[] array, so that one code loop thru these tokens can handle all the necessary vars to be preserved, such as in function "commit_preserve_vars_to_form". Note that when class.bosend gets the submitted compose form and determines it needs to be directed to this class for spellchecking, class.bosend MUST USE THE SET_* CODE in this class to set any vars that class.bosend thinks should be saved. Class spell does not grab these vars, the calling process must use the OOP style access methods to set them. Only then will this class be able to preserve them, this class can only preserve what it is told to preserve.
Discussion: Uses a loop of vars we need to preserve (that are not preserved elsewhere) that tells the widget class to make them hiddenvars in the form we will use in the spell check page.
Discussion: This class needs all the information that is available about a message, which it will preserve and pass back to the compose (or send) code when the spell check is done. This is for the subject of the message to be spell checked. NOTE: in the future the subject *should* be spell checked too, currently the subject is *NOT* spellchecked,
Access: PublicDiscussion: ?
Access: PublicDiscussion: An this original, unmodified copy of the body is stored and available after the spell check if you wish to compare to the spell fixed text. This explains why this is "body_orig" instead of just "body". NOTE this is the text that gets spell checked, so it is REQUIRED to set this or else there is nothing to spellcheck. NOTE: if it is necessary, STRIP SLASHES BEFORE SETTING THIS. This class has no way of knowing if the body has the "magic" GPC slashes or not. It is recommended to pass the text thru function "stripslashes_gpc" (in the mail_msg class) before setting this value.
Access: PublicDiscussion: An this original, unmodified copy of the body is stored and available after the spell check if you wish to compare to the spell fixed text, or for any reason, if you want it use this function.
Access: PublicDiscussion: YOU MUST STRIPSLASHES BEFORE calling ->set_body_orig(), which in turn calls this function, because this function has no way of knowing if it should stripslashes on submitted data or not, but YOU do because you are writting the code that uses this object, so YOU must strip slashes (if necessary) before calling ->set_body_orig(), which in turn calls this function.
Access: PrivateDiscussion: In order to show text in an html browser this functions does a few things to it, such as convery CRLF chars into BR tags, and to encode HTML offensive chars into their htlp specialchar equivalents. Returns the prepared string and also directly fills class var $this->body_display with this prepared text, but that is a private class param.
Access: PrivateDiscussion: returns True if we should spell check the text, False if we should ignore this text. Uses a variety of tests to determine what is probably not a "real word" so these words can be skipped during the spell checking. This is because the spell checker will often report these type of words to be misspelled, mostly because of strange punctuation of ASCII "art". Here is a list of the kind of strings what will cause a return of False : empty strings, CR or LF chars, single letter words, numbers, email addresses, URLs, internet host names, anything surrounded by typical markup brackets < >, words with a dot in the middle of it. Not every check is perfect, but this function will return it best assumption about the given string, whether it should be considered a "real word" or not.
Access: PrivateDiscussion: spell checker is stupid, this utility function will strip punctuation from text so that the spell checker can look at the word itself, and not be confused by any punctuation.
Access: PrivateDiscussion: This Depreciated function was used during developement of this class, before comboboxes were used, it uses HTML tags to make the misspelled word bold and red, then puts up to $this->max_suggest suggestions after the word in brackets, with each suggestion seperated by the pipe character. Although this is no loner used at this moment, it may be of some use in the future. In theory, the user would get back the text as described, then have to hand edit the corrections. Not very user friendly so it is DEPRECIATED.
Unknown: #example ## User gets spell corrections like this: Could you pleeze [ please | sneeze | freeze ] send it to me. ## note: this example is fictional, not actual spell suggestions.Discussion: Uses class.html_widgets to simplify the HTML of the select boxes. Must operate on an entire line of text because the suggesion data targets the mispelled word by storing its line number and word number within that line, where the line is exploded by space. Thus, in adding the comboboxes there will be additional spaces and words added to the line, but this is not a problem is an entire line of text is processed in one pass. The function simply stores an unmodified version of the line and uses that to target words in any location in the line of text. Additonally, this function directly access the class var $this->bad_words which contains an object of type "correction_info" (as defined in file class.spell_struct) to obtain the suggestion data.
Access: PrivateDiscussion: This function uses the code in class.bocompose to generate the return value. It does this by creating a class.bocompose object and calling its function get_compose_form_action_url(). The only difference is we pass a $menuaction_target var unique to this forms needs, whereas the compose form uses a different $menuaction_target specific to the compose form.
Discussion: the spell review form submits correction data in the form of URI string which is made into an array with parse_str. This data originated as "correction_info" structure data generated during spell_review, designed to be very similar to the "correction_info" structure, so it is possible to match the submitted badword data array to the "correction_info" structure it was modeled after.
Discussion: Must operate on an entire line of text because the suggesion data targets the mispelled word by line number and word number within that line, where the line is exploded by space. Thus, if a corrected word has a space there will be additional spaces and words added to the line, but this is not a problem is an entire line of text is processed in one pass. The function simply stores an unmodified version of the line and uses that to target words in any location in the line of text. Additonally, this function directly access the class var $this->bad_words which contains an object of type "correction_info" (as defined in file class.spell_struct) to obtain the suggestion data. That data was recovered from the user submitted form, made into an array, then made into the "correction_info" data. IMPORTANT: $this->bad_words->suggestions[0] IS THE USERS CHOICE of replacement word. During the initial spell checking it holds the suggestions from the spell checker backend, BUT after user submits the form with corrections, ->suggestions[0] is the bombobox value which was the users choice of a replacement word for that particular misspelled word, unless ->suggestions[0] is the special token "K_E_E_P" in which case the user desires no change for this word.
Access: PrivateDiscussion: ?
Discussion: Spell check form is submitted to this funcion, which replaces any misspelled words the user wants replaced, then invokes class.bocompose and takes the user back to the compose page with the corrected message text. Note this function must pass any GPC vars preserved when the compose form eas submitted for spellcheck, and put those bars back in the compose form where they are needed for when the compose form is submitted to class.bosend.
Discussion: Class Email Spell can be used with other classess such as the html widget class, however the html widget class, in this example, must be made aware of any data structures that the spell class may pass to it. Use this file like an include file for such purposes. I suggest require_once.
Discussion: there should be different ways to spell check depending on what your system has installed. The php builtin pspell extension appears to take one word at a time, the command line version of aspell takes a string, a line of text, at one time. class.spell constructor should determine this and fill $this->sp_feed_type.
Discussion: holds information about a misspelled word including where it appears in the original text and up to MAX_SUGGEST suggestions
Discussion: If PHP psspell support is not compiled in, this dummy module spell_ svc_none is loaded so there are no errors related to undefined pspell functions.
Access: publicDiscussion: The calling spell class will ask if this spell service is capable of spell check or not. This function is exposed to the calling spell class for this purpose. The calling spell class then maked that information public. This is a dummy placeholder module so it returns False.
Access: privateDiscussion: The calling spell class will ask if this spell service takes single words or strings. This function is exposed to the calling spell class for this purpose. The calling spell class then maked that information public.
Access: privateDiscussion: returns False so ignorant calling code will sense something is wrong with spelling code.
Access: publicDiscussion: Returns True to imitate a word is spelled correctly, then ignorant calling code will not ask for suggestions, hopefully.
Access: publicDiscussion: Returns empty array to imitate pspell hafving no suggestions, since this is a dummy module there are indeed no suggestions, and ignorant calling code will not act on any suggestions if it gets an empty array back.
Access: public
Discussion: This is loaded if PHP has psspell support compiled in. If it is not compiled in, a dummy module spell_ svc_none is loaded so there are no errors related to undefined pspell functions.
Discussion: The calling spell class will ask if this spell service is capable of spell check or not. This function is exposed to the calling spell class for this purpose. The calling spell class then maked that information public.
Access: privateDiscussion: The calling spell class will ask if this spell service takes single words or strings. This function is exposed to the calling spell class for this purpose. The calling spell class then maked that information public.
Access: privateDiscussion: Php manual shows params to be: pspell_new (string language, string [spelling], string [jargon], string [encoding], int [mode])
Access: publicDiscussion: Php manual shows params to be: pspell_check (int dictionary_link, string word)
Access: publicDiscussion: Php manual shows params to be: pspell_suggest (int dictionary_link, string word)
Access: public
Discussion: Uncomment the "public_functions" line to enable the Email Debug Page. Should be disabled by default, this is a developers tool.
Author: AnglesDiscussion: Uncomment the next line of code to enable the Email Debug Page. This is file email / class.ui_mail_debug.inc.php
Discussion: Uncomment the "public_functions" line to enable the Email Debug Page. Should be disabled by default, this is a developers tool. If enabled, call this function to display the page.
Example:/index.php?menuaction=email.ui_mail_debug.indexAuthor: Angles
Discussion: email bopreferences class vars ->std_prefs[] and ->cust_prefs[], as filled by email bopreferences->init_available_prefs(), represent a standardized preferences schema, this function generates TR's from that data, using elements "id", "widget", "other_props", "lang_blurb", and "values" from that array structure. This function uses that data to fill a template block that contatains the requested widget and the appropriate data. Available HTML widgets are: * textarea * textbox * passwordbox * combobox * checkbox If prefs data "other_props" contains "hidden", as with password data, then the actual preference value is not shown and the "text blurb" is appended with "(hidden)". Array can contain any number of preference "records", all generated TR's are cumulative.
Unknown: #author AnglesDiscussion: should obtain the desired account number the user wants to see prefs for, if possible
Unknown: #author AnglesDiscussion: This is ONLY FOR THE DEFAULT ACCOUNT for 2 reasons 1) the defaut account has slightly different prefs then the extra account, and 2) author too lazy to combine this function with ex_accounts_edit() like it should be
Unknown: #author Angles, skeeter
Discussion: magic_quotes_runtime essentially handles slashes when communicating with databases. PHP MANUAL says: If magic_quotes_runtime is enabled, most functions that return data from any sort of external source including databases and text files will have quotes escaped with a backslash. this is undesirable - turn it off.