text:
<?php
/**
 * Module Name: Subscriptions
 * Module Description: Notify your readers of new posts and comments by email.
 * Jumpstart Description: Give visitors two easy subscription options — while commenting, or via a separate email subscription widget you can display.
 * Sort Order: 9
 * Recommendation Order: 8
 * First Introduced: 1.2
 * Requires Connection: Yes
 * Auto Activate: Yes
 * Module Tags: Social
 * Feature: Engagement, Jumpstart
 * Additional Search Queries: subscriptions, subscription, email, follow, followers, subscribers, signup
 */

add_action( 'jetpack_modules_loaded', 'jetpack_subscriptions_load' );

function jetpack_subscriptions_load() {
	Jetpack::enable_module_configurable( __FILE__ );
	Jetpack::module_configuration_load( __FILE__, 'jetpack_subscriptions_configuration_load' );
}

function jetpack_subscriptions_configuration_load() {
	wp_safe_redirect( admin_url( 'options-discussion.php#jetpack-subscriptions-settings' ) );
	exit;
}

class Jetpack_Subscriptions {
	public $jetpack = false;

	public static $hash;

	/**
	 * Singleton
	 * @static
	 */
	static function init() {
		static $instance = false;

		if ( !$instance ) {
			$instance = new Jetpack_Subscriptions;
		}

		return $instance;
	}

	function __construct() {
		$this->jetpack = Jetpack::init();

		// Don't use COOKIEHASH as it could be shared across installs && is non-unique in multisite.
		// @see: https://twitter.com/nacin/status/378246957451333632
		self::$hash = md5( get_option( 'siteurl' ) );

		add_filter( 'jetpack_xmlrpc_methods', array( $this, 'xmlrpc_methods' ) );

		// @todo remove sync from subscriptions and move elsewhere...

		// Add Configuration Page
		add_action( 'admin_init', array( $this, 'configure' ) );

		// Set up the subscription widget.
		add_action( 'widgets_init', array( $this, 'widget_init' ) );

		// Catch subscription widget submits
		if ( isset( $_REQUEST['jetpack_subscriptions_widget'] ) )
			add_action( 'template_redirect', array( $this, 'widget_submit' ) );

		// Set up the comment subscription checkboxes
		add_action( 'comment_form', array( $this, 'comment_subscribe_init' ) );

		// Catch comment posts and check for subscriptions.
		add_action( 'comment_post', array( $this, 'comment_subscribe_submit' ), 50, 2 );

		// Adds post meta checkbox in the post submit metabox
		add_action( 'post_submitbox_misc_actions', array( $this, 'subscription_post_page_metabox' ) );

		add_action( 'transition_post_status', array( $this, 'maybe_send_subscription_email' ), 10, 3 );
	}

	function post_is_public( $the_post ) {
		if ( !$post = get_post( $the_post ) ) {
			return false;
		}

		if ( 'publish' === $post->post_status && strlen( (string) $post->post_password ) < 1 ) {
			/**
			 * Filter whether posts can be emailed to subscribers.
			 *
			 * @module subscriptions
			 *
			 * @since 2.4.0
			 *
			 * @param bool true Can the post be emailed to Subscribers. Default to true.
			 */
			return apply_filters( 'jetpack_is_post_mailable', true );
		}
	}

	/**
	 * Jetpack_Subscriptions::xmlrpc_methods()
	 *
	 * Register subscriptions methods with the Jetpack XML-RPC server.
	 * @param array $methods
	 */
	function xmlrpc_methods( $methods ) {
		return array_merge(
			$methods,
			array(
				'jetpack.subscriptions.subscribe' => array( $this, 'subscribe' ),
			)
		);
	}

	/*
	 * Disable Subscribe on Single Post
	 * Register post meta
	 */
	function subscription_post_page_metabox() {
		if (
			/**
			 * Filter whether or not to show the per-post subscription option.
			 *
			 * @module subscriptions
			 *
			 * @since 3.7.0
			 *
			 * @param bool true = show checkbox option on all new posts | false = hide the option.
			 */
			 ! apply_filters( 'jetpack_allow_per_post_subscriptions', false ) )
		{
			return;
		}

		if ( has_filter( 'jetpack_subscriptions_exclude_these_categories' ) || has_filter( 'jetpack_subscriptions_include_only_these_categories' ) ) {
			return;
		}

		global $post;
		$disable_subscribe_value = get_post_meta( $post->ID, '_jetpack_dont_email_post_to_subs', true );
		// Nonce it
		wp_nonce_field( 'disable_subscribe', 'disable_subscribe_nonce' );
		// only show checkbox if post hasn't been published and is a 'post' post type.
		if ( get_post_status( $post->ID ) !== 'publish' && get_post_type( $post->ID ) == 'post' ) : ?>

				<?php _e( 'Jetpack Subscriptions:', 'jetpack' ); ?>

				<input type="checkbox" name="_jetpack_dont_email_post_to_subs" id="jetpack-per-post-subscribe" value="1" <?php checked( $disable_subscribe_value, 1, true ); ?> />
				<?php _e( 'Don’t send this to subscribers', 'jetpack' ); ?>

		<?php endif;
	}

	/**
	 * Checks whether or not the post should be emailed to subscribers
	 *
	 * It checks for the following things in order:
	 * - Usage of filter jetpack_subscriptions_exclude_these_categories
	 * - Usage of filter jetpack_subscriptions_include_only_these_categories
	 * - Existence of the per-post checkbox option
	 *
	 * Only one of these can be used at any given time.
	 *
	 * @param $new_status string - the "new" post status of the transition when saved
	 * @param $old_status string - the "old" post status of the transition when saved
	 * @param $post obj - The post object
	 */
	function maybe_send_subscription_email( $new_status, $old_status, $post ) {
		// Only do things on publish
		if ( 'publish' !== $new_status ) {
			return;
		}
		if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
			return;
		}

		/**
		 * If we're updating the post, let's make sure the flag to not send to subscribers
		 * is set to minimize the chances of sending posts multiple times.
		 */
		if ( 'publish' == $old_status ) {
			update_post_meta( $post->ID, '_jetpack_dont_email_post_to_subs', 1 );
		}

		/**
		 * Array of categories that will never trigger subscription emails.
		 *
		 * Will not send subscription emails from any post from within these categories.
		 *
		 * @module subscriptions
		 *
		 * @since 3.7.0
		 *
		 * @param array $args Array of category slugs or ID's.
		 */
		$excluded_categories = apply_filters( 'jetpack_subscriptions_exclude_these_categories', array() );

		// Never email posts from these categories
		if ( ! empty( $excluded_categories ) && in_category( $excluded_categories, $post->ID ) ) {
			update_post_meta( $post->ID, '_jetpack_dont_email_post_to_subs', 1 );
		}

		/**
		 * ONLY send subscription emails for these categories
		 *
		 * Will ONLY send subscription emails to these categories.
		 *
		 * @module subscriptions
		 *
		 * @since 3.7.0
		 *
		 * @param array $args Array of category slugs or ID's.
		 */
		$only_these_categories = apply_filters( 'jetpack_subscriptions_exclude_all_categories_except', array() );

		// Only emails posts from these categories
		if ( ! empty( $only_these_categories ) && ! in_category( $only_these_categories, $post->ID ) ) {
			update_post_meta( $post->ID, '_jetpack_dont_email_post_to_subs', 1 );
		}

