[california/wip/731543-attendees: 12/12] Input validation



commit df2c17c20c0b0432be716217f5861bfca21ae5ad
Author: Jim Nelson <jim yorba org>
Date:   Wed Oct 29 18:52:26 2014 -0700

    Input validation

 src/collection/collection-iterable.vala |   17 +++++++++++++++++
 src/host/host-create-update-event.vala  |   12 ++++++++++++
 src/host/host.vala                      |    2 ++
 src/rc/create-update-event.ui           |    4 ++--
 src/util/util-mailto.vala               |   18 ------------------
 src/util/util-uri.vala                  |   19 +++++++++++++++++++
 src/util/util.vala                      |    2 ++
 7 files changed, 54 insertions(+), 20 deletions(-)
---
diff --git a/src/collection/collection-iterable.vala b/src/collection/collection-iterable.vala
index d51e82d..3ee25ba 100644
--- a/src/collection/collection-iterable.vala
+++ b/src/collection/collection-iterable.vala
@@ -111,6 +111,11 @@ public class Iterable<G> : Object {
     public delegate void Iterate<G>(G element);
     
     /**
+     * For simple transformation of elements in the { link Iterable}.
+     */
+    public delegate G Transform<G>(G element);
+    
+    /**
      * For mapping a single value of one type to multiple values of another.
      */
     public delegate Gee.Collection<A> Bloom<A, G>(G element);
@@ -166,6 +171,18 @@ public class Iterable<G> : Object {
         return new Iterable<G>(list.iterator());
     }
     
+    /**
+     * Like { link iterate}, called for each element, but adds the returned (possibly transformed)
+     * element.
+     */
+    public Iterable<G> transform(Transform<G> transformer) {
+        Gee.ArrayList<G> list = new Gee.ArrayList<G>();
+        foreach (G g in this)
+            list.add(transformer(g));
+        
+        return new Iterable<G>(list.iterator());
+    }
+    
     public Iterable<A> map<A>(Gee.MapFunc<A, G> f) {
         return new Iterable<A>(i.map<A>(f));
     }
diff --git a/src/host/host-create-update-event.vala b/src/host/host-create-update-event.vala
index 68aeea1..922d8c6 100644
--- a/src/host/host-create-update-event.vala
+++ b/src/host/host-create-update-event.vala
@@ -94,6 +94,9 @@ public class CreateUpdateEvent : Gtk.Grid, Toolkit.Card {
         update_this_button.clicked.connect(on_update_this_button_clicked);
         cancel_recurring_button.clicked.connect(on_cancel_recurring_button_clicked);
         
+        attendees_entry.bind_property("text", accept_button, "sensitive",
+            BindingFlags.SYNC_CREATE, transform_attendees_to_accept);
+        
         rotating_button_box.pack_end(FAMILY_NORMAL, cancel_button);
         rotating_button_box.pack_end(FAMILY_NORMAL, accept_button);
         
@@ -124,6 +127,15 @@ public class CreateUpdateEvent : Gtk.Grid, Toolkit.Card {
         return true;
     }
     
+    private bool transform_attendees_to_accept(Binding binding, Value source_value, ref Value target_value) {
+        target_value = from_array<string>(attendees_entry.text.split_set(" \t,;"))
+            .transform(str => str.strip())
+            .filter(str => !String.is_empty(str))
+            .all(str => URI.is_valid_mailbox(str));
+        
+        return true;
+    }
+    
     public void jumped_to(Toolkit.Card? from, Toolkit.Card.Jump reason, Value? message) {
         // if no message, leave everything as it is
         if (message == null)
diff --git a/src/host/host.vala b/src/host/host.vala
index 0e5d330..6e075a6 100644
--- a/src/host/host.vala
+++ b/src/host/host.vala
@@ -24,12 +24,14 @@ public void init() throws Error {
     Calendar.init();
     Toolkit.init();
     Component.init();
+    Util.init();
 }
 
 public void terminate() {
     if (!Unit.do_terminate(ref init_count))
         return;
     
+    Util.terminate();
     Component.terminate();
     View.terminate();
     Backing.terminate();
diff --git a/src/rc/create-update-event.ui b/src/rc/create-update-event.ui
index 4e381b8..26f672c 100644
--- a/src/rc/create-update-event.ui
+++ b/src/rc/create-update-event.ui
@@ -328,10 +328,10 @@
         <property name="visible">True</property>
         <property name="can_focus">True</property>
         <property name="tooltip_text" translatable="yes">For example:
-alice example com, Bob &lt;bob example com&gt;</property>
+alice example com, bob example com</property>
         <property name="activates_default">True</property>
         <property name="caps_lock_warning">False</property>
-        <property name="placeholder_text" translatable="yes">Email addresses separated by commas</property>
+        <property name="placeholder_text" translatable="yes">Email address(es)</property>
       </object>
       <packing>
         <property name="left_attach">1</property>
diff --git a/src/util/util-uri.vala b/src/util/util-uri.vala
index 83390ed..0a61e1a 100644
--- a/src/util/util-uri.vala
+++ b/src/util/util-uri.vala
@@ -14,6 +14,18 @@ errordomain URIError {
 
 namespace California.URI {
 
+private Regex email_regex;
+
+internal void init() throws Error {
+    // http://www.regular-expressions.info/email.html
+    // matches john dep aol museum not john aol   com
+    email_regex = new Regex("[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\\.)+[A-Z]{2,5}", RegexCompileFlags.CASELESS);
+}
+
+internal void terminate() {
+    email_regex = null;
+}
+
 /**
  * Basic validation of a string intended to be parsed as an absolute URI.
  *
@@ -57,5 +69,12 @@ public Soup.URI parse(string uri) throws Error {
     return parsed;
 }
 
+/**
+ * Validates a string as a valid RFC822 mailbox (i.e. email) address.
+ */
+public bool is_valid_mailbox(string str) {
+    return email_regex.match(str);
+}
+
 }
 
diff --git a/src/util/util.vala b/src/util/util.vala
index 8bc0b78..66337b3 100644
--- a/src/util/util.vala
+++ b/src/util/util.vala
@@ -14,12 +14,14 @@ public void init() throws Error {
     
     // internal init
     Markup.init();
+    URI.init();
 }
 
 public void terminate() {
     if (!Unit.do_terminate(ref init_count))
         return;
     
+    URI.terminate();
     Markup.terminate();
 }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]