The branch, master has been updated
       via  c85a4c9... s3: Move the global variable Protocol to struct 
smbd_server_connection
       via  6a14902... s3: Make the implicit reference to get_Protocol in 
lp_use_sendfile() explicit
       via  f7b4151... s3: Make the implicit reference to Protocol in 
is_in_path() explicit
       via  1e22899... s3: Make the implicit reference to Protocol in 
mask_match_list() explicit
       via  e23d8a3... s3: Make the implicit reference to Protocol in 
mask_match() explicit
       via  b2db4c5... mount.cifs: Fix a const error
       via  b79bcd9... s3: Fix some nonempty blank lines
       via  97525d0... s3: Avoid two calls to strcmp()
       via  e6f9596... s3: Fix a bool/enum mismatch
      from  ae1e949... s4:lsa RPC - Fix type of variable "atype"

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit c85a4c9ba4a7de65a7850f6f9708df66bd24deea
Author: Volker Lendecke <[email protected]>
Date:   Sat Nov 21 19:57:41 2009 +0100

    s3: Move the global variable Protocol to struct smbd_server_connection

commit 6a149022976fe6a5579ec9afc7a4d2dcb44dc8af
Author: Volker Lendecke <[email protected]>
Date:   Sat Nov 21 19:37:27 2009 +0100

    s3: Make the implicit reference to get_Protocol in lp_use_sendfile() 
explicit

commit f7b4151a64d8c6851e62255a7139fd00a5fc63a3
Author: Volker Lendecke <[email protected]>
Date:   Sat Nov 21 19:26:25 2009 +0100

    s3: Make the implicit reference to Protocol in is_in_path() explicit

commit 1e22899d268ae5a089f941a204413c07ee64fc78
Author: Volker Lendecke <[email protected]>
Date:   Sat Nov 21 19:04:34 2009 +0100

    s3: Make the implicit reference to Protocol in mask_match_list() explicit

commit e23d8a3d1f558a7e98ef2afd71e1d15c5b3a71bc
Author: Volker Lendecke <[email protected]>
Date:   Sat Nov 21 19:04:34 2009 +0100

    s3: Make the implicit reference to Protocol in mask_match() explicit

commit b2db4c51625077569ccc0fdf39471a67c3646066
Author: Volker Lendecke <[email protected]>
Date:   Sat Nov 21 19:03:45 2009 +0100

    mount.cifs: Fix a const error

commit b79bcd972cd028a494603f7254d3a266904be2d1
Author: Volker Lendecke <[email protected]>
Date:   Sat Nov 21 16:17:16 2009 +0100

    s3: Fix some nonempty blank lines

commit 97525d0a0e7e101cad5cbc218aed7fed982f30cc
Author: Volker Lendecke <[email protected]>
Date:   Sat Nov 21 16:15:16 2009 +0100

    s3: Avoid two calls to strcmp()

commit e6f95967cc0a4877d62b7656882bbed920b02b2e
Author: Volker Lendecke <[email protected]>
Date:   Sat Nov 21 16:10:52 2009 +0100

    s3: Fix a bool/enum mismatch

-----------------------------------------------------------------------

Summary of changes:
 client/mount.cifs.c           |    4 +-
 source3/client/client.c       |    3 +-
 source3/client/clitar.c       |    9 ++++-
 source3/include/proto.h       |   16 ++++++---
 source3/include/smb.h         |    1 +
 source3/include/smb_macros.h  |    3 --
 source3/lib/ms_fnmatch.c      |    2 +-
 source3/lib/substitute.c      |   53 +++++++++++++++---------------
 source3/lib/util.c            |   69 +++++++++++++++++---------------------
 source3/modules/onefs_open.c  |    3 +-
 source3/modules/vfs_preopen.c |    3 +-
 source3/param/loadparm.c      |   72 ++++++++++++++++++++--------------------
 source3/smbd/dir.c            |    4 ++-
 source3/smbd/dosmode.c        |   12 ++++--
 source3/smbd/filename.c       |    3 +-
 source3/smbd/globals.c        |   10 ++++++
 source3/smbd/globals.h        |    1 +
 source3/smbd/negprot.c        |   13 ++++---
 source3/smbd/nttrans.c        |    2 +-
 source3/smbd/open.c           |    5 ++-
 source3/smbd/process.c        |    1 +
 source3/smbd/reply.c          |   28 +++++++++++-----
 source3/smbd/sesssetup.c      |    4 +-
 source3/smbd/smb2_negprot.c   |    2 +-
 source3/smbd/trans2.c         |   11 ++++--
 25 files changed, 185 insertions(+), 149 deletions(-)