		// Email the post, depending on the checkbox option
		if ( ! empty( $_POST['disable_subscribe_nonce'] ) && wp_verify_nonce( $_POST['disable_subscribe_nonce'], 'disable_subscribe' ) ) {
			if ( isset( $_POST['_jetpack_dont_email_post_to_subs'] ) ) {
				update_post_meta( $post->ID, '_jetpack_dont_email_post_to_subs', $_POST['_jetpack_dont_email_post_to_subs'] );
			}
		}
	}

	/**
	 * Jetpack_Subscriptions::configure()
	 *
	 * Jetpack Subscriptions configuration screen.
	 */
	function configure() {
		// Create the section
		add_settings_section(
			'jetpack_subscriptions',
			__( 'Jetpack Subscriptions Settings', 'jetpack' ),
			array( $this, 'subscriptions_settings_section' ),
			'discussion'
		);

		/** Subscribe to Posts ***************************************************/

		add_settings_field(
			'jetpack_subscriptions_post_subscribe',
			__( 'Follow Blog', 'jetpack' ),
			array( $this, 'subscription_post_subscribe_setting' ),
			'discussion',
			'jetpack_subscriptions'
		);

		register_setting(
			'discussion',
			'stb_enabled'
		);

		/** Subscribe to Comments ******************************************************/

		add_settings_field(
			'jetpack_subscriptions_comment_subscribe',
			__( 'Follow Comments', 'jetpack' ),
			array( $this, 'subscription_comment_subscribe_setting' ),
			'discussion',
			'jetpack_subscriptions'
		);

		register_setting(
			'discussion',
			'stc_enabled'
		);

		/** Subscription Messaging Options ******************************************************/

		register_setting(
			'reading',
			'subscription_options',
			array( $this, 'validate_settings' )
		);

		add_settings_section(
			'email_settings',
			__( 'Follower Settings', 'jetpack' ),
			array( $this, 'reading_section' ),
			'reading'
		);

		add_settings_field(
			'invitation',
			__( 'Blog follow email text', 'jetpack' ),
			array( $this, 'setting_invitation' ),
			'reading',
			'email_settings'
		);

		add_settings_field(
			'comment-follow',
			__( 'Comment follow email text', 'jetpack' ),
			array( $this, 'setting_comment_follow' ),
			'reading',
			'email_settings'
		);
	}

	/**
	 * Discussions setting section blurb
	 *
	 */
	function subscriptions_settings_section() {
	?>

<?php _e( 'Change whether your visitors can subscribe to your posts or comments or both.', 'jetpack' ); ?>

	<?php
	}

	/**
	 * Post Subscriptions Toggle
	 *
	 */
	function subscription_post_subscribe_setting() {

		$stb_enabled = get_option( 'stb_enabled', 1 ); ?>

			<input type="checkbox" name="stb_enabled" id="jetpack-post-subscribe" value="1" <?php checked( $stb_enabled, 1 ); ?> />
			<?php _e( "Show a 'follow blog' option in the comment form", 'jetpack' ); ?>

	<?php
	}

	/**
	 * Comments Subscriptions Toggle
	 *
	 */
	function subscription_comment_subscribe_setting() {

		$stc_enabled = get_option( 'stc_enabled', 1 ); ?>

			<input type="checkbox" name="stc_enabled" id="jetpack-comment-subscribe" value="1" <?php checked( $stc_enabled, 1 ); ?> />
			<?php _e( "Show a 'follow comments' option in the comment form", 'jetpack' ); ?>

	<?php
	}

	function validate_settings( $settings ) {
		global $allowedposttags;

		$default = $this->get_default_settings();

		// Blog Follow
		$settings['invitation'] = trim( wp_kses( $settings['invitation'], $allowedposttags ) );
		if ( empty( $settings['invitation'] ) )
			$settings['invitation'] = $default['invitation'];

		// Comments Follow (single post)
		$settings['comment_follow'] = trim( wp_kses( $settings['comment_follow'], $allowedposttags ) );
		if ( empty( $settings['comment_follow'] ) )
			$settings['comment_follow'] = $default['comment_follow'];

		return $settings;
	}

	public function reading_section() {
		echo '
';
		_e( 'These settings change emails sent from your blog to followers.', 'jetpack' );
		echo '
';
	}

	public function setting_invitation() {
		$settings = $this->get_settings();
		echo '<textarea name="subscription_options[invitation]" class="large-text" cols="50" rows="5">' . esc_textarea( $settings['invitation'] ) . '</textarea>';
		echo '
'.__( 'Introduction text sent when someone follows your blog. (Site and confirmation details will be automatically added for you.)', 'jetpack' ).'
';
	}

	public function setting_comment_follow() {
		$settings = $this->get_settings();
		echo '<textarea name="subscription_options[comment_follow]" class="large-text" cols="50" rows="5">' . esc_textarea( $settings['comment_follow'] ) . '</textarea>';
		echo '
'.__( 'Introduction text sent when someone follows a post on your blog. (Site and confirmation details will be automatically added for you.)', 'jetpack' ).'
';
	}

	function get_default_settings() {
		return array(
			'invitation'     => __( "Howdy.\n\nYou recently followed this blog's posts. This means you will receive each new post by email.\n\nTo activate, click confirm below. If you believe this is an error, ignore this message and we'll never bother you again.", 'jetpack' ),
			'comment_follow' => __( "Howdy.\n\nYou recently followed one of my posts. This means you will receive an email when new comments are posted.\n\nTo activate, click confirm below. If you believe this is an error, ignore this message and we'll never bother you again.", 'jetpack' )
		);
	}

	function get_settings() {
		return wp_parse_args( (array) get_option( 'subscription_options', array() ), $this->get_default_settings() );
	}

	/**
	 * Jetpack_Subscriptions::subscribe()
	 *
	 * Send a synchronous XML-RPC subscribe to blog posts or subscribe to post comments request.
	 *
	 * @param string $email
	 * @param array  $post_ids (optional) defaults to 0 for blog posts only: array of post IDs to subscribe to blog's posts
	 * @param bool   $async    (optional) Should the subscription be performed asynchronously?  Defaults to true.
	 *
	 * @return true|Jetpack_Error true on success
	 *	invalid_email   : not a valid email address
	 *	invalid_post_id : not a valid post ID
	 *	unknown_post_id : unknown post
	 *	not_subscribed  : strange error.  Jetpack servers at WordPress.com could subscribe the email.
	 *	disabled        : Site owner has disabled subscriptions.
	 *	active          : Already subscribed.
	 *	unknown         : strange error.  Jetpack servers at WordPress.com returned something malformed.
	 *	unknown_status  : strange error.  Jetpack servers at WordPress.com returned something I didn't understand.
	 */
	function subscribe( $email, $post_ids = 0, $async = true, $extra_data = array() ) {
		if ( !is_email( $email ) ) {
			return new Jetpack_Error( 'invalid_email' );
		}

		if ( !$async ) {
			Jetpack::load_xml_rpc_client();
			$xml = new Jetpack_IXR_ClientMulticall();
		}

		foreach ( (array) $post_ids as $post_id ) {
			$post_id = (int) $post_id;
			if ( $post_id < 0 ) {
				return new Jetpack_Error( 'invalid_post_id' );
			} else if ( $post_id && !$post = get_post( $post_id ) ) {
				return new Jetpack_Error( 'unknown_post_id' );
			}

			if ( $async ) {
				Jetpack::xmlrpc_async_call( 'jetpack.subscribeToSite', $email, $post_id, serialize( $extra_data ) );
			} else {
				$xml->addCall( 'jetpack.subscribeToSite', $email, $post_id, serialize( $extra_data ) );
			}
		}

		if ( $async ) {
			return;
		}

		// Call
		$xml->query();

		if ( $xml->isError() ) {
			return $xml->get_jetpack_error();
		}

		$responses = $xml->getResponse();

		$r = array();
		foreach ( (array) $responses as $response ) {
			if ( isset( $response['faultCode'] ) || isset( $response['faultString'] ) ) {
				$r[] = $xml->get_jetpack_error( $response['faultCode'], $response['faultString'] );
				continue;
			}

			if ( !is_array( $response[0] ) || empty( $response[0]['status'] ) ) {
				$r[] = new Jetpack_Error( 'unknown' );
				continue;
			}

			switch ( $response[0]['status'] ) {
			case 'error' :
				$r[] = new Jetpack_Error( 'not_subscribed' );
				continue 2;
			case 'disabled' :
				$r[] = new Jetpack_Error( 'disabled' );
				continue 2;
			case 'active' :
				$r[] = new Jetpack_Error( 'active' );
				continue 2;
			case 'pending' :
				$r[] = true;
				continue 2;
			default :
				$r[] = new Jetpack_Error( 'unknown_status', (string) $response[0]['status'] );
				continue 2;
			}
		}

		return $r;
	}

	/**
	 * Jetpack_Subscriptions::widget_init()
	 *
	 * Initialize and register the Jetpack Subscriptions widget.
	 */
	function widget_init() {
		register_widget( 'Jetpack_Subscriptions_Widget' );
	}

	/**
	 * Jetpack_Subscriptions::widget_submit()
	 *
	 * When a user submits their email via the blog subscription widget, check the details and call the subsribe() method.
	 */
	function widget_submit() {
		// Check the nonce.
		if ( is_user_logged_in() ) {
			check_admin_referer( 'blogsub_subscribe_' . get_current_blog_id() );
		}

		if ( empty( $_REQUEST['email'] ) )
			return false;

		$redirect_fragment = false;
		if ( isset( $_REQUEST['redirect_fragment'] ) ) {
			$redirect_fragment = preg_replace( '/[^a-z0-9_-]/i', '', $_REQUEST['redirect_fragment'] );
		}
		if ( !$redirect_fragment ) {
			$redirect_fragment = 'subscribe-blog';
		}

		$subscribe = Jetpack_Subscriptions::subscribe(
												$_REQUEST['email'],
												0,
												false,
												array(
													'source'         => 'widget',
													'widget-in-use'  => is_active_widget( false, false, 'blog_subscription', true ) ? 'yes' : 'no',
													'comment_status' => '',
													'server_data'    => $_SERVER,
												)
		);

		if ( is_wp_error( $subscribe ) ) {
			$error = $subscribe->get_error_code();
		} else {
			$error = false;
			foreach ( $subscribe as $response ) {
				if ( is_wp_error( $response ) ) {
					$error = $response->get_error_code();
					break;
				}
			}
		}

		switch ( $error ) {
			case false:
				$result = 'success';
				break;
			case 'invalid_email':
				$result = $error;
				break;
			case 'active':
			case 'blocked_email':
				$result = 'opted_out';
				break;
			case 'pending':
				$result = 'already';
				break;
			default:
				$result = 'error';
				break;
		}

		$redirect = add_query_arg( 'subscribe', $result );

		/**
		 * Fires on each subscription form submission.
		 *
		 * @module subscriptions
		 *
		 * @since 3.7.0
		 *
		 * @param string $result Result of form submission: success, invalid_email, already, error.
		 */
		do_action( 'jetpack_subscriptions_form_submission', $result );

		wp_safe_redirect( "$redirect#$redirect_fragment" );
		exit;
	}

	/**
	 * Jetpack_Subscriptions::comment_subscribe_init()
	 *
	 * Set up and add the comment subscription checkbox to the comment form.
	 */
	function comment_subscribe_init() {
		global $post;

		$comments_checked = '';
		$blog_checked     = '';

		// Check for a comment / blog submission and set a cookie to retain the setting and check the boxes.
		if ( isset( $_COOKIE[ 'jetpack_comments_subscribe_' . self::$hash ] ) && $_COOKIE[ 'jetpack_comments_subscribe_' . self::$hash ] == $post->ID )
			$comments_checked = ' checked="checked"';

		if ( isset( $_COOKIE[ 'jetpack_blog_subscribe_' . self::$hash ] ) )
			$blog_checked = ' checked="checked"';

		// Some themes call this function, don't show the checkbox again
		remove_action( 'comment_form', 'subscription_comment_form' );

		// Check if Mark Jaquith's Subscribe to Comments plugin is active - if so, suppress Jetpack checkbox

		$str = '';

		if ( FALSE === has_filter( 'comment_form', 'show_subscription_checkbox' ) && 1 == get_option( 'stc_enabled', 1 ) && empty( $post->post_password ) && 'post' == get_post_type() ) {
			// Subscribe to comments checkbox
			$str .= '
<input type="checkbox" name="subscribe_comments" id="subscribe_comments" value="subscribe" style="width: auto; -moz-appearance: checkbox; -webkit-appearance: checkbox;"' . $comments_checked . ' /> ';
			$comment_sub_text = __( 'Notify me of follow-up comments by email.', 'jetpack' );
			$str .=	'' . esc_html(
				/**
				 * Filter the Subscribe to comments text appearing below the comment form.
				 *
				 * @module subscriptions
				 *
				 * @since 3.4.0
				 *
				 * @param string $comment_sub_text Subscribe to comments text.
				 */
				apply_filters( 'jetpack_subscribe_comment_label', $comment_sub_text )
			) . '';
			$str .= '
';
		}

		if ( 1 == get_option( 'stb_enabled', 1 ) ) {
			// Subscribe to blog checkbox
			$str .= '
<input type="checkbox" name="subscribe_blog" id="subscribe_blog" value="subscribe" style="width: auto; -moz-appearance: checkbox; -webkit-appearance: checkbox;"' . $blog_checked . ' /> ';
			$blog_sub_text = __( 'Notify me of new posts by email.', 'jetpack' );
			$str .=	'' . esc_html(
				/**
				 * Filter the Subscribe to blog text appearing below the comment form.
				 *
				 * @module subscriptions
				 *
				 * @since 3.4.0
				 *
				 * @param string $comment_sub_text Subscribe to blog text.
				 */
				apply_filters( 'jetpack_subscribe_blog_label', $blog_sub_text )
			) . '';
			$str .= '
';
		}

		/**
		 * Filter the output of the subscription options appearing below the comment form.
		 *
		 * @module subscriptions
		 *
		 * @since 1.2.0
		 *
		 * @param string $str Comment Subscription form HTML output.
		 */
		echo apply_filters( 'jetpack_comment_subscription_form', $str );
	}

	/**
	 * Jetpack_Subscriptions::comment_subscribe_init()
	 *
	 * When a user checks the comment subscribe box and submits a comment, subscribe them to the comment thread.
	 */
	function comment_subscribe_submit( $comment_id, $approved ) {
		if ( 'spam' === $approved ) {
			return;
		}

		// Set cookies for this post/comment
		$this->set_cookies( isset( $_REQUEST['subscribe_comments'] ), isset( $_REQUEST['subscribe_blog'] ) );

		if ( !isset( $_REQUEST['subscribe_comments'] ) && !isset( $_REQUEST['subscribe_blog'] ) )
			return;

		$comment  = get_comment( $comment_id );
		$post_ids = array();

		if ( isset( $_REQUEST['subscribe_comments'] ) )
			$post_ids[] = $comment->comment_post_ID;

		if ( isset( $_REQUEST['subscribe_blog'] ) )
			$post_ids[] = 0;

		Jetpack_Subscriptions::subscribe(
									$comment->comment_author_email,
									$post_ids,
									true,
									array(
										'source'         => 'comment-form',
										'widget-in-use'  => is_active_widget( false, false, 'blog_subscription', true ) ? 'yes' : 'no',
										'comment_status' => $approved,
										'server_data'    => $_SERVER,
									)
		);
	}

	/**
	 * Jetpack_Subscriptions::set_cookies()
	 *
	 * Set a cookie to save state on the comment and post subscription checkboxes.
	 */
	function set_cookies( $comments = true, $posts = true ) {
		global $post;

		/** This filter is already documented in core/wp-includes/comment-functions.php */
		$cookie_lifetime = apply_filters( 'comment_cookie_lifetime',       30000000 );
		/**
		 * Filter the Jetpack Comment cookie path.
		 *
		 * @module subscriptions
		 *
		 * @since 2.5.0
		 *
		 * @param string COOKIEPATH Cookie path.
		 */
		$cookie_path     = apply_filters( 'jetpack_comment_cookie_path',   COOKIEPATH );
		/**
		 * Filter the Jetpack Comment cookie domain.
		 *
		 * @module subscriptions
		 *
		 * @since 2.5.0
		 *
		 * @param string COOKIE_DOMAIN Cookie domain.
		 */
		$cookie_domain   = apply_filters( 'jetpack_comment_cookie_domain', COOKIE_DOMAIN );

		if ( $comments )
			setcookie( 'jetpack_comments_subscribe_' . self::$hash, $post->ID, time() + $cookie_lifetime, $cookie_path, $cookie_domain );
		else
			setcookie( 'jetpack_comments_subscribe_' . self::$hash, '', time() - 3600, $cookie_path, $cookie_domain );

		if ( $posts )
			setcookie( 'jetpack_blog_subscribe_' . self::$hash, 1, time() + $cookie_lifetime, $cookie_path, $cookie_domain );
		else
			setcookie( 'jetpack_blog_subscribe_' . self::$hash, '', time() - 3600, $cookie_path, $cookie_domain );
	}
}

Jetpack_Subscriptions::init();

/***
 * Blog Subscription Widget
 */

class Jetpack_Subscriptions_Widget extends WP_Widget {
	function __construct() {
		$widget_ops  = array( 'classname' => 'jetpack_subscription_widget', 'description' => __( 'Add an email signup form to allow people to subscribe to your blog.', 'jetpack' ) );
		$control_ops = array( 'width' => 300 );

		parent::__construct(
			'blog_subscription',
			/** This filter is documented in modules/widgets/facebook-likebox.php */
			apply_filters( 'jetpack_widget_name', __( 'Blog Subscriptions', 'jetpack' ) ),
			$widget_ops,
			$control_ops
		);
	}

