I am sure you guys are really busy, but some reviews, ideas, comments, critics etc would be really helpful. <b>Eagerly</b> waiting for your replies.<br><br>:)<br><br>Thanking you,<br>Sorry to make you guys read long boring emails :P<br>
<br><div class="gmail_quote">On Tue, Jun 16, 2009 at 11:31 PM, Sulabh Mahajan <span dir="ltr"><<a href="mailto:sulabh.dev@gmail.com">sulabh.dev@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<span lang="">
<div>Here are some details of the plan to implement the privacy rewrite in view of the discussions that have happened on the devel list:</div>
<div> </div>
<div>1. We use the following structures to define the privacy states and types:</div>
<blockquote dir="ltr" style="margin-right: 0px;">
<p>PurplePrivacyListType defines the types of possible privacy lists supported by a protocol</p><span lang="">
<div>typedef enum _PurplePrivacyListType</div>
<div>{</div>
<div>        PURPLE_PRIVACY_ALLOW_LIST = 1,</div>
<div>        PURPLE_PRIVACY_BLOCK_LIST,</div>
<div>        PURPLE_PRIVACY_VISIBLE_LIST,</div>
<div>        PURPLE_PRIVACY_INVISIBLE_LIST</div>
<div>} PurplePrivacyListType;</div>
<div> </div>
<div>Following structures are used to define the privacy states for an account, or a list of these are used by a protocol to specify the supported privacy types:</div>
<div> </div>
<div>typedef enum _PrivacyStateType</div>
<div>{</div>
<div>        ALLOW_ALL = 1,</div>
<div>        ALLOW_BUDDY_LIST,</div>
<div>        ALLOW_ALLOW_LIST,</div>
<div>        BLOCK_ALL,</div>
<div>        BLOCK_BLOCK_LIST</div>
<div>} PrivacyStateType;</div>
<div> </div>
<div><span lang="">/* The following structure defines what we are allowing or blocking, messages or presence or both */</span></div>
<div><span lang=""></span> </div>
<div><span lang="">typedef enum _PrivacyStateOf</span></div>
<div><span lang="">{</span></div>
<div><span lang="">        </span><span lang="">PRIVACY_STATE_MESSAGE = 1,</span></div>
<div><span lang="">        PRIVACY_STATE_PRESENCE,</span></div>
<div><span lang="">        PRIVACY_STATE_BOTH, /* when msg, presence both tied together, blocking blocks both */</span></div>
<div><span lang="">        PRIVACY_STATE_EITHER /* when msg, presence can be blocked separately for a contact */</span></div>
<div><span lang="">} PrivacyStateOf;</span></div>
<div><span lang=""></span> </div>
<div><span lang="">The following structure combines the above two along with some flags to define the scope of the features: local only or supported by the server; Need a local list or not.</span></div>
<div><span lang=""></span> </div>
<div><span lang="">typedef struct _PurplePrivacyState</span></div>
<div><span lang="">{</span></div>
<div><span lang="">        PrivacyStateType privacytype;</span></div>
<div><span lang="">        PrivacyStateOf privacyof;</span></div>
<div><span lang="">        gboolean privacy_state_local; /* defines whether this features is local only/faked or implemented on server */</span></div>
<div><span lang="">        gboolean privacy_state_needs_local_storage; /* to keep track of which states require storage of list locally */</span></div>
<div><span lang="">} PurplePrivacyState;</span></div><span lang=""><span lang="">
<p>privacy_state_needs_local_storage is required so as to NOT implement those states which require locally storing a privacy list. As stated by Will such states wont be of any use for Telepathy.</p></span></span></span></blockquote>


<div><span lang=""></span> 2. Each <span lang="">protocol/prpl implements privacy features using the function specified through PurplePluginProtocolInfo prpl_info:</span></div>
<ul>
<li><span lang="">void (*privacy_list_add)(PurpleConnection *, PurplePrivacyListType list_type, const char *name);</span></li>
<li><span lang="">void (*privacy_list_rem)(PurpleConnection *, PurplePrivacyListType list_type, const char *name);</span></li>
<li><span lang="">void (*set_privacy_state)(PurpleConnection *);</span></li>
<li><span lang="">void (*define_supported_privacy_states)(PurpleConnection *);</span></li></ul>
<blockquote dir="ltr" style="margin-right: 0px;">
<p><b>privacy_list_add(), privacy_list_rem()</b> as the name suggest adds and removes the given contact's id in the privacy lists of the server. The type of list is given by the struct PurplePrivacyListType.</p>

<p><span lang=""><b>set_privacy_state()</b> sets the privacy state for the particular account. </span><span lang="">account->account_privacy_type stores the state to be set for a particular account.</span></p>
<span lang=""><span lang="">
<p><b>define_supported_privacy_states()</b> is a function that necessarily be implemented by each protocol. It registers a list of states of type PurplePrivacyState that a protocol supports. It can also be replaced by a linked list of elements of type PurplePrivacyState.</p>

</span></span></blockquote>
<p dir="ltr">3. The idea is to define the complete list of supported states using these structures.</p>
<p dir="ltr">For example,</p><span lang="">
<p>For AIM:</p>
<p>PrivacyStateType                        PrivacyStateOf                privacy_state_local                privacy_state_needs_local_storage</p>
<p>ALLOW_ALL                         PRIVACY_STATE_BOTH              FALSE                                            FALSE</p>
<p>ALLOW_BUDDY_LIST           PRIVACY_STATE_BOTH              FALSE                                            FALSE</p>
<p>ALLOW_ALLOW_LIST           PRIVACY_STATE_BOTH              FALSE                                            FALSE</p>
<p>BLOCK_ALL                          PRIVACY_STATE_BOTH              FALSE                                            FALSE</p>
<p>BLOCK_BLOCK_LIST             PRIVACY_STATE_BOTH              FALSE                                            FALSE</p>
<p>BLOCK_ALL                           PRIVACY_STATE_EITHER           TRUE                                              FALSE</p>
<p>The last entry corresponds to the fact that we can "separately" block messages from everyone and presence to everyone. This is a faked option, where being invisible to everyone (blocking presence to everyone) is supported on server, but, blocking messages from everyone while being visible to everyone is faked by dropping messages locally (under ALLOW_ALL state). The entry "BLOCK_ALL, PRIVACY_STATE_BOTH, FALSE" corresponds to blocking both message and presence to everyone, which is different from blocking either of message or presence at a time.</p>


<p><span lang="">For IRC:</span></p>
<p>PrivacyStateType                         PrivacyStateOf                         privacy_state_local         privacy_state_needs_local_storage</p>
<p>ALLOW_ALL                          PRIVACY_STATE_BOTH                     FALSE                                    FALSE</p>
<p>ALLOW_BUDDY_LIST            PRIVACY_STATE_MESSAGE             TRUE                                       FALSE</p>
<p>ALLOW_ALLOW_LIST            PRIVACY_STATE_MESSAGE             TRUE                                       TRUE</p>
<p>BLOCK_ALL                           PRIVACY_STATE_MESSAGE             TRUE                                       FALSE</p>
<p>BLOCK_BLOCK_LIST             PRIVACY_STATE_MESSAGE              TRUE                                      TRUE</p><span lang="">
<p>As you can see "completely" specifying supported privacy states for every protocol can be a challenging task, especially since we can fake several of the features the protocol doesn't provide. This is by far the best way I have figured to solve this issue.</p>


<p>4. <span lang="">Privacy Public API:</span></p>
<p><span lang=""></span><span lang=""><span lang="">(We will have a global PurplePrivacyState, or states can be set separately for each account (account->account_privacy_type))</span></span></p>
<ul>
<li><span lang=""><span lang=""><span lang="">purple_privacy_state_set_global(...,PurplePrivacyState global_state,...)</span></span></span></li>
<li><span lang=""><span lang=""><span lang="">purple_privacy_state_set_account(...,PurpleConnection *, PurplePrivacyState state,...)</span></span></span></li>
<li><span lang=""><span lang=""><span lang="">purple_privacy_list_add(...,PurplePrivacyListType tp, PurplePrivacyListAddedCb cb,...)</span></span></span></li>
<li><span lang=""><span lang=""><span lang="">purple_privacy_list_remove(...,PurplePrivacyListType tp, PurplePrivacyListRemovedCb cb,...)</span></span></span></li></ul>
<blockquote dir="ltr" style="margin-right: 0px;">
<p>UI can register Cb that would be called on removing/adding a contact to a list, specifying error with error type if any ( if list modification fails asynchronously with the server, as stated by Will). Similarly callback will be implemented for every function that interacts with the server and might result in an error. </p>

</blockquote>
<ul dir="ltr">
<li>
<div>purple_privacy_allow_message(...,PurpleConnection *, const char *,...)</div></li>
<li>
<div>purple_privacy_allow_presence(...,PurpleConnection *, const char *,...)</div></li>
<li>
<div>purple_privacy_allow_both(...,PurpleConnection *, const char *,...)</div></li>
<li>
<div>purple_privacy_deny_message(...,PurpleConnection *, const char *,...)</div></li>
<li>
<div>purple_privacy_deny_presence(...,PurpleConnection *, const char *,...)</div></li>
<li>
<div>purple_privacy_deny_both(...,PurpleConnection *, const char *,...)</div></li>
<li>
<div>purple_privacy_check(...,PurpleConnection *, const char *,...)</div></li></ul>
<blockquote dir="ltr" style="margin-right: 0px;">
<p>returns whether message/presence/both allowed?</p></blockquote>
<ul>
<li dir="ltr">purple_privacy_init(...,gboolean disable_local_features,...)</li></ul>
<blockquote dir="ltr" style="margin-right: 0px;">
<p>UI can call privacy subsystem to disable the local/faked features, as stated by Will needed by Telepathy</p></blockquote>
<ul dir="ltr">
<li>
<div>purple_privacy_set_ui_ops(..)</div></li>
<li>
<div>purple_privacy_get_ui_ops(..)</div></li>
<li>
<div>purple_privacy_item_blocked(...,PurplePrivacyItemType,...)</div></li></ul>
<blockquote dir="ltr" style="margin-right: 0px;">
<p>libpurple on receiving an item (chat, notification, file transfer, anything) calls this function, which in turns callbacks a function registered by the UI/plugin. PurplePrivacyItemType is defined as the various types of items we block from a contact:</p>


<div>typedef enum _PurplePrivacyItemType</div>
<div>{</div>
<div>        PRIVACY_ITEM_TYPE_MESSAGE =1,</div>
<div>        PRIVACY_ITEM_TYPE_CHAT,</div>
<div>        PRIVACY_ITEM_TYPE_NOTIFICATION,</div>
<div>        PRIVACY_ITEM_TYPE_FT,</div>
<div>        ...,</div>
<div>        ...</div>
<div>} PurplePrivacyItemType;</div>
<div> </div></blockquote>
<div dir="ltr">5.  </div></span></span></span>As discussed on the devel list, it is preferred to store the privacy information about contacts in the blist itself. This is a great idea, but another approach that we can follow is to construct a separate list for privacy, "plist" stored in a file, "plist.xml". This list would contain an entry to each and every contact that we ever encounter, including the buddies as well. This follows the idea of having a super list which is the union of buddy list, and all the various privacy lists.<br>

<br>Following an approach similar to blist, our plist structures will look somewhat like: 
<blockquote dir="ltr" style="margin-right: 0px;">
<div dir="ltr">struct _PurplePList</div>
<div dir="ltr">{</div>
<div dir="ltr">        PurplePlistNode *root;<br>        GHashTable *contacts;</div>
<div dir="ltr">        void *ui_data;</div>
<div dir="ltr">};<br><br>struct _PurplePlistNode</div>
<div dir="ltr">{</div>
<div dir="ltr">        PurplePlistNode *prev;</div>
<div dir="ltr">        PurplePlistNode *next;</div>
<div dir="ltr">        void *ui_data;</div>
<div dir="ltr">        void *proto_data;</div>
<div dir="ltr">        char *name;<br>        char *alias;</div>
<div dir="ltr">        PurpleAccount *account;</div>
<div dir="ltr">        PurplePrivacyContactType privacy;</div>
<div dir="ltr">};<br><br>PurplePrivacyContactType defines the privacy information associated with the buddy:</div>
<div dir="ltr"><br>typedef struct _PurplePrivacyContactType</div>
<div dir="ltr">{</div>
<div dir="ltr">       gboolean purple_privacy_receive_message;</div>
<div dir="ltr">       gboolean purple_privacy_send_presence;</div>
<div dir="ltr">       gboolean contact_on_server_list;             /* whether this contact is in some list on server or not */<br>} PurplePrivacyContactType;<br></div>
<div dir="ltr"><br>plist xml tree would look like:</div>
<div dir="ltr"> </div>
<div dir="ltr">--<purple ver></div>
<div dir="ltr">        --<plist></div>
<div dir="ltr">               --<account></div>
<div dir="ltr">                       --<contacts></div>
<div dir="ltr">                       --<contacts></div>
<div dir="ltr">                       ....<br>                       --<contacts></div>
<div dir="ltr">               --<account></div>
<div dir="ltr">                       --<contacts></div>
<div dir="ltr">                       --<contacts></div>
<div dir="ltr">                       ....</div>
<div dir="ltr">                       --<contacts></div>
<div dir="ltr">               .....</div>
<div dir="ltr">               .....</div>
<div dir="ltr"> </div></blockquote>
<div dir="ltr">6. plist API: similar to blist API, probable functions that would be implemented:</div>
<blockquote dir="ltr" style="margin-right: 0px;">
<div dir="ltr">plist management:</div>
<div dir="ltr">       purple_plist_new(), purple_set_plist(), purple_get_plist(),</div>
<div dir="ltr">       purple_plist_get_ui_data(), purple_plist_set_ui_data(),</div>
<div dir="ltr">       purple_plist_load(), purple_plist_save()</div>
<div dir="ltr"> </div>
<div dir="ltr">plist iteration, account addition/removing:</div>
<div dir="ltr">       purple_plist_get_root(), purple_plist_node_next(), purple_plist_get_contacts(),</div>
<div dir="ltr">       purple_plist_add_account(), purple_plist_remove_account()</div>
<div dir="ltr"> </div>
<div dir="ltr">contact management:</div>
<div dir="ltr">       purple_plist_contact_new(), purple_plist_contact_destroy(),</div>
<div dir="ltr">       purple_plist_contact_add(), purple_plist_contact_remove(),</div>
<div dir="ltr">       purple_plist_contact_get_ui_data(), purple_plist_contact_set_ui_data(), purple_plist_contact_update_state(),</div>
<div dir="ltr">       purple_plist_contact_get_protocol_data(), purple_plist_contact_set_protocol_data(),</div>
<div dir="ltr">       purple_plist_contact_get_alias(), purple_plist_contact_set_alias()</div>
<div dir="ltr"> </div>
<div dir="ltr">ui ops:</div>
<div dir="ltr">       purple_plist_set_ui_ops(), purple_plist_get_ui_ops()</div>
<div dir="ltr"> </div></blockquote>
<div dir="ltr">6. A<span lang="">part from plist, buddies in blist will have PurplePrivacyBuddyType structure as a member to structure PurpleBuddy so as to store </span>privacy state for easy access by buddy tooltip.<br>

        typedef struct _PurplePrivacyContactType PurplePrivacyBuddytype;</div>
<div dir="ltr"><br>blist API would have additions of following functions to enable showing the least restrictive privacy state in buddy tooltip:<br>        PurplePrivacyState *purple_contact_get_priority_privacystate(...)</div>


<div dir="ltr"> </div>
<div dir="ltr"> </div>
<div dir="ltr"><span lang="">
<p>This is roughly an idea on how I am implementing the privacy rewrite. I have tried to keep the mail short :-p , hence I am sure I might have missed a few things, specifically I have not mentioned anything about multi user chat. I don't really understand how we can have any level of privacy in MUC. I tried searching but couldn't find anything about privacy in context of MUC.</p>


<p>MUC needs to be discussed, please feel free to write any idea you have regarding privacy in MUC.</p>
<p>I am sure I have covered most of the points that have been discussed in the devel list regarding privacy. Let me know if some idea sounds substandard or if you have some better way to implement something.</p>
<p></p></span>Will and other telepathy developers are especially requested to present their views. I have followed most of the suggestions Will proposed like allowing UI to disable features that require storing lists locally, having callback functions to report errors when some function dealing with server can fail asynchronously, and using union of all the lists to store privacy information.
<p>Florian, what are your views about this implementation in view of Instantbird development.</p>
<p>Zachary, and other Adium developers are requested to comment upon the mentioned ideas.</p>
<p>Also I would love to listen the views of Pidgin developers, especially Sadrul, and John.</p>
<p> </p><font color="#888888">
<p>Sulabh</p></font></div>
</blockquote></div><br>