Changeset truncated at 500 lines:

diff --git a/client/mount.cifs.c b/client/mount.cifs.c
index a9c1827..459a9f3 100644
--- a/client/mount.cifs.c
+++ b/client/mount.cifs.c
@@ -121,7 +121,7 @@ static char * user_name = NULL;
 static char * mountpassword = NULL;
 char * domain_name = NULL;
 char * prefixpath = NULL;
-char *cifs_fstype = "cifs";
+const char *cifs_fstype = "cifs";
 
 /* glibc doesn't have strlcpy, strlcat. Ensure we do. JRA. We
  * don't link to libreplace so need them here. */
@@ -1637,7 +1637,7 @@ mount_retry:
        }
        mountent.mnt_fsname = dev_name;
        mountent.mnt_dir = mountpoint;
-       mountent.mnt_type = cifs_fstype;
+       mountent.mnt_type = (char *)(void *)cifs_fstype;
        mountent.mnt_opts = (char *)malloc(220);
        if(mountent.mnt_opts) {
                char * mount_user = getusername();
diff --git a/source3/client/client.c b/source3/client/client.c
index 6773e6d..19efa03 100644
--- a/source3/client/client.c
+++ b/source3/client/client.c
@@ -472,7 +472,8 @@ static bool do_this_one(file_info *finfo)
        }
 
        if (*client_get_fileselection() &&
-           !mask_match(finfo->name,client_get_fileselection(),false)) {
+           !mask_match(finfo->name, client_get_fileselection(),
+                       PROTOCOL_NONE, false)) {
                DEBUG(3,("mask_match %s failed\n", finfo->name));
                return false;
        }