	function widget( $args, $instance ) {
		if (
			( ! defined( 'IS_WPCOM' ) || ! IS_WPCOM ) &&
			/** This filter is already documented in modules/contact-form/grunion-contact-form.php */
			false === apply_filters( 'jetpack_auto_fill_logged_in_user', false )
		) {
			$subscribe_email = '';
		} else {
			global $current_user;
			if ( ! empty( $current_user->user_email ) ) {
				$subscribe_email = esc_attr( $current_user->user_email );
			} else {
				$subscribe_email = '';
			}
		}

		$source                 = 'widget';
		$instance            	= wp_parse_args( (array) $instance, $this->defaults() );
		$subscribe_text      	= isset( $instance['subscribe_text'] )        ? stripslashes( $instance['subscribe_text'] )        : '';
		$subscribe_placeholder 	= isset( $instance['subscribe_placeholder'] ) ? stripslashes( $instance['subscribe_placeholder'] ) : '';
		$subscribe_button    	= isset( $instance['subscribe_button'] )      ? stripslashes( $instance['subscribe_button'] )      : '';
		$success_message    	= isset( $instance['success_message'] )       ? stripslashes( $instance['success_message'] )      : '';
		$widget_id              = esc_attr( !empty( $args['widget_id'] )      ? esc_attr( $args['widget_id'] ) : mt_rand( 450, 550 ) );

		$show_subscribers_total = (bool) $instance['show_subscribers_total'];
		$subscribers_total      = $this->fetch_subscriber_count(); // Only used for the shortcode [total-subscribers]

		// Give the input element a unique ID
		/**
		 * Filter the subscription form's ID prefix.
		 *
		 * @module subscriptions
		 *
		 * @since 2.7.0
		 *
		 * @param string subscribe-field Subscription form field prefix.
		 * @param int $widget_id Widget ID.
		 */
		$subscribe_field_id = apply_filters( 'subscribe_field_id', 'subscribe-field', $widget_id );

		// Enqueue the form's CSS
		wp_register_style( 'jetpack-subscriptions', plugins_url( 'subscriptions/subscriptions.css', __FILE__ ) );
		wp_enqueue_style( 'jetpack-subscriptions' );

		// Display the subscription form
		echo $args['before_widget'];

		// Only show the title if there actually is a title
		if( ! empty( $instance['title'] ) ) {
			echo $args['before_title'] . esc_attr( $instance['title'] ) . $args['after_title'] . "\n";
		}

		$referer = set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] );

		// Display any errors
		if ( isset( $_GET['subscribe'] ) ) :
			switch ( $_GET['subscribe'] ) :
				case 'invalid_email' : ?>

<?php esc_html_e( 'The email you entered was invalid. Please check and try again.', 'jetpack' ); ?>

				<?php break;
				case 'opted_out' : ?>

<?php printf( __( 'The email address has opted out of subscription emails.
 You can manage your preferences at subscribe.wordpress.com', 'jetpack' ),
							'https://subscribe.wordpress.com/',
							__( 'Manage your email preferences.', 'jetpack' )
						); ?>
				<?php break;
				case 'already' : ?>

<?php esc_html_e( 'You have already subscribed to this site. Please check your inbox.', 'jetpack' ); ?>

				<?php break;
				case 'success' : ?>

<?php echo wpautop( str_replace( '[total-subscribers]', number_format_i18n( $subscribers_total['value'] ), $success_message ) ); ?>

					<?php break;
				default : ?>

<?php esc_html_e( 'There was an error when subscribing. Please try again.', 'jetpack' ); ?>

				<?php break;
			endswitch;
		endif;

		// Display a subscribe form
		if ( isset( $_GET['subscribe'] ) && 'success' == $_GET['subscribe'] ) { ?>
			<?php
		} else { ?>
			<form action="#" method="post" accept-charset="utf-8" id="subscribe-blog-<?php echo $widget_id; ?>">
				<?php
				if ( ! isset ( $_GET['subscribe'] ) || 'success' != $_GET['subscribe'] ) {
					?>
<?php echo wpautop( str_replace( '[total-subscribers]', number_format_i18n( $subscribers_total['value'] ), $subscribe_text ) ); ?>
<?php
				}

				if ( $show_subscribers_total && 0 < $subscribers_total['value'] ) {
					echo wpautop( sprintf( _n( 'Join %s other subscriber', 'Join %s other subscribers', $subscribers_total['value'], 'jetpack' ), number_format_i18n( $subscribers_total['value'] ) ) );
				}
				if ( ! isset ( $_GET['subscribe'] ) || 'success' != $_GET['subscribe'] ) { ?>

						<label id="jetpack-subscribe-label" for="<?php echo esc_attr( $subscribe_field_id ) . '-' . esc_attr( $widget_id ); ?>">
							<?php echo !empty( $subscribe_placeholder ) ? esc_html( $subscribe_placeholder ) : esc_html__( 'Email Address:', 'jetpack' ); ?>

						<input type="email" name="email" required="required" class="required" value="<?php echo esc_attr( $subscribe_email ); ?>" id="<?php echo esc_attr( $subscribe_field_id ) . '-' . esc_attr( $widget_id ); ?>" placeholder="<?php echo esc_attr( $subscribe_placeholder ); ?>" />

						<input type="hidden" name="action" value="subscribe" />
						<input type="hidden" name="source" value="<?php echo esc_url( $referer ); ?>" />
						<input type="hidden" name="sub-type" value="<?php echo esc_attr( $source ); ?>" />
						<input type="hidden" name="redirect_fragment" value="<?php echo $widget_id; ?>" />
						<?php
							if ( is_user_logged_in() ) {
								wp_nonce_field( 'blogsub_subscribe_'. get_current_blog_id(), '_wpnonce', false );
							}
						?>
						<input type="submit" value="<?php echo esc_attr( $subscribe_button ); ?>" name="jetpack_subscriptions_widget" />

				<?php }?>
			</form>

		<?php } ?>
		<?php

		echo "\n" . $args['after_widget'];
	}

	function increment_subscriber_count( $current_subs_array = array() ) {
		$current_subs_array['value']++;

		set_transient( 'wpcom_subscribers_total', $current_subs_array, 3600 ); // try to cache the result for at least 1 hour

		return $current_subs_array;
	}

	function fetch_subscriber_count() {
		$subs_count = get_transient( 'wpcom_subscribers_total' );

		if ( FALSE === $subs_count || 'failed' == $subs_count['status'] ) {
			Jetpack:: load_xml_rpc_client();

			$xml = new Jetpack_IXR_Client( array( 'user_id' => JETPACK_MASTER_USER, ) );

			$xml->query( 'jetpack.fetchSubscriberCount' );

			if ( $xml->isError() ) { // if we get an error from .com, set the status to failed so that we will try again next time the data is requested
				$subs_count = array(
					'status'  => 'failed',
					'code'    => $xml->getErrorCode(),
					'message' => $xml->getErrorMessage(),
					'value'	  => ( isset( $subs_count['value'] ) ) ? $subs_count['value'] : 0,
				);
			} else {
				$subs_count = array(
					'status' => 'success',
					'value'  => $xml->getResponse(),
				);
			}

			set_transient( 'wpcom_subscribers_total', $subs_count, 3600 ); // try to cache the result for at least 1 hour
		}

		return $subs_count;
	}

	function update( $new_instance, $old_instance ) {
		$instance = $old_instance;

		$instance['title']					= wp_kses( stripslashes( $new_instance['title'] ), array() );
		$instance['subscribe_text']			= wp_filter_post_kses( stripslashes( $new_instance['subscribe_text'] ) );
		$instance['subscribe_placeholder']	= wp_kses( stripslashes( $new_instance['subscribe_placeholder'] ), array() );
		$instance['subscribe_button']		= wp_kses( stripslashes( $new_instance['subscribe_button'] ), array() );
		$instance['success_message']		= wp_kses( stripslashes( $new_instance['success_message'] ), array() );
		$instance['show_subscribers_total']	= isset( $new_instance['show_subscribers_total'] ) && $new_instance['show_subscribers_total'];

		return $instance;
	}

	public static function defaults() {
		return array(
			'title'               	 => esc_html__( 'Subscribe to Blog via Email', 'jetpack' ),
			'subscribe_text'      	 => esc_html__( 'Enter your email address to subscribe to this blog and receive notifications of new posts by email.', 'jetpack' ),
			'subscribe_placeholder'	 => esc_html__( 'Email Address', 'jetpack' ),
			'subscribe_button'    	 => esc_html__( 'Subscribe', 'jetpack' ),
			'success_message'    	 => esc_html__( 'Success! An email was just sent to confirm your subscription. Please find the email now and click activate to start subscribing.', 'jetpack' ),
			'show_subscribers_total' => true,
		);
	}

	function form( $instance ) {
		$instance = wp_parse_args( (array) $instance, $this->defaults() );

		$title               	= stripslashes( $instance['title'] );
		$subscribe_text      	= stripslashes( $instance['subscribe_text'] );
		$subscribe_placeholder 	= stripslashes( $instance['subscribe_placeholder'] );
		$subscribe_button    	= stripslashes( $instance['subscribe_button'] );
		$success_message		= stripslashes( $instance['success_message']);
		$show_subscribers_total = checked( $instance['show_subscribers_total'], true, false );

		$subs_fetch = $this->fetch_subscriber_count();

		if ( 'failed' == $subs_fetch['status'] ) {
			printf( '

' . __( '%s: %s', 'jetpack' ) . '

', esc_html( $subs_fetch['code'] ), esc_html( $subs_fetch['message'] ) );
		}
		$subscribers_total = number_format_i18n( $subs_fetch['value'] );
?>

	<label for="<?php echo $this->get_field_id( 'title' ); ?>">
		<?php _e( 'Widget title:', 'jetpack' ); ?>
		<input class="widefat" id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" type="text" value="<?php echo esc_attr( $title ); ?>" />

	<label for="<?php echo $this->get_field_id( 'subscribe_text' ); ?>">
		<?php _e( 'Optional text to display to your readers:', 'jetpack' ); ?>
		<textarea style="width: 95%" id="<?php echo $this->get_field_id( 'subscribe_text' ); ?>" name="<?php echo $this->get_field_name( 'subscribe_text' ); ?>" type="text"><?php echo esc_html( $subscribe_text ); ?></textarea>

	<label for="<?php echo $this->get_field_id( 'subscribe_placeholder' ); ?>">
		<?php esc_html_e( 'Subscribe Placeholder:', 'jetpack' ); ?>
		<input class="widefat" id="<?php echo $this->get_field_id( 'subscribe_placeholder' ); ?>" name="<?php echo $this->get_field_name( 'subscribe_placeholder' ); ?>" type="text" value="<?php echo esc_attr( $subscribe_placeholder ); ?>" />

	<label for="<?php echo $this->get_field_id( 'subscribe_button' ); ?>">
		<?php _e( 'Subscribe Button:', 'jetpack' ); ?>
		<input class="widefat" id="<?php echo $this->get_field_id( 'subscribe_button' ); ?>" name="<?php echo $this->get_field_name( 'subscribe_button' ); ?>" type="text" value="<?php echo esc_attr( $subscribe_button ); ?>" />

	<label for="<?php echo $this->get_field_id( 'success_message' ); ?>">
		<?php _e( 'Success Message Text:', 'jetpack' ); ?>
		<textarea style="width: 95%" id="<?php echo $this->get_field_id( 'success_message' ); ?>" name="<?php echo $this->get_field_name( 'success_message' ); ?>" type="text"><?php echo esc_html( $success_message ); ?></textarea>

	<label for="<?php echo $this->get_field_id( 'show_subscribers_total' ); ?>">
		<input type="checkbox" id="<?php echo $this->get_field_id( 'show_subscribers_total' ); ?>" name="<?php echo $this->get_field_name( 'show_subscribers_total' ); ?>" value="1"<?php echo $show_subscribers_total; ?> />
		<?php echo esc_html( sprintf( _n( 'Show total number of subscribers? (%s subscriber)', 'Show total number of subscribers? (%s subscribers)', $subscribers_total, 'jetpack' ), $subscribers_total ) ); ?>

<?php
	}
}

add_shortcode( 'jetpack_subscription_form', 'jetpack_do_subscription_form' );

function jetpack_do_subscription_form( $instance ) {
	$instance['show_subscribers_total'] = empty( $instance['show_subscribers_total'] ) ? false : true;
	$instance = shortcode_atts( Jetpack_Subscriptions_Widget::defaults(), $instance, 'jetpack_subscription_form' );
	$args = array(
		'before_widget' => sprintf( '
', 'jetpack_subscription_widget' ),
	);
	ob_start();
	the_widget( 'Jetpack_Subscriptions_Widget', $instance, $args );
	$output = ob_get_clean();
	return $output;
}


text:
package index

import (
	"bytes"
	"encoding/json"
	"fmt"

	"github.com/blevesearch/bleve/document"
	"github.com/blevesearch/bleve/index/store"
)

var ErrorUnknownStorageType = fmt.Errorf("unknown storage type")

type Index interface {
	Open() error
	Close() error

	Update(doc *document.Document) error
	Delete(id string) error
	Batch(batch *Batch) error

	SetInternal(key, val []byte) error
	DeleteInternal(key []byte) error

	// Reader returns a low-level accessor on the index data. Close it to
	// release associated resources.
	Reader() (IndexReader, error)

	Stats() json.Marshaler
	StatsMap() map[string]interface{}

	Analyze(d *document.Document) *AnalysisResult

	Advanced() (store.KVStore, error)
}

type DocumentFieldTermVisitor func(field string, term []byte)

type IndexReader interface {
	TermFieldReader(term []byte, field string, includeFreq, includeNorm, includeTermVectors bool) (TermFieldReader, error)

	// DocIDReader returns an iterator over all doc ids
	// The caller must close returned instance to release associated resources.
	DocIDReaderAll() (DocIDReader, error)

	DocIDReaderOnly(ids []string) (DocIDReader, error)

	FieldDict(field string) (FieldDict, error)

	// FieldDictRange is currently defined to include the start and end terms
	FieldDictRange(field string, startTerm []byte, endTerm []byte) (FieldDict, error)
	FieldDictPrefix(field string, termPrefix []byte) (FieldDict, error)

	Document(id string) (*document.Document, error)
	DocumentVisitFieldTerms(id IndexInternalID, fields []string, visitor DocumentFieldTermVisitor) error

	Fields() ([]string, error)

	GetInternal(key []byte) ([]byte, error)

	DocCount() (uint64, error)

	ExternalID(id IndexInternalID) (string, error)
	InternalID(id string) (IndexInternalID, error)

	DumpAll() chan interface{}
	DumpDoc(id string) chan interface{}
	DumpFields() chan interface{}

	Close() error
}

// FieldTerms contains the terms used by a document, keyed by field
type FieldTerms map[string][]string

// FieldsNotYetCached returns a list of fields not yet cached out of a larger list of fields
func (f FieldTerms) FieldsNotYetCached(fields []string) []string {
	rv := make([]string, 0, len(fields))
	for _, field := range fields {
		if _, ok := f[field]; !ok {
			rv = append(rv, field)
		}
	}
	return rv
}

// Merge will combine two FieldTerms
// it assumes that the terms lists are complete (thus do not need to be merged)
// field terms from the other list always replace the ones in the receiver
func (f FieldTerms) Merge(other FieldTerms) {
	for field, terms := range other {
		f[field] = terms
	}
}

type TermFieldVector struct {
	Field          string
	ArrayPositions []uint64
	Pos            uint64
	Start          uint64
	End            uint64
}

// IndexInternalID is an opaque document identifier interal to the index impl
type IndexInternalID []byte

func (id IndexInternalID) Equals(other IndexInternalID) bool {
	return id.Compare(other) == 0
}

func (id IndexInternalID) Compare(other IndexInternalID) int {
	return bytes.Compare(id, other)
}

type TermFieldDoc struct {
	Term    string
	ID      IndexInternalID
	Freq    uint64
	Norm    float64
	Vectors []*TermFieldVector
}

// Reset allows an already allocated TermFieldDoc to be reused
func (tfd *TermFieldDoc) Reset() *TermFieldDoc {
	// remember the []byte used for the ID
	id := tfd.ID
	// idiom to copy over from empty TermFieldDoc (0 allocations)
	*tfd = TermFieldDoc{}
	// reuse the []byte already allocated (and reset len to 0)
	tfd.ID = id[:0]
	return tfd
}

// TermFieldReader is the interface exposing the enumeration of documents
// containing a given term in a given field. Documents are returned in byte
// lexicographic order over their identifiers.
type TermFieldReader interface {
	// Next returns the next document containing the term in this field, or nil
	// when it reaches the end of the enumeration.  The preAlloced TermFieldDoc
	// is optional, and when non-nil, will be used instead of allocating memory.
	Next(preAlloced *TermFieldDoc) (*TermFieldDoc, error)

	// Advance resets the enumeration at specified document or its immediate
	// follower.
	Advance(ID IndexInternalID, preAlloced *TermFieldDoc) (*TermFieldDoc, error)

	// Count returns the number of documents contains the term in this field.
	Count() uint64
	Close() error
}

type DictEntry struct {
	Term  string
	Count uint64
}

type FieldDict interface {
	Next() (*DictEntry, error)
	Close() error
}

// DocIDReader is the interface exposing enumeration of documents identifiers.
// Close the reader to release associated resources.
type DocIDReader interface {
	// Next returns the next document internal identifier in the natural
	// index order, nil when the end of the sequence is reached.
	Next() (IndexInternalID, error)

	// Advance resets the iteration to the first internal identifier greater than
	// or equal to ID. If ID is smaller than the start of the range, the iteration
	// will start there instead. If ID is greater than or equal to the end of
	// the range, Next() call will return io.EOF.
	Advance(ID IndexInternalID) (IndexInternalID, error)
	Close() error
}

type Batch struct {
	IndexOps    map[string]*document.Document
	InternalOps map[string][]byte
}

func NewBatch() *Batch {
	return &Batch{
		IndexOps:    make(map[string]*document.Document),
		InternalOps: make(map[string][]byte),
	}
}

func (b *Batch) Update(doc *document.Document) {
	b.IndexOps[doc.ID] = doc
}

func (b *Batch) Delete(id string) {
	b.IndexOps[id] = nil
}

func (b *Batch) SetInternal(key, val []byte) {
	b.InternalOps[string(key)] = val
}

func (b *Batch) DeleteInternal(key []byte) {
	b.InternalOps[string(key)] = nil
}

func (b *Batch) String() string {
	rv := fmt.Sprintf("Batch (%d ops, %d internal ops)\n", len(b.IndexOps), len(b.InternalOps))
	for k, v := range b.IndexOps {
		if v != nil {
			rv += fmt.Sprintf("\tINDEX - '%s'\n", k)
		} else {
			rv += fmt.Sprintf("\tDELETE - '%s'\n", k)
		}
	}
	for k, v := range b.InternalOps {
		if v != nil {
			rv += fmt.Sprintf("\tSET INTERNAL - '%s'\n", k)
		} else {
			rv += fmt.Sprintf("\tDELETE INTERNAL - '%s'\n", k)
		}
	}
	return rv
}

func (b *Batch) Reset() {
	b.IndexOps = make(map[string]*document.Document)
	b.InternalOps = make(map[string][]byte)
}

redpajama_set_name: RedPajamaGithub


text:
package com.klatunetworks.webhooks.core;

public class RetryFunctionBuilderTest {

}


text:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;

namespace System.IO.Packaging
{
    /// <summary>
    /// This class is used to get an enumerator for the Parts in a container.
    /// This is a part of the MMCF Packaging Layer APIs
    /// </summary>
    public class PackagePartCollection : IEnumerable<PackagePart>
    {
        #region Public Methods

        /// <summary>
        /// Returns an enumerator over all the Parts in the container
        /// </summary>
        /// <returns></returns>
        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        /// <summary>
        /// Returns an enumerator over all the Parts in the container
        /// </summary>
        /// <returns></returns>
        IEnumerator<PackagePart> IEnumerable<PackagePart>.GetEnumerator()
        {
            return GetEnumerator();
        }

        /// <summary>
        /// Returns an enumerator over all the Parts in the Container
        /// </summary>
        /// <returns></returns>
        public IEnumerator<PackagePart> GetEnumerator()
        {
            //The Dictionary.Values property always returns a collection, even if empty. It never returns a null.
            return _partList.Values.GetEnumerator();
        }
        #endregion Public Methods

        #region Internal Constructor

        internal PackagePartCollection(SortedList<PackUriHelper.ValidatedPartUri, PackagePart> partList)
        {
            Debug.Assert(partList != null, "partDictionary parameter cannot be null");
            _partList = partList;
        }

        #endregion Internal Constructor

        #region Private Members

        private readonly SortedList<PackUriHelper.ValidatedPartUri, PackagePart> _partList;

        #endregion Private Members
    }
}


text:
<!DOCTYPE html>

    <title>Remove Item Example</title>
    <link href="removeItem.css" rel="stylesheet" />
    <meta name="viewport"
          content="user-scalable=no,
          initial-scale=1,
          maximum-scale=1,
          minimum-scale=1,
          width=device-width,
          height=device-height,
          target-densitydpi=device-dpi" />

    <div virtual-for='[
         { "name" : "Matrix" },
         { "name" : "This the End" },
         { "name" : "Ghostbusters" },
         { "name" : "300" },
         { "name" : "Top Five" },
         { "name" : "Wedding Crashers" },
         { "name" : "Mission Impossible 2" },
         { "name" : "Despicable Me" },
         { "name" : "Her" },
         { "name" : "Argo" },
         { "name" : "The Two" },
         { "name" : "Pain and No Gain" },
         { "name" : "The Wedding Ringer" },
         { "name" : "The Town" },
         { "name" : "Hangover" },
         { "name" : "Terminator" },
         { "name" : "Avengers" },
         { "name" : "The Transporter" },
         { "name" : "X-Men 3" },
         { "name" : "Fast 7" },
         { "name" : "Coming To America" }]'
         virtual-for-of="movie"
         virtual-for-name="MyList">

{{ movie.name }}


text:
package gigigo.com.orchextra.data.datasources.db.model.mappers;

import com.gigigo.ggglib.mappers.Mapper;
import com.gigigo.ggglib.mappers.MapperUtils;
import gigigo.com.orchextra.data.datasources.db.model.KeyWordRealm;
import io.realm.RealmList;
import java.util.ArrayList;
import java.util.List;

public class KeyWordRealmMapper implements Mapper<String, KeyWordRealm> {

  @Override public KeyWordRealm modelToExternalClass(String s) {
    KeyWordRealm keyWordRealm = new KeyWordRealm(s);
    return keyWordRealm;
  }

  @Override public String externalClassToModel(KeyWordRealm keyWordRealm) {
    return keyWordRealm.getKeyword();
  }

  public RealmList<KeyWordRealm> stringKeyWordsToRealmList(List<String> keywords) {

    RealmList<KeyWordRealm> keyWordRealms = new RealmList<>();
    if (keywords == null) {
      return keyWordRealms;
    }

    for (String keyword : keywords) {
      keyWordRealms.add(MapperUtils.checkNullDataRequest(this, keyword));
    }
    return keyWordRealms;
  }

  public List<String> realmKeyWordsToStringList(RealmList<KeyWordRealm> keyWordRealms) {

    List<String> keyWords = new ArrayList<>();
    if (keyWordRealms == null) {
      return keyWords;
    }

    for (KeyWordRealm keyWordRealm : keyWordRealms) {
      keyWords.add(MapperUtils.checkNullDataResponse(this, keyWordRealm));
    }
    return keyWords;
  }
}


text:
//
// The following methods are ONLY for use by _ASDisplayLayer, _ASDisplayView, and ASDisplayNode.
// These methods must never be called or overridden by other classes.
//

#import "_ASDisplayLayer.h"
#import "_AS-objc-internal.h"
#import "ASDisplayNodeExtraIvars.h"
#import "ASDisplayNode.h"
#import "ASSentinel.h"
#import "ASThread.h"
#import "ASLayoutOptions.h"

BOOL ASDisplayNodeSubclassOverridesSelector(Class subclass, SEL selector);
void ASDisplayNodePerformBlockOnMainThread(void (^block)());
void ASDisplayNodeRespectThreadAffinityOfNode(ASDisplayNode *node, void (^block)());

typedef NS_OPTIONS(NSUInteger, ASDisplayNodeMethodOverrides) {
  ASDisplayNodeMethodOverrideNone = 0,
  ASDisplayNodeMethodOverrideTouchesBegan          = 1 << 0,
  ASDisplayNodeMethodOverrideTouchesCancelled      = 1 << 1,
  ASDisplayNodeMethodOverrideTouchesEnded          = 1 << 2,
  ASDisplayNodeMethodOverrideTouchesMoved          = 1 << 3,
  ASDisplayNodeMethodOverrideLayoutSpecThatFits    = 1 << 4
};

@class _ASPendingState;

// Allow 2^n increments of begin disabling hierarchy notifications
#define VISIBILITY_NOTIFICATIONS_DISABLED_BITS 4

#define TIME_DISPLAYNODE_OPS (DEBUG || PROFILE)

@interface ASDisplayNode () <_ASDisplayLayerDelegate>
{
@protected
  // Protects access to _view, _layer, _pendingViewState, _subnodes, _supernode, and other properties which are accessed from multiple threads.
  ASDN::RecursiveMutex _propertyLock;

  ASDisplayNode * __weak _supernode;

  ASSentinel *_displaySentinel;
  ASSentinel *_replaceAsyncSentinel;

  // This is the desired contentsScale, not the scale at which the layer's contents should be displayed
  CGFloat _contentsScaleForDisplay;

  ASLayout *_layout;
  ASSizeRange _constrainedSize;
  UIEdgeInsets _hitTestSlop;
  NSMutableArray *_subnodes;

  ASDisplayNodeViewBlock _viewBlock;
  ASDisplayNodeLayerBlock _layerBlock;
  ASDisplayNodeDidLoadBlock _nodeLoadedBlock;
  Class _viewClass;
  Class _layerClass;
  UIView *_view;
  CALayer *_layer;

  UIImage *_placeholderImage;
  CALayer *_placeholderLayer;

  // keeps track of nodes/subnodes that have not finished display, used with placeholders
  NSMutableSet *_pendingDisplayNodes;

  _ASPendingState *_pendingViewState;

  struct ASDisplayNodeFlags {
    // public properties
    unsigned synchronous:1;
    unsigned layerBacked:1;
    unsigned displaysAsynchronously:1;
    unsigned shouldRasterizeDescendants:1;
    unsigned shouldBypassEnsureDisplay:1;
    unsigned displaySuspended:1;

    // whether custom drawing is enabled
    unsigned implementsDrawRect:1;
    unsigned implementsImageDisplay:1;
    unsigned implementsDrawParameters:1;

    // internal state
    unsigned isMeasured:1;
    unsigned isEnteringHierarchy:1;
    unsigned isExitingHierarchy:1;
    unsigned isInHierarchy:1;
    unsigned visibilityNotificationsDisabled:VISIBILITY_NOTIFICATIONS_DISABLED_BITS;
  } _flags;

  ASDisplayNodeExtraIvars _extra;

#if TIME_DISPLAYNODE_OPS
@public
  NSTimeInterval _debugTimeToCreateView;
  NSTimeInterval _debugTimeToApplyPendingState;
  NSTimeInterval _debugTimeToAddSubnodeViews;
  NSTimeInterval _debugTimeForDidLoad;
#endif

}

// The _ASDisplayLayer backing the node, if any.
@property (nonatomic, readonly, retain) _ASDisplayLayer *asyncLayer;

// Creates a pendingViewState if one doesn't exist. Allows setting view properties on a bg thread before there is a view.
@property (atomic, retain, readonly) _ASPendingState *pendingViewState;

// Bitmask to check which methods an object overrides.
@property (nonatomic, assign, readonly) ASDisplayNodeMethodOverrides methodOverrides;

// Swizzle to extend the builtin functionality with custom logic
- (BOOL)__shouldLoadViewOrLayer;
- (BOOL)__shouldSize;
- (void)__exitedHierarchy;

// Core implementation of -measureWithSizeRange:. Must be called with _propertyLock held.
- (ASLayout *)__measureWithSizeRange:(ASSizeRange)constrainedSize;

- (void)__setNeedsLayout;
- (void)__layout;
- (void)__setSupernode:(ASDisplayNode *)supernode;

// Changed before calling willEnterHierarchy / didExitHierarchy.
@property (nonatomic, readwrite, assign, getter = isInHierarchy) BOOL inHierarchy;

// Private API for helper functions / unit tests.  Use ASDisplayNodeDisableHierarchyNotifications() to control this.
- (BOOL)__visibilityNotificationsDisabled;
- (void)__incrementVisibilityNotificationsDisabled;
- (void)__decrementVisibilityNotificationsDisabled;

// Call willEnterHierarchy if necessary and set inHierarchy = YES if visibility notifications are enabled on all of its parents
- (void)__enterHierarchy;
// Call didExitHierarchy if necessary and set inHierarchy = NO if visibility notifications are enabled on all of its parents
- (void)__exitHierarchy;

// Display the node's view/layer immediately on the current thread, bypassing the background thread rendering. Will be deprecated.
- (void)displayImmediately;

// Returns the ancestor node that rasterizes descendants, or nil if none.
- (ASDisplayNode *)__rasterizedContainerNode;

// Alternative initialiser for backing with a custom view class.  Supports asynchronous display with _ASDisplayView subclasses.
- (id)initWithViewClass:(Class)viewClass;

// Alternative initialiser for backing with a custom layer class.  Supports asynchronous display with _ASDisplayLayer subclasses.
- (id)initWithLayerClass:(Class)layerClass;

@property (nonatomic, assign) CGFloat contentsScaleForDisplay;

@end

@interface UIView (ASDisplayNodeInternal)
@property (nonatomic, assign, readwrite) ASDisplayNode *asyncdisplaykit_node;
@end

@interface CALayer (ASDisplayNodeInternal)
@property (nonatomic, assign, readwrite) ASDisplayNode *asyncdisplaykit_node;
@end


text:
  Abos est
       un village
       situé dans le département des Pyrénées-Atlantiques en Aquitaine. Elle totalisait 467 habitants en 2008.

La commune compte quelques  équipements sportifs, elle dispose, entre autres, de une boucle de randonnée.

À coté de Abos sont localisées les villes de
Luc-Armau située à 2 km, 106 habitants,
Momy située à 2 km, 130 habitants,
Peyrelongue-Abos localisée à 1 km, 132 habitants,
Samsons-Lion à 2 km, 71 habitants,
Anoye localisée à 4 km, 144 habitants,
Maspie-Lalonquère-Juillacq à 4 km, 252 habitants,
 entre autres. De plus, Abos est située à seulement 26 km de Pau.

Si vous envisagez de demenager à Abos, vous pourrez facilement trouver une maison à vendre.

Le parc de logements, à Abos, se décomposait en 2011 en deux appartements et 218 maisons soit
 un marché relativement équilibré.


text:
SYNONYM

#### According to
The Catalogue of Life, 3rd January 2011

#### Published in
J. Bombay Nat. Hist. Soc. 4:123. 1889

#### Original name
null

### Remarks
null


text:
'use strict';

var request = require('request').defaults({
    headers: { 'User-Agent': 'nodejs/0.4.0' } }),
    _Promise = require('bluebird');

var rootPath = '/text/weblm/v1.0/';
var workBreakPath = '/breakIntoWords';
var listModelsPath = '/models';
var generateNextWordsPath = '/generateNextWords';
var calculateJointProbPath = '/calculateJointProbability';
var calculateCondProbPath = '/calculateConditionalProbability';

/**
 * @namespace
 * @memberof Client
 */
var weblm = function weblm(key, host) {
    /**
     * @private
     */
    function _return(error, response, resolve, reject) {
        if (error) {
            return reject(error);
        }

        if (response.statusCode !== 200) {
            reject(response.body);
        }

        return resolve(response.body.error || response.body);
    }

    /**
     * List available language models for the service currently.
     *
     * @return {Promise} - Promise resolving with the resulting JSON
     */
    function listModels() {
        return new _Promise(function (resolve, reject) {
            request({
                uri: host + rootPath + listModelsPath,
                json: true,
                headers: {
                    'Ocp-Apim-Subscription-Key': key
                }
            }, function (error, response) {
                return _return(error, response, resolve, reject);
            });
        });
    }

    /**
     * (Private) Helper method for processing text.
     *
     * @private
     * @param  {string} url                    - Url of the API
     * @param  {string} model                  - Name of model. Currently one of title/anchor/query/body
     * @param  {Object} qs                     - Method-specific queryString options
     * @param  {Object} body                   - Method-specific body, optional
     * @param  {Object} options                - Options object
     * @param  {Number} options.order          - Optional N-gram order. Default is 5
     * @param  {Number} options.maxCandidates  - Optional maximum candidate count. Default is 5
     * @return {Promise}                       - Promise resolving with the resulting JSON
     */
    function _processWords(url, model, qs, body, options) {
        qs.model = model;
        if (options && options.order) {
            qs.order = options.order;
        }
        if (options && options.maxCandidates) {
            qs.maxNumOfCandidatesReturned = options.maxCandidates;
        }
        return new _Promise(function (resolve, reject) {
            request.post({
                uri: host + rootPath + url,
                headers: {
                    'Ocp-Apim-Subscription-Key': key,
                    'Content-Type': 'application/json'
                },
                qs: qs,
                json: true,
                body: body
            }, function (error, response) {
                return _return(error, response, resolve, reject);
            });
        });
    }

    /**
     * Breaks text in to consituent words
     *
     * @param  {string} model                  - Name of model. Currently one of title/anchor/query/body
     * @param  {string} text                   - Text to break.  E.g. onetwothree
     * @param  {Object} options                - Options object
     * @param  {Number} options.order          - Optional N-gram order. Default is 5
     * @param  {Number} options.maxCandidates  - Optional maximum candidate count. Default is 5
     * @return {Promise}                       - Promise resolving with the resulting JSON
     */
    function breakIntoWords(model, text, options) {
        return _processWords(workBreakPath, model, { text: text }, undefined, options);
    }

    /**
     * Generates a list of candidate of words that would follow the a given sequence of one or more words
     *
     * @param  {string} model                  - Name of model. Currently one of title/anchor/query/body
     * @param  {string} words                  - Text to break.  E.g. 'hello world wide'
     * @param  {Object} options                - Options object
     * @param  {Number} options.order          - Optional N-gram order. Default is 5
     * @param  {Number} options.maxCandidates  - Optional maximum candidate count. Default is 5
     * @return {Promise}                       - Promise resolving with the resulting JSON
     */
    function generateWords(model, words, options) {
        return _processWords(generateNextWordsPath, model, { words: words }, undefined, options);
    }

    /**
     * Generates a list of candidate of words that would follow the a given sequence of one or more words
     *
     * @param  {string} model                  - Name of model. Currently one of title/anchor/query/body
     * @param  {string[]} phrases              - One or more phrases for which to look up the probalities of the word sequences
     * @param  {Number} order                  - Optional N-gram order. Default is 5
     * @return {Promise}                       - Promise resolving with the resulting JSON
     */
    function getJointProbabilities(model, phrases, order) {
        return _processWords(calculateJointProbPath, model, {}, { queries: phrases }, { order: order });
    }

    /**
     * Generates a list of candidate of words that would follow the a given sequence of one or more words
     *
     * @param  {string} model                  - Name of model. Currently one of title/anchor/query/body
     * @param  {Array} queries                 - One of more objects consisting of 'words'/'word' pairs,
     *      where the conditional probability of 'word' in the context of 'words' is computed.
     * @param  {Number} order                  - Optional N-gram order. Default is 5
     * @return {Promise}                       - Promise resolving with the resulting JSON
     */
    function getConditionalProbabilities(model, queries, order) {
        return _processWords(calculateCondProbPath, model, {}, { queries: queries }, { order: order });
    }

    return {
        breakIntoWords: breakIntoWords,
        generateWords: generateWords,
        getConditionalProbabilities: getConditionalProbabilities,
        getJointProbabilities: getJointProbabilities,
        listModels: listModels
    };
};

module.exports = weblm;


text:
<?php

namespace siblh\mantenimientoBundle\Util\JasperReport;

class DIMEFile {

    public $type_format;
    public $type;
    public $id;
    public $data;

}
?>


text:
package org.oscm.saml2.api;

import java.util.Arrays;
import java.util.List;

import org.oscm.internal.types.exception.SAML2StatusCodeInvalidException;

/**
 * Class for validating the status code from a SAML LogoutResponse received from an IdP.
 *
 * @author mgrubski
 */
public class SAMLLogoutResponseValidator {

    SAMLResponseExtractor
            samlResponseExtractor = new SAMLResponseExtractor();

    private final List<String> saml2ErrorStatusCodes = Arrays
            .asList(new String[] { "Requester", "Responder", "VersionMismatch",
                    "AuthnFailed", "InvalidAttrNameOrValue",
                    "InvalidNameIDPolicy", "NoAuthnContext", "NoAvailableIDP",
                    "NoPassive", "NoSupportedIDP", "ProxyCountExceeded",
                    "RequestDenied", "RequestUnsupported",
                    "RequestVersionDeprecated", "RequestVersionTooHigh",
                    "RequestVersionTooLow", "ResourceNotRecognized",
                    "TooManyResponses", "UnknownAttrProfile",
                    "UnknownPrincipal", "UnsupportedBinding" });

    public boolean responseStatusCodeSuccessful(String encodedSamlResponse)
            throws SAML2StatusCodeInvalidException {
        final String statusCode = samlResponseExtractor.getSAMLLogoutResponseStatusCode(
                encodedSamlResponse);
        if (isSuccessful(statusCode)) {
            return true;
        } else if (saml2ErrorStatusCodes.contains(statusCode)) {
            return false;
        } else {
            throw new SAML2StatusCodeInvalidException();
        }
    }

    private boolean isSuccessful(String statusCode) {
        if (statusCode.equalsIgnoreCase("Success")
                || statusCode.equalsIgnoreCase("PartialLogout")) {
            return true;
        }
        return false;
    }

}


text:
package osutils

import (
	"os"
)

func GetEnvList(enVars []string) map[string]string {
	tmpBucket := make(map[string]string, len(enVars))

	for _, name := range enVars {
		v := os.Getenv(name)
		if v != "" {
			tmpBucket[name] = v
		}
	}

	return tmpBucket
}

func SetEnvList(enVars map[string]string) error {
	var err error

	for name, value := range enVars {
		err = os.Setenv(name, value)
		if err != nil {
			return err
		}
	}

	return nil
}


text:
/**
 * Module dependencies.
 */

var mongoose = require('mongoose')
var utils = require('../../lib/utils')

/**
 * Load comment
 */

exports.load = function (req, res, next, id) {
  var media = req.media
  utils.findByParam(media.comments, { id: id }, function (err, comment) {
    if (err) return next(err)
    req.comment = comment
    next()
  })
}

/**
 * Create comment
 */

exports.create = function (req, res) {
  var media = req.media
  var user = req.user

  if (!req.body.body) return res.redirect('/medias/'+ media.id)

  media.addComment(user, req.body, function (err) {
    if (err) return res.render('500')
    res.redirect('/medias/'+ media.id)
  })
}

/**
 * Delete comment
 */

exports.destroy = function (req, res) {
  var media = req.media
  media.removeComment(req.param('commentId'), function (err) {
    if (err) {
      req.flash('error', 'Oops! The comment was not found')
    } else {
      req.flash('info', 'Removed comment')
    }
    res.redirect('/medias/' + media.id)
  })
}


text:
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <base href="<?php echo base_url(); ?>">
    <title>Nanoarthplus</title>

    <link href='assets/css/style1.css' rel='stylesheet' type='text/css'>
    <link href='assets/css/style2.css' rel='stylesheet' type='text/css'>
    <link href='assets/css/style3.css' rel='stylesheet' type='text/css'>

    <link rel="stylesheet" href="assets/css/bootstrap.min.css">

    <link rel="stylesheet" href="assets/css/font-awesome.min.css">
    <link rel="stylesheet" href="assets/css/common.css">

    <link rel="stylesheet" href="assets/css/owl.carousel.css">
    <link rel="stylesheet" href="assets/style.css">
    <link rel="stylesheet" href="assets/css/responsive.css">

<a href="<?php echo base_url(); ?>">

        <form method="post" class="form-inline pull-right" style="padding-top:15px">
            <input type="text" name="search_prod" id="search" class="form-control" placeholder="Search products...">
            <input type="button" value="Search" onClick="genericSearch()" class="btn btn-xs" style="padding:8px">
        </form>

                    <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                        Toggle navigation

                    </button>

<a href="<?php echo base_url(); ?>">Home

About Us

Products

Category

Contact us


text:
    <winery-uploader (onSucces)="loadFiles()" [uploadUrl]="uploadUrl" [allowMultipleFiles]="true">
    </winery-uploader>

Already included Files:

{{file.name}}

                {{file.size / 1024 | number: '1.2-2'}} KB

                <button class="btn btn-sm btn-danger" (click)="deleteFile(file)">Delete</button>

<winery-modal bsModal #removeElementModal="bs-modal" [modalRef]="removeElementModal">
    <winery-modal-header [title]="'Delete File'"></winery-modal-header>
    <winery-modal-body>

            Are you sure you want to remove {{ fileToRemove?.name }}?

    </winery-modal-body>
    <winery-modal-footer [closeButtonLabel]="'Cancel'" [okButtonLabel]="'Delete'"
                         (onOk)="onRemoveElement()">
    </winery-modal-footer>
</winery-modal>


text:
const fetchStyles = (target, linkHref) => {
  return new Promise((resolve, reject) => {
    const link = document.createElement('link')
    link.setAttribute('rel', 'stylesheet')
    link.onload = resolve
    link.onerror = () => reject(new Error(`${linkHref} is not found`))
    link.setAttribute('href', linkHref)
    target.appendChild(link)
  })
}

before(async () => {
  await fetchStyles(parent.document.head, '/cypress/styles.css')
  await fetchStyles(document.head, '/dist/sweetalert2.css')
})


text:
<!DOCTYPE html>

    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="">
    <meta name="author" content="">
    <link rel="shortcut icon" href="assets/favicon.ico">

    <title><?php echo $title;?></title>

    <link rel="stylesheet" href="https://github.com/necolas/normalize.css/blob/master/normalize.css" type="text/css" />
    <link rel="stylesheet" href="https://code.getmdl.io/1.1.3/material.indigo-blue.min.css" type="text/css" />
    <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons" type="text/css" />
    <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:700,400,300" type="text/css" />

    <link href="/view/css/admin.css" rel="stylesheet" />

          <?php echo $title?>

        <?php
        if(isset($_SESSION['loggedin']) && $_SESSION['loggedin']){

          echo '

          <button id="demo-menu-lower-right"
          class="mdl-button mdl-js-button mdl-button--icon">
          more_vert
          </button>

';

          $registerLinkSmall = ' href="/admin/register">';
          $addPointsLinkSmall = ' href="/admin/addPoints">';
          $pointsTableLinkSmall = ' href="/admin/pointsTable">';

          $registerEndSmall = 'Register';
          $addPointsEndSmall = 'Punkte Hinzufügen';
          $pointsTableEndSmall = 'Punkte Tabelle';

          $requested = $_SERVER['REQUEST_URI'];

          $liStart = '
<a class="navigationLink ';
          $liEnd = '
';

          if ($_SESSION['admin'] == 0){
          }
          else if ($requested=="/admin/addPoints" && $_SESSION['admin'] == 1){
            echo $liStart . ' disabledLink">'. $addPointsEndSmall . $liEnd;
            echo $liStart . '"' . $pointsTableLinkSmall . $pointsTableEndSmall . $liEnd;
            echo $liStart . '"' . $registerLinkSmall . $registerEndSmall . $liEnd;
          }
          else if ($requested=="/admin/pointsTable" && $_SESSION['admin'] == 1){
            echo $liStart . '"' . $addPointsLinkSmall . $addPointsEndSmall . $liEnd;
            echo $liStart .  ' disabledLink">' . $pointsTableEndSmall . $liEnd;
            echo $liStart . '"' . $registerLinkSmall . $registerEndSmall . $liEnd;
          }
          else if ($requested=="/admin/register" && $_SESSION['admin'] == 1){
            echo $liStart . '"' . $addPointsLinkSmall . $addPointsEndSmall . $liEnd;
            echo $liStart . '"' . $pointsTableLinkSmall . $pointsTableEndSmall . $liEnd;
            echo $liStart . ' disabledLink">' . $registerEndSmall . $liEnd;
          }
          echo '
Logout
';
          ?>

        <?php
        $registerLink = null;
        if($_SESSION['admin']){
          $registerLink = 'Register';
        }
        $addPointsLink = 'Punkte Hinzufügen';
        $pointsTableLink = 'Punkte Tabelle';

        if ($requested=="/admin/addPoints"){
          echo $pointsTableLink;
          echo $registerLink;
        }
        else if ($requested=="/admin/pointsTable"){
          echo $addPointsLink;
          echo $registerLink;
        }
        else if ($requested=="/admin/register"){
          echo $addPointsLink;
          echo $pointsTableLink;
        }
        echo 'Logout';
      }
      ?>


text:
import {createElementWithAttributes} from '#core/dom';
import * as Preact from '#core/dom/jsx';

import {toggleExperiment} from '#experiments';

import {Services} from '#service';
import {installPerformanceService} from '#service/performance-impl';
import {xhrServiceForTesting} from '#service/xhr-impl';

import {AmpCacheUrlService} from '../../../amp-cache-url/0.1/amp-cache-url';
import {fetchCachedSources} from '../video-cache';

describes.realWin('amp-video cached-sources', {amp: true}, (env) => {
  let cacheUrlService;
  let extensionsService;
  let xhrService;

  beforeEach(() => {
    xhrService = xhrServiceForTesting(env.win);
    env.sandbox.stub(Services, 'xhrFor').returns(xhrService);

    extensionsService = {
      installExtensionForDoc: env.sandbox.spy(() => Promise.resolve()),
    };
    env.sandbox.stub(Services, 'extensionsFor').returns(extensionsService);

    cacheUrlService = new AmpCacheUrlService();
    env.sandbox
      .stub(Services, 'cacheUrlServicePromiseForDoc')
      .resolves(cacheUrlService);
    env.sandbox.stub(Services, 'documentInfoForDoc').returns({
      sourceUrl: 'https://example.com',
      canonicalUrl: 'https://canonical.com',
    });

    installPerformanceService(env.win);
  });

  describe('select sources', () => {
    it('should select the source if there is only one source', async () => {
      const videoEl = createVideo([{src: 'video1.mp4'}]);
      const xhrSpy = env.sandbox.spy(xhrService, 'fetch');

      await fetchCachedSources(videoEl, env.ampdoc);

      expect(xhrSpy).to.have.been.calledWith(
        'https://example-com.cdn.ampproject.org/mbv/s/example.com/video1.mp4?amp_video_host_url=https%3A%2F%2Fcanonical.com&amp_video_require_acao_header=1'
      );
    });

    it('should select the first source if there are similar sources', async () => {
      const videoEl = createVideo([{src: 'video1.mp4'}, {src: 'video2.mp4'}]);
      const xhrSpy = env.sandbox.spy(xhrService, 'fetch');

      await fetchCachedSources(videoEl, env.ampdoc);

      expect(xhrSpy).to.have.been.calledWith(
        'https://example-com.cdn.ampproject.org/mbv/s/example.com/video1.mp4?amp_video_host_url=https%3A%2F%2Fcanonical.com&amp_video_require_acao_header=1'
      );
    });

    it('should select the mp4 source if there are many sources', async () => {
      const videoEl = createVideo([
        {src: 'video1.mp4'},
        {src: 'video2.mp4', type: 'video/mp4'},
      ]);
      const xhrSpy = env.sandbox.spy(xhrService, 'fetch');

      await fetchCachedSources(videoEl, env.ampdoc);

      expect(xhrSpy).to.have.been.calledWith(
        'https://example-com.cdn.ampproject.org/mbv/s/example.com/video2.mp4?amp_video_host_url=https%3A%2F%2Fcanonical.com&amp_video_require_acao_header=1'
      );
    });

    it('should select the video[src] and never the sources children', async () => {
      const videoEl = createVideo([
        {src: 'video2.mp4'},
        {src: 'video3.mp4', type: 'video/mp4'},
      ]);
      videoEl.setAttribute('src', 'video1.mp4');
      const xhrSpy = env.sandbox.spy(xhrService, 'fetch');

      await fetchCachedSources(videoEl, env.ampdoc);

      expect(xhrSpy).to.have.been.calledWith(
        'https://example-com.cdn.ampproject.org/mbv/s/example.com/video1.mp4?amp_video_host_url=https%3A%2F%2Fcanonical.com&amp_video_require_acao_header=1'
      );
    });
  });

  describe('url forming', () => {
    it('should send the request to the correct address if the video has an absolute url', async () => {
      const videoEl = createVideo([{'src': 'https://website.com/video.html'}]);
      const xhrSpy = env.sandbox.spy(xhrService, 'fetch');

      await fetchCachedSources(videoEl, env.ampdoc);

      expect(xhrSpy).to.have.been.calledWith(
        'https://website-com.cdn.ampproject.org/mbv/s/website.com/video.html?amp_video_host_url=https%3A%2F%2Fcanonical.com&amp_video_require_acao_header=1'
      );
    });

    it('should always add the ACAO header', async () => {
      const videoEl = createVideo([{'src': 'https://website.com/video.html'}]);
      const xhrSpy = env.sandbox.spy(xhrService, 'fetch');

      await fetchCachedSources(videoEl, env.ampdoc);

      expect(xhrSpy).to.have.been.calledWith(
        'https://website-com.cdn.ampproject.org/mbv/s/website.com/video.html?amp_video_host_url=https%3A%2F%2Fcanonical.com&amp_video_require_acao_header=1'
      );
    });

    it('should send the request to the correct address if the video has a relative url', async () => {
      const videoEl = createVideo([{'src': 'video.html'}]);
      const xhrSpy = env.sandbox.spy(xhrService, 'fetch');

      await fetchCachedSources(videoEl, env.ampdoc);

      expect(xhrSpy).to.have.been.calledWith(
        'https://example-com.cdn.ampproject.org/mbv/s/example.com/video.html?amp_video_host_url=https%3A%2F%2Fcanonical.com&amp_video_require_acao_header=1'
      );
    });

    it('should send the request to the correct address if the video has a .gif extension', async () => {
      const videoEl = createVideo([{'src': 'https://website.com/video.gif'}]);
      const xhrSpy = env.sandbox.spy(xhrService, 'fetch');

      await fetchCachedSources(videoEl, env.ampdoc);

      expect(xhrSpy).to.have.been.calledWith(
        'https://website-com.cdn.ampproject.org/mbv/s/website.com/video.gif?amp_video_host_url=https%3A%2F%2Fcanonical.com&amp_video_require_acao_header=1'
      );
    });
  });

  describe('add sources', () => {
    it('should set the correct attributes on the source added', async () => {
      env.sandbox.stub(xhrService, 'fetch').resolves({
        json: () =>
          Promise.resolve({
            sources: [
              {
                'url': 'video1.mp4',
                'codec': 'h264',
                'bitrate_kbps': 700,
                type: 'video/mp4',
              },
            ],
          }),
      });

      const videoEl = createVideo([{src: 'video.mp4'}]);
      await fetchCachedSources(videoEl, env.ampdoc);

      const addedSource = videoEl.querySelector('source');
      expect(addedSource.getAttribute('src')).to.equal('video1.mp4');
      expect(addedSource.getAttribute('data-bitrate')).to.equal('700');
      expect(addedSource.getAttribute('type')).to.equal('video/mp4');
    });

    it('should add the sources sorted by codec priority', async () => {
      env.sandbox.stub(xhrService, 'fetch').resolves({
        json: () =>
          Promise.resolve({
            sources: [
              {
                'url': 'video1.mp4',
                'codec': 'vp09.00.30.08',
                'bitrate_kbps': 700,
                type: 'video/mp4',
              },
              {
                'url': 'video2.mp4',
                'codec': 'unknown',
                'bitrate_kbps': 2000,
                type: 'video/mp4',
              },
              {
                'url': 'video3.mp4',
                'codec': 'h264',
                'bitrate_kbps': 1500,
                type: 'video/mp4',
              },
            ],
          }),
      });

      const videoEl = createVideo([{src: 'video.mp4'}]);

      await fetchCachedSources(videoEl, env.ampdoc);

      const addedSources = videoEl.querySelectorAll('source');

      const srcType0 = addedSources[0].getAttribute('type');
      const srcType1 = addedSources[1].getAttribute('type');
      const srcType2 = addedSources[2].getAttribute('type');
      expect(srcType0).to.equal('video/mp4; codecs=vp09.00.30.08');
      expect(srcType1).to.equal('video/mp4');
      expect(srcType2).to.equal('video/mp4; codecs=unknown');
    });

    it('should add the sources sorted by bitrate, for any subset of sources whose codecs have equivalent priority', async () => {
      env.sandbox.stub(xhrService, 'fetch').resolves({
        json: () =>
          Promise.resolve({
            sources: [
              {
                'url': 'video1.mp4',
                'codec': 'vp09.00.30.08',
                'bitrate_kbps': 700,
                type: 'video/mp4',
              },
              {
                'url': 'video2.mp4',
                'codec': 'vp09.00.30.08',
                'bitrate_kbps': 2000,
                type: 'video/mp4',
              },
              {
                'url': 'video3.mp4',
                'codec': 'vp09.00.30.08',
                'bitrate_kbps': 1500,
                type: 'video/mp4',
              },
            ],
          }),
      });

      const videoEl = createVideo([{src: 'video.mp4'}]);

      await fetchCachedSources(videoEl, env.ampdoc);

      const addedSources = videoEl.querySelectorAll('source');
      expect(addedSources[0].getAttribute('data-bitrate')).to.equal('2000');
      expect(addedSources[1].getAttribute('data-bitrate')).to.equal('1500');
      expect(addedSources[2].getAttribute('data-bitrate')).to.equal('700');
    });

    it('should add the sources sorted first by codec priority, and then by bitrate', async () => {
      env.sandbox.stub(xhrService, 'fetch').resolves({
        json: () =>
          Promise.resolve({
            sources: [
              {
                'url': 'video1.mp4',
                'codec': 'h264',
                'bitrate_kbps': 2000,
                type: 'video/mp4',
              },
              {
                'url': 'video2.mp4',
                'codec': 'vp09.00.30.08',
                'bitrate_kbps': 1000,
                type: 'video/mp4',
              },
              {
                'url': 'video3.mp4',
                'codec': 'vp09.00.30.08',
                'bitrate_kbps': 2000,
                type: 'video/mp4',
              },
              {
                'url': 'video4.mp4',
                'codec': 'h264',
                'bitrate_kbps': 3000,
                type: 'video/mp4',
              },
            ],
          }),
      });

      const videoEl = createVideo([{src: 'video.mp4'}]);

      await fetchCachedSources(videoEl, env.ampdoc);

      const addedSources = videoEl.querySelectorAll('source');
      const srcType0 = addedSources[0].getAttribute('type');
      const srcType1 = addedSources[1].getAttribute('type');
      const srcType2 = addedSources[2].getAttribute('type');
      const srcType3 = addedSources[3].getAttribute('type');

      expect(addedSources[0].getAttribute('data-bitrate')).to.equal('2000');
      expect(srcType0).to.equal('video/mp4; codecs=vp09.00.30.08');

      expect(addedSources[1].getAttribute('data-bitrate')).to.equal('1000');
      expect(srcType1).to.equal('video/mp4; codecs=vp09.00.30.08');

      expect(addedSources[2].getAttribute('data-bitrate')).to.equal('3000');
      expect(srcType2).to.equal('video/mp4');

      expect(addedSources[3].getAttribute('data-bitrate')).to.equal('2000');
      expect(srcType3).to.equal('video/mp4');
    });

    it('should add video[src] as the last fallback source', async () => {
      env.sandbox.stub(xhrService, 'fetch').resolves({
        json: () =>
          Promise.resolve({
            sources: [
              {
                'url': 'video1.mp4',
                'codec': 'h264',
                'bitrate_kbps': 700,
                type: 'video/mp4',
              },
              {
                'url': 'video2.mp4',
                'codec': 'h264',
                'bitrate_kbps': 2000,
                type: 'video/mp4',
              },
              {
                'url': 'video3.mp4',
                'codec': 'h264',
                'bitrate_kbps': 1500,
                type: 'video/mp4',
              },
            ],
          }),
      });

      const videoEl = createVideo([{src: 'video.mp4'}]);
      videoEl.setAttribute('src', 'video1.mp4');
      videoEl.setAttribute('type', 'video/mp4');

      await fetchCachedSources(videoEl, env.ampdoc);

      const lastSource = videoEl.querySelector('source:last-of-type');
      expect(lastSource.getAttribute('src')).to.equal('video1.mp4');
      expect(lastSource.getAttribute('type')).to.equal('video/mp4');
    });

    it('should clear the unused sources when video[src]', async () => {
      env.sandbox.stub(xhrService, 'fetch').resolves({
        json: () =>
          Promise.resolve({
            sources: [
              {
                'url': 'video1.mp4',
                'codec': 'h264',
                'bitrate_kbps': 700,
                type: 'video/mp4',
              },
              {
                'url': 'video2.mp4',
                'codec': 'h264',
                'bitrate_kbps': 2000,
                type: 'video/mp4',
              },
              {
                'url': 'video3.mp4',
                'codec': 'h264',
                'bitrate_kbps': 1500,
                type: 'video/mp4',
              },
            ],
          }),
      });

      const videoEl = createVideo([
        {src: 'video.mp4'},
        {src: 'video.mp4'},
        {src: 'video.mp4'},
        {src: 'video.mp4'},
        {src: 'video.mp4'},
      ]);
      videoEl.setAttribute('src', 'video1.mp4');

      await fetchCachedSources(videoEl, env.ampdoc);

      const addedSources = videoEl.querySelectorAll('source');
      expect(addedSources).to.have.lengthOf(4); // 3 from cache + 1 fallback.
    });
  });

  describe('end to end', () => {
    it('should create the sources from the request with the correct attributes', async () => {
      env.sandbox.stub(xhrService, 'fetch').resolves({
        json: () =>
          Promise.resolve({
            sources: [
              {
                'url': 'video.mp4',
                'codec': 'h264',
                'bitrate_kbps': 700,
                'type': 'video/mp4',
              },
            ],
          }),
      });

      const videoEl = createVideo([{src: 'video.mp4'}]);

      await fetchCachedSources(videoEl, env.ampdoc);

      expect(videoEl.querySelector('source[data-bitrate]')).to.not.be.null;
    });

    it('should set the crossorigin attribute to the video', async () => {
      const videoEl = createVideo([{'src': 'video.html'}]);

      await fetchCachedSources(videoEl, env.ampdoc);

      expect(videoEl.hasAttribute('crossorigin')).to.be.true;
    });

    it('should set an attribute on cached video sources', async () => {
      env.sandbox.stub(xhrService, 'fetch').resolves({
        json: () =>
          Promise.resolve({
            sources: [
              {
                'url': 'video.mp4',
                'codec': 'h264',
                'bitrate_kbps': 700,
                'type': 'video/mp4',
              },
            ],
          }),
      });

      const videoEl = createVideo([{src: 'video.mp4'}]);

      await fetchCachedSources(videoEl, env.ampdoc);

      const source = videoEl.querySelector('source[data-bitrate]');
      expect(source).to.exist;
      expect(source).to.have.attribute('i-amphtml-video-cached-source');
    });

    it('should not set an attribute on non cached video sources', async () => {
      env.sandbox.stub(xhrService, 'fetch').resolves({
        json: () =>
          Promise.resolve({
            sources: [
              {
                'url': 'video.mp4',
                'codec': 'h264',
                'bitrate_kbps': 700,
                'type': 'video/mp4',
              },
            ],
          }),
      });

      const videoEl = createVideo([{src: 'video.mp4'}]);

      await fetchCachedSources(videoEl, env.ampdoc);

      const source = videoEl.querySelector('source:not(source[data-bitrate])');
      expect(source).to.exist;
      expect(source).to.not.have.attribute('i-amphtml-video-cached-source');
    });
  });

  describe('has_audio field', async () => {
    beforeEach(() => {
      toggleExperiment(env.win, 'story-video-cache-apply-audio', true);
    });

    afterEach(() => {
      toggleExperiment(env.win, 'story-video-cache-apply-audio', false);
    });
    it('should set noaudio if the cache responds with has_audio: false', async () => {
      env.sandbox.stub(xhrService, 'fetch').resolves({
        json: () =>
          Promise.resolve({
            'has_audio': false,
            'sources': [
              {'url': 'video.mp4', 'bitrate_kbps': 700, 'type': 'video/mp4'},
            ],
          }),
      });
      const videoEl = createVideo([{src: 'video.mp4'}]);
      await fetchCachedSources(videoEl, env.ampdoc);

      expect(videoEl).to.have.attribute('noaudio');
    });

    it('should not set noaudio if the cache responds with has_audio: true', async () => {
      env.sandbox.stub(xhrService, 'fetch').resolves({
        json: () =>
          Promise.resolve({
            'has_audio': true,
            'sources': [
              {'url': 'video.mp4', 'bitrate_kbps': 700, 'type': 'video/mp4'},
            ],
          }),
      });
      const videoEl = createVideo([{src: 'video.mp4'}]);
      await fetchCachedSources(videoEl, env.ampdoc);

      expect(videoEl).to.not.have.attribute('noaudio');
    });

    it('should not set noaudio if the cache responds without has_audio', async () => {
      env.sandbox.stub(xhrService, 'fetch').resolves({
        json: () =>
          Promise.resolve({
            'sources': [
              {'url': 'video.mp4', 'bitrate_kbps': 700, 'type': 'video/mp4'},
            ],
          }),
      });
      const videoEl = createVideo([{src: 'video.mp4'}]);
      await fetchCachedSources(videoEl, env.ampdoc);

      expect(videoEl).to.not.have.attribute('noaudio');
    });
  });

  function stubSourcesWithCapionsRequest() {
    env.sandbox.stub(xhrService, 'fetch').resolves({
      json: () =>
        Promise.resolve({
          'captions': {
            'src': 'captions_src_response.vtt',
            'srclang': 'en-us',
          },
          'sources': [
            {'url': 'video.mp4', 'bitrate_kbps': 700, 'type': 'video/mp4'},
          ],
        }),
    });
  }
  describe('captions field', async () => {
    it('should append track element if the cache responds with captions', async () => {
      stubSourcesWithCapionsRequest();
      const videoEl = createVideo([{src: 'video.mp4'}]);
      await fetchCachedSources(videoEl, env.ampdoc);

      const trackEl = videoEl.querySelector('track');
      expect(trackEl).to.exist;
    });
    it('should append story-captions element if the cache responds with captions', async () => {
      stubSourcesWithCapionsRequest();
      const videoEl = createVideo([{src: 'video.mp4'}]);
      await fetchCachedSources(videoEl, env.ampdoc);

      const captionsEl = videoEl.querySelector('amp-story-captions');
      expect(captionsEl).to.exist;
    });
    it('should not append track element if video already has a track child', async () => {
      stubSourcesWithCapionsRequest();
      const videoEl = createVideo([{src: 'video.mp4'}]);
      videoEl.appendChild(<track />);
      await fetchCachedSources(videoEl, env.ampdoc);

      const trackEl = videoEl.querySelector(
        'track[src="captions_src_response.vtt"]'
      );
      expect(trackEl).to.not.exist;
    });
    it('should not append track element if captions does not exist', async () => {
      env.sandbox.stub(xhrService, 'fetch').resolves({
        json: () =>
          Promise.resolve({
            'sources': [
              {'url': 'video.mp4', 'bitrate_kbps': 700, 'type': 'video/mp4'},
            ],
          }),
      });
      const videoEl = createVideo([{src: 'video.mp4'}]);
      await fetchCachedSources(videoEl, env.ampdoc);

      const trackEl = videoEl.querySelector('track');
      expect(trackEl).to.not.exist;
    });
  });

  describe('web stories: inlined video', async () => {
    it('should use the inlined source for the first video in the story instead of sending an XHR request', async () => {
      // Set up an inlined source response for the first video in the story
      const storyEl = createStoryForInlineVideoTesting();
      env.win.document.body.appendChild(storyEl);
      setUpInlinedVideoResponse();

      const xhrSpy = env.sandbox.spy(xhrService, 'fetch');

      // Fetch the sources for the first video in the story
      const videoEl = storyEl.querySelectorAll('amp-video')[0];
      await fetchCachedSources(videoEl, env.ampdoc);

      expect(xhrSpy).to.have.not.been.called;
      const inlinedSources = videoEl.querySelectorAll(
        'source[src="inlined_video_response.mp4"]'
      );
      expect(inlinedSources).to.have.lengthOf(1);
    });

    it('should send an XHR request for any video that is not the very first one within the story', async () => {
      // Set up an inlined source response for the first video in the story
      const storyEl = createStoryForInlineVideoTesting();
      env.win.document.body.appendChild(storyEl);
      setUpInlinedVideoResponse();

      const xhrSpy = env.sandbox.spy(xhrService, 'fetch');

      // Fetch the sources for video #2: the 2nd video on the first story page
      const videoEl2 = storyEl.querySelectorAll('amp-video')[1];
      await fetchCachedSources(videoEl2, env.ampdoc);

      // Fetch the sources for video #3: the 1st video on the 2nd story page
      const videoEl3 = storyEl.querySelectorAll('amp-video')[2];
      await fetchCachedSources(videoEl3, env.ampdoc);

      expect(xhrSpy).to.have.been.calledWith(
        'https://example-com.cdn.ampproject.org/mbv/s/example.com/video2.mp4?amp_video_host_url=https%3A%2F%2Fcanonical.com&amp_video_require_acao_header=1'
      );
      expect(xhrSpy).to.have.been.calledWith(
        'https://example-com.cdn.ampproject.org/mbv/s/example.com/video3.mp4?amp_video_host_url=https%3A%2F%2Fcanonical.com&amp_video_require_acao_header=1'
      );
    });

    it('should send XHR request if inline config not provided', async () => {
      // Create story without setting an inlined source response
      const storyEl = createStoryForInlineVideoTesting();
      env.win.document.body.appendChild(storyEl);

      const xhrSpy = env.sandbox.spy(xhrService, 'fetch');

      // Fetch the sources for the first video in the story
      const videoEl = storyEl.querySelectorAll('amp-video')[0];
      await fetchCachedSources(videoEl, env.ampdoc);

      expect(xhrSpy).to.have.been.calledWith(
        'https://example-com.cdn.ampproject.org/mbv/s/example.com/video1.mp4?amp_video_host_url=https%3A%2F%2Fcanonical.com&amp_video_require_acao_header=1'
      );
    });

    it('should send XHR request if inlined video response fails to parse', async () => {
      // Set up an improperly configured response for the first video in the story
      const storyEl = createStoryForInlineVideoTesting();
      env.win.document.body.appendChild(storyEl);
      const scriptEl = createElementWithAttributes(env.win.document, 'script', {
        'id': 'amp-google-video-cache-response',
        'type': 'application/json',
      });
      scriptEl.textContent = '{"faulty": [{}]}';

      const xhrSpy = env.sandbox.spy(xhrService, 'fetch');

      // Fetch the sources for the first video in the story
      const videoEl = storyEl.querySelectorAll('amp-video')[0];
      await fetchCachedSources(videoEl, env.ampdoc);

      expect(xhrSpy).to.have.been.calledWith(
        'https://example-com.cdn.ampproject.org/mbv/s/example.com/video1.mp4?amp_video_host_url=https%3A%2F%2Fcanonical.com&amp_video_require_acao_header=1'
      );
    });
  });

  function createVideo(children) {
    const videoEl = createElementWithAttributes(env.win.document, 'amp-video', {
      'cache': 'google',
      'layout': 'fill',
    });
    children.forEach((childJson) => {
      const sourceEl = createElementWithAttributes(
        env.win.document,
        'source',
        childJson
      );
      videoEl.appendChild(sourceEl);
    });
    env.win.document.body.appendChild(videoEl);
    return videoEl;
  }

  function createStoryForInlineVideoTesting() {
    const storyEl = env.win.document.createElement('amp-story');
    const storyPageEl1 = env.win.document.createElement('amp-story-page');
    const storyPageEl2 = env.win.document.createElement('amp-story-page');
    storyEl.appendChild(storyPageEl1);
    storyEl.appendChild(storyPageEl2);

    // Place two videos on the first page. video #1 is nested more deeply than
    // video #2, but it should still be considered the first video on the page.
    const gridLayerEl = env.win.document.createElement('amp-story-grid-layer');
    const videoEl1 = createVideo([{src: 'video1.mp4'}]);
    gridLayerEl.appendChild(videoEl1);
    storyPageEl1.appendChild(gridLayerEl);

    // Place video #2 on the first page.
    const videoEl2 = createVideo([{src: 'video2.mp4'}]);
    storyPageEl1.appendChild(videoEl2);

    // Place video #3 on the second page.
    const videoEl3 = createVideo([{src: 'video3.mp4'}]);
    storyPageEl2.appendChild(videoEl3);

    return storyEl;
  }

  function setUpInlinedVideoResponse() {
    const scriptEl = createElementWithAttributes(env.win.document, 'script', {
      'id': 'amp-google-video-cache-response',
      'type': 'application/json',
    });
    scriptEl.textContent = `
      {
        "sources": [
          {
            "url": "inlined_video_response.mp4",
            "codec": "h264",
            "type": "video/mp4",
            "bitrate_kbps": 400
          }
        ],
        "has_audio": false
      }`;
    env.win.document.head.appendChild(scriptEl);
  }
});


text:
<?xml version="1.0" encoding="UTF-8"?>

PHOS-FLUR ORTHO DEFENSE- sodium fluoride rinse
Colgate Oral Pharmaceuticals, Inc.

Disclaimer: Most OTC drugs are not reviewed and approved by FDA, however they may be marketed if they comply with applicable regulations and policies. FDA has not evaluated whether this product complies.

Colgate®
 Phos-Flur®
 Ortho Defense™

Drug Facts

Active ingredient (in each 10 ml)

Sodium fluoride 4.4 mg

Purpose

Anticavity

Use

aids in the prevention of dental decay

Warnings

Keep out of reach of children. If more than used for rinsing is accidentally swallowed, get medical help or contact a Poison Control Center right away.

Directions

<col align="left" valign="top" width="35%">
<col align="left" valign="top" width="65%">

adults and children 6 years of age and older

use once a day after brushing your teeth with a toothpaste

vigorously swish 10 milliliters (10 ml mark on cap or 2 teaspoonfuls) of rinse between your teeth for 1 minute then spit out

do not swallow the rinse

do not eat or drink for 30 minutes after rinsing

 instruct children under 12 years of age in good rinsing habits (to minimize swallowing)

supervise children as necessary until capable of using without supervision

children under 6 years of age

ask a dentist or physician

Other information

store at controlled room temperature 68-77°F (20-25°C)

Inactive ingredients

FD&C blue no. 1, FD&C red no. 40, flavor, phosphoric acid, polysorbate 20, potassium sorbate, sodium phosphate, sorbitol, water

Questions or comments?

Call toll-free 1-800-962-2345

Colgate Oral
Pharmaceuticals, Inc.
a subsidiary of
Colgate-Palmolive Company
New York, NY 10022 U.S.A.

PRINCIPAL DISPLAY PANEL - 473 ml Bottle Label

IMPORTANT: Read directions for proper use

Colgate®

Phos-Flur®

Ortho Defense™
Acidulated Phosphate Fluoride Solution
 Anticavity Dental Rinse

#1 Orthodontist Recommended

Ideal protection while wearing braces

Proven to help prevent cavities

Helps prevent white spots

Gushing Grape

ADA
Accepted
American
Dental
Association ®

16 FL OZ (1 PT) 473 ml

P10001719

PHOS-FLUR ORTHO DEFENSE

sodium fluoride rinse

Product Information

Product Type
HUMAN OTC DRUG LABEL
Item Code (Source)
NDC:0126-0138

Route of Administration
DENTAL
DEA Schedule

Active Ingredient/Active Moiety

Ingredient Name
Basis of Strength
Strength

SODIUM FLUORIDE (FLUORIDE ION)
SODIUM FLUORIDE
4.42 mg  in 10 mL

Inactive Ingredients

Ingredient Name
Strength

WATER

SORBITOL

POTASSIUM SORBATE

PHOSPHORIC ACID

SODIUM PHOSPHATE, MONOBASIC, MONOHYDRATE

POLYSORBATE 20

FD&C BLUE NO. 1

FD&C RED NO. 40

Product Characteristics

Color
PURPLE
Score

Shape

Size

Flavor
GRAPE
Imprint Code

Contains

Packaging

#
Item Code
Package Description
Marketing Start Date
Marketing End Date

1
NDC:0126-0138-16
473 mL in 1 BOTTLE

Marketing Information

Marketing Category
Application Number or Monograph Citation
Marketing Start Date
Marketing End Date

OTC MONOGRAPH FINAL
part355
02/15/2011

Labeler - Colgate Oral Pharmaceuticals, Inc.
							(055002195)

Revised: 7/2011

Document Id: b1c3b16f-fae6-463d-a4e5-d0b5fe4a0b62

Set id: 84de9ca9-7959-4d5f-9bb0-884cee1b8038

Version: 1

Effective Time: 20110705

Colgate Oral Pharmaceuticals, Inc.