diff --git a/source3/client/clitar.c b/source3/client/clitar.c
index d973329..7a956f9 100644
--- a/source3/client/clitar.c
+++ b/source3/client/clitar.c
@@ -827,7 +827,9 @@ static void do_tar(file_info *finfo, const char *dir)
                DEBUG(5, ("...tar_re_search: %d\n", tar_re_search));
 
                if ((!tar_re_search && clipfind(cliplist, clipn, exclaim)) ||
-                               (tar_re_search && mask_match_list(exclaim, 
cliplist, clipn, True))) {
+                   (tar_re_search
+                    && mask_match_list(exclaim, cliplist, clipn,
+                                       PROTOCOL_NONE, True))) {
                        DEBUG(3,("Skipping file %s\n", exclaim));
                        TALLOC_FREE(exclaim);
                        return;
@@ -1210,7 +1212,10 @@ static void do_tarput(void)
                /* Well, now we have a header, process the file ...            
*/
                /* Should we skip the file? We have the long name as well here 
*/
                skip = clipn && ((!tar_re_search && clipfind(cliplist, clipn, 
finfo.name) ^ tar_excl) ||
-                                       (tar_re_search && 
mask_match_list(finfo.name, cliplist, clipn, True)));
+                                (tar_re_search
+                                 && mask_match_list(finfo.name, cliplist,
+                                                    clipn, PROTOCOL_NONE,
+                                                    True)));
 
                DEBUG(5, ("Skip = %i, cliplist=%s, file=%s\n", skip, 
(cliplist?cliplist[0]:NULL), finfo.name));
                if (skip) {
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 92cb997..8cf4769 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -1075,8 +1075,8 @@ struct passwd *Get_Pwnam_alloc(TALLOC_CTX *mem_ctx, const 
char *user);
 
 /* The following definitions come from lib/util.c  */
 
-enum protocol_types get_Protocol(void);
-void set_Protocol(enum protocol_types  p);
+enum protocol_types get_Protocol(const struct smbd_server_connection *c);
+void set_Protocol(struct smbd_server_connection *c, enum protocol_types p);
 bool all_zero(const uint8_t *ptr, size_t size);
 bool set_global_myname(const char *myname);
 const char *global_myname(void);
@@ -1158,7 +1158,8 @@ gid_t nametogid(const char *name);
 void smb_panic(const char *const why);
 void log_stack_trace(void);
 const char *readdirname(SMB_STRUCT_DIR *p);
-bool is_in_path(const char *name, name_compare_entry *namelist, bool 
case_sensitive);
+bool is_in_path(const char *name, name_compare_entry *namelist,
+               enum protocol_types proto, bool case_sensitive);
 void set_namearray(name_compare_entry **ppname_array, const char *namelist);
 void free_namearray(name_compare_entry *name_array);
 bool fcntl_lock(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type);
@@ -1188,9 +1189,11 @@ bool parent_dirname(TALLOC_CTX *mem_ctx, const char 
*dir, char **parent,
                    const char **name);
 bool ms_has_wild(const char *s);
 bool ms_has_wild_w(const smb_ucs2_t *s);
-bool mask_match(const char *string, const char *pattern, bool 
is_case_sensitive);
+bool mask_match(const char *string, const char *pattern,
+               enum protocol_types proto, bool is_case_sensitive);
 bool mask_match_search(const char *string, const char *pattern, bool 
is_case_sensitive);
-bool mask_match_list(const char *string, char **list, int listLen, bool 
is_case_sensitive);
+bool mask_match_list(const char *string, char **list, int listLen,
+                    enum protocol_types proto, bool is_case_sensitive);
 bool unix_wild_match(const char *pattern, const char *string);
 bool name_to_fqdn(fstring fqdn, const char *name);
 void *talloc_append_blob(TALLOC_CTX *mem_ctx, void *buf, DATA_BLOB blob);
@@ -4386,7 +4389,8 @@ const char *lp_printcapname(void);
 bool lp_disable_spoolss( void );
 void lp_set_spoolss_state( uint32 state );
 uint32 lp_get_spoolss_state( void );
-bool lp_use_sendfile(int snum, struct smb_signing_state *signing_state);
+bool lp_use_sendfile(int snum, enum protocol_types proto,
+                    struct smb_signing_state *signing_state);
 void set_use_sendfile(int snum, bool val);
 void set_store_dos_attributes(int snum, bool val);
 void lp_set_mangling_method(const char *new_method);
diff --git a/source3/include/smb.h b/source3/include/smb.h
index a3acb7c..94d2aa2 100644
--- a/source3/include/smb.h
+++ b/source3/include/smb.h
@@ -652,6 +652,7 @@ struct smb_request {
        size_t unread_bytes;
        bool encrypted;
        connection_struct *conn;
+       struct smbd_server_connection *sconn;
        struct smb_perfcount_data pcd;
 
        /*
diff --git a/source3/include/smb_macros.h b/source3/include/smb_macros.h
index 10ee78b..95f427c 100644
--- a/source3/include/smb_macros.h
+++ b/source3/include/smb_macros.h
@@ -79,9 +79,6 @@
 #define MAP_HIDDEN(conn)   ((conn) && lp_map_hidden(SNUM(conn)))
 #define MAP_SYSTEM(conn)   ((conn) && lp_map_system(SNUM(conn)))
 #define MAP_ARCHIVE(conn)   ((conn) && lp_map_archive(SNUM(conn)))
-#define IS_HIDDEN_PATH(conn,path)  ((conn) && 
is_in_path((path),(conn)->hide_list,(conn)->case_sensitive))
-#define IS_VETO_PATH(conn,path)  ((conn) && 
is_in_path((path),(conn)->veto_list,(conn)->case_sensitive))
-#define IS_VETO_OPLOCK_PATH(conn,path)  ((conn) && 
is_in_path((path),(conn)->veto_oplock_list,(conn)->case_sensitive))
 
 /* 
  * Used by the stat cache code to check if a returned
diff --git a/source3/lib/ms_fnmatch.c b/source3/lib/ms_fnmatch.c
index 1eac9fa..bff7382 100644
--- a/source3/lib/ms_fnmatch.c
+++ b/source3/lib/ms_fnmatch.c
@@ -234,5 +234,5 @@ int ms_fnmatch(const char *pattern, const char *string, 
bool translate_pattern,
 /* a generic fnmatch function - uses for non-CIFS pattern matching */
 int gen_fnmatch(const char *pattern, const char *string)
 {
-       return ms_fnmatch(pattern, string, PROTOCOL_NT1, False);
+       return ms_fnmatch(pattern, string, true, False);
 }
diff --git a/source3/lib/substitute.c b/source3/lib/substitute.c
index c9dc1d2..55acdd9 100644
--- a/source3/lib/substitute.c
+++ b/source3/lib/substitute.c
@@ -3,17 +3,17 @@
    string substitution functions
    Copyright (C) Andrew Tridgell 1992-2000
    Copyright (C) Gerald Carter   2006
-   
+
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
-   
+
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
-   
+
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
@@ -276,12 +276,12 @@ static char * realloc_expand_env_var(char *str, char *p)
 
        r = p + 3;
        copylen = q - r;
-       
+
        /* reserve space for use later add %$() chars */
        if ( (envname = (char *)SMB_MALLOC(copylen + 1 + 4)) == NULL ) {
                return NULL;
        }
-       
+
        strncpy(envname,r,copylen);
        envname[copylen] = '\0';
 
@@ -301,7 +301,7 @@ static char * realloc_expand_env_var(char *str, char *p)
        envname[copylen] = '\0';
        r = realloc_string_sub(str, envname, envval);
        SAFE_FREE(envname);
-               
+
        return r;
 }
 
@@ -313,17 +313,17 @@ static char *longvar_domainsid( void )
        DOM_SID sid;
        fstring tmp;
        char *sid_string;
-       
+
        if ( !secrets_fetch_domain_sid( lp_workgroup(), &sid ) ) {
                return NULL;
        }
-       
+
        sid_string = SMB_STRDUP( sid_to_fstring( tmp, &sid ) );
-       
+
        if ( !sid_string ) {
                DEBUG(0,("longvar_domainsid: failed to dup SID string!\n"));
        }
-       
+
        return sid_string;
 }
 
@@ -343,15 +343,15 @@ static struct api_longvar longvar_table[] = {
 static char *get_longvar_val( const char *varname )
 {
        int i;
-       
+
        DEBUG(7,("get_longvar_val: expanding variable [%s]\n", varname));
-       
+
        for ( i=0; longvar_table[i].name; i++ ) {
                if ( strequal( longvar_table[i].name, varname ) ) {
                        return longvar_table[i].fn();
                }
        }
-       
+
        return NULL;
 }
 
@@ -515,13 +515,12 @@ void standard_sub_basic(const char *smb_name, const char 
*domain_name,
                        char *str, size_t len)
 {
        char *s;
-       
+
        if ( (s = alloc_sub_basic( smb_name, domain_name, str )) != NULL ) {
                strncpy( str, s, len );
        }
-       
+
        SAFE_FREE( s );
-       
 }
 
 /****************************************************************************
@@ -533,7 +532,7 @@ char *talloc_sub_basic(TALLOC_CTX *mem_ctx, const char 
*smb_name,
                       const char *domain_name, const char *str)
 {
        char *a, *t;
-       
+
        if ( (a = alloc_sub_basic(smb_name, domain_name, str)) == NULL ) {
                return NULL;
        }
@@ -555,12 +554,12 @@ char *alloc_sub_basic(const char *smb_name, const char 
*domain_name,
        TALLOC_CTX *tmp_ctx = NULL;
 
        /* workaround to prevent a crash while looking at bug #687 */
-       
+
        if (!str) {
                DEBUG(0,("alloc_sub_basic: NULL source string!  This should not 
happen\n"));
                return NULL;
        }
-       
+
        a_string = SMB_STRDUP(str);
        if (a_string == NULL) {
                DEBUG(0, ("alloc_sub_basic: Out of memory!\n"));
@@ -722,11 +721,11 @@ char *talloc_sub_specified(TALLOC_CTX *mem_ctx,
                DEBUG(0, ("talloc_sub_specified: Out of memory!\n"));
                goto done;
        }
-       
+
        for (b = s = a_string; (p = strchr_m(s, '%')); s = a_string + (p - b)) {
-               
+
                b = a_string;
-               
+
                switch (*(p+1)) {
                case 'U' : 
                        a_string = talloc_string_sub(
@@ -802,11 +801,11 @@ static char *alloc_sub_advanced(const char *servicename, 
const char *user,
                DEBUG(0, ("alloc_sub_advanced: Out of memory!\n"));
                return NULL;
        }
-       
+
        for (b = s = a_string; (p = strchr_m(s, '%')); s = a_string + (p - b)) {
-               
+
                b = a_string;
-               
+
                switch (*(p+1)) {
                case 'N' :
                        a_string = realloc_string_sub(a_string, "%N", 
automount_server(user));
@@ -830,7 +829,7 @@ static char *alloc_sub_advanced(const char *servicename, 
const char *user,
                case 'u': 
                        a_string = realloc_string_sub(a_string, "%u", user); 
                        break;
-                       
+
                        /* Patch from [email protected] Left the %N (NIS
                         * server name) in standard_sub_basic as it is
                         * a feature for logon servers, hence uses the
@@ -842,7 +841,7 @@ static char *alloc_sub_advanced(const char *servicename, 
const char *user,
                        a_string = realloc_string_sub(a_string, "%p",
                                                      
automount_path(servicename)); 
                        break;
-                       
+
                default: 
                        break;
                }
diff --git a/source3/lib/util.c b/source3/lib/util.c
index 9d12e5b..d194c3a 100644
--- a/source3/lib/util.c
+++ b/source3/lib/util.c
@@ -11,12 +11,12 @@
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
-   
+
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
-   
+
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
@@ -55,18 +55,6 @@ extern unsigned int global_clobber_region_line;
 #endif /* WITH_NISPLUS_HOME */
 #endif /* HAVE_NETGROUP && WITH_AUTOMOUNT */
 
-static enum protocol_types Protocol = PROTOCOL_COREPLUS;
-
-enum protocol_types get_Protocol(void)
-{
-       return Protocol;
-}
-
-void set_Protocol(enum protocol_types  p)
-{
-       Protocol = p;
-}
-
 static enum remote_arch_types ra_type = RA_UNKNOWN;
 
 /***********************************************************************
@@ -532,7 +520,7 @@ bool file_exist_stat(const char *fname,SMB_STRUCT_STAT 
*sbuf)
        SMB_STRUCT_STAT st;
        if (!sbuf)
                sbuf = &st;
-  
+
        if (sys_stat(fname,sbuf) != 0) 
                return(False);
 
@@ -626,7 +614,7 @@ void show_msg(char *buf)
 
        if (!DEBUGLVL(5))
                return;
-       
+
        
DEBUG(5,("size=%d\nsmb_com=0x%x\nsmb_rcls=%d\nsmb_reh=%d\nsmb_err=%d\nsmb_flg=%d\nsmb_flg2=%d\n",
                        smb_len(buf),
                        (int)CVAL(buf,smb_com),
@@ -645,7 +633,7 @@ void show_msg(char *buf)
        for (i=0;i<(int)CVAL(buf,smb_wct);i++)
                DEBUGADD(5,("smb_vwv[%2d]=%5d (0x%X)\n",i,
                        SVAL(buf,smb_vwv+2*i),SVAL(buf,smb_vwv+2*i)));
-       
+
        bcc = (int)SVAL(buf,smb_vwv+2*(CVAL(buf,smb_wct)));
 
        DEBUGADD(5,("smb_bcc=%d\n",bcc));
@@ -896,7 +884,7 @@ void smb_msleep(unsigned int t)
 
        GetTimeOfDay(&t1);
        t2 = t1;
-  
+
        while (tdiff < t) {
                tval.tv_sec = (t-tdiff)/1000;
                tval.tv_usec = 1000*((t-tdiff)%1000);
@@ -1217,9 +1205,9 @@ int interpret_protocol(const char *str,int def)
                return(PROTOCOL_COREPLUS);
        if (strequal(str,"CORE+"))
                return(PROTOCOL_COREPLUS);
-  
+
        DEBUG(0,("Unrecognised protocol level %s\n",str));
-  
+
        return(def);
 }
 
@@ -1577,7 +1565,7 @@ libunwind_failed:
 
        DEBUG(0, ("BACKTRACE: %lu stack frames:\n", 
                  (unsigned long)backtrace_size));
-       
+
        if (backtrace_strings) {
                int i;
 
@@ -1641,7 +1629,7 @@ const char *readdirname(SMB_STRUCT_DIR *p)
 
        if (!p)
                return(NULL);
-  
+
        ptr = (SMB_STRUCT_DIRENT *)sys_readdir(p);
        if (!ptr)
                return(NULL);
@@ -1666,7 +1654,8 @@ const char *readdirname(SMB_STRUCT_DIR *p)
  of a path matches a (possibly wildcarded) entry in a namelist.
 ********************************************************************/
 
-bool is_in_path(const char *name, name_compare_entry *namelist, bool 
case_sensitive)
+bool is_in_path(const char *name, name_compare_entry *namelist,
+               enum protocol_types proto, bool case_sensitive)
 {
        const char *last_component;
 
@@ -1687,7 +1676,8 @@ bool is_in_path(const char *name, name_compare_entry 
*namelist, bool case_sensit
 
        for(; namelist->name != NULL; namelist++) {
                if(namelist->is_wild) {
-                       if (mask_match(last_component, namelist->name, 
case_sensitive)) {
+                       if (mask_match(last_component, namelist->name,
+                                      proto, case_sensitive)) {
                                DEBUG(8,("is_in_path: mask match succeeded\n"));
                                return True;
                        }
@@ -1715,7 +1705,7 @@ bool is_in_path(const char *name, name_compare_entry 
*namelist, bool case_sensit
  remove a potentially expensive call to mask_match
  if possible.
 ********************************************************************/
- 
+
 void set_namearray(name_compare_entry **ppname_array, const char *namelist)
 {
        char *name_end;
@@ -1791,7 +1781,7 @@ void set_namearray(name_compare_entry **ppname_array, 
const char *namelist)
                nameptr = name_end + 1;
                i++;
        }
-  
+
        (*ppname_array)[i].name = NULL;
 
        return;
@@ -1851,7 +1841,7 @@ bool fcntl_getlock(int fd, SMB_OFF_T *poffset, SMB_OFF_T 
*pcount, int *ptype, pi
        *poffset = lock.l_start;
        *pcount = lock.l_len;
        *ppid = lock.l_pid;
-       
+
        DEBUG(3,("fcntl_getlock: fd %d is returned info %d pid %u\n",
                        fd, (int)lock.l_type, (unsigned int)lock.l_pid));
        return True;
@@ -2310,7 +2300,7 @@ bool parent_dirname(TALLOC_CTX *mem_ctx, const char *dir, 
char **parent,
 {
        char *p;
        ptrdiff_t len;
- 
+
        p = strrchr_m(dir, '/'); /* Find final '/', if any */
 
        if (p == NULL) {
@@ -2384,14 +2374,16 @@ bool ms_has_wild_w(const smb_ucs2_t *s)
  of the ".." name.
 *******************************************************************/
 
-bool mask_match(const char *string, const char *pattern, bool 
is_case_sensitive)
+bool mask_match(const char *string, const char *pattern,
+               enum protocol_types proto, bool is_case_sensitive)
 {
-       if (strcmp(string,"..") == 0)
+       if (ISDOTDOT(string))
                string = ".";
-       if (strcmp(pattern,".") == 0)
+       if (ISDOT(pattern))


-- 
Samba Shared Repository

Reply via email to