shell bypass 403

GrazzMean Shell

Uname: Linux web3.us.cloudlogin.co 5.10.226-xeon-hst #2 SMP Fri Sep 13 12:28:44 UTC 2024 x86_64
Software: Apache
PHP version: 8.1.31 [ PHP INFO ] PHP os: Linux
Server Ip: 162.210.96.117
Your Ip: 3.142.212.51
User: edustar (269686) | Group: tty (888)
Safe Mode: OFF
Disable Function:
NONE

name : contact-form-7.tar
wp-contact-form-7.php000064400000003550147510545420010453 0ustar00<?php
/*
 * Plugin Name: Contact Form 7
 * Plugin URI: https://contactform7.com/
 * Description: Just another contact form plugin. Simple but flexible.
 * Author: Takayuki Miyoshi
 * Author URI: https://ideasilo.wordpress.com/
 * License: GPL v2 or later
 * License URI: https://www.gnu.org/licenses/gpl-2.0.html
 * Version: 6.0.3
 * Requires at least: 6.6
 * Requires PHP: 7.4
 */

define( 'WPCF7_VERSION', '6.0.3' );

define( 'WPCF7_REQUIRED_WP_VERSION', '6.6' );

define( 'WPCF7_TEXT_DOMAIN', 'contact-form-7' );

define( 'WPCF7_PLUGIN', __FILE__ );

define( 'WPCF7_PLUGIN_BASENAME', plugin_basename( WPCF7_PLUGIN ) );

define( 'WPCF7_PLUGIN_NAME', trim( dirname( WPCF7_PLUGIN_BASENAME ), '/' ) );

define( 'WPCF7_PLUGIN_DIR', untrailingslashit( dirname( WPCF7_PLUGIN ) ) );

define( 'WPCF7_PLUGIN_MODULES_DIR', WPCF7_PLUGIN_DIR . '/modules' );

if ( ! defined( 'WPCF7_LOAD_JS' ) ) {
	define( 'WPCF7_LOAD_JS', true );
}

if ( ! defined( 'WPCF7_LOAD_CSS' ) ) {
	define( 'WPCF7_LOAD_CSS', true );
}

if ( ! defined( 'WPCF7_AUTOP' ) ) {
	define( 'WPCF7_AUTOP', true );
}

if ( ! defined( 'WPCF7_USE_PIPE' ) ) {
	define( 'WPCF7_USE_PIPE', true );
}

if ( ! defined( 'WPCF7_ADMIN_READ_CAPABILITY' ) ) {
	define( 'WPCF7_ADMIN_READ_CAPABILITY', 'edit_posts' );
}

if ( ! defined( 'WPCF7_ADMIN_READ_WRITE_CAPABILITY' ) ) {
	define( 'WPCF7_ADMIN_READ_WRITE_CAPABILITY', 'publish_pages' );
}

if ( ! defined( 'WPCF7_VERIFY_NONCE' ) ) {
	define( 'WPCF7_VERIFY_NONCE', false );
}

if ( ! defined( 'WPCF7_USE_REALLY_SIMPLE_CAPTCHA' ) ) {
	define( 'WPCF7_USE_REALLY_SIMPLE_CAPTCHA', false );
}

if ( ! defined( 'WPCF7_VALIDATE_CONFIGURATION' ) ) {
	define( 'WPCF7_VALIDATE_CONFIGURATION', true );
}

// Deprecated, not used in the plugin core. Use wpcf7_plugin_url() instead.
define( 'WPCF7_PLUGIN_URL',
	untrailingslashit( plugins_url( '', WPCF7_PLUGIN ) )
);

require_once WPCF7_PLUGIN_DIR . '/load.php';
uninstall.php000064400000001006147510545420007272 0ustar00<?php

if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {
	exit();
}

function wpcf7_delete_plugin() {
	global $wpdb;

	delete_option( 'wpcf7' );

	$posts = get_posts(
		array(
			'numberposts' => -1,
			'post_type' => 'wpcf7_contact_form',
			'post_status' => 'any',
		)
	);

	foreach ( $posts as $post ) {
		wp_delete_post( $post->ID, true );
	}

	$wpdb->query( sprintf(
		"DROP TABLE IF EXISTS %s",
		$wpdb->prefix . 'contact_form_7'
	) );

	return true;
}

if ( ! defined( 'WPCF7_VERSION' ) ) {
	wpcf7_delete_plugin();
}
languages/readme.txt000064400000000200147510545420010507 0ustar00Translations have moved to
https://translate.wordpress.org/projects/wp-plugins/contact-form-7

Thank you for your contribution.
assets/icon.svg000064400000002777147510545420007543 0ustar00<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 242.5 239.46"><defs><style>.cls-1,.cls-6{fill:none;}.cls-2{clip-path:url(#clip-path);}.cls-3{fill:#33c6f4;}.cls-4{fill:#1b447e;}.cls-5{fill:#fff;}.cls-6{stroke:#221e1f;stroke-miterlimit:10;stroke-width:7.16px;}</style><clipPath id="clip-path" transform="translate(1.72)"><circle class="cls-1" cx="119.73" cy="119.73" r="116.15"/></clipPath></defs><g id="Layer_2" data-name="Layer 2"><g id="Layer_1" data-name="Layer 1"><g class="cls-2"><circle class="cls-3" cx="121.45" cy="119.73" r="116.15"/><path class="cls-4" d="M239.32,167.79c-53.41-24-108.37-91.46-113-94.55s-10.84.77-10.84.77c-3.87-6.19-10.06.77-10.06.77C76.77,123.55.14,170.11.14,170.11S36.94,237.79,122,237.79C208.48,237.79,239.32,167.79,239.32,167.79Z" transform="translate(1.72)"/><path class="cls-5" d="M67.48,116.58s15.48-7,12.38,4.65-15.48,28.64-11.61,29.41S83,140.58,86.06,142.12s5.42.78,3.87,6.2-3.1,9.29,0,9.29,5.42-7,9.29-13.94,10.06-3.87,12.38-1.55,9.29,15.49,14.71,13.94,8.51-8.52,6.19-24,1.55-20.12,1.55-20.12,4.64-2.32,13.16,8.51,24,27.09,26.31,26.32-10.83-17.8-7.74-19.35,15.48,2.32,21.68,7.74c0,0,2.12,8.87,2.12.36L126.31,73.24,115.47,74l-10.06.77S80.64,111.94,67.48,116.58Z" transform="translate(1.72)"/><path class="cls-6" d="M239.32,170.11c-53.41-24-108.37-93.78-113-96.87s-10.84.77-10.84.77c-3.87-6.19-10.06.77-10.06.77C76.77,123.55.14,170.11.14,170.11" transform="translate(1.72)"/></g><circle class="cls-6" cx="121.45" cy="119.73" r="116.15"/></g></g></svg>
assets/icon.png000064400000072155147510545420007525 0ustar00�PNG


IHDR\r�fgAMA���a cHRMz&�����u0�`:�p��Q<�eXIfMM*JR(�iZHH�����wJ	pHYs��hiTXtXML:com.adobe.xmp<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 5.4.0">
   <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
      <rdf:Description rdf:about=""
            xmlns:tiff="http://ns.adobe.com/tiff/1.0/"
            xmlns:exif="http://ns.adobe.com/exif/1.0/">
         <tiff:Orientation>1</tiff:Orientation>
         <tiff:ResolutionUnit>2</tiff:ResolutionUnit>
         <exif:ColorSpace>1</exif:ColorSpace>
         <exif:PixelXDimension>240</exif:PixelXDimension>
         <exif:PixelYDimension>241</exif:PixelYDimension>
      </rdf:Description>
   </rdf:RDF>
</x:xmpmeta>
�#P�@IDATx�}|\��W�N��.�r�c�4�{�$!�����@B��Hh�%��j:��a�ދ,[���{=I��w�t��{�Tm���gtw���훷;;;;3��;����bK։�J��Ć^��p�m֛�F�i�h%�m�L�?�DE�!Z��e@��]K��0�S�/"�!:�9$J��U�4�C���C��|s=�㈱�2�É�D������:�
J��F`n�RCS�w���4�y��DaG�{���� ����K�w1�(3�T�bѵ����.�{��7+��c�16�����Dr�A��:�a
֎t��rZn�λȀ�G�D�%�/���	��0�b)1�(�`W��0
N3tpz	>���H�A�"�b.���#
dY z�'f�ER�L��Ou��#E�����Ȍn�"�'e�Gu��@�D�p���(KaV���0���@R��.o~�#�!N&ʠ�_��S��EE*e��BH�D�!EQ7�(�;�O�|���ڪ-������p<���G'g8xx����-ͨ1 �7.Q�wM���(χ��Gg865��������4�!7�R��U�Z5v�v��T�E�(�a"#�G�%�?�3��P���2�O"�%�C�}�>�ր	am���������y�&GDy{���	F�78xn�xx���BЂZ�
<���3����Rx�s�;:���	���h57��L���M�-Ȫ�D��QEpn���ME��߹d�'����k9;��!V�@��0�cD�@��h"�'e�M���K�
���pxD��S@�����HO�&�z���������V��L	A��	I��;H:we�t�[B�� ��R
�`��#���9+i4R(9J	�,C#�����5h*-�_IZJrP{|?J�� �z���,g5+�_S��z�=���zH(�}4Qf��"�"�)�`�A�8��#���8q�q���썖e�+�hG�sE�~7��
�(%X�����0''�S��D�R��������0��0C��]�8!~��)Q��G�D�����H�y�h�/$^AL$�DY�4
�!�h�
Apd,B�#���������n�n�����ٻύ�)�K�K��O�#B+
�wu�Ǒ�����L83��!�;~¼�M��׉��H	=[���H���qQމ��h�ě�D���n^nN�M��kv��(L�ϸ�q���߬H��9�ef�U�J���?!���"z
~:�A�Dp�?���;���4�,e�Q� ǽ���F�� �F<D��A�+�5��k_��K��/8��+���}ھ�ps�Gp$*�ޘ�2ɓ�bH����T;Q��`w��ĺ�w����B+��(/=�͈�9H/�Hݹ��w]��2� \�o ��]���fb�+��
t�uN���/'Zg��%�rb'v����ڌ��[��Y��8n���Q��9ev����,�%��`�vc4w�v���+�m���X��݈Y�jy�ć����|x^�3����Ϗ��e��'�����W�yƅ(���{�m��>U8�/�Y���;�-_ ����,�bv��)bi�k&�t :���Q����&�]u5|g_��1Po4q}�YL4�L��S@^��3��{}
b��A�7o�o��K��Zd�A���_&��ш�^w�aD�k�,�É�={.!W۰N෩?�5�nF9���
0��e�rN���&3,D���V���/?�����;�A*X�0Q�Y�8�}U�"�#u�ƻZ�M4QC�ۧ�=��=�b�@�����p�1�����Gabj����z.����K���#*?�d� ;�XO��_�^?�`$1�ֻ�x1�(�}�O�wE<���,x/�y�f�����^hj�d#���	vzsv�w��QWE��r��[��7�����	�������"�A|�he%�:|a8�]y6딼��� N'���>�4Z�71�Wދ�Yp�@%��ӏ��0x( FG�Vx�T������Q��	��}����i7�.c���E*�ؗ�R�����EA���,��x҉�����S�r�/М0΁a(7�)�#gJ:^
4s�we���.C�����F�7�`�F�5"��w��2aX��~��
��8,�������y���~��x1ѝ�	�g��E땏�s���Ơ���|}�k�oPf#p���_S�#�?��_<������v|�v��y�_'�!
t�cm)C��pc�*D�w
���qD����-��������~����FZ�y���b�>�j��G%w�~��b8݋��kQ��S�I`7�ұ��f���)���2�(�\�޳�&��`�U����{�=�|�O@���R�Q�ڳ�o�~��u��1,�����8a&�ܝQ�vО�Q�>B�"�uhQ;�c��pa��a>Q;�~߅ؑ��-L�{6|��	�/G���(��}+�nG�}�-��v��d�lju@1��1�K�X�7�#?/�'(�.1��I�'yM�p`�տ��"�*���	e�|'�d�1�H��f�-�Ja��8�Ɂ�gv���ڮ�
(���:�+*���D�����/
t@��~7�9�(��0�z␅��bH�_�!�DG��ӌ��S�Z��oD��q0i��
>}�k�n��[A=�K��clLZ|�`��Q��ݾ,��#d��rQ���C�*�v�ũ�֞P���q\�Q߄�W#�n�Z��}�=�X/3d)�0.�r4�s�,�����Ue%0Ӻ��>x61���(L���Ђ��$�d��D��k|˾aјr�툾�؝4S��u�]���L�"	�nj����q5��#��d�/Ac�w��CJ/0��(b.!�N��-L�1��x5�݄\w����-�F^�\h�����Ɉ������dLwbZ.K�}�lbϴ	,x�a(1�ݗ��eDO����N�������c�Rb�o�:�Q@��:�
�Q7�0n&bq�^ꐻ],��z���* �������ŧ
b�����OO��_2O���z���S@��mX����H	
ơMm��'��ƅ�̑X���X�I�?G���C-�V�d�I�|���ӌ�_��l�Y:��P�/�I��)�����J_���2��e�iqP{V`�2��L��(r�*�9x���Esa���J��7����V�z���S���e����-���=�$צ#5���T�J)A�R�<�Da��+F ����0�D��Ӝ���`\}����?�"*
|aR����4X�!Ckgl��O<o�9y6&����]J$c%���Ȅ%�gD7��XKt]r�1+�e��O�э�	�.��_P��V��
3��g�QZ�	�Nk_jb�j4��3B�qp��5]L����b+0�$�����_�~��e�	B�s{�YKQ�����5����3�I�r�I��{h,���Q��K4گW樱Do⠓2�����D����l�|�u��X�<o^F���S3K����Y��G�{���	(_��]ӧ����Ȝee�z�a01�!�N���')ھ�'��g�B��n2���)[6'��:N!������n�	�BHb
�U֝���J#�]S$�	D1f�*�g��`aA$Ÿ��"�*���$���ϹA?����\����dt
�v
H��r#hj�4z��Q������0�����'[���3
���H�껋h���>��P��x���r--ڢ�2Y�g�b9XF&���`���Q��f�	Hs�f��Un���g�Ȥ�S��.�S�"3�,����U��NڡN.=��P@�@��ǘE$�ϛ
Bs
*3w�V<���&�ŭ����d�����u�dCY��x��
�f=T�
��3N��Qh�L$�Gc%J3�؛�e�{	Q�ψ$p��<�t�J���g&����ޥ��2��q��*:F
X�@Kx<�<�ӑ���]S�c���<���V�]s����=�B���n51�>�ލ�I�_��QL�?��>Z��S�t�\�Ke_��6�2x1��r�$�LH1|�g�c�=�XM���o&��b�a:��:�
�*��;:j,�h'Ѝ��l
�!�'V��g<� ��W��R�h��0�\�r�_�u�S`(Q@�@���B"=z<�����E~,�OV�u{�t2��o#���
�T
Хw�B��%����RJO
��*�>�^H	��z8�h2;��`� ���Np!�9�C؀��Jh���c�{9
�i�K.jWChS���S`pQ@,�$i��HL�rƁ�?vO�>�&b��x�S���W8���C�ʁ!�Z���K����ߠ$ R�ö^�v���S`(P@��Lc��p
�����H�Ȧ��f�	2�(��D͂��7�J��@[)}h���DQ�]T�2F;=�ĥW�Á2,�&���#l��Ȳ�`�+��)��*�E���ؿ��^-#X"��D�M����[���xȩ�"6�S`8Q@�t�vmD"<^��Xۃ˸��x*'�S[9
�>��Aj��G_C儳��"Ɓ:��Pdy��|1j4RWj�Ae��|��J<%p*���l��?��OM��W@��kQe��c�iRI�.��B��k@(����{��G�e�?q/��^���
 m�!��x)Qs���K�q�]�	�?	��𧀢�c�q{00,�G�u,�ރ�2S��%��T1�_��?'��
I�q3� 򆻑7I�﷊
6���Ì־^�s"����QQT�L�*�*�e���(���©`��B��lZھ����I?��_��~}�߆Nzˆ��D�jdl�0�y��XU�M?+{�D1�#�!����`ϰy������u���'0]tJHA�q��t
j
�9��ca�(D���07kJ�2ϏhWs�ۇhp ��p,��/Ɲ{�.�’��m
�	:Fd,t5!����J=���!aLjC`@` ��eDٺP�ѓ�#���p`�R����R�AO�)0�( �n�a	�h��%?e%��W�N�!�O4�
�bzk����:EDv�}!�3χ��^����S`�R�������k�Eݑ ���PO�J��g��g�
�/�	��颿*��đL�,��X�3L͵�>�)�u��ּM��/�Jx�
Q]�K��i�p`�L�6�/��E�^��i��k��Ɲ
J�T��N4I�l�?�_���z1�YH�8���N=�����f��A��Nm
41���Z�;��uu�Bƚ�ɖ{�6���=����D[f�=����B���X�x8���Z�D�Ù�TV���ڄ��8��i,�3�^�=lm�k�]�_e=b�H�$�&��Ce�t����w)���C� �����A�y��V�D* ��$Ўj�kl��|!k�u��Dٛ���%���+o@��K�ȣ��[�:���D�s5"ڡ�%�HK�
 "�7��!����mK�UpcUW��6`a\���ν呣�ʠ��m��'��G.��cƢi���ZL�U@9_C�dL��*Ѓ/��ё�4v��w�e�y(�����ߕL�o�v) �jnpvB��G��ulu�P�@"Q���.y�� �O�V���]��Sx�_@�[�m?5:��4	=���M�9ob�e�l�o���e��9�*cJƖ���I����H�އ���������?��<�\y��g��_J���M��X
�����upqqA��	�Y_*LB$5y_Nm��]�"H���yE�X��Ù��о��
.�09���P��^T �i_�U�4���7 �l�L�6 �?���:�4�p���6D���%�|dE�ʋa.�CSU1r��X]F��0�#F�-$~�(����wM9,������7��J�;R�ps3����ިg�������V't�,�������F�k cr1��c�`o@$+��h�X��w�U��3�]t`C��L��:��
��0�_���ob��-�S�4i���Y8���fJ��}h��I=�ƭ���}6�O�e�#���zO_���C��u8��M����rۯ���ʎ��R��n1����-c��/ת<���oGC�(v}��"����V��F�=w-6����ʌO��Q�i4b�1���D��/�^���h�r�!0c�=ٯL��3d�����#;��E�o�2���q̀��X�]���/��������)�K�SC�ھ��?��9��]��]���O�s(ʼn;R7��w���;���#,,
\>����w{�P�ዼ�ZW�pW �Hݻ��]E�+��RIo�òƐ�U�`j�K�`��HU�4���k+���{���ة"���~��8��)��.Z�Lt8�p$ݝ9�\^ם�_$��z*Ⱦ�u��Z�^x�u�_x�A�g-�7]�gc-¶�e��2����n������#�Pw0.2%�����R@Xn��+j��3��8Ri�˘AO���څ�2�.�{��P�ɿ{uAQhRDD�"zb?( B���ѹ0�n���7ۏ{�\*��OQV*K1%>�a��džP�6A����@���|����D �F̲WH�z��3�/��ܱ�85��7�X/5
@��ѻW�#dի(��z]E�"�s�U�MM���5�q��ժ�<ph�Ș��7�N����HR�mD17T�s�~U�c8���]B�B�K�������n�ݭZYG���y��Op�
7���G��T��x���q�K�ݻv*�;��P��������DKq.F���2F����Q@����$���7�n\�̽�R{�zb ;G�*�/k���y0;t��"��>uUh��	�ڔ�����/�w�b�����Ԅ�v+���S�������ګ����7ϫ�Ә�v���{��3��矃E͖�ve`�;�����/i9舀{^���k�\�멤�Xg�I��)�6��w+)��x�^��$���V�L�J�;�'��d�Eh��O3���6|���~M�������-APu��)$�d�@ ֬Y�\��Ï୷�œ�3����pqv�s;���!))I���M����@��75�Qs�ܜ�<��t8=)���a)G��T2iU�2��E}�
�1���Fb���-&��a�F)��je�S��/:� N�w`�oE�FU2���s��m��C9///���q�wÓO>�K/����l�p	|}�GE���6nؠ\�έ�Ҋ���%�w��f�L�=��
���(���\����nߨU�viDMe`w�J^|=Ѧ��Հ�g�C�%��F]$�8�h��{���c���A�6g���x�ܶz]��gΜ�x�w�0F��H11��$Y�v-�4DQ�*�Ѵ�{$'&�&:�KA2�@Sg������W <�|��<��P�H��}�-Da6`3�;���Q�����"1�«��2�y�u�\�'�
���������Sm�~������Q=&�xz�L�����t��O�r��|���3����Y�J] ��ߍt:2�bMb��p*)�zN������yu<UHd6( �"�U�mg���uD�_)S����J_e�)i:ğ?��.��!�?"��NS��2v����4��U��~���FIY%���e��$���Ô�	"�g���u�N�?�ѯ=I��=ܱs�*�����M8�X
��˞p3��Y��L��偩��r�u6��j��k���E!盾E+_Ŏ���H����^���-[�)S&���/������r�0G3�#3㨢 �E�8�SȭhE@�QŦ��/��3�./l r�5z� ��vTe@c��ƛ�<J�A��6�������گ�M����������R���@q�7|���?R*���ݲ&��`������̞5�q�P@t��#H�G6lف�O_��ѝ�k�Gs�r�ѿ���w$L�
_2]
01}Qu��O�0�_E��
�>!hJ�Gj�u8
�`	���Ӧ�Q��GQ̪�4��\r)n��&F�Q��ר��\��]��ln!.���$�kW�pk����>��_�o�axPLեĮ���N�B��?�^�I�<[���^��b���a��Rt�F���ɩ	&�L�}��Jb0%	��Y�n�y޼�q�ͷ >6�/���5��x���g�Ԭ����'�bV�\��ÿ �d�Ӯ�S@���$��G�C��(fɖ�
h��a��6��;a
&�s��&�b���4���s�>x{WN�_
�j+X%�ظx�7��n�t`�=}�"��?-��~شY]7!�vrEֶ�2y�?2u\���p�|��s���@���,�fi-.{��!�I�&�I�-4�&t��K�:���]+����ˏ1��>y_��vq��/	VI��/�W\qF�������ދ{~�;E!hM��)�)�
����Q��;�.�o����*�G_(@��=~,\�k��5_�,`!��o(�C�uc�����o���_�D�٩��+���Q�6���U�&�ę���.��
ekP�.�6����F��%˃3!��6n�$��8z,99ہ�M뚯��b�Ю�wBDc���35�!M�p����/>�A���Tr
���
�?[^���A?��X��"mI�B�!
��n��O�6����I�3�!*4��Ι2���zg5�=,�*K�L��ع�!?4���eE�C( �]�ҷ�=���=v��˟��[o��R��ZE����)S�����h>CW��v!�����¡�G�B=�G�ĚBT� 'K��֒p�ot��*��O����K(y�>�;��O��@&�8���7�ޭZ���~��{��9�v}]����Ą�8��_�����ܻ����A�y��Z�	�׾�&��J����t
���r��1�J1�<b'Aª�n�s�\�V=�G���cc�����\�%�fN�]@���?�\��g?��I�.]�:s?��"���;��X��
��堙����P?Q?5z�^�ȅ��i9vp/���@U��؀H�Q����g����x�$���r�e�H������p�e_�GOa�ǯ��J�t�A����Œŋ:��b�3���r���Ĭ��&��Hi�q��ԢqFČS�I���z���-�~ʑ�pI߄��z�k��(���fv�)�3Cl�m�;a��Cy�����!NZ����X���˰�GPX��ub��m*�l�6=���/&~Ѣ�����D�_�� =��ؿ�eLLߦl���R�����p����������tdAL
>���cX�B"i��3�.���O9�S4�q�7c��w"�V�2��x�o�`����GL��8Qz�����k�+��@"�4TQ��[6�л/ %}�RukA5�&MƦkp8\8V5@$�>a4ؑ�À8u�Z�(0�49tֵ���ӓ2�}y g(�z����&�J׎׻r�744৷���{.Ex��9F���ww��[�o���6�!�����H��g�+��~�y�_��Z����6���X�'�Б�a�
�5\3��Q�C	�h/$F/@�g�h5靗������k�������A��F���c ϟbTR�*��x�`�.��e�]��_yEi��4T��U�>{�>��B{�xHg}{�rxk!�\��Q�kk�UDL�
tT�p
�&��	)�y.*����U�=��x�ys�{�A�Woc���h#Oq�G>w��V��+/��ӧ��O]l�x�`�.�C"""���իW)LO��t�Q)Ǜ?�nd�1�a6y�L�t������IH��pH_��rUE���s��"�#�U%y0#
ܽ}��<kI��J9S�`���o�ƦןVd�~��ʩ?�h9�Ὶ�C�[�"�o��F<�ȣJR+g������L�o�������W��x�n�V*��S����7LQ�.)�f	 ��(bG��D�4r�Pg'�b�Pɉ�߫����‘W��g���⩧���.Z�mWo�~�=+,,��rx�!��V�ש��f��b�s��n���ePq#֙@'*u�C��\8��k���%Κi�d��܊�g��:�`��J�n>e�k�,�㺏P��*1���z���}�Oo�M	��1}8}

���S�r�m�c���B�(�/_�,����W��Sp�݁��9����)0��e�T
X@4��r� {�V[�Hڞ���Wm\V�����V�1�����k~~���~&ϡ���R�	�r෿�-.��=�Bc5�X��_Q��{(�ᡨ��$Ԝ�l�3�DXi�F���E��G$�X�be"�2q<ug8�z*��W $ӆV*�ܸ��J���'�Q�e����]{��}�݇��8R�5��;cƤࡇ��k�	J,�>���^�P��$�:tO٥�����ɞ���1��8�5�bb�1��B39���Jb�G~�>�>�'��\"�ҫ+��.�wމ������0����x��'�x�UKA���z图�7�(HP%M�g�ʹH�ƸI)Ze�GI����z@��a���w�Zv@f�z�X�v<�>�Օ�K�=�~�`�yvj�Y�G'��3�>�Y�f�V�nh��G�T��p����(�c	�Ҩk
�*��0h
��4����b��E��u�ױ��Aq�:������,Ư~u'�Y]�F�oab����݃1cO�J���`����p��
x2z��P%ӉDѯ8��^g��W��"���ʆ-4�����1T�H���o_���������D%�����ZY
]��|<���Oh۷�Ҫ+uR��p������Zt&Е@~p4z��K������+�^�D+�
�*�*i`�^�w�a�G�!}�v�B����2��}�o�j��(��Ƥ�SZ�Y���F�go�㳗t&�F��4�4���m %�	_(=�x3ѕh����)h�Ȧ3�6��:TaW�����#{��td�������Y��^�ކ�#+A��D
��Bzz&r�JL�����QQ\�֊"�l�èIhd?�eG
QXg��mj@���8��w�3O�{�oE�g�~n�p��Q%j�ɺF�7;�3�!b׽�]teM; �/ۂtj�q�o����Z3���#/E��w�b������M�#�͍��%ɞ��\jџ"Q��܊j٢欧C�c��;�~���	2�݅$U�"(�ErV���M���1��J=�J��u�z��5w)��G�a0Qh��ED�z챿�
� ��E�#�P?����F<i�%7�Fb�L@!���'���!�z7a�&T��@�
�����,@�}�k��J}���w$OHK�<�t��>��W��׮U��J� <g�|��O�!�[������ؙ	H��Yp|�׈qd7^x5jx.��[Fz_�"�������}�0u�3<"F�H��J�q�B,7ܡ�"�g}5��}����Zeﺫ�O��,�Ռ���3��VQQ������1x	��]��9�/\0M�����oV��wW8T���_!�g]�Z*�D��L������1�Ae�deB"a"'���b��1���j���;�p��e�(�ZH�� b�U��3�r�_=�]�~�v��A���&� 4����ܪa%O�ߌF7�s�����lV���	Ԙ��F�x�/���Q��3�D�����=j��)Q��{'HH�)�Q�#��t�N���%��CX�v�B����c�h�i���\����փ����w�����ǎ�
�ߝ���9��7E���@yx���gm�.�Ш����#>>+W�T�(R����#��?Lk?���1���fZ��@+��G~&̛W �H5���S[�
�EK@=@ʌ�`?%<P⍍h�N0����O��3la0eGJ����A�s����?E`��ư aC�>����ctf�R�B]��֊/>KÖ�9�qCp�/�\U}�zD�F�		񈎎�_|�jYj�0��ӚO�5j,�@8����	X�|Ks�rh+�e��[�y�zۅ���3{5�ݮ�.k�p�l�m��N���wb[u��OO?5���K1v��ԶPL�̲�܄�6�k�c�|xrQX�'�V�c�U��Q\B;�>'v���q��?���=��V������R��{���O�°�[x�T(�X#Q-(ѻ�����N!���6�~�b�X+Cbd����C+�W��������ˎ�5󇇆".�,��'���W�w~��5\���B�_9Pߨ�8�}�Pw���◷}�w?ހҲ�~���ӓASn�SO���U��@��	l�!�]w�G�nj,`o���l����~�(F����|���ۍ??�O#?z�
�QAR���G�ݏ���5<��z�U����-�-=8y��|�7�[��J����an��;~��y�`�/��]��m0}�:�rWב(	t'��|1�h���M���i(�p`�{��l�tXy��,���gP�ߢ\R�i$=<2�'/ľ�4��RCx���C��&��'V��+�aG������:c����u��1q�*������L�>�8�������Qr�w$g`�nZ� F[
�ND%��][ߕ��'EN���ts�6QwRa-�>�$E%��?�凱�O�U������[j��8(v���_�(��ۤ�/�Xt(~1;��
n]�Z��́j��ۉg_Z��:u=��j��'��?܃����OP+҉qo|�1�/���'��m�^;�G<5ıg|�~�.�]g���q�[��`p���T6c�PxЂr8�(�R�j�F���	x�;�ix���=��n9��/��<���4���yK;^}�`���a-:�Q`DSB�ă�ߏa����i��qq�=�ll����>�}(��E�פ�?BSݝp�ˇ���NJ���
�.��|2�G0a��l׶lS�\\����42�~�ՅhRv��J����w^��1k����
�wnԜ��'�$&MC�؋��>�"���7˹	!��7��^��� M��W��b���Ι}�%Z	��c�i���u){�>y�_�+�dl�ẎG8�8��M����_��e�±5��J�h�<z&“�"��S��5�He��[� ��/b]�CW
K�ঌ���w(,����Xl^x���0m�,�
[�h�&���
l_�<��
9�U��@Æ@#�(�!������������S����ؙ8��z�-�)��z��ʩ��d�w��'�Q}K+�ٛ���
�vh�!����"��_��Ys�BSS���A�������1!��J"O��\�e �(�+
D��fi���h�9}��<���ޥ�Ev�GM9��cP`�@U�\Ԕ~�W�O���8>
^��A��j�,xm�Ax�`h�v�^�Ȭ�x�9�����"���JW��AE�U�"���%�H�z������Hd1�g�
;@��q �rQ3/V|�.0s��z�R���k�x����D��u�Ϛ&|����?ŭ&T�X�~�UQc3���(�x����:���X��J�������9r8�+�_柍 �c���k�/ՠ"֗����X��H��N�
��s��^3>e��P_�����
�K ޔS�6�@}�q8��+/��C�J?~��;q�����(�`�Ț6&)������w���ե'���7�u:<Mß�)���,ۃ��u�?Va}�?�����=�/��~ww7bڴ����3�O�|�`p�u��l�6lٲ�"��E
wy*�C?��tYY5U�u%������d�#��=�cpi2�Q{��A"��]�zߴw=r?}��~�i�s;O�њ���C�>Un1(m1P��I�=���3��1)�p�&���T�n�0�H/�W�3�l����hMX�Ҍ'^^
##�L˵���Ŷ211>��A]BۚNޭ�Ƀ�Y8�d�eTʺ��GS.�2�5��8m>��9��^W�ӬQ�@e�yIo� ���L�	��.
:Č&�u9�����c�jd��(��K�������ĐN3�f��q(s��z�e�;�@I���~6����#
D�L���
x�@+P�F���vd��յ���HJ�Vk$yoiG
𓿬��'���&�J���@̘����JY��8��e��S��g�}�������y.�i_O&��E�X�j�5]��T���&њ��@Βw%7�(��W ��{���?�%-3f:��&#�9�*�؉z:�I��fH��Λ�CT�>=�AfO7JQ��b>ꎷ�LE|�/n�n�#{d����oG�-�!Cjۢm`�������:
n!F,�8�E���Fv>�������[�������Y�0�@$���<Ĕ�N|OUT~V�����7X*@Qu	���'��>�l�7o7� �~o�'[�����cv��8��D��cg�'&�BX�tl��i���J��Z0!!�=��4�2�2H�h��Xq�f�E	O4�X_#��l�г�3JI�@|��+O�Q�Sb�xBt0g��"��5�G���CN��{u�;�~q|{�WU�s��cH,*)J%& ��f�����ٺ���bKb[��Ja)!]�����هP��]X�>��Z~��(�H��h���E�����xr�q�y�>l��a!� ��3���wZz��0���~��/Wc�=ڽ�"�5>�AФ”�M(�yp����nɈI^���x��[�:�1ֿ�T����탉��L2C���^��%���>F�<�����jx628(�`1�0R܋ڳiߊ����4U�@]A���¢�8�)�`G�����˫����&Da��8�d32��vA��liە�}�-B|�"~r�
|��U��w�x�YclB��4�VX��%T�f��U|:Bâ����g��l�ڏ�B�[�#*m+���}�)�=
_ź1���e2�k���:y�L�&;�e%��%4�|\�x����K������d��,M�'H'o�Qc��;���u�pfP:�zB=7�xŜ]��
g����	tvB�:���&��lz�c�M������m�cS�1�RI8߇Hr��6hd�6Db��EQ��:8��<���p�;�e%iSҗ�b�M�'=ڑmw��`v@t;�H@UM�hn�#��S;si��m�����>zN���"n�ld8&!�A,���N�t1#g��Vϝ��#���`�qz��"��p��c�k�|����C�n}|>��Pw�d�dL��C)-�y��w�Gb�̥
I���,%w<��}���pRs�K�
OC�H��u�p�,�w7�P֞�͒��k�1Pk&�d�#/�@K�؜�h��
���ev�xO>��1S3�ll3G�����3�\k�yp�ųll
N�q�~�1���
p*!�˪J3��j�o�{��\�����4���.�=��>�<��&�QҬKɃ�a���
�����X�RPt_�\�k3�ʲ_�ߑ�n�r��*�m�8[$�D�g�m�m+��}7a���Pf�nn2n�|ş��upwP�s��p2�:���‚y����d���������&�FA�����Mv+���ٸpJ8�k��d�5��2$�̐���[P�
l�G���ك҉H1��DC�Q�g�n��bv��󎠾�z@촵Zӓt9�˧�
�+_���9i���ڵ�h��)3��YH�7�ȪO��ο
n��q�y�S���S�%�a)1�h>���~y�{p'ì���v|���N <����$���V��<����0�IDAT7��.T��Z��u$�2r*ʐ��K��>L8�}�a�`�!�
%�Z����Қ�S�
7��L�M��di�/F�ܥpN'�v����M.<a&�N
����/�CY~��Sx��6~tb�_�c�QLͯ��b��h9o͇�SQ�ۍFľ����8�~SvdS�r�EC����ɨ����!�ވ��Wkb�CQWQ�o7f�ӳgf�R���z7�MH�
�KK1�+�΀T�(k�mIEF*�r0��
��h�]�(��48С�`�vd��4*����ù���
T��F�������S���[ď��<��u�f��[��-�N���3�fL�'�)(A j[�4�������zl��l.���Ѓ���N�tR@,����I+��u
1f�H�!�7��	IX8.krK��{2$�Y$��ف����"6��RӴi ���[����jT̽e>܄=|O�j�~'�v}%e3�v�d��sˬ���iw'�����
����i8"LH�`�P�yp�-�|�&2�|/����%g�͙�-�)<&����½�;��nq�1�f\|(Ǝ���3
{�e�\T��2��#�}�16%�4�=������H
>}l@���پ\���<0s�-X0o�r��h���q�SE�D��J.-Q�6`���?@iO΄T��Swo�S]‹z�OP��1��klGwߒ��P,b�+}��^%��)��I�W��3��+
�b
��;����q^Ex#E���`��92���OMU��(K��_*��f_�f�ZL��M�x�M��Q\ی�`Z�Xbҟ9����盰eOv)ƞ���~L�	SSR�­�%'wkF۟'�8|1��e}ޟ�z�,9��ÈB--k����i	�*2P�7�R�u�û;�#ԋ'	u*��Cag�����PF��'�ٳ�),��b�H�@Cڃ�./C�ס2vJh>,;V�$�KY!\����V<����'�YJ����
S�8�&�T����
pKݎگ���<����S�l��ǎFH�"z�$ ��C	�e�l|�~�t��f�4.]:C�y�R��.��>CIi5O�Y�;Yσ9ʐG�����4NI����y���,xZ��C�d_�Sb��B7;��p���A���v.-�+qSn��KA)�	a���Ӊ����a
up�bUʎNt~�/�&+-HW��rP�Ļ �V�ӊ0��� %����ݏ�ޫ�[(��eЌz3o=vL�Z�"M�2ɴ2�.S��
��=���U�)p���@�p3	�}7���y�[�r�K�#��=gL?.�����&W���C����⊸�t��\s�l���N�.*������Ǹ�<���J��j��ٞ�jZUU�h~��g�7{�h�E,6P$��<����_-K���!>���3�L@4��b��#�^�d�
��-��Ȉ��Ĭhb�CN(f�8K�3�k�zg�B���ZbAT3\���L~t��{��՘�R?��?���]�
��O ���Jh��Z�\Rw�l��(�P5X��k�Ғ� ��gm�ڝ
K�J����S�`�p�@�,nd�A�p���>yѤ����Fj��2�\��!�ʾ�fz~q��z��D�_G���K���s���u��^^^������5�q�k���x���xm�Q8s[��ɂFzkxkWҞ��Є
?�W���<��׺H1��r���d��5H�
��@SS3֮�QLj��	�Z�:�œM�k8���Hü1��c�6��כ���>9���E�� �^Y�r���wwx�JN؞v�������ðv%|B��A&���jJ��ڱ�Z�{�V.��t�{De?�#�P���� ��D�Y�=��	�=OT��KH/>�c��ŋX��C(�c�m	S`G���狨�s1{��4y��j���R_!g��E���q��Ϛ���(�Ͽ�v�>������G'�O?z�V�ߟ�7݁��b̚�ќQx�������o�����έ�f�<��o�����0F�q�wI����f��r�Q�.�L�'g�C�8
�#�[�_�.$M�eW#�z7-�I�
}فߧ�g8�x#��^F'�\
Z�	0�H!on�q
u4�|(
��QE�=T��4�ʿ��됹��>A�}¹�E̕��@,�n"�n�&��х2��!�bd���$�TYW^X�čX�z����bk�	�����؄	<�|��'`O�3-���S��_֌__;�����n��W�`���x��/�؋�9��F1�v��M_u��3�qn�Y^���Y��5�����3[����4\��S���!c��0&9��kV�%C$�uS�+�dP0i�0�:7>��n���?O��y1.��C�}u<B��Lޟ���8}�1N���� ?��\e�Z�ό�;�{a�!ܡ
���H�b�{Xh����u�V!��^��s��Q1��(�1QP,yh)�VJ�@O��n�x������ٝ�`K�IN�.���݄��g!4~6��#��\���TB1�����x�-
�T�"��WT��7�`�]�b9��BF{(A)��2k2�D�\�Yy�d���G�q��4�+��wY��[��w���f��R�(-���V�'=!��GaK|p�U����C��,	�2��V���{�Β���>�R�Y0rBC:+ �u��ç{�m۰������J�7Ѽ~�]��4�0ɜ{�ڄ��B&��O���D?2s,�faZytJ��s�@eFb�����ջ��w��=ݽ�4f.�"�a]��k��+�Y��	�/��rI�K��5���3�g�ď�e��s����'�I�١�P�:��{43G6qy�W���X��!�<?ߒKٽ?6~��_&��������i�X��ݏ��g�o�3�#c"�m�B�ɬ)LPbI���
��n����Fߔ�-j�.�Ϗ�>����5wӣr�$h[��\��$�TX��2�i��)N@���r+�"vb"���ՠ8����$�Ľ��m�j�Xڷ�wvJ���i�D��BT�\���†*g92��F��L����r�c�*�up�ٌ��X�|������۶���yp�~ִD*;
b'�b��t<��6`�{��Y�����G�it��ߥ'o��o�<�pMr�]�Xé�L|B���
��O�e0p)F�`��@��l�%q��K:��HH�G��>�\@$;_�1�X����:�&��fW�~K"M5��`A���W�Ҷc����"�Bמ'rb�5�iˣ�s��ګ�U�ɍ��s��x�:��r�Zo�|�3	I/F�)j�����Щ����ޒb⺹3��0�����8;0����́/����HG���8Ru�o6[��]���#��k@�����x,!�� ����n�h�{s4����hc�p{t Ǜ�V�u�#����,D���5���Z�ooB��7��\4�5+�!
���4r�
X�l�b���$te{��iC�*k�c�
�z��
;~��I��}ߣ��7�W��1��yg_�����
�tᶧ�%��p[Y�oٖ��~��}�sZr�{�J�^4N��㲓#��^�n?�e��uPY��՚"j}~V�ۅCt.je����/�c���ǔ��c�����j/�$.�����C��Go�����DB��`�>��9&[�2�R�e�|2��u,�6m�c���%ݝ&��cfA���A
i�cX�V�s��h{�������߈�(3Ӛ�4|�3��i�K+ܸ�?�Q�U��Ǜ�7�O7#�{������E��ל;�Qm�q�z_��M�u���� ��e�\��p�`q
�%�X8g|�శ������xS�˾����)���������x���h���v}�¢b�Z�s�<���7j�%Co��Ǜ�����uT���)�����7���Y`:ѷcA�^Fk4��E���œZ[~n�ħ�����Wo�ȵ�p6m���L��x��{¥(tAeK[���]��H��9�sK��?#{2q��
�\�
�]��c����P����d2$�W/��( my%�����|�F3�iϤ9�Wt�����Vn=t��מ��H?��V_DE!��Ü��|T�#�J��yXj�!���/�džC"5��(c�g��)j<U8��;m�1�%Fm $,II�����[:��i1�↔�"����/c����ȳ�=���_I7�q�����m2i��zթ����!U�u\������"�S\��Kx��|�v���x��$��)kּB*��`fP	�S����O����ZΘ	pO�z���ےwLg@2#&�!�
��*����m�Sk��jP�qG�R��Z��hӜX���n3�g�D�_�����a�������q�Rˣ�1�2�5V:�	��R�B�Ii��C.���3>�`@:p'F�\r�߄1��=N�(�@}�݇=q�i�"��@B��x~`�j�yk�mIW�l>U�l����x��=p�u�/n]�֔Ni�4Zz�__bwq��\:��?l) �F��o6��c4&.�As�F��w�L��G����m�1*:�[ʎ#�0���BU�d:����~�FG+@��h ���k�v(�&Hvq�F�a�>���%yN_�8840vz"}��?~��o�Á����i�>�T��?��3Q���8�o��8]���o	:à�g}��N�PVV��Vlij?d ��q@O���(��{S�����ѣbx���@x�U�()���|��>�Ͼ�ԫ���I_n"����l��G$�p���,��Dz��kаg+��˳9¼���O}��6��$���$�e�q�2&O���o���Hi���$]�60�_p���)��P��q�Q�(��l_�m��֞�~����C;*ܟ���P r/�]�����B�z.)S��y�y�]g��/�ن7ic�Sg�7v�D�(cx��6p�ֱet7�UN8�WXRZ�
�`�כq����p�^�Է�T?��_z�Ll�4!nv4���!Qt(*A	����,��Y�~i���~3ԭ����Ճ�۔����;��W���L��(����lb'�b�YJ�”N����7:������~��8V�iEܾ�aDW`���v�w#p��v$u)q*	���qq����v�NNj�Ƿb`��N�^�;ݽ?]w{�
��T���B%��ڍ܉XF/���L�~6_�^R@���qy��<��h�{8bCܑ��e�6a�Ս(�#��܁wBc
�{���K	�|7|���P�`$����y}�z���C���É^G
߿��k�psP:*<�B0j�y0Ө����Fn�p�O�3�@���\“{�#U�Hf�`����{I�v:h#�&j��̍��L|��A���|���Bm�
�V~�����.�@�u����B#`�;��9��"y�ee�j�Jr���a��t��Z��A��m�=�u��!�F�,�R�E��oD��5H��ɇh��S��g�z�Ã+��� �J�!ZL�RZ��X�M��f�t1H��H��Pxn�M�[��M()>O�q�����4�-�u�������$�|�O����:��߽ĵj���/x�x�څ=I���D|9�16?�N�9oO�x��(L����FՇ�x7
tq��>�ňr*CM�1ۆ���6:p���&���yb_V
��B^g����i-�7�dO>�ED�r��m�X�����3���ȴ���g�y:��B��MT�h�s���tJ~
���5w��1~�pt����;��ը��uw�[n��dS�M�b���R������F�#c$�P��٨3��`��{��-�pz�K�F�����5!20Fw��8��
T�ow4���55��1�^<�8�h�C?�H$�����8f��l����z�N�
DW�#���	���/%�()��J���y��)xw�Ď!�xх�
����S!�)�fF&�=G��9���u
tC��%�]G^��?����kBvv�J��R���׈{:��|��Ҧxb��P���f�=rқ|�"KN�'iE�f=M��Ȥ�2yr�(����!�F��Ag�n@t�=�,#����=ab�Ie�*1@b�K"�x8�j	=Q��N��P@	8BK��w�G`rR4�+����]u/������x���vb�Ve�w�dȵ*xq�O[!�u���S@�@w�%uq�3�,Q�4��ؿ��B�� �E����lnYJ����'��:t
�R@��u��6[5�C��U�kkٞ2Y�`�H�s���P_�6�y�2z�N�}��H�2�Bj�u�*{��C��U���=���}��Z���Z[�$��	��E&=]�@�( cJƖ����o�:c亮�^�p�].�L�-)�c)�(" U	�ip�I�H'pp�NVYQ�(�%�Y")Q�H�/ۖ�:����������H$�͛���3;�ߔ��k�{��s�ml�+,�`S�����p�A�����W�+�v�R���ŀb�
P��Sԭ�W_.v�o#��X��r�����|�7�&�3+�I�1�hCU,�.~��@�P��S�-�������ShKn�z�r
�_�=8�,)���H��*��%J%*Jg��?u�:E��䶮��y���O'Y1���E'��C�Gfŕ��)�MI%(%3��S\�)�\l�c�o0�8���z<��j��8rq�X�� ����I�)Ja����'eaꢶKN�t��;�M�&Ub����wdNZp�T�ˣ�Ð(���;�JS4,��ƿ�N���/����u��Y���X�l���~)�`���� ��n���@>Q*E1P���̑I��O	j�Wu랝�E��w+K
��"GaG�Z�<a=e[tKyqU��&��*A1�Pg:L�G�d�T��O�@��WBL����F�_�̗�����Hss�,�БA�擤R�0�N?�Q�/�
J�����=�ʖ��4/�s��z�Mh�L���6���<J��U�#\���4���Ǎ�u��|�.V$k�xB���!����K�LN��q���2��Sy6��Q:���3�a����Or��gx��Je-�I���m��A�k��
c�s.j����J[���,�$�c�~�=wL]�ޱm�:X�TK#?�+�Eҕ�����Ѵ�D1��g`��; �И����ͺ��e�U����G�A �*�L3�0y�k����2dE�b`�N�ȝ���s2�wҨX_�_^�w��ÿ��Ĉ�):"-�	fu
�q?����d ��4W|L2��b���תu���x=��p␟��<���iwʃ�;d(n�j��H%4!�o
���y�]�bQ�d>�(����j��:p8��ph^,V��l�-4^(��4,􌏸�V��Y�d�`�X��J5ɪ��q� ��]�s����p$���vY��[�������b�˳��1��)�d����4�@�d=/����E�J3q��;{ďUP�%�u3�D��d�^~��Ǽ��N��d
��c����j����ș��ǁ</�7���(��.�j�)�4�K�ˈ4%����@�]�����Y��wQ҅��]|�|	�U��2�P?p��HV��ٳs�X��`aD�ʳ:{�$�@�2@��?]ִX����w~T�V^E������^�:p8��@3�+��7d��37�لuR�[�pNSF�h?{��b��C��N�X�4�&6W8�'�{�$��g�e�^Y1�4#��1oO���/��ڰ�g{zN|��	���9ҏ~����cj���Nץ`��/�e_�Yl��:��M��R���:��t`����2��HzCy[�(���p�7���/�!Ȧ� O8jplbB��j+�F1	2	SF �*�P����;�i�]�7Ϝ1��;<�9pXW5Xo���d��~�i)�|p���!���W�f,3�Z�H��C����kL��>9q�{P~�{���Ri������Iex�#�
��#XVČ��]��v�h̓���sR��XW�P�ݶ��V|r��K��߰�[������u�i��q�������I{�q9�%��ѕСJ%�<|�{�Y�G��/�}��w����l��T�#ixG����
�te��D�m�#M�m�&�v�D1P/$���Y���$�qcy
�?Lg��֍6�����+a�A1����n�$zJ)�K�J�1��{�&1�|2q�dn�=�
�M��Z����]�ns�`���L�EĹ|M���b�TIR)*x5j�b�8|G�6���dj�2;���PX�
0h�k�6n��[!O�)�~
((��Iiq[���+!s������
ҥ6l"|��������K2<̹;��'��5�!�
��2�Q���C�Go@WR`uy�/^�2��Ě`�n�
ʿ�4%�K2:tA|y�T���G
gM[6��“'a,�1@W�0� ���F�I��b�	���.]*q��aX/�;P��[g$b�ϗM���i�O�6���	\����%8QJ8���$-�����"ҔcJ6��\�/�4 Q���)?]}v��a�}���k#���<X�<�'07�fۊحNi�a��#oo���.�ЃM}fD�'��:��$9�oaasK}��c�M�Z1$�-4M��n�a��¼�"C҆�DܮV	a.Up��(Yo��E�s&ż<*c��@������jBj�P�	�8�����$%��SZZwK�ۃ�V���2`Nɺ1@�gq�kôv�>�]~^��2*�7��恚yMk�����3B\��¡��"z����H4k�
5�.�Hɖa�1}���FѷXN�|Q��l���)�a=��񪺹�o���3��	03���\�C��b�5�Y�F����Ur�g�i��yt����!'O����9<��ׁ/5����Z4���x�=@��-3�ߔC=^,<╔	�� @��)QT��!�h�5��ô$��E9y�UmT_��=l�G W�竘�%�YR� �=�D�X.1�{u(���n�J��
��o@M4�ϕJ)�j+�ݒ���$�N��g�A�Q��G��P��
|������Kي���9
/��{0<��Z��2��k^@�ܨ���ԍf��M�'Ć��o|[�P��;fp=��>�,`������=��-u��%�N�ɍ#.���+]�m2��kn\��*]1p/q.��
�������w��T�����;�Լԋ �t�8��-ࣀ0���Aiw�d��&Ici�`ڤz2�6�sO'B��M�4���?�v��ppۓ��u����z2�^z'�'T��ea~FB����Jo[�%��@4WU	�yk��,�Y�|ț���%�{M��G��s41X�q��*��u#�fH,�U���]�a��d2�F#��kSL�vaX1�)��11��D1��<^�Ev�ȴ��u팄BK�*?�����R~>�z4�n�%���2��ὤS	YNI"�,�tD��꒑�
F@y�!�~z4k�G��ٱK��I,ξ;E�w�1�h�Pz��kE��V.��:8��U�
�S�a\ ��H`i��%�Nʑ��1���e�^�55�&�ݘ��>۴L�.������K*]R!>�C|xX�V���x�k�_����C���0;*.kJRX��pG�2N�'��j���W�Yw��ﲘ�gH�&�Hd�ܼ�J}�%�w��O��JrJ:�&e�
������\����MK:Џ��6���-.�6� ��!o���%>��<P����x�c��㚌�xU��'�$������g|��^���=.<‡�z����n�GEpffTZlAI����c�&�SV0�0��T�P�n?��N(�.{J��g$<}S���e�´r�;C�#���nm�j�J��\��9��^�	��[���t6���؊�Ǽv�,c�2vQ3��&7�=�d�⧥%� ��!�.ɕ�oiϚϼ�0�w�W�a���;"O�Ȗ��;��;�ǁ�:��J��E�!�#�I]��v1;�e&i��&���Jj��$�f6�v[J2q�ě�C5�\�Lǐ]y�._I�5d�P��q}�V6����~���i�h�!�yOy�8ڏ�Bv�8�^�OY��N?�^6�c�CNC���:؍��Ҏ�{�kr��w��\W"c��kW����}~S�|�VS���V6�>"7>|�p�a���Ǥ�縌'an,\
�o7�%�����1g�ằx3�,ɢ�]����ᲄ�ׁ�`Ur�K#���T�x�'(Y������`l.
W��<@#�Y2qU�H�'�n(>�q������Sr���3�>�~����@�H#���S�C�@k�O�����t��Nɚ,0f�/h#�Z.����3j�4��Ϧe�%*��)9���r���T|�"e�?^N�]e��
��ZP6'?�ēb��G��mZ�RD��:)_X%kg����+&�pc����£��Trp>F����_��_�'e��[��v���O�T$ǎ��=G$j�3�#`�B����,1�i/J�{�Q�p�%Y`�\��=�|��eV?y���><
x��ČfD��.�dL~�ò����-t�Rf&�ly���^���6�uY����gez�\�x��b��d�R�������P�6+��"�>Y`����)�7��-�C�X�,��G�Ȟ���z�*��K�1���,�ڭ��\��0�&��M�l�i�`η���ޒ�kפ�m��JP��x�����|
`�6��M��1q�7��c	�	|��<e���%�-]����m���{'F!������.G$��e��EHKw����Ǵב�V˲ģ�208 +�:�$%���q(S�|6t�^ة�who���V}���5��G��C��'�g��@ły'�k���[P-p���C���,��[��6�,JEV��U�F��Hm[UxT��V,��I6]��%�X���a(~�`�C23=&\�q�����m���!�@)�(�G����k7F!v���+��]�V���&o+�5�a��l�0�
��]Xs�NmV�7�[v�b�Υ���,���%���Y/��_l�8z�%%�Ȕ����uJ�E*<��A�M|J�0�@�t6�j@/�Ճ�~��"6e���r�A��Ja�"�Gv�o�6��DWd��� �pҡUV0�	MA^CN,�:���Cf���L)��2��
���*,����m��s�S�i�$���
�X�^J*�fk՚��De�7����1�$�8Ϋ�����X�WR"�?�wP��b`/��#�1���R�YK��V��{P\�V�����GfO8��Xaw��b[mn��<��7�ȭ��LeaTc mA������3��jI��MZ3̍^�$��^H*Ռͥ�Y�n��-@:�,1(���'���.#�y`'���@I(Piv�1�?�-��<x�Av1#�Њ!�V�τ��0�ı
i� �.,�Ĕ�m4X
NJ�w��V�ff>�ђ�E)����\�Jo{C����!}o,�W��ᇒ�P�r�
�ق
4���&��V@I�������\��ķ�*1�@��,p;�?�8@���`�꾒�`cɧŸ�@N���cr9�wQ�(JQ��^T�G���хo��$��l�'��ӟ��w��wnW�+d@�
���nn���~�;h����Z��.�2��0�.���[�3��np:>����C�.=4�-@���C�>7���@e���9�=�=��9 a��V_���V��j�
67����	�O����8�����H0��B�e=�BE'��9���l�[�����o�UR�(P���K�Ah�1��a���:�� 0`�4�r�
M��;B�Tho��g��.=�_I�1�.��x[IEND�B`�includes/rest-api.php000064400000031612147510545420010621 0ustar00<?php

add_action(
	'rest_api_init',
	static function () {
		$controller = new WPCF7_REST_Controller;
		$controller->register_routes();
	},
	10, 0
);


class WPCF7_REST_Controller {

	const route_namespace = 'contact-form-7/v1';

	public function register_routes() {

		register_rest_route( self::route_namespace,
			'/contact-forms',
			array(
				array(
					'methods' => WP_REST_Server::READABLE,
					'callback' => array( $this, 'get_contact_forms' ),
					'permission_callback' => static function () {
						if ( current_user_can( 'wpcf7_read_contact_forms' ) ) {
							return true;
						} else {
							return new WP_Error( 'wpcf7_forbidden',
								__( "You are not allowed to access contact forms.", 'contact-form-7' ),
								array( 'status' => 403 )
							);
						}
					},
				),
				array(
					'methods' => WP_REST_Server::CREATABLE,
					'callback' => array( $this, 'create_contact_form' ),
					'permission_callback' => static function () {
						if ( current_user_can( 'wpcf7_edit_contact_forms' ) ) {
							return true;
						} else {
							return new WP_Error( 'wpcf7_forbidden',
								__( "You are not allowed to create a contact form.", 'contact-form-7' ),
								array( 'status' => 403 )
							);
						}
					},
				),
			)
		);

		register_rest_route( self::route_namespace,
			'/contact-forms/(?P<id>\d+)',
			array(
				array(
					'methods' => WP_REST_Server::READABLE,
					'callback' => array( $this, 'get_contact_form' ),
					'permission_callback' => static function ( WP_REST_Request $request ) {
						$id = (int) $request->get_param( 'id' );

						if ( current_user_can( 'wpcf7_edit_contact_form', $id ) ) {
							return true;
						} else {
							return new WP_Error( 'wpcf7_forbidden',
								__( "You are not allowed to access the requested contact form.", 'contact-form-7' ),
								array( 'status' => 403 )
							);
						}
					},
				),
				array(
					'methods' => WP_REST_Server::EDITABLE,
					'callback' => array( $this, 'update_contact_form' ),
					'permission_callback' => static function ( WP_REST_Request $request ) {
						$id = (int) $request->get_param( 'id' );

						if ( current_user_can( 'wpcf7_edit_contact_form', $id ) ) {
							return true;
						} else {
							return new WP_Error( 'wpcf7_forbidden',
								__( "You are not allowed to access the requested contact form.", 'contact-form-7' ),
								array( 'status' => 403 )
							);
						}
					},
				),
				array(
					'methods' => WP_REST_Server::DELETABLE,
					'callback' => array( $this, 'delete_contact_form' ),
					'permission_callback' => static function ( WP_REST_Request $request ) {
						$id = (int) $request->get_param( 'id' );

						if ( current_user_can( 'wpcf7_delete_contact_form', $id ) ) {
							return true;
						} else {
							return new WP_Error( 'wpcf7_forbidden',
								__( "You are not allowed to access the requested contact form.", 'contact-form-7' ),
								array( 'status' => 403 )
							);
						}
					},
				),
			)
		);

		register_rest_route( self::route_namespace,
			'/contact-forms/(?P<id>\d+)/feedback',
			array(
				array(
					'methods' => WP_REST_Server::CREATABLE,
					'callback' => array( $this, 'create_feedback' ),
					'permission_callback' => '__return_true',
				),
			)
		);

		register_rest_route( self::route_namespace,
			'/contact-forms/(?P<id>\d+)/feedback/schema',
			array(
				array(
					'methods' => WP_REST_Server::READABLE,
					'callback' => array( $this, 'get_schema' ),
					'permission_callback' => '__return_true',
				),
				'schema' => 'wpcf7_swv_get_meta_schema',
			)
		);

		register_rest_route( self::route_namespace,
			'/contact-forms/(?P<id>\d+)/refill',
			array(
				array(
					'methods' => WP_REST_Server::READABLE,
					'callback' => array( $this, 'get_refill' ),
					'permission_callback' => '__return_true',
				),
			)
		);
	}

	public function get_contact_forms( WP_REST_Request $request ) {
		$args = array();

		$per_page = $request->get_param( 'per_page' );

		if ( null !== $per_page ) {
			$args['posts_per_page'] = (int) $per_page;
		}

		$offset = $request->get_param( 'offset' );

		if ( null !== $offset ) {
			$args['offset'] = (int) $offset;
		}

		$order = $request->get_param( 'order' );

		if ( null !== $order ) {
			$args['order'] = (string) $order;
		}

		$orderby = $request->get_param( 'orderby' );

		if ( null !== $orderby ) {
			$args['orderby'] = (string) $orderby;
		}

		$search = $request->get_param( 'search' );

		if ( null !== $search ) {
			$args['s'] = (string) $search;
		}

		$items = WPCF7_ContactForm::find( $args );

		$response = array();

		foreach ( $items as $item ) {
			$response[] = array(
				'id' => $item->id(),
				'hash' => $item->hash(),
				'slug' => $item->name(),
				'title' => $item->title(),
				'locale' => $item->locale(),
			);
		}

		return rest_ensure_response( $response );
	}

	public function create_contact_form( WP_REST_Request $request ) {
		$id = (int) $request->get_param( 'id' );

		if ( $id ) {
			return new WP_Error( 'wpcf7_post_exists',
				__( "Cannot create existing contact form.", 'contact-form-7' ),
				array( 'status' => 400 )
			);
		}

		$args = $request->get_params();
		$args['id'] = -1; // Create
		$context = $request->get_param( 'context' );
		$item = wpcf7_save_contact_form( $args, $context );

		if ( ! $item ) {
			return new WP_Error( 'wpcf7_cannot_save',
				__( "There was an error saving the contact form.", 'contact-form-7' ),
				array( 'status' => 500 )
			);
		}

		$response = array(
			'id' => $item->id(),
			'slug' => $item->name(),
			'title' => $item->title(),
			'locale' => $item->locale(),
			'properties' => $this->get_properties( $item ),
			'config_errors' => array(),
		);

		if ( wpcf7_validate_configuration() ) {
			$config_validator = new WPCF7_ConfigValidator( $item );
			$config_validator->validate();

			$response['config_errors'] = $config_validator->collect_error_messages();

			if ( 'save' == $context ) {
				$config_validator->save();
			}
		}

		return rest_ensure_response( $response );
	}

	public function get_contact_form( WP_REST_Request $request ) {
		$id = (int) $request->get_param( 'id' );
		$item = wpcf7_contact_form( $id );

		if ( ! $item ) {
			return new WP_Error( 'wpcf7_not_found',
				__( "The requested contact form was not found.", 'contact-form-7' ),
				array( 'status' => 404 )
			);
		}

		$response = array(
			'id' => $item->id(),
			'slug' => $item->name(),
			'title' => $item->title(),
			'locale' => $item->locale(),
			'properties' => $this->get_properties( $item ),
		);

		return rest_ensure_response( $response );
	}

	public function update_contact_form( WP_REST_Request $request ) {
		$id = (int) $request->get_param( 'id' );
		$item = wpcf7_contact_form( $id );

		if ( ! $item ) {
			return new WP_Error( 'wpcf7_not_found',
				__( "The requested contact form was not found.", 'contact-form-7' ),
				array( 'status' => 404 )
			);
		}

		$args = $request->get_params();
		$context = $request->get_param( 'context' );
		$item = wpcf7_save_contact_form( $args, $context );

		if ( ! $item ) {
			return new WP_Error( 'wpcf7_cannot_save',
				__( "There was an error saving the contact form.", 'contact-form-7' ),
				array( 'status' => 500 )
			);
		}

		$response = array(
			'id' => $item->id(),
			'slug' => $item->name(),
			'title' => $item->title(),
			'locale' => $item->locale(),
			'properties' => $this->get_properties( $item ),
			'config_errors' => array(),
		);

		if ( wpcf7_validate_configuration() ) {
			$config_validator = new WPCF7_ConfigValidator( $item );
			$config_validator->validate();

			$response['config_errors'] = $config_validator->collect_error_messages();

			if ( 'save' == $context ) {
				$config_validator->save();
			}
		}

		return rest_ensure_response( $response );
	}

	public function delete_contact_form( WP_REST_Request $request ) {
		$id = (int) $request->get_param( 'id' );
		$item = wpcf7_contact_form( $id );

		if ( ! $item ) {
			return new WP_Error( 'wpcf7_not_found',
				__( "The requested contact form was not found.", 'contact-form-7' ),
				array( 'status' => 404 )
			);
		}

		$result = $item->delete();

		if ( ! $result ) {
			return new WP_Error( 'wpcf7_cannot_delete',
				__( "There was an error deleting the contact form.", 'contact-form-7' ),
				array( 'status' => 500 )
			);
		}

		$response = array( 'deleted' => true );

		return rest_ensure_response( $response );
	}

	public function create_feedback( WP_REST_Request $request ) {
		$content_type = $request->get_header( 'Content-Type' );

		if ( ! str_starts_with( $content_type, 'multipart/form-data' ) ) {
			return new WP_Error( 'wpcf7_unsupported_media_type',
				__( "The request payload format is not supported.", 'contact-form-7' ),
				array( 'status' => 415 )
			);
		}

		$url_params = $request->get_url_params();

		$item = null;

		if ( ! empty( $url_params['id'] ) ) {
			$item = wpcf7_contact_form( $url_params['id'] );
		}

		if ( ! $item ) {
			return new WP_Error( 'wpcf7_not_found',
				__( "The requested contact form was not found.", 'contact-form-7' ),
				array( 'status' => 404 )
			);
		}

		$unit_tag = wpcf7_sanitize_unit_tag(
			$request->get_param( '_wpcf7_unit_tag' )
		);

		if ( empty( $unit_tag ) ) {
			return new WP_Error( 'wpcf7_unit_tag_not_found',
				__( "There is no valid unit tag.", 'contact-form-7' ),
				array( 'status' => 400 )
			);
		}

		$result = $item->submit();

		$response = array_merge( $result, array(
			'into' => sprintf( '#%s', $unit_tag ),
			'invalid_fields' => array(),
		) );

		if ( ! empty( $result['invalid_fields'] ) ) {
			$invalid_fields = array();

			foreach ( (array) $result['invalid_fields'] as $name => $field ) {
				if ( ! wpcf7_is_name( $name ) ) {
					continue;
				}

				$name = strtr( $name, '.', '_' );

				$invalid_fields[] = array(
					'field' => $name,
					'message' => $field['reason'],
					'idref' => $field['idref'],
					'error_id' => sprintf(
						'%1$s-ve-%2$s',
						$unit_tag,
						$name
					),
				);
			}

			$response['invalid_fields'] = $invalid_fields;
		}

		$response = wpcf7_apply_filters_deprecated(
			'wpcf7_ajax_json_echo',
			array( $response, $result ),
			'5.2',
			'wpcf7_feedback_response'
		);

		$response = apply_filters( 'wpcf7_feedback_response', $response, $result );

		return rest_ensure_response( $response );
	}


	public function get_schema( WP_REST_Request $request ) {
		$url_params = $request->get_url_params();

		$item = null;

		if ( ! empty( $url_params['id'] ) ) {
			$item = wpcf7_contact_form( $url_params['id'] );
		}

		if ( ! $item ) {
			return new WP_Error( 'wpcf7_not_found',
				__( "The requested contact form was not found.", 'contact-form-7' ),
				array( 'status' => 404 )
			);
		}

		$schema = $item->get_schema();

		$response = isset( $schema ) ? $schema->to_array() : array();

		return rest_ensure_response( $response );
	}


	public function get_refill( WP_REST_Request $request ) {
		$id = (int) $request->get_param( 'id' );
		$item = wpcf7_contact_form( $id );

		if ( ! $item ) {
			return new WP_Error( 'wpcf7_not_found',
				__( "The requested contact form was not found.", 'contact-form-7' ),
				array( 'status' => 404 )
			);
		}

		$response = wpcf7_apply_filters_deprecated(
			'wpcf7_ajax_onload',
			array( array() ),
			'5.2',
			'wpcf7_refill_response'
		);

		$response = apply_filters( 'wpcf7_refill_response', array() );

		return rest_ensure_response( $response );
	}

	private function get_properties( WPCF7_ContactForm $contact_form ) {
		$properties = $contact_form->get_properties();

		$properties['form'] = array(
			'content' => (string) $properties['form'],
			'fields' => array_map(
				static function ( WPCF7_FormTag $form_tag ) {
					return array(
						'type' => $form_tag->type,
						'basetype' => $form_tag->basetype,
						'name' => $form_tag->name,
						'options' => $form_tag->options,
						'raw_values' => $form_tag->raw_values,
						'labels' => $form_tag->labels,
						'values' => $form_tag->values,
						'pipes' => $form_tag->pipes instanceof WPCF7_Pipes
							? $form_tag->pipes->to_array()
							: $form_tag->pipes,
						'content' => $form_tag->content,
					);
				},
				$contact_form->scan_form_tags()
			),
		);

		$properties['additional_settings'] = array(
			'content' => (string) $properties['additional_settings'],
			'settings' => array_filter( array_map(
				static function ( $setting ) {
					$pattern = '/^([a-zA-Z0-9_]+)[\t ]*:(.*)$/';

					if ( preg_match( $pattern, $setting, $matches ) ) {
						$name = trim( $matches[1] );
						$value = trim( $matches[2] );

						if ( in_array( $value, array( 'on', 'true' ), true ) ) {
							$value = true;
						} elseif ( in_array( $value, array( 'off', 'false' ), true ) ) {
							$value = false;
						}

						return array( $name, $value );
					}

					return false;
				},
				explode( "\n", $properties['additional_settings'] )
			) ),
		);

		return $properties;
	}

	private function get_argument_schema() {
		return array(
			'id' => array(
				'description' => __( "Unique identifier for the contact form.", 'contact-form-7' ),
				'type' => 'integer',
				'required' => true,
			),
		);
	}

}
includes/upgrade.php000064400000005777147510545420010541 0ustar00<?php

add_action( 'wpcf7_upgrade', 'wpcf7_upgrade_58', 10, 2 );

/**
 * Runs functions necessary when upgrading from old plugin versions before 5.8.
 *
 * @since 5.8.0 New `_config_validation` post meta is introduced.
 */
function wpcf7_upgrade_58( $new_ver, $old_ver ) {
	if ( ! version_compare( $old_ver, '5.8-dev', '<' ) ) {
		return;
	}

	$posts = WPCF7_ContactForm::find( array(
		'post_status' => 'any',
		'posts_per_page' => -1,
	) );

	foreach ( $posts as $post ) {
		$post_id = $post->id();

		// Delete the old post meta for config-validation results.
		delete_post_meta( $post_id, '_config_errors' );

		// Add the contact form hash.
		add_post_meta( $post_id, '_hash',
			wpcf7_generate_contact_form_hash( $post_id ),
			true // Unique
		);
	}
}


add_action( 'wpcf7_upgrade', 'wpcf7_convert_to_cpt', 10, 2 );

/**
 * Converts old data in the dedicated database table to custom posts.
 *
 * @since 3.0.0 `wpcf7_contact_form` CPT is introduced.
 */
function wpcf7_convert_to_cpt( $new_ver, $old_ver ) {
	global $wpdb;

	if ( ! version_compare( $old_ver, '3.0-dev', '<' ) ) {
		return;
	}

	$old_rows = array();

	$table_name = $wpdb->prefix . "contact_form_7";

	if ( $wpdb->get_var( "SHOW TABLES LIKE '$table_name'" ) ) {
		$old_rows = $wpdb->get_results( "SELECT * FROM $table_name" );
	} elseif ( $opt = get_option( 'wpcf7' )
	and ! empty( $opt['contact_forms'] ) ) {
		foreach ( (array) $opt['contact_forms'] as $key => $value ) {
			$old_rows[] = (object) array_merge(
				$value,
				array( 'cf7_unit_id' => $key )
			);
		}
	}

	foreach ( (array) $old_rows as $row ) {
		$q = "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_old_cf7_unit_id'"
			. $wpdb->prepare( " AND meta_value = %d", $row->cf7_unit_id );

		if ( $wpdb->get_var( $q ) ) {
			continue;
		}

		$postarr = array(
			'post_type' => 'wpcf7_contact_form',
			'post_status' => 'publish',
			'post_title' => maybe_unserialize( $row->title ),
		);

		$post_id = wp_insert_post( $postarr );

		if ( $post_id ) {
			update_post_meta( $post_id, '_old_cf7_unit_id', $row->cf7_unit_id );

			$metas = array(
				'form',
				'mail',
				'mail_2',
				'messages',
				'additional_settings',
			);

			foreach ( $metas as $meta ) {
				update_post_meta( $post_id, '_' . $meta,
					wpcf7_normalize_newline_deep( maybe_unserialize( $row->{$meta} ) )
				);
			}
		}
	}
}


add_action( 'wpcf7_upgrade', 'wpcf7_prepend_underscore', 10, 2 );

/**
 * Prepends an underscore to post meta keys.
 */
function wpcf7_prepend_underscore( $new_ver, $old_ver ) {
	if ( version_compare( $old_ver, '3.0-dev', '<' ) ) {
		return;
	}

	if ( ! version_compare( $old_ver, '3.3-dev', '<' ) ) {
		return;
	}

	$posts = WPCF7_ContactForm::find( array(
		'post_status' => 'any',
		'posts_per_page' => -1,
	) );

	foreach ( $posts as $post ) {
		$props = $post->get_properties();

		foreach ( $props as $prop => $value ) {
			if ( metadata_exists( 'post', $post->id(), '_' . $prop ) ) {
				continue;
			}

			update_post_meta( $post->id(), '_' . $prop, $value );
			delete_post_meta( $post->id(), $prop );
		}
	}
}
includes/mail.php000064400000035034147510545420010021 0ustar00<?php

add_filter( 'wpcf7_mail_html_body', 'wpcf7_mail_html_body_autop', 10, 1 );

/**
 * Filter callback that applies auto-p to HTML email message body.
 */
function wpcf7_mail_html_body_autop( $body ) {
	if ( wpcf7_autop_or_not( array( 'for' => 'mail' ) ) ) {
		$body = wpcf7_autop( $body );
	}

	return $body;
}


/**
 * Class that represents an attempt to compose and send email.
 */
class WPCF7_Mail {

	private static $current = null;

	private $name = '';
	private $locale = '';
	private $template = array();
	private $component = '';
	private $use_html = false;
	private $exclude_blank = false;


	/**
	 * Returns the singleton instance of this class.
	 */
	public static function get_current() {
		return self::$current;
	}


	/**
	 * Returns the name of the email template currently processed.
	 *
	 * Expected output: 'mail' or 'mail_2'
	 */
	public static function get_current_template_name() {
		$current = self::get_current();

		if ( $current instanceof self ) {
			return $current->get_template_name();
		}
	}


	/**
	 * Returns the name of the email template component currently processed.
	 *
	 * Expected output: 'recipient', 'sender', 'subject',
	 *                  'additional_headers', 'body', or 'attachments'
	 */
	public static function get_current_component_name() {
		$current = self::get_current();

		if ( $current instanceof self ) {
			return $current->get_component_name();
		}
	}


	/**
	 * Composes and sends email based on the specified template.
	 *
	 * @param array $template Array of email template.
	 * @param string $name Optional name of the template, such as
	 *               'mail' or 'mail_2'. Default empty string.
	 * @return bool Whether the email was sent successfully.
	 */
	public static function send( $template, $name = '' ) {
		self::$current = new self( $name, $template );
		return self::$current->compose();
	}


	/**
	 * The constructor method.
	 *
	 * @param string $name The name of the email template.
	 *               Such as 'mail' or 'mail_2'.
	 * @param array $template Array of email template.
	 */
	private function __construct( $name, $template ) {
		$this->name = trim( $name );
		$this->use_html = ! empty( $template['use_html'] );
		$this->exclude_blank = ! empty( $template['exclude_blank'] );

		$this->template = wp_parse_args( $template, array(
			'subject' => '',
			'sender' => '',
			'body' => '',
			'recipient' => '',
			'additional_headers' => '',
			'attachments' => '',
		) );

		if ( $submission = WPCF7_Submission::get_instance() ) {
			$contact_form = $submission->get_contact_form();
			$this->locale = $contact_form->locale();
		}
	}


	/**
	 * Returns the name of the email template.
	 */
	public function name() {
		return $this->name;
	}


	/**
	 * Returns the name of the email template. A wrapper method of name().
	 */
	public function get_template_name() {
		return $this->name();
	}


	/**
	 * Returns the name of the email template component currently processed.
	 */
	public function get_component_name() {
		return $this->component;
	}


	/**
	 * Retrieves a component from the email template.
	 *
	 * @param string $component The name of the component.
	 * @param bool $replace_tags Whether to replace mail-tags
	 *             within the component.
	 * @return string The text representation of the email component.
	 */
	public function get( $component, $replace_tags = false ) {
		$this->component = $component;

		$use_html = ( $this->use_html && 'body' === $component );
		$exclude_blank = ( $this->exclude_blank && 'body' === $component );

		$template = $this->template;
		$component = isset( $template[$component] ) ? $template[$component] : '';

		if ( $replace_tags ) {
			$component = $this->replace_tags( $component, array(
				'html' => $use_html,
				'exclude_blank' => $exclude_blank,
			) );

			if ( $use_html ) {
				// Convert <example@example.com> to &lt;example@example.com&gt;.
				$component = preg_replace_callback(
					'/<(.*?)>/',
					static function ( $matches ) {
						if ( is_email( $matches[1] ) ) {
							return sprintf( '&lt;%s&gt;', $matches[1] );
						} else {
							return $matches[0];
						}
					},
					$component
				);

				if ( ! preg_match( '%<html[>\s].*</html>%is', $component ) ) {
					$component = $this->htmlize( $component );
				}
			}
		}

		$this->component = '';

		return $component;
	}


	/**
	 * Creates HTML message body by adding the header and footer.
	 *
	 * @param string $body The body part of HTML.
	 * @return string Formatted HTML.
	 */
	private function htmlize( $body ) {
		if ( $this->locale ) {
			$lang_atts = sprintf( ' %s',
				wpcf7_format_atts( array(
					'dir' => wpcf7_is_rtl( $this->locale ) ? 'rtl' : 'ltr',
					'lang' => str_replace( '_', '-', $this->locale ),
				) )
			);
		} else {
			$lang_atts = '';
		}

		$header = apply_filters( 'wpcf7_mail_html_header',
			'<!doctype html>
<html xmlns="http://www.w3.org/1999/xhtml"' . $lang_atts . '>
<head>
<title>' . esc_html( $this->get( 'subject', true ) ) . '</title>
</head>
<body>
',
			$this
		);

		$body = apply_filters( 'wpcf7_mail_html_body', $body, $this );

		$footer = apply_filters( 'wpcf7_mail_html_footer',
			'</body>
</html>',
			$this
		);

		return $header . $body . $footer;
	}


	/**
	 * Composes an email message and attempts to send it.
	 *
	 * @param bool $send Whether to attempt to send email. Default true.
	 */
	private function compose( $send = true ) {
		$components = array(
			'subject' => $this->get( 'subject', true ),
			'sender' => $this->get( 'sender', true ),
			'body' => $this->get( 'body', true ),
			'recipient' => $this->get( 'recipient', true ),
			'additional_headers' => $this->get( 'additional_headers', true ),
			'attachments' => $this->attachments(),
		);

		$components = apply_filters( 'wpcf7_mail_components',
			$components, wpcf7_get_current_contact_form(), $this
		);

		if ( ! $send ) {
			return $components;
		}

		$subject = wpcf7_strip_newline( $components['subject'] );
		$sender = wpcf7_strip_newline( $components['sender'] );
		$recipient = wpcf7_strip_newline( $components['recipient'] );
		$body = $components['body'];
		$additional_headers = trim( $components['additional_headers'] );

		$headers = "From: $sender\n";

		if ( $this->use_html ) {
			$headers .= "Content-Type: text/html\n";
			$headers .= "X-WPCF7-Content-Type: text/html\n";
		} else {
			$headers .= "X-WPCF7-Content-Type: text/plain\n";
		}

		if ( $additional_headers ) {
			$headers .= $additional_headers . "\n";
		}

		$attachments = array_filter(
			(array) $components['attachments'],
			function ( $attachment ) {
				$path = path_join( WP_CONTENT_DIR, $attachment );

				if ( ! wpcf7_is_file_path_in_content_dir( $path ) ) {
					wp_trigger_error(
						'',
						sprintf(
							/* translators: %s: Attachment file path. */
							__( 'Failed to attach a file. %s is not in the allowed directory.', 'contact-form-7' ),
							$path
						),
						E_USER_NOTICE
					);

					return false;
				}

				if ( ! is_readable( $path ) or ! is_file( $path ) ) {
					wp_trigger_error(
						'',
						sprintf(
							/* translators: %s: Attachment file path. */
							__( 'Failed to attach a file. %s is not a readable file.', 'contact-form-7' ),
							$path
						),
						E_USER_NOTICE
					);

					return false;
				}

				static $total_size = array();

				if ( ! isset( $total_size[$this->name] ) ) {
					$total_size[$this->name] = 0;
				}

				$file_size = (int) @filesize( $path );

				if ( 25 * MB_IN_BYTES < $total_size[$this->name] + $file_size ) {
					wp_trigger_error(
						'',
						__( 'Failed to attach a file. The total file size exceeds the limit of 25 megabytes.', 'contact-form-7' ),
						E_USER_NOTICE
					);

					return false;
				}

				$total_size[$this->name] += $file_size;

				return true;
			}
		);

		return wp_mail( $recipient, $subject, $body, $headers, $attachments );
	}


	/**
	 * Replaces mail-tags within the given text.
	 */
	public function replace_tags( $content, $options = '' ) {
		if ( true === $options ) {
			$options = array( 'html' => true );
		}

		$options = wp_parse_args( $options, array(
			'html' => false,
			'exclude_blank' => false,
		) );

		return wpcf7_mail_replace_tags( $content, $options );
	}


	/**
	 * Creates an array of attachments based on uploaded files and local files.
	 */
	private function attachments( $template = null ) {
		if ( ! $template ) {
			$template = $this->get( 'attachments' );
		}

		$attachments = array();

		if ( $submission = WPCF7_Submission::get_instance() ) {
			$uploaded_files = $submission->uploaded_files();

			foreach ( (array) $uploaded_files as $name => $paths ) {
				if ( false !== strpos( $template, "[{$name}]" ) ) {
					$attachments = array_merge( $attachments, (array) $paths );
				}
			}
		}

		foreach ( explode( "\n", $template ) as $line ) {
			$line = trim( $line );

			if ( '' === $line or '[' == substr( $line, 0, 1 ) ) {
				continue;
			}

			$attachments[] = path_join( WP_CONTENT_DIR, $line );
		}

		if ( $submission = WPCF7_Submission::get_instance() ) {
			$attachments = array_merge(
				$attachments,
				(array) $submission->extra_attachments( $this->name )
			);
		}

		return $attachments;
	}
}


/**
 * Replaces all mail-tags within the given text content.
 *
 * @param string $content Text including mail-tags.
 * @param string|array $options Optional. Output options.
 * @return string Result of replacement.
 */
function wpcf7_mail_replace_tags( $content, $options = '' ) {
	$options = wp_parse_args( $options, array(
		'html' => false,
		'exclude_blank' => false,
	) );

	if ( is_array( $content ) ) {
		foreach ( $content as $key => $value ) {
			$content[$key] = wpcf7_mail_replace_tags( $value, $options );
		}

		return $content;
	}

	$content = explode( "\n", $content );

	foreach ( $content as $num => $line ) {
		$line = new WPCF7_MailTaggedText( $line, $options );
		$replaced = $line->replace_tags();

		if ( $options['exclude_blank'] ) {
			$replaced_tags = $line->get_replaced_tags();

			if ( empty( $replaced_tags )
			or array_filter( $replaced_tags, 'strlen' ) ) {
				$content[$num] = $replaced;
			} else {
				unset( $content[$num] ); // Remove a line.
			}
		} else {
			$content[$num] = $replaced;
		}
	}

	$content = implode( "\n", $content );

	return $content;
}


add_action( 'phpmailer_init', 'wpcf7_phpmailer_init', 10, 1 );

/**
 * Adds custom properties to the PHPMailer object.
 */
function wpcf7_phpmailer_init( $phpmailer ) {
	$custom_headers = $phpmailer->getCustomHeaders();
	$phpmailer->clearCustomHeaders();
	$wpcf7_content_type = false;

	foreach ( (array) $custom_headers as $custom_header ) {
		$name = $custom_header[0];
		$value = $custom_header[1];

		if ( 'X-WPCF7-Content-Type' === $name ) {
			$wpcf7_content_type = trim( $value );
		} else {
			$phpmailer->addCustomHeader( $name, $value );
		}
	}

	if ( 'text/html' === $wpcf7_content_type ) {
		$phpmailer->msgHTML( $phpmailer->Body );
	} elseif ( 'text/plain' === $wpcf7_content_type ) {
		$phpmailer->AltBody = '';
	}
}


/**
 * Class that represents a single-line text including mail-tags.
 */
class WPCF7_MailTaggedText {

	private $html = false;
	private $callback = null;
	private $content = '';
	private $replaced_tags = array();


	/**
	 * The constructor method.
	 */
	public function __construct( $content, $options = '' ) {
		$options = wp_parse_args( $options, array(
			'html' => false,
			'callback' => null,
		) );

		$this->html = (bool) $options['html'];

		if ( null !== $options['callback']
		and is_callable( $options['callback'] ) ) {
			$this->callback = $options['callback'];
		} elseif ( $this->html ) {
			$this->callback = array( $this, 'replace_tags_callback_html' );
		} else {
			$this->callback = array( $this, 'replace_tags_callback' );
		}

		$this->content = $content;
	}


	/**
	 * Retrieves mail-tags that have been replaced by this instance.
	 *
	 * @return array List of mail-tags replaced.
	 */
	public function get_replaced_tags() {
		return $this->replaced_tags;
	}


	/**
	 * Replaces mail-tags based on regexp.
	 */
	public function replace_tags() {
		$regex = '/(\[?)\[[\t ]*'
			. '([a-zA-Z_][0-9a-zA-Z:._-]*)' // [2] = name
			. '((?:[\t ]+"[^"]*"|[\t ]+\'[^\']*\')*)' // [3] = values
			. '[\t ]*\](\]?)/';

		return preg_replace_callback( $regex, $this->callback, $this->content );
	}


	/**
	 * Callback function for replacement. For HTML message body.
	 */
	private function replace_tags_callback_html( $matches ) {
		return $this->replace_tags_callback( $matches, true );
	}


	/**
	 * Callback function for replacement.
	 */
	private function replace_tags_callback( $matches, $html = false ) {
		// allow [[foo]] syntax for escaping a tag
		if ( $matches[1] == '['
		and $matches[4] == ']' ) {
			return substr( $matches[0], 1, -1 );
		}

		$tag = $matches[0];
		$tagname = $matches[2];
		$values = $matches[3];

		$mail_tag = new WPCF7_MailTag( $tag, $tagname, $values );
		$field_name = $mail_tag->field_name();

		$submission = WPCF7_Submission::get_instance();
		$submitted = $submission
			? $submission->get_posted_data( $field_name )
			: null;

		if ( $mail_tag->get_option( 'do_not_heat' ) ) {
			$submitted = wp_unslash( $_POST[$field_name] ?? '' );
		}

		$replaced = $submitted;

		if ( null !== $replaced ) {
			if ( $format = $mail_tag->get_option( 'format' ) ) {
				$replaced = $this->format( $replaced, $format );
			}

			$separator = ( 'body' === WPCF7_Mail::get_current_component_name() )
				? wp_get_list_item_separator()
				: ', ';

			$replaced = wpcf7_flat_join( $replaced, array(
				'separator' => $separator,
			) );

			if ( $html ) {
				$replaced = esc_html( $replaced );
				$replaced = wptexturize( $replaced );
			}
		}

		if ( $form_tag = $mail_tag->corresponding_form_tag() ) {
			$type = $form_tag->type;

			$replaced = apply_filters(
				"wpcf7_mail_tag_replaced_{$type}", $replaced,
				$submitted, $html, $mail_tag
			);
		}

		$replaced = apply_filters(
			'wpcf7_mail_tag_replaced', $replaced,
			$submitted, $html, $mail_tag
		);

		if ( null !== $replaced ) {
			$replaced = trim( $replaced );

			$this->replaced_tags[$tag] = $replaced;
			return $replaced;
		}

		$special = apply_filters( 'wpcf7_special_mail_tags', null,
			$mail_tag->tag_name(), $html, $mail_tag
		);

		if ( null !== $special ) {
			$this->replaced_tags[$tag] = $special;
			return $special;
		}

		return $tag;
	}


	/**
	 * Formats string based on the formatting option in the form-tag.
	 */
	public function format( $original, $format ) {
		$original = (array) $original;

		foreach ( $original as $key => $value ) {
			if ( preg_match( '/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/', $value ) ) {
				$datetime = date_create( $value, wp_timezone() );

				if ( false !== $datetime ) {
					$original[$key] = wp_date( $format, $datetime->getTimestamp() );
				}
			}
		}

		return $original;
	}

}
includes/contact-form-functions.php000064400000024401147510545420013475 0ustar00<?php
/**
 * Contact form helper functions
 */


/**
 * Wrapper function of WPCF7_ContactForm::get_instance().
 *
 * @param WPCF7_ContactForm|WP_Post|int $post Object or post ID.
 * @return WPCF7_ContactForm|null Contact form object. Null if unset.
 */
function wpcf7_contact_form( $post ) {
	return WPCF7_ContactForm::get_instance( $post );
}


/**
 * Searches for a contact form by an old unit ID.
 *
 * @param int $old_id Old unit ID.
 * @return WPCF7_ContactForm Contact form object.
 */
function wpcf7_get_contact_form_by_old_id( $old_id ) {
	global $wpdb;

	$q = "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_old_cf7_unit_id'"
		. $wpdb->prepare( " AND meta_value = %d", $old_id );

	if ( $new_id = $wpdb->get_var( $q ) ) {
		return wpcf7_contact_form( $new_id );
	}
}


/**
 * Searches for a contact form by a hash string.
 *
 * @param string $hash Part of a hash string.
 * @return WPCF7_ContactForm Contact form object.
 */
function wpcf7_get_contact_form_by_hash( $hash ) {
	global $wpdb;

	$hash = trim( $hash );

	if ( strlen( $hash ) < 7 ) {
		return null;
	}

	$like = $wpdb->esc_like( $hash ) . '%';

	$q = "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_hash'"
		. $wpdb->prepare( " AND meta_value LIKE %s", $like );

	if ( $post_id = $wpdb->get_var( $q ) ) {
		return wpcf7_contact_form( $post_id );
	}
}


/**
 * Searches for a contact form by title.
 *
 * @param string $title Title of contact form.
 * @return WPCF7_ContactForm|null Contact form object if found, null otherwise.
 */
function wpcf7_get_contact_form_by_title( $title ) {
	if ( ! is_string( $title ) or '' === $title ) {
		return null;
	}

	$contact_forms = WPCF7_ContactForm::find( array(
		'title' => $title,
		'posts_per_page' => 1,
	) );

	if ( $contact_forms ) {
		return wpcf7_contact_form( reset( $contact_forms ) );
	}
}


/**
 * Wrapper function of WPCF7_ContactForm::get_current().
 *
 * @return WPCF7_ContactForm Contact form object.
 */
function wpcf7_get_current_contact_form() {
	if ( $current = WPCF7_ContactForm::get_current() ) {
		return $current;
	}
}


/**
 * Returns true if it is in the state that a non-Ajax submission is accepted.
 */
function wpcf7_is_posted() {
	if ( ! $contact_form = wpcf7_get_current_contact_form() ) {
		return false;
	}

	return $contact_form->is_posted();
}


/**
 * Retrieves the user input value through a non-Ajax submission.
 *
 * @param string $name Name of form control.
 * @param string $default_value Optional default value.
 * @return string The user input value through the form-control.
 */
function wpcf7_get_hangover( $name, $default_value = null ) {
	if ( ! wpcf7_is_posted() ) {
		return $default_value;
	}

	$submission = WPCF7_Submission::get_instance();

	if ( ! $submission
	or $submission->is( 'mail_sent' ) ) {
		return $default_value;
	}

	return isset( $_POST[$name] ) ? wp_unslash( $_POST[$name] ) : $default_value;
}


/**
 * Retrieves an HTML snippet of validation error on the given form control.
 *
 * @param string $name Name of form control.
 * @return string Validation error message in a form of HTML snippet.
 */
function wpcf7_get_validation_error( $name ) {
	if ( ! $contact_form = wpcf7_get_current_contact_form() ) {
		return '';
	}

	return $contact_form->validation_error( $name );
}


/**
 * Returns a reference key to a validation error message.
 *
 * @param string $name Name of form control.
 * @param string $unit_tag Optional. Unit tag of the contact form.
 * @return string Reference key code.
 */
function wpcf7_get_validation_error_reference( $name, $unit_tag = '' ) {
	if ( '' === $unit_tag ) {
		$contact_form = wpcf7_get_current_contact_form();

		if ( $contact_form and $contact_form->validation_error( $name ) ) {
			$unit_tag = $contact_form->unit_tag();
		} else {
			return null;
		}
	}

	return preg_replace( '/[^0-9a-z_-]+/i', '',
		sprintf(
			'%1$s-ve-%2$s',
			$unit_tag,
			$name
		)
	);
}


/**
 * Retrieves a message for the given status.
 */
function wpcf7_get_message( $status ) {
	if ( ! $contact_form = wpcf7_get_current_contact_form() ) {
		return '';
	}

	return $contact_form->message( $status );
}


/**
 * Returns a class names list for a form-tag of the specified type.
 *
 * @param string $type Form-tag type.
 * @param string $default_classes Optional default classes.
 * @return string Whitespace-separated list of class names.
 */
function wpcf7_form_controls_class( $type, $default_classes = '' ) {
	$type = trim( $type );

	if ( is_string( $default_classes ) ) {
		$default_classes = explode( ' ', $default_classes );
	}

	$classes = array(
		'wpcf7-form-control',
		sprintf( 'wpcf7-%s', rtrim( $type, '*' ) ),
	);

	if ( str_ends_with( $type, '*' ) ) {
		$classes[] = 'wpcf7-validates-as-required';
	}

	$classes = array_merge( $classes, $default_classes );
	$classes = array_filter( array_unique( $classes ) );

	return implode( ' ', $classes );
}


/**
 * Callback function for the contact-form-7 shortcode.
 */
function wpcf7_contact_form_tag_func( $atts, $content = null, $code = '' ) {
	if ( is_feed() ) {
		return '[contact-form-7]';
	}

	if ( 'contact-form-7' === $code ) {
		$atts = shortcode_atts(
			array(
				'id' => '',
				'title' => '',
				'html_id' => '',
				'html_name' => '',
				'html_title' => '',
				'html_class' => '',
				'output' => 'form',
			),
			$atts, 'wpcf7'
		);

		$id = trim( $atts['id'] );
		$title = trim( $atts['title'] );

		$contact_form = wpcf7_get_contact_form_by_hash( $id );

		if ( ! $contact_form ) {
			$contact_form = wpcf7_contact_form( $id );
		}

		if ( ! $contact_form ) {
			$contact_form = wpcf7_get_contact_form_by_title( $title );
		}

	} else {
		if ( is_string( $atts ) ) {
			$atts = explode( ' ', $atts, 2 );
		}

		$id = (int) array_shift( $atts );
		$contact_form = wpcf7_get_contact_form_by_old_id( $id );
	}

	if ( ! $contact_form ) {
		return sprintf(
			'<p class="wpcf7-contact-form-not-found"><strong>%1$s</strong> %2$s</p>',
			esc_html( __( 'Error:', 'contact-form-7' ) ),
			esc_html( __( "Contact form not found.", 'contact-form-7' ) )
		);
	}

	$callback = static function ( $contact_form, $atts ) {
		return $contact_form->form_html( $atts );
	};

	$output = wpcf7_switch_locale(
		$contact_form->locale(),
		$callback,
		$contact_form, $atts
	);

	do_action( 'wpcf7_shortcode_callback', $contact_form, $atts );

	return $output;
}


/**
 * Saves the contact form data.
 */
function wpcf7_save_contact_form( $data = '', $context = 'save' ) {
	$data = wp_parse_args( $data, array(
		'id' => -1,
		'title' => null,
		'locale' => null,
		'form' => null,
		'mail' => null,
		'mail_2' => null,
		'messages' => null,
		'additional_settings' => null,
	) );

	$data = wp_unslash( $data );

	$data['id'] = (int) $data['id'];

	if ( -1 == $data['id'] ) {
		$contact_form = WPCF7_ContactForm::get_template();
	} else {
		$contact_form = wpcf7_contact_form( $data['id'] );
	}

	if ( empty( $contact_form ) ) {
		return false;
	}

	if ( null !== $data['title'] ) {
		$contact_form->set_title( $data['title'] );
	}

	if ( null !== $data['locale'] ) {
		$contact_form->set_locale( $data['locale'] );
	}

	$properties = array();

	if ( null !== $data['form'] ) {
		$properties['form'] = wpcf7_sanitize_form( $data['form'] );
	}

	if ( null !== $data['mail'] ) {
		$properties['mail'] = wpcf7_sanitize_mail( $data['mail'] );
		$properties['mail']['active'] = true;
	}

	if ( null !== $data['mail_2'] ) {
		$properties['mail_2'] = wpcf7_sanitize_mail( $data['mail_2'] );
	}

	if ( null !== $data['messages'] ) {
		$properties['messages'] = wpcf7_sanitize_messages( $data['messages'] );
	}

	if ( null !== $data['additional_settings'] ) {
		$properties['additional_settings'] = wpcf7_sanitize_additional_settings(
			$data['additional_settings']
		);
	}

	$contact_form->set_properties( $properties );

	do_action( 'wpcf7_save_contact_form', $contact_form, $data, $context );

	if ( 'save' == $context ) {
		$contact_form->save();
	}

	return $contact_form;
}


/**
 * Sanitizes the form property data.
 */
function wpcf7_sanitize_form( $input, $default_template = '' ) {
	if ( null === $input ) {
		return $default_template;
	}

	$output = trim( $input );

	if ( ! current_user_can( 'unfiltered_html' ) ) {
		$output = wpcf7_kses( $output, 'form' );
	}

	return $output;
}


/**
 * Sanitizes the mail property data.
 */
function wpcf7_sanitize_mail( $input, $defaults = array() ) {
	$input = wp_parse_args( $input, array(
		'active' => false,
		'subject' => '',
		'sender' => '',
		'recipient' => '',
		'body' => '',
		'additional_headers' => '',
		'attachments' => '',
		'use_html' => false,
		'exclude_blank' => false,
	) );

	$input = wp_parse_args( $input, $defaults );

	$output = array();
	$output['active'] = (bool) $input['active'];
	$output['subject'] = trim( $input['subject'] );
	$output['sender'] = trim( $input['sender'] );
	$output['recipient'] = trim( $input['recipient'] );
	$output['body'] = trim( $input['body'] );

	if ( ! current_user_can( 'unfiltered_html' ) ) {
		$output['body'] = wpcf7_kses( $output['body'], 'mail' );
	}

	$output['additional_headers'] = '';

	$headers = str_replace( "\r\n", "\n", $input['additional_headers'] );
	$headers = explode( "\n", $headers );

	foreach ( $headers as $header ) {
		$header = trim( $header );

		if ( '' !== $header ) {
			$output['additional_headers'] .= $header . "\n";
		}
	}

	$output['additional_headers'] = trim( $output['additional_headers'] );
	$output['attachments'] = trim( $input['attachments'] );
	$output['use_html'] = (bool) $input['use_html'];
	$output['exclude_blank'] = (bool) $input['exclude_blank'];

	return $output;
}


/**
 * Sanitizes the messages property data.
 */
function wpcf7_sanitize_messages( $input, $defaults = array() ) {
	$output = array();

	foreach ( wpcf7_messages() as $key => $val ) {
		if ( isset( $input[$key] ) ) {
			$output[$key] = trim( $input[$key] );
		} elseif ( isset( $defaults[$key] ) ) {
			$output[$key] = $defaults[$key];
		}
	}

	return $output;
}


/**
 * Sanitizes the additional settings property data.
 */
function wpcf7_sanitize_additional_settings( $input, $default_template = '' ) {
	if ( null === $input ) {
		return $default_template;
	}

	$output = trim( $input );
	return $output;
}


/**
 * Generates a random hash string for a contact form.
 *
 * @param int $post_id Post ID.
 * @return string SHA-1 hash.
 */
function wpcf7_generate_contact_form_hash( $post_id ) {
	return sha1( implode( '|', array(
		get_current_user_id(),
		$post_id,
		time(),
		home_url(),
	) ) );
}
includes/block-editor/block.json000064400000001363147510545420012727 0ustar00{
	"$schema": "https://schemas.wp.org/trunk/block.json",
	"apiVersion": 3,
	"name": "contact-form-7/contact-form-selector",
	"title": "Contact Form 7",
	"category": "widgets",
	"description": "Insert a contact form you have created with Contact Form 7.",
	"keywords": [ "form" ],
	"textdomain": "contact-form-7",
	"attributes": {
		"id": {
			"type": "integer"
		},
		"hash": {
			"type": "string"
		},
		"title": {
			"type": "string"
		},
		"htmlId": {
			"type": "string"
		},
		"htmlName": {
			"type": "string"
		},
		"htmlTitle": {
			"type": "string"
		},
		"htmlClass": {
			"type": "string"
		},
		"output": {
			"enum": [ "form", "raw_form" ],
			"default": "form"
		}
	},
	"editorScript": [ "file:./index.js", "contact-form-7-block-editor" ]
}
includes/block-editor/index.js000064400000011762147510545420012413 0ustar00(()=>{"use strict";var t={n:e=>{var l=e&&e.__esModule?()=>e.default:()=>e;return t.d(l,{a:l}),l},d:(e,l)=>{for(var a in l)t.o(l,a)&&!t.o(e,a)&&Object.defineProperty(e,a,{enumerable:!0,get:l[a]})},o:(t,e)=>Object.prototype.hasOwnProperty.call(t,e)};const e=window.wp.i18n,l=window.wp.blocks,a=window.wp.blockEditor,r=window.ReactJSXRuntime,o=(0,r.jsxs)("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 242.5 239.46",children:[(0,r.jsx)("defs",{children:(0,r.jsx)("clipPath",{id:"clip-path",transform:"translate(1.72)",children:(0,r.jsx)("circle",{className:"cls-1",cx:"119.73",cy:"119.73",r:"116.15",fill:"none"})})}),(0,r.jsx)("g",{id:"Layer_2","data-name":"Layer 2",children:(0,r.jsxs)("g",{id:"Layer_1","data-name":"Layer 1",children:[(0,r.jsxs)("g",{className:"cls-2",clipPath:"url(#clip-path)",children:[(0,r.jsx)("circle",{className:"cls-3",cx:"121.45",cy:"119.73",r:"116.15",fill:"#33c6f4"}),(0,r.jsx)("path",{className:"cls-4",d:"M239.32,167.79c-53.41-24-108.37-91.46-113-94.55s-10.84.77-10.84.77c-3.87-6.19-10.06.77-10.06.77C76.77,123.55.14,170.11.14,170.11S36.94,237.79,122,237.79C208.48,237.79,239.32,167.79,239.32,167.79Z",transform:"translate(1.72)",fill:"#1b447e"}),(0,r.jsx)("path",{className:"cls-5",d:"M67.48,116.58s15.48-7,12.38,4.65-15.48,28.64-11.61,29.41S83,140.58,86.06,142.12s5.42.78,3.87,6.2-3.1,9.29,0,9.29,5.42-7,9.29-13.94,10.06-3.87,12.38-1.55,9.29,15.49,14.71,13.94,8.51-8.52,6.19-24,1.55-20.12,1.55-20.12,4.64-2.32,13.16,8.51,24,27.09,26.31,26.32-10.83-17.8-7.74-19.35,15.48,2.32,21.68,7.74c0,0,2.12,8.87,2.12.36L126.31,73.24,115.47,74l-10.06.77S80.64,111.94,67.48,116.58Z",transform:"translate(1.72)",fill:"#fff"}),(0,r.jsx)("path",{className:"cls-6",d:"M239.32,170.11c-53.41-24-108.37-93.78-113-96.87s-10.84.77-10.84.77c-3.87-6.19-10.06.77-10.06.77C76.77,123.55.14,170.11.14,170.11",transform:"translate(1.72)",fill:"none",stroke:"#221e1f",strokeMiterlimit:"10",strokeWidth:"8px"})]}),(0,r.jsx)("circle",{className:"cls-6",cx:"121.45",cy:"119.73",r:"116.15",fill:"none",stroke:"#1b447e",strokeMiterlimit:"10",strokeWidth:"8px"})]})})]}),s=window.wp.element,c=window.wp.components,n=window.wp.apiFetch;var i=t.n(n);const m=window.wp.url,h=async t=>i()({path:(0,m.addQueryArgs)("/contact-form-7/v1/contact-forms",{posts_per_page:20,orderby:"modified",order:"DESC",...t})}).then((t=>t)),d=t=>{let e="[contact-form-7]";return t.hash?e=e.replace(/\]$/,` id="${t.hash}"]`):t.id&&(e=e.replace(/\]$/,` id="${t.id}"]`)),t.title&&(e=e.replace(/\]$/,` title="${t.title}"]`)),t.htmlId&&(e=e.replace(/\]$/,` html_id="${t.htmlId}"]`)),t.htmlName&&(e=e.replace(/\]$/,` html_name="${t.htmlName}"]`)),t.htmlTitle&&(e=e.replace(/\]$/,` html_title="${t.htmlTitle}"]`)),t.htmlClass&&(e=e.replace(/\]$/,` html_class="${t.htmlClass}"]`)),"raw_form"===t.output&&(e=e.replace(/\]$/,` output="${t.output}"]`)),e},p=t=>{const e=ajaxurl.replace(/\/admin-ajax\.php$/,"/admin.php");return(0,m.addQueryArgs)(e,{page:"wpcf7",post:t.id,action:"edit"})},f={from:[],to:[{type:"block",blocks:["core/shortcode"],transform:t=>{const e=d(t);return(0,l.createBlock)("core/shortcode",{text:e})}}]};(0,l.registerBlockType)("contact-form-7/contact-form-selector",{icon:o,transforms:f,edit:function({attributes:t,setAttributes:l}){const o=t=>t.reduce(((t,e)=>t.set(e.id,e)),new Map),[n,i]=(0,s.useState)((()=>o([])));return(0,s.useEffect)((()=>{h().then((t=>{i(o(t))}))}),[]),(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)(a.InspectorControls,{children:[t.id&&(0,r.jsx)(c.PanelBody,{title:t.title,children:(0,r.jsx)(c.ExternalLink,{href:p(t),children:(0,e.__)("Edit this contact form","contact-form-7")})}),t.id&&(0,r.jsxs)(c.PanelBody,{title:(0,e.__)("Form attributes","contact-form-7"),initialOpen:!1,children:[(0,r.jsx)(c.TextControl,{label:(0,e.__)("ID","contact-form-7"),value:t.htmlId,onChange:t=>l({htmlId:t}),help:(0,e.__)("Used for the id attribute value of the form element.","contact-form-7")}),(0,r.jsx)(c.TextControl,{label:(0,e.__)("Name","contact-form-7"),value:t.htmlName,onChange:t=>l({htmlName:t}),help:(0,e.__)("Used for the name attribute value of the form element.","contact-form-7")}),(0,r.jsx)(c.TextControl,{label:(0,e.__)("Title","contact-form-7"),value:t.htmlTitle,onChange:t=>l({htmlTitle:t}),help:(0,e.__)("Used for the aria-label attribute value of the form element.","contact-form-7")}),(0,r.jsx)(c.TextControl,{label:(0,e.__)("Class","contact-form-7"),value:t.htmlClass,onChange:t=>l({htmlClass:t}),help:(0,e.__)("Used for the class attribute value of the form element.","contact-form-7")})]})]}),(0,r.jsx)("div",{...(0,a.useBlockProps)({className:"components-placeholder",style:{marginTop:"28px",marginBottom:"28px"}}),children:(0,r.jsx)(c.ComboboxControl,{label:(0,e.__)("Select a contact form:","contact-form-7"),options:(t=>{const e=[];for(const[l,a]of t)e.push({value:l,label:a.title});return e})(n),value:t.id,onChange:t=>l({id:parseInt(t),hash:n.get(parseInt(t))?.hash,title:n.get(parseInt(t))?.title}),onFilterValueChange:t=>{h({search:t}).then((t=>{i(o(t))}))}})})]})},save:({attributes:t})=>{const e=d(t);return(0,r.jsx)("div",{...a.useBlockProps.save(),children:e})}})})();includes/block-editor/index.asset.php000064400000000334147510545420013675 0ustar00<?php

return array(
	'dependencies' => array(
		'react-jsx-runtime',
		'wp-api-fetch',
		'wp-block-editor',
		'wp-blocks',
		'wp-components',
		'wp-element',
		'wp-i18n',
		'wp-url',
	),
	'version' => WPCF7_VERSION,
);
includes/block-editor/block-editor.php000064400000000301147510545420014020 0ustar00<?php

add_action(
	'init',
	'wpcf7_init_block_editor_assets',
	10, 0
);

function wpcf7_init_block_editor_assets() {
	register_block_type(
		wpcf7_plugin_path( 'includes/block-editor' )
	);
}
includes/config-validator/form.php000064400000016456147510545420013301 0ustar00<?php

trait WPCF7_ConfigValidator_Form {

	/**
	 * Runs error detection for the form section.
	 */
	public function validate_form() {
		$section = 'form.body';
		$form = $this->contact_form->prop( 'form' );

		if ( $this->supports( 'multiple_controls_in_label' ) ) {
			if ( $this->detect_multiple_controls_in_label( $section, $form ) ) {
				$this->add_error( $section, 'multiple_controls_in_label',
					array(
						'message' => __( "Multiple form controls are in a single label element.", 'contact-form-7' ),
					)
				);
			} else {
				$this->remove_error( $section, 'multiple_controls_in_label' );
			}
		}

		if ( $this->supports( 'unavailable_names' ) ) {
			$ng_names = $this->detect_unavailable_names( $section, $form );

			if ( $ng_names ) {
				$this->add_error( $section, 'unavailable_names',
					array(
						'message' =>
							/* translators: %names%: a list of form control names */
							__( "Unavailable names (%names%) are used for form controls.", 'contact-form-7' ),
						'params' => array( 'names' => implode( ', ', $ng_names ) ),
					)
				);
			} else {
				$this->remove_error( $section, 'unavailable_names' );
			}
		}

		if ( $this->supports( 'unavailable_html_elements' ) ) {
			if ( $this->detect_unavailable_html_elements( $section, $form ) ) {
				$this->add_error( $section, 'unavailable_html_elements',
					array(
						'message' => __( "Unavailable HTML elements are used in the form template.", 'contact-form-7' ),
					)
				);
			} else {
				$this->remove_error( $section, 'unavailable_html_elements' );
			}
		}

		if ( $this->supports( 'dots_in_names' ) ) {
			if ( $this->detect_dots_in_names( $section, $form ) ) {
				$this->add_error( $section, 'dots_in_names',
					array(
						'message' => __( "Dots are used in form-tag names.", 'contact-form-7' ),
					)
				);
			} else {
				$this->remove_error( $section, 'dots_in_names' );
			}
		}

		if ( $this->supports( 'colons_in_names' ) ) {
			if ( $this->detect_colons_in_names( $section, $form ) ) {
				$this->add_error( $section, 'colons_in_names',
					array(
						'message' => __( "Colons are used in form-tag names.", 'contact-form-7' ),
					)
				);
			} else {
				$this->remove_error( $section, 'colons_in_names' );
			}
		}

		if ( $this->supports( 'upload_filesize_overlimit' ) ) {
			if ( $this->detect_upload_filesize_overlimit( $section, $form ) ) {
				$this->add_error( $section, 'upload_filesize_overlimit',
					array(
						'message' => __( "Uploadable file size exceeds PHP’s maximum acceptable size.", 'contact-form-7' ),
					)
				);
			} else {
				$this->remove_error( $section, 'upload_filesize_overlimit' );
			}
		}
	}


	/**
	 * Detects errors of multiple form controls in a single label.
	 *
	 * @link https://contactform7.com/configuration-errors/multiple-controls-in-label/
	 */
	public function detect_multiple_controls_in_label( $section, $content ) {
		$pattern = '%<label(?:[ \t\n]+.*?)?>(.+?)</label>%s';

		if ( preg_match_all( $pattern, $content, $matches ) ) {
			$form_tags_manager = WPCF7_FormTagsManager::get_instance();

			foreach ( $matches[1] as $insidelabel ) {
				$tags = $form_tags_manager->scan( $insidelabel );
				$fields_count = 0;

				foreach ( $tags as $tag ) {
					$is_multiple_controls_container = wpcf7_form_tag_supports(
						$tag->type, 'multiple-controls-container'
					);

					$is_zero_controls_container = wpcf7_form_tag_supports(
						$tag->type, 'zero-controls-container'
					);

					if ( $is_multiple_controls_container ) {
						$fields_count += count( $tag->values );

						if ( $tag->has_option( 'free_text' ) ) {
							$fields_count += 1;
						}
					} elseif ( $is_zero_controls_container ) {
						$fields_count += 0;
					} elseif ( ! empty( $tag->name ) ) {
						$fields_count += 1;
					}

					if ( 1 < $fields_count ) {
						return true;
					}
				}
			}
		}

		return false;
	}


	/**
	 * Detects errors of unavailable form-tag names.
	 *
	 * @link https://contactform7.com/configuration-errors/unavailable-names/
	 */
	public function detect_unavailable_names( $section, $content ) {
		$public_query_vars = array( 'm', 'p', 'posts', 'w', 'cat',
			'withcomments', 'withoutcomments', 's', 'search', 'exact', 'sentence',
			'calendar', 'page', 'paged', 'more', 'tb', 'pb', 'author', 'order',
			'orderby', 'year', 'monthnum', 'day', 'hour', 'minute', 'second',
			'name', 'category_name', 'tag', 'feed', 'author_name', 'static',
			'pagename', 'page_id', 'error', 'attachment', 'attachment_id',
			'subpost', 'subpost_id', 'preview', 'robots', 'taxonomy', 'term',
			'cpage', 'post_type', 'embed',
		);

		$form_tags_manager = WPCF7_FormTagsManager::get_instance();

		$ng_named_tags = $form_tags_manager->filter( $content, array(
			'name' => $public_query_vars,
		) );

		$ng_names = array();

		foreach ( $ng_named_tags as $tag ) {
			$ng_names[] = sprintf( '"%s"', $tag->name );
		}

		if ( $ng_names ) {
			return array_unique( $ng_names );
		}

		return false;
	}


	/**
	 * Detects errors of unavailable HTML elements.
	 *
	 * @link https://contactform7.com/configuration-errors/unavailable-html-elements/
	 */
	public function detect_unavailable_html_elements( $section, $content ) {
		$pattern = '%(?:<form[\s\t>]|</form>)%i';

		if ( preg_match( $pattern, $content ) ) {
			return true;
		}

		return false;
	}


	/**
	 * Detects errors of dots in form-tag names.
	 *
	 * @link https://contactform7.com/configuration-errors/dots-in-names/
	 */
	public function detect_dots_in_names( $section, $content ) {
		$form_tags_manager = WPCF7_FormTagsManager::get_instance();

		$tags = $form_tags_manager->filter( $content, array(
			'feature' => 'name-attr',
		) );

		foreach ( $tags as $tag ) {
			if ( str_contains( $tag->raw_name, '.' ) ) {
				return true;
			}
		}

		return false;
	}


	/**
	 * Detects errors of colons in form-tag names.
	 *
	 * @link https://contactform7.com/configuration-errors/colons-in-names/
	 */
	public function detect_colons_in_names( $section, $content ) {
		$form_tags_manager = WPCF7_FormTagsManager::get_instance();

		$tags = $form_tags_manager->filter( $content, array(
			'feature' => 'name-attr',
		) );

		foreach ( $tags as $tag ) {
			if ( str_contains( $tag->raw_name, ':' ) ) {
				return true;
			}
		}

		return false;
	}


	/**
	 * Detects errors of uploadable file size overlimit.
	 *
	 * @link https://contactform7.com/configuration-errors/upload-filesize-overlimit
	 */
	public function detect_upload_filesize_overlimit( $section, $content ) {
		$upload_max_filesize = ini_get( 'upload_max_filesize' );

		if ( ! $upload_max_filesize ) {
			return false;
		}

		$upload_max_filesize = strtolower( $upload_max_filesize );
		$upload_max_filesize = trim( $upload_max_filesize );

		if ( ! preg_match( '/^(\d+)([kmg]?)$/', $upload_max_filesize, $matches ) ) {
			return false;
		}

		if ( 'k' === $matches[2] ) {
			$upload_max_filesize = (int) $matches[1] * KB_IN_BYTES;
		} elseif ( 'm' === $matches[2] ) {
			$upload_max_filesize = (int) $matches[1] * MB_IN_BYTES;
		} elseif ( 'g' === $matches[2] ) {
			$upload_max_filesize = (int) $matches[1] * GB_IN_BYTES;
		} else {
			$upload_max_filesize = (int) $matches[1];
		}

		$form_tags_manager = WPCF7_FormTagsManager::get_instance();

		$tags = $form_tags_manager->filter( $content, array(
			'basetype' => 'file',
		) );

		foreach ( $tags as $tag ) {
			if ( $upload_max_filesize < $tag->get_limit_option() ) {
				return true;
			}
		}

		return false;
	}

}
includes/config-validator/validator.php000064400000020137147510545420014312 0ustar00<?php

require_once path_join( __DIR__, 'form.php' );
require_once path_join( __DIR__, 'mail.php' );
require_once path_join( __DIR__, 'messages.php' );
require_once path_join( __DIR__, 'additional-settings.php' );
require_once path_join( __DIR__, 'actions.php' );


/**
 * Configuration validator.
 *
 * @link https://contactform7.com/configuration-errors/
 */
class WPCF7_ConfigValidator {

	/**
	 * The plugin version in which important updates happened last time.
	 */
	const last_important_update = '5.8.1';

	const error_codes = array(
		'maybe_empty',
		'invalid_mailbox_syntax',
		'email_not_in_site_domain',
		'html_in_message',
		'multiple_controls_in_label',
		'file_not_found',
		'unavailable_names',
		'invalid_mail_header',
		'deprecated_settings',
		'file_not_in_content_dir',
		'unavailable_html_elements',
		'attachments_overweight',
		'dots_in_names',
		'colons_in_names',
		'upload_filesize_overlimit',
		'unsafe_email_without_protection',
	);

	use WPCF7_ConfigValidator_Form;
	use WPCF7_ConfigValidator_Mail;
	use WPCF7_ConfigValidator_Messages;
	use WPCF7_ConfigValidator_AdditionalSettings;

	private $contact_form;
	private $errors = array();
	private $include;
	private $exclude;


	/**
	 * Returns a URL linking to the documentation page for the error type.
	 */
	public static function get_doc_link( $child_page = '' ) {
		$url = __( 'https://contactform7.com/configuration-errors/',
			'contact-form-7'
		);

		if ( '' !== $child_page ) {
			$child_page = strtr( $child_page, '_', '-' );

			$url = sprintf( '%s/%s', untrailingslashit( $url ), $child_page );
		}

		return esc_url( $url );
	}


	/**
	 * Constructor.
	 */
	public function __construct( WPCF7_ContactForm $contact_form, $options = '' ) {
		$options = wp_parse_args( $options, array(
			'include' => null,
			'exclude' => null,
		) );

		$this->contact_form = $contact_form;

		if ( isset( $options['include'] ) ) {
			$this->include = (array) $options['include'];
		}

		if ( isset( $options['exclude'] ) ) {
			$this->exclude = (array) $options['exclude'];
		}
	}


	/**
	 * Returns the contact form object that is tied to this validator.
	 */
	public function contact_form() {
		return $this->contact_form;
	}


	/**
	 * Returns true if no error has been detected.
	 */
	public function is_valid() {
		return ! $this->count_errors();
	}


	/**
	 * Returns true if the given error code is supported by this instance.
	 */
	public function supports( $error_code ) {
		if ( isset( $this->include ) ) {
			$supported_codes = array_intersect( self::error_codes, $this->include );
		} else {
			$supported_codes = self::error_codes;
		}

		if ( isset( $this->exclude ) ) {
			$supported_codes = array_diff( $supported_codes, $this->exclude );
		}

		return in_array( $error_code, $supported_codes, true );
	}


	/**
	 * Counts detected errors.
	 */
	public function count_errors( $options = '' ) {
		$options = wp_parse_args( $options, array(
			'section' => '',
			'code' => '',
		) );

		$count = 0;

		foreach ( $this->errors as $key => $errors ) {
			if ( preg_match( '/^mail_[0-9]+\.(.*)$/', $key, $matches ) ) {
				$key = sprintf( 'mail.%s', $matches[1] );
			}

			if ( $options['section']
			and $key !== $options['section']
			and preg_replace( '/\..*$/', '', $key, 1 ) !== $options['section'] ) {
				continue;
			}

			foreach ( $errors as $error ) {
				if ( empty( $error ) ) {
					continue;
				}

				if ( $options['code'] and $error['code'] !== $options['code'] ) {
					continue;
				}

				$count += 1;
			}
		}

		return $count;
	}


	/**
	 * Collects messages for detected errors.
	 */
	public function collect_error_messages() {
		$error_messages = array();

		foreach ( $this->errors as $section => $errors ) {
			$error_messages[$section] = array();

			foreach ( $errors as $error ) {
				if ( empty( $error['args']['message'] ) ) {
					$message = $this->get_default_message( $error['code'] );
				} elseif ( empty( $error['args']['params'] ) ) {
					$message = $error['args']['message'];
				} else {
					$message = $this->build_message(
						$error['args']['message'],
						$error['args']['params']
					);
				}

				$link = '';

				if ( ! empty( $error['args']['link'] ) ) {
					$link = $error['args']['link'];
				}

				$error_messages[$section][] = array(
					'message' => $message,
					'link' => esc_url( $link ),
				);
			}
		}

		return $error_messages;
	}


	/**
	 * Builds an error message by replacing placeholders.
	 */
	public function build_message( $message, $params = '' ) {
		$params = wp_parse_args( $params, array() );

		foreach ( $params as $key => $val ) {
			if ( ! preg_match( '/^[0-9A-Za-z_]+$/', $key ) ) { // invalid key
				continue;
			}

			$placeholder = '%' . $key . '%';

			if ( false !== stripos( $message, $placeholder ) ) {
				$message = str_ireplace( $placeholder, $val, $message );
			}
		}

		return $message;
	}


	/**
	 * Returns a default message that is used when the message for the error
	 * is not specified.
	 */
	public function get_default_message( $code = '' ) {
		return __( "Configuration error is detected.", 'contact-form-7' );
	}


	/**
	 * Returns true if the specified section has the specified error.
	 *
	 * @param string $section The section where the error detected.
	 * @param string $code The unique code of the error.
	 */
	public function has_error( $section, $code ) {
		if ( empty( $this->errors[$section] ) ) {
			return false;
		}

		foreach ( (array) $this->errors[$section] as $error ) {
			if ( isset( $error['code'] ) and $error['code'] === $code ) {
				return true;
			}
		}

		return false;
	}


	/**
	 * Adds a validation error.
	 *
	 * @param string $section The section where the error detected.
	 * @param string $code The unique code of the error.
	 * @param string|array $args Optional options for the error.
	 */
	public function add_error( $section, $code, $args = '' ) {
		$args = wp_parse_args( $args, array(
			'message' => '',
			'params' => array(),
		) );

		$available_error_codes = (array) apply_filters(
			'wpcf7_config_validator_available_error_codes',
			self::error_codes,
			$this->contact_form
		);

		if ( ! in_array( $code, $available_error_codes, true ) ) {
			return false;
		}

		if ( ! isset( $args['link'] ) ) {
			$args['link'] = self::get_doc_link( $code );
		}

		if ( ! isset( $this->errors[$section] ) ) {
			$this->errors[$section] = array();
		}

		$this->errors[$section][] = array(
			'code' => $code,
			'args' => $args,
		);

		return true;
	}


	/**
	 * Removes an error.
	 *
	 * @param string $section The section where the error detected.
	 * @param string $code The unique code of the error.
	 */
	public function remove_error( $section, $code ) {
		if ( empty( $this->errors[$section] ) ) {
			return;
		}

		foreach ( (array) $this->errors[$section] as $key => $error ) {
			if ( isset( $error['code'] ) and $error['code'] === $code ) {
				unset( $this->errors[$section][$key] );
			}
		}

		if ( empty( $this->errors[$section] ) ) {
			unset( $this->errors[$section] );
		}
	}


	/**
	 * The main validation runner.
	 *
	 * @return bool True if there is no error detected.
	 */
	public function validate() {
		$this->validate_form();
		$this->validate_mail( 'mail' );
		$this->validate_mail( 'mail_2' );
		$this->validate_messages();
		$this->validate_additional_settings();

		do_action( 'wpcf7_config_validator_validate', $this );

		return $this->is_valid();
	}


	/**
	 * Saves detected errors as a post meta data.
	 */
	public function save() {
		if ( $this->contact_form->initial() ) {
			return;
		}

		delete_post_meta( $this->contact_form->id(), '_config_validation' );

		if ( $this->errors ) {
			update_post_meta(
				$this->contact_form->id(), '_config_validation', $this->errors
			);
		}
	}


	/**
	 * Restore errors from the database.
	 */
	public function restore() {
		$config_errors = get_post_meta(
			$this->contact_form->id(), '_config_validation', true
		);

		foreach ( (array) $config_errors as $section => $errors ) {
			if ( empty( $errors ) ) {
				continue;
			}

			foreach ( (array) $errors as $error ) {
				if ( ! empty( $error['code'] ) ) {
					$code = $error['code'];
					$args = isset( $error['args'] ) ? $error['args'] : '';
					$this->add_error( $section, $code, $args );
				}
			}
		}
	}

}
includes/config-validator/additional-settings.php000064400000001306147510545420016270 0ustar00<?php

trait WPCF7_ConfigValidator_AdditionalSettings {

	/**
	 * Runs error detection for the additional settings section.
	 */
	public function validate_additional_settings() {
		$section = 'additional_settings.body';

		if ( $this->supports( 'deprecated_settings' ) ) {
			$deprecated_settings_used =
				$this->contact_form->additional_setting( 'on_sent_ok' ) ||
				$this->contact_form->additional_setting( 'on_submit' );

			if ( $deprecated_settings_used ) {
				$this->add_error( $section, 'deprecated_settings',
					array(
						'message' => __( "Deprecated settings are used.", 'contact-form-7' ),
					)
				);
			} else {
				$this->remove_error( $section, 'deprecated_settings' );
			}
		}
	}

}
includes/config-validator/mail.php000064400000034377147510545420013262 0ustar00<?php

trait WPCF7_ConfigValidator_Mail {

	/**
	 * Replaces all mail-tags in the given content.
	 */
	public function replace_mail_tags( $content, $options = '' ) {
		$options = wp_parse_args( $options, array(
			'html' => false,
			'callback' =>
				array( $this, 'replace_mail_tags_with_minimum_input_callback' ),
		) );

		$content = new WPCF7_MailTaggedText( $content, $options );

		return $content->replace_tags();
	}


	/**
	 * Callback function for WPCF7_MailTaggedText. Replaces mail-tags with
	 * the most conservative inputs.
	 */
	public function replace_mail_tags_with_minimum_input_callback( $matches ) {
		// allow [[foo]] syntax for escaping a tag
		if ( $matches[1] === '[' and $matches[4] === ']' ) {
			return substr( $matches[0], 1, -1 );
		}

		$tag = $matches[0];
		$tagname = $matches[2];
		$values = $matches[3];

		$mail_tag = new WPCF7_MailTag( $tag, $tagname, $values );
		$field_name = $mail_tag->field_name();

		$example_email = 'example@example.com';
		$example_text = 'example';
		$example_blank = '';

		// for back-compat
		$field_name = preg_replace( '/^wpcf7\./', '_', $field_name );

		if ( '_site_admin_email' === $field_name ) {
			return get_bloginfo( 'admin_email', 'raw' );

		} elseif ( '_user_agent' === $field_name ) {
			return $example_text;

		} elseif ( '_user_email' === $field_name ) {
			return $this->contact_form->is_true( 'subscribers_only' )
				? $example_email
				: $example_blank;

		} elseif ( str_starts_with( $field_name, '_user_' ) ) {
			return $this->contact_form->is_true( 'subscribers_only' )
				? $example_text
				: $example_blank;

		} elseif ( str_starts_with( $field_name, '_' ) ) {
			return str_ends_with( $field_name, '_email' )
				? $example_email
				: $example_text;

		}

		static $opcalcset = array();

		if ( ! isset( $opcalcset[$this->contact_form->id()] ) ) {
			$opcalcset[$this->contact_form->id()] =
				new WPCF7_MailTag_OutputCalculator( $this->contact_form );
		}

		$opcalc = $opcalcset[$this->contact_form->id()];
		$op = $opcalc->calc_output( $mail_tag );

		if ( WPCF7_MailTag_OutputCalculator::email === $op ) {
			return $example_email;
		} elseif ( ! ( WPCF7_MailTag_OutputCalculator::blank & $op ) ) {
			return $example_text;
		} else {
			return $example_blank;
		}
	}


	/**
	 * Runs error detection for the mail sections.
	 */
	public function validate_mail( $template = 'mail' ) {
		if (
			$this->contact_form->is_true( 'demo_mode' ) or
			$this->contact_form->is_true( 'skip_mail' )
		) {
			return;
		}

		$components = (array) $this->contact_form->prop( $template );

		if ( ! $components ) {
			return;
		}

		if ( 'mail' !== $template and empty( $components['active'] ) ) {
			return;
		}

		$components = wp_parse_args( $components, array(
			'subject' => '',
			'sender' => '',
			'recipient' => '',
			'additional_headers' => '',
			'body' => '',
			'attachments' => '',
		) );

		$this->validate_mail_subject(
			$template,
			$components['subject']
		);

		$this->validate_mail_sender(
			$template,
			$components['sender']
		);

		$this->validate_mail_recipient(
			$template,
			$components['recipient']
		);

		$this->validate_mail_additional_headers(
			$template,
			$components['additional_headers']
		);

		$this->validate_mail_body(
			$template,
			$components['body']
		);

		$this->validate_mail_attachments(
			$template,
			$components['attachments']
		);
	}


	/**
	 * Runs error detection for the mail subject section.
	 */
	public function validate_mail_subject( $template, $content ) {
		$section = sprintf( '%s.subject', $template );

		if ( $this->supports( 'maybe_empty' ) ) {
			if ( $this->detect_maybe_empty( $section, $content ) ) {
				$this->add_error( $section, 'maybe_empty',
					array(
						'message' => __( "There is a possible empty field.", 'contact-form-7' ),
					)
				);
			} else {
				$this->remove_error( $section, 'maybe_empty' );
			}
		}
	}


	/**
	 * Runs error detection for the mail sender section.
	 */
	public function validate_mail_sender( $template, $content ) {
		$section = sprintf( '%s.sender', $template );

		if ( $this->supports( 'invalid_mailbox_syntax' ) ) {
			if ( $this->detect_invalid_mailbox_syntax( $section, $content ) ) {
				$this->add_error( $section, 'invalid_mailbox_syntax',
					array(
						'message' => __( "Invalid mailbox syntax is used.", 'contact-form-7' ),
					)
				);
			} else {
				$this->remove_error( $section, 'invalid_mailbox_syntax' );
			}
		}

		if ( $this->supports( 'email_not_in_site_domain' ) ) {
			$this->remove_error( $section, 'email_not_in_site_domain' );

			if ( ! $this->has_error( $section, 'invalid_mailbox_syntax' ) ) {
				$sender = $this->replace_mail_tags( $content );
				$sender = wpcf7_strip_newline( $sender );

				if ( ! wpcf7_is_email_in_site_domain( $sender ) ) {
					$this->add_error( $section, 'email_not_in_site_domain',
						array(
							'message' => __( "Sender email address does not belong to the site domain.", 'contact-form-7' ),
						)
					);
				}
			}
		}
	}


	/**
	 * Runs error detection for the mail recipient section.
	 */
	public function validate_mail_recipient( $template, $content ) {
		$section = sprintf( '%s.recipient', $template );

		if ( $this->supports( 'invalid_mailbox_syntax' ) ) {
			if ( $this->detect_invalid_mailbox_syntax( $section, $content ) ) {
				$this->add_error( $section, 'invalid_mailbox_syntax',
					array(
						'message' => __( "Invalid mailbox syntax is used.", 'contact-form-7' ),
					)
				);
			} else {
				$this->remove_error( $section, 'invalid_mailbox_syntax' );
			}
		}

		if ( $this->supports( 'unsafe_email_without_protection' ) ) {
			$this->remove_error( $section, 'unsafe_email_without_protection' );

			if ( ! $this->has_error( $section, 'invalid_mailbox_syntax' ) ) {
				if (
					$this->detect_unsafe_email_without_protection( $section, $content )
				) {
					$this->add_error( $section, 'unsafe_email_without_protection',
						array(
							'message' => __( "Unsafe email config is used without sufficient protection.", 'contact-form-7' ),
						)
					);
				}
			}
		}
	}


	/**
	 * Runs error detection for the mail additional headers section.
	 */
	public function validate_mail_additional_headers( $template, $content ) {
		$section = sprintf( '%s.additional_headers', $template );

		$invalid_mail_headers = array();
		$invalid_mailbox_fields = array();
		$unsafe_email_fields = array();

		foreach ( explode( "\n", $content ) as $header ) {
			$header = trim( $header );

			if ( '' === $header ) {
				continue;
			}

			$is_valid_header = preg_match(
				'/^([0-9A-Za-z-]+):(.*)$/',
				$header,
				$matches
			);

			if ( ! $is_valid_header ) {
				$invalid_mail_headers[] = $header;
				continue;
			}

			$header_name = $matches[1];
			$header_value = trim( $matches[2] );

			if (
				in_array(
					strtolower( $header_name ), array( 'reply-to', 'cc', 'bcc' )
				) and
				'' !== $header_value and
				$this->detect_invalid_mailbox_syntax( $section, $header_value )
			) {
				$invalid_mailbox_fields[] = $header_name;
				continue;
			}

			if (
				in_array( strtolower( $header_name ), array( 'cc', 'bcc' ) ) and
				$this->detect_unsafe_email_without_protection( $section, $header_value )
			) {
				$unsafe_email_fields[] = $header_name;
			}
		}

		if ( $this->supports( 'invalid_mail_header' ) ) {
			if ( ! empty( $invalid_mail_headers ) ) {
				$this->add_error( $section, 'invalid_mail_header',
					array(
						'message' => __( "There are invalid mail header fields.", 'contact-form-7' ),
					)
				);
			} else {
				$this->remove_error( $section, 'invalid_mail_header' );
			}
		}

		if ( $this->supports( 'invalid_mailbox_syntax' ) ) {
			if ( ! empty( $invalid_mailbox_fields ) ) {
				foreach ( $invalid_mailbox_fields as $header_name ) {
					$this->add_error( $section, 'invalid_mailbox_syntax',
						array(
							'message' => __( "Invalid mailbox syntax is used in the %name% field.", 'contact-form-7' ),
							'params' => array( 'name' => $header_name ),
						)
					);
				}
			} else {
				$this->remove_error( $section, 'invalid_mailbox_syntax' );
			}
		}

		if ( $this->supports( 'unsafe_email_without_protection' ) ) {
			if ( ! empty( $unsafe_email_fields ) ) {
				$this->add_error( $section, 'unsafe_email_without_protection',
					array(
						'message' => __( "Unsafe email config is used without sufficient protection.", 'contact-form-7' ),
					)
				);
			} else {
				$this->remove_error( $section, 'unsafe_email_without_protection' );
			}
		}
	}


	/**
	 * Runs error detection for the mail body section.
	 */
	public function validate_mail_body( $template, $content ) {
		$section = sprintf( '%s.body', $template );

		if ( $this->supports( 'maybe_empty' ) ) {
			if ( $this->detect_maybe_empty( $section, $content ) ) {
				$this->add_error( $section, 'maybe_empty',
					array(
						'message' => __( "There is a possible empty field.", 'contact-form-7' ),
					)
				);
			} else {
				$this->remove_error( $section, 'maybe_empty' );
			}
		}
	}


	/**
	 * Runs error detection for the mail attachments section.
	 */
	public function validate_mail_attachments( $template, $content ) {
		$section = sprintf( '%s.attachments', $template );

		$total_size = 0;
		$files_not_found = array();
		$files_out_of_content = array();

		if ( '' !== $content ) {
			$attachables = array();

			$tags = $this->contact_form->scan_form_tags(
				array( 'type' => array( 'file', 'file*' ) )
			);

			foreach ( $tags as $tag ) {
				$name = $tag->name;

				if ( ! str_contains( $content, "[{$name}]" ) ) {
					continue;
				}

				$limit = (int) $tag->get_limit_option();

				if ( empty( $attachables[$name] ) or $attachables[$name] < $limit ) {
					$attachables[$name] = $limit;
				}
			}

			$total_size = array_sum( $attachables );

			foreach ( explode( "\n", $content ) as $line ) {
				$line = trim( $line );

				if ( '' === $line or str_starts_with( $line, '[' ) ) {
					continue;
				}

				if ( $this->detect_file_not_found( $section, $line ) ) {
					$files_not_found[] = $line;
				} elseif ( $this->detect_file_not_in_content_dir( $section, $line ) ) {
					$files_out_of_content[] = $line;
				} else {
					$total_size += (int) @filesize( $path );
				}
			}
		}

		if ( $this->supports( 'file_not_found' ) ) {
			if ( ! empty( $files_not_found ) ) {
				foreach ( $files_not_found as $line ) {
					$this->add_error( $section, 'file_not_found',
						array(
							'message' => __( "Attachment file does not exist at %path%.", 'contact-form-7' ),
							'params' => array( 'path' => $line ),
						)
					);
				}
			} else {
				$this->remove_error( $section, 'file_not_found' );
			}
		}

		if ( $this->supports( 'file_not_in_content_dir' ) ) {
			if ( ! empty( $files_out_of_content ) ) {
				$this->add_error( $section, 'file_not_in_content_dir',
					array(
						'message' => __( "It is not allowed to use files outside the wp-content directory.", 'contact-form-7' ),
					)
				);
			} else {
				$this->remove_error( $section, 'file_not_in_content_dir' );
			}
		}

		if ( $this->supports( 'attachments_overweight' ) ) {
			$max = 25 * MB_IN_BYTES; // 25 MB

			if ( $max < $total_size ) {
				$this->add_error( $section, 'attachments_overweight',
					array(
						'message' => __( "The total size of attachment files is too large.", 'contact-form-7' ),
					)
				);
			} else {
				$this->remove_error( $section, 'attachments_overweight' );
			}
		}
	}


	/**
	 * Detects errors of invalid mailbox syntax.
	 *
	 * @link https://contactform7.com/configuration-errors/invalid-mailbox-syntax/
	 */
	public function detect_invalid_mailbox_syntax( $section, $content ) {
		$content = $this->replace_mail_tags( $content );
		$content = wpcf7_strip_newline( $content );

		if ( ! wpcf7_is_mailbox_list( $content ) ) {
			return true;
		}

		return false;
	}


	/**
	 * Detects errors of empty message fields.
	 *
	 * @link https://contactform7.com/configuration-errors/maybe-empty/
	 */
	public function detect_maybe_empty( $section, $content ) {
		$content = $this->replace_mail_tags( $content );
		$content = wpcf7_strip_newline( $content );

		if ( '' === $content ) {
			return true;
		}

		return false;
	}


	/**
	 * Detects errors of nonexistent attachment files.
	 *
	 * @link https://contactform7.com/configuration-errors/file-not-found/
	 */
	public function detect_file_not_found( $section, $content ) {
		$path = path_join( WP_CONTENT_DIR, $content );

		if ( ! is_readable( $path ) or ! is_file( $path ) ) {
			return true;
		}

		return false;
	}


	/**
	 * Detects errors of attachment files out of the content directory.
	 *
	 * @link https://contactform7.com/configuration-errors/file-not-in-content-dir/
	 */
	public function detect_file_not_in_content_dir( $section, $content ) {
		$path = path_join( WP_CONTENT_DIR, $content );

		if ( ! wpcf7_is_file_path_in_content_dir( $path ) ) {
			return true;
		}

		return false;
	}


	/**
	 * Detects errors of that unsafe email config is used without
	 * sufficient protection.
	 *
	 * @link https://contactform7.com/configuration-errors/unsafe-email-without-protection/
	 */
	public function detect_unsafe_email_without_protection( $section, $content ) {
		static $is_recaptcha_active = null;

		if ( null === $is_recaptcha_active ) {
			$is_recaptcha_active = call_user_func( function () {
				$service = WPCF7_RECAPTCHA::get_instance();
				return $service->is_active();
			} );
		}

		if ( $is_recaptcha_active ) {
			return false;
		}

		$example_email = 'user-specified@example.com';

		// Replace mail-tags connected to an email type form-tag first.
		$content = $this->replace_mail_tags( $content, array(
			'callback' => function ( $matches ) use ( $example_email ) {
				// allow [[foo]] syntax for escaping a tag
				if ( $matches[1] === '[' and $matches[4] === ']' ) {
					return substr( $matches[0], 1, -1 );
				}

				$tag = $matches[0];
				$tagname = $matches[2];
				$values = $matches[3];

				$mail_tag = new WPCF7_MailTag( $tag, $tagname, $values );
				$field_name = $mail_tag->field_name();

				$form_tags = $this->contact_form->scan_form_tags(
					array( 'name' => $field_name )
				);

				if ( $form_tags ) {
					$form_tag = new WPCF7_FormTag( $form_tags[0] );

					if ( 'email' === $form_tag->basetype ) {
						return $example_email;
					}
				}

				return $tag;
			},
		) );

		// Replace remaining mail-tags.
		$content = $this->replace_mail_tags( $content );

		$content = wpcf7_strip_newline( $content );

		if ( str_contains( $content, $example_email ) ) {
			return true;
		}

		return false;
	}

}
includes/config-validator/actions.php000064400000001203147510545420013756 0ustar00<?php

add_action(
	'wpcf7_update_option',
	'wpcf7_config_validator_update_option',
	10, 3
);

/**
 * Runs bulk validation after the reCAPTCHA integration option is updated.
 */
function wpcf7_config_validator_update_option( $name, $value, $old_option ) {
	if ( 'recaptcha' === $name ) {
		$contact_forms = WPCF7_ContactForm::find();

		$options = array(
			'include' => 'unsafe_email_without_protection',
		);

		foreach ( $contact_forms as $contact_form ) {
			$config_validator = new WPCF7_ConfigValidator( $contact_form, $options );
			$config_validator->restore();
			$config_validator->validate();
			$config_validator->save();
		}
	}
}
includes/config-validator/messages.php000064400000002230147510545420014126 0ustar00<?php

trait WPCF7_ConfigValidator_Messages {

	/**
	 * Runs error detection for the messages section.
	 */
	public function validate_messages() {
		$messages = (array) $this->contact_form->prop( 'messages' );

		if ( ! $messages ) {
			return;
		}

		if (
			isset( $messages['captcha_not_match'] ) and
			! wpcf7_use_really_simple_captcha()
		) {
			unset( $messages['captcha_not_match'] );
		}

		foreach ( $messages as $key => $message ) {
			$section = sprintf( 'messages.%s', $key );

			if ( $this->supports( 'html_in_message' ) ) {
				if ( $this->detect_html_in_message( $section, $message ) ) {
					$this->add_error( $section, 'html_in_message',
						array(
							'message' => __( "HTML tags are used in a message.", 'contact-form-7' ),
						)
					);
				} else {
					$this->remove_error( $section, 'html_in_message' );
				}
			}
		}
	}


	/**
	 * Detects errors of HTML uses in a message.
	 *
	 * @link https://contactform7.com/configuration-errors/html-in-message/
	 */
	public function detect_html_in_message( $section, $content ) {
		$stripped = wp_strip_all_tags( $content );

		if ( $stripped !== $content ) {
			return true;
		}

		return false;
	}

}
includes/form-tag.php000064400000032655147510545420010621 0ustar00<?php

/**
 * A form-tag.
 *
 * @link https://contactform7.com/tag-syntax/#form_tag
 */
class WPCF7_FormTag implements ArrayAccess {

	public $type;
	public $basetype;
	public $raw_name = '';
	public $name = '';
	public $options = array();
	public $raw_values = array();
	public $values = array();
	public $pipes;
	public $labels = array();
	public $attr = '';
	public $content = '';

	public function __construct( $tag = array() ) {
		if ( is_array( $tag )
		or $tag instanceof self ) {
			foreach ( $tag as $key => $value ) {
				if ( property_exists( __CLASS__, $key ) ) {
					$this->{$key} = $value;
				}
			}
		}
	}


	/**
	 * Returns true if the type has a trailing asterisk.
	 */
	public function is_required() {
		return str_ends_with( $this->type, '*' );
	}


	/**
	 * Returns true if the form-tag has a specified option.
	 */
	public function has_option( $option_name ) {
		$pattern = sprintf( '/^%s(:.+)?$/i', preg_quote( $option_name, '/' ) );
		return (bool) preg_grep( $pattern, $this->options );
	}


	/**
	 * Retrieves option values with the specified option name.
	 *
	 * @param string $option_name Option name.
	 * @param string $pattern Optional. A regular expression pattern or one of
	 *               the keys of preset patterns. If specified, only options
	 *               whose value part matches this pattern will be returned.
	 * @param bool $single Optional. If true, only the first matching option
	 *             will be returned. Default false.
	 * @return string|array|bool The option value or an array of option values.
	 *                           False if there is no option matches the pattern.
	 */
	public function get_option( $option_name, $pattern = '', $single = false ) {
		$preset_patterns = array(
			'date' => '[0-9]{4}-[0-9]{2}-[0-9]{2}',
			'int' => '[0-9]+',
			'signed_int' => '[-]?[0-9]+',
			'num' => '(?:[0-9]+|(?:[0-9]+)?[.][0-9]+)',
			'signed_num' => '[-]?(?:[0-9]+|(?:[0-9]+)?[.][0-9]+)',
			'class' => '[-0-9a-zA-Z_]+',
			'id' => '[-0-9a-zA-Z_]+',
		);

		if ( isset( $preset_patterns[$pattern] ) ) {
			$pattern = $preset_patterns[$pattern];
		}

		if ( '' == $pattern ) {
			$pattern = '.+';
		}

		$pattern = sprintf(
			'/^%s:%s$/i',
			preg_quote( $option_name, '/' ),
			$pattern
		);

		if ( $single ) {
			$matches = $this->get_first_match_option( $pattern );

			if ( ! $matches ) {
				return false;
			}

			return substr( $matches[0], strlen( $option_name ) + 1 );
		} else {
			$matches_a = $this->get_all_match_options( $pattern );

			if ( ! $matches_a ) {
				return false;
			}

			$results = array();

			foreach ( $matches_a as $matches ) {
				$results[] = substr( $matches[0], strlen( $option_name ) + 1 );
			}

			return $results;
		}
	}


	/**
	 * Retrieves the id option value from the form-tag.
	 */
	public function get_id_option() {
		static $used = array();

		$option = $this->get_option( 'id', 'id', true );

		if (
			! $option or
			str_starts_with( $option, 'wpcf7' ) or
			in_array( $option, $used, true )
		) {
			return false;
		}

		$used[] = $option;

		return $option;
	}


	/**
	 * Retrieves the class option value from the form-tag.
	 *
	 * @param string|array $default_classes Optional. Preset classes as an array
	 *                     or a whitespace-separated list. Default empty string.
	 * @return string|bool A whitespace-separated list of classes.
	 *                     False if there is no class to return.
	 */
	public function get_class_option( $default_classes = '' ) {
		if ( is_string( $default_classes ) ) {
			$default_classes = explode( ' ', $default_classes );
		}

		$options = array_merge(
			(array) $default_classes,
			(array) $this->get_option( 'class' )
		);

		$options = array_map( 'sanitize_html_class', $options );
		$options = array_filter( array_unique( $options ) );

		if ( empty( $options ) ) {
			return false;
		}

		return implode( ' ', $options );
	}


	/**
	 * Retrieves the size option value from the form-tag.
	 *
	 * @param string $default_value Optional default value.
	 * @return string The option value.
	 */
	public function get_size_option( $default_value = false ) {
		$option = $this->get_option( 'size', 'int', true );

		if ( $option ) {
			return $option;
		}

		$matches_a = $this->get_all_match_options( '%^([0-9]*)/[0-9]*$%' );

		foreach ( (array) $matches_a as $matches ) {
			if ( isset( $matches[1] ) and '' !== $matches[1] ) {
				return $matches[1];
			}
		}

		return $default_value;
	}


	/**
	 * Retrieves the maxlength option value from the form-tag.
	 *
	 * @param string $default_value Optional default value.
	 * @return string The option value.
	 */
	public function get_maxlength_option( $default_value = false ) {
		$option = $this->get_option( 'maxlength', 'int', true );

		if ( $option ) {
			return $option;
		}

		$matches_a = $this->get_all_match_options(
			'%^(?:[0-9]*x?[0-9]*)?/([0-9]+)$%'
		);

		foreach ( (array) $matches_a as $matches ) {
			if ( isset( $matches[1] ) and '' !== $matches[1] ) {
				return $matches[1];
			}
		}

		return $default_value;
	}


	/**
	 * Retrieves the minlength option value from the form-tag.
	 *
	 * @param string $default_value Optional default value.
	 * @return string The option value.
	 */
	public function get_minlength_option( $default_value = false ) {
		$option = $this->get_option( 'minlength', 'int', true );

		if ( $option ) {
			return $option;
		} else {
			return $default_value;
		}
	}


	/**
	 * Retrieves the cols option value from the form-tag.
	 *
	 * @param string $default_value Optional default value.
	 * @return string The option value.
	 */
	public function get_cols_option( $default_value = false ) {
		$option = $this->get_option( 'cols', 'int', true );

		if ( $option ) {
			return $option;
		}

		$matches_a = $this->get_all_match_options(
			'%^([0-9]*)x([0-9]*)(?:/[0-9]+)?$%'
		);

		foreach ( (array) $matches_a as $matches ) {
			if ( isset( $matches[1] ) and '' !== $matches[1] ) {
				return $matches[1];
			}
		}

		return $default_value;
	}


	/**
	 * Retrieves the rows option value from the form-tag.
	 *
	 * @param string $default_value Optional default value.
	 * @return string The option value.
	 */
	public function get_rows_option( $default_value = false ) {
		$option = $this->get_option( 'rows', 'int', true );

		if ( $option ) {
			return $option;
		}

		$matches_a = $this->get_all_match_options(
			'%^([0-9]*)x([0-9]*)(?:/[0-9]+)?$%'
		);

		foreach ( (array) $matches_a as $matches ) {
			if ( isset( $matches[2] ) and '' !== $matches[2] ) {
				return $matches[2];
			}
		}

		return $default_value;
	}


	/**
	 * Retrieves a date-type option value from the form-tag.
	 *
	 * @param string $option_name A date-type option name, such as 'min' or 'max'.
	 * @return string|bool The option value in YYYY-MM-DD format. False if the
	 *                     option does not exist or the date value is invalid.
	 */
	public function get_date_option( $option_name ) {
		$option_value = $this->get_option( $option_name, '', true );

		if ( empty( $option_value ) ) {
			return false;
		}

		$date = apply_filters( 'wpcf7_form_tag_date_option',
			null,
			array( $option_name => $option_value )
		);

		if ( $date ) {
			$date_pattern = '/^([0-9]{4})-([0-9]{2})-([0-9]{2})$/';

			if ( preg_match( $date_pattern, $date, $matches )
			and checkdate( $matches[2], $matches[3], $matches[1] ) ) {
				return $date;
			}
		} else {
			$datetime_obj = date_create_immutable(
				preg_replace( '/[_]+/', ' ', $option_value ),
				wp_timezone()
			);

			if ( $datetime_obj ) {
				return $datetime_obj->format( 'Y-m-d' );
			}
		}

		return false;
	}


	/**
	 * Retrieves the default option value from the form-tag.
	 *
	 * @param string|array $default_value Optional default value.
	 * @param string|array $args Optional options for the option value retrieval.
	 * @return string|array The option value. If the multiple option is enabled,
	 *                      an array of option values.
	 */
	public function get_default_option( $default_value = '', $args = '' ) {
		$args = wp_parse_args( $args, array(
			'multiple' => false,
			'shifted' => false,
		) );

		$options = (array) $this->get_option( 'default' );
		$values = array();

		if ( empty( $options ) ) {
			return $args['multiple'] ? $values : $default_value;
		}

		foreach ( $options as $opt ) {
			$opt = sanitize_key( $opt );

			if ( 'user_' == substr( $opt, 0, 5 ) and is_user_logged_in() ) {
				$primary_props = array( 'user_login', 'user_email', 'user_url' );
				$opt = in_array( $opt, $primary_props ) ? $opt : substr( $opt, 5 );

				$user = wp_get_current_user();
				$user_prop = $user->get( $opt );

				if ( ! empty( $user_prop ) ) {
					if ( $args['multiple'] ) {
						$values[] = $user_prop;
					} else {
						return $user_prop;
					}
				}

			} elseif ( 'post_meta' === $opt and in_the_loop() ) {
				if ( $args['multiple'] ) {
					$values = array_merge( $values,
						get_post_meta( get_the_ID(), $this->name )
					);
				} else {
					$val = (string) get_post_meta( get_the_ID(), $this->name, true );

					if ( strlen( $val ) ) {
						return $val;
					}
				}

			} elseif ( 'get' === $opt and isset( $_GET[$this->name] ) ) {
				$vals = (array) $_GET[$this->name];
				$vals = array_map( 'wpcf7_sanitize_query_var', $vals );

				if ( $args['multiple'] ) {
					$values = array_merge( $values, $vals );
				} else {
					$val = isset( $vals[0] ) ? (string) $vals[0] : '';

					if ( strlen( $val ) ) {
						return $val;
					}
				}

			} elseif ( 'post' === $opt and isset( $_POST[$this->name] ) ) {
				$vals = (array) $_POST[$this->name];
				$vals = array_map( 'wpcf7_sanitize_query_var', $vals );

				if ( $args['multiple'] ) {
					$values = array_merge( $values, $vals );
				} else {
					$val = isset( $vals[0] ) ? (string) $vals[0] : '';

					if ( strlen( $val ) ) {
						return $val;
					}
				}

			} elseif ( 'shortcode_attr' === $opt ) {
				if ( $contact_form = WPCF7_ContactForm::get_current() ) {
					$val = $contact_form->shortcode_attr( $this->name );

					if ( isset( $val ) and strlen( $val ) ) {
						if ( $args['multiple'] ) {
							$values[] = $val;
						} else {
							return $val;
						}
					}
				}

			} elseif ( preg_match( '/^[0-9_]+$/', $opt ) ) {
				$nums = explode( '_', $opt );

				foreach ( $nums as $num ) {
					$num = absint( $num );
					$num = $args['shifted'] ? $num : $num - 1;

					if ( isset( $this->values[$num] ) ) {
						if ( $args['multiple'] ) {
							$values[] = $this->values[$num];
						} else {
							return $this->values[$num];
						}
					}
				}
			}
		}

		if ( $args['multiple'] ) {
			$values = array_unique( $values );
			return $values;
		} else {
			return $default_value;
		}
	}


	/**
	 * Retrieves the data option value from the form-tag.
	 *
	 * @param string|array $args Optional options for the option value retrieval.
	 * @return mixed The option value.
	 */
	public function get_data_option( $args = '' ) {
		$options = (array) $this->get_option( 'data' );

		return apply_filters( 'wpcf7_form_tag_data_option', null, $options, $args );
	}


	/**
	 * Retrieves the limit option value from the form-tag.
	 *
	 * @param int $default_value Optional default value. Default 1048576.
	 * @return int The option value.
	 */
	public function get_limit_option( $default_value = MB_IN_BYTES ) {
		$pattern = '/^limit:([1-9][0-9]*)([kKmM]?[bB])?$/';

		$matches = $this->get_first_match_option( $pattern );

		if ( $matches ) {
			$size = (int) $matches[1];

			if ( ! empty( $matches[2] ) ) {
				$kbmb = strtolower( $matches[2] );

				if ( 'kb' === $kbmb ) {
					$size *= KB_IN_BYTES;
				} elseif ( 'mb' === $kbmb ) {
					$size *= MB_IN_BYTES;
				}
			}

			return $size;
		}

		return (int) $default_value;
	}


	/**
	 * Retrieves the value of the first option matches the given
	 * regular expression pattern.
	 *
	 * @param string $pattern Regular expression pattern.
	 * @return array|bool Option value as an array of matched strings.
	 *                    False if there is no option matches the pattern.
	 */
	public function get_first_match_option( $pattern ) {
		foreach( (array) $this->options as $option ) {
			if ( preg_match( $pattern, $option, $matches ) ) {
				return $matches;
			}
		}

		return false;
	}


	/**
	 * Retrieves values of options that match the given
	 * regular expression pattern.
	 *
	 * @param string $pattern Regular expression pattern.
	 * @return array Array of arrays of strings that match the pattern.
	 */
	public function get_all_match_options( $pattern ) {
		$result = array();

		foreach( (array) $this->options as $option ) {
			if ( preg_match( $pattern, $option, $matches ) ) {
				$result[] = $matches;
			}
		}

		return $result;
	}


	/**
	 * Assigns a value to the specified offset.
	 *
	 * @link https://www.php.net/manual/en/arrayaccess.offsetset.php
	 */
	#[ReturnTypeWillChange]
	public function offsetSet( $offset, $value ) {
		if ( property_exists( __CLASS__, $offset ) ) {
			$this->{$offset} = $value;
		}
	}


	/**
	 * Returns the value at specified offset.
	 *
	 * @link https://www.php.net/manual/en/arrayaccess.offsetget.php
	 */
	#[ReturnTypeWillChange]
	public function offsetGet( $offset ) {
		if ( property_exists( __CLASS__, $offset ) ) {
			return $this->{$offset};
		}

		return null;
	}


	/**
	 * Returns true if the specified offset exists.
	 *
	 * @link https://www.php.net/manual/en/arrayaccess.offsetexists.php
	 */
	#[ReturnTypeWillChange]
	public function offsetExists( $offset ) {
		return property_exists( __CLASS__, $offset );
	}


	/**
	 * Unsets an offset.
	 *
	 * @link https://www.php.net/manual/en/arrayaccess.offsetunset.php
	 */
	#[ReturnTypeWillChange]
	public function offsetUnset( $offset ) {
	}

}
includes/contact-form.php000064400000075126147510545420011501 0ustar00<?php

class WPCF7_ContactForm {

	use WPCF7_SWV_SchemaHolder;
	use WPCF7_PipesHolder;

	const post_type = 'wpcf7_contact_form';

	private static $found_items = 0;
	private static $current = null;

	private $id;
	private $name;
	private $title;
	private $locale;
	private $properties = array();
	private $unit_tag;
	private $responses_count = 0;
	private $scanned_form_tags;
	private $shortcode_atts = array();
	private $hash = '';


	/**
	 * Returns count of contact forms found by the previous retrieval.
	 *
	 * @return int Count of contact forms.
	 */
	public static function count() {
		return self::$found_items;
	}


	/**
	 * Returns the contact form that is currently processed.
	 *
	 * @return WPCF7_ContactForm|null Current contact form object. Null if unset.
	 */
	public static function get_current() {
		return self::$current;
	}


	/**
	 * Registers the post type for contact forms.
	 */
	public static function register_post_type() {
		register_post_type( self::post_type, array(
			'labels' => array(
				'name' => __( 'Contact Forms', 'contact-form-7' ),
				'singular_name' => __( 'Contact Form', 'contact-form-7' ),
			),
			'rewrite' => false,
			'query_var' => false,
			'public' => false,
			'capability_type' => 'page',
			'capabilities' => array(
				'edit_post' => 'wpcf7_edit_contact_form',
				'read_post' => 'wpcf7_read_contact_form',
				'delete_post' => 'wpcf7_delete_contact_form',
				'edit_posts' => 'wpcf7_edit_contact_forms',
				'edit_others_posts' => 'wpcf7_edit_contact_forms',
				'publish_posts' => 'wpcf7_edit_contact_forms',
				'read_private_posts' => 'wpcf7_edit_contact_forms',
			),
		) );
	}


	/**
	 * Retrieves contact form data that match given conditions.
	 *
	 * @param string|array $args Optional. Arguments to be passed to WP_Query.
	 * @return array Array of WPCF7_ContactForm objects.
	 */
	public static function find( $args = '' ) {
		$defaults = array(
			'post_status' => 'any',
			'posts_per_page' => -1,
			'offset' => 0,
			'orderby' => 'ID',
			'order' => 'ASC',
		);

		$args = wp_parse_args( $args, $defaults );

		$args['post_type'] = self::post_type;

		$q = new WP_Query();
		$posts = $q->query( $args );

		self::$found_items = $q->found_posts;

		$objs = array();

		foreach ( (array) $posts as $post ) {
			$objs[] = new self( $post );
		}

		return $objs;
	}


	/**
	 * Returns a contact form data filled by default template contents.
	 *
	 * @param string|array $options Optional. Contact form options.
	 * @return WPCF7_ContactForm A new contact form object.
	 */
	public static function get_template( $options = '' ) {
		$options = wp_parse_args( $options, array(
			'locale' => null,
			'title' => __( 'Untitled', 'contact-form-7' ),
		) );

		if ( ! isset( $options['locale'] ) ) {
			$options['locale'] = determine_locale();
		}

		$callback = static function ( $options ) {
			$contact_form = new self;
			$contact_form->title = $options['title'];
			$contact_form->locale = $options['locale'];

			$properties = $contact_form->get_properties();

			foreach ( $properties as $key => $value ) {
				$default_template = WPCF7_ContactFormTemplate::get_default( $key );

				if ( isset( $default_template ) ) {
					$properties[$key] = $default_template;
				}
			}

			$contact_form->properties = $properties;

			return $contact_form;
		};

		$contact_form = wpcf7_switch_locale(
			$options['locale'],
			$callback,
			$options
		);

		self::$current = apply_filters( 'wpcf7_contact_form_default_pack',
			$contact_form, $options
		);

		return self::$current;
	}


	/**
	 * Creates a WPCF7_ContactForm object and sets it as the current instance.
	 *
	 * @param WPCF7_ContactForm|WP_Post|int $post Object or post ID.
	 * @return WPCF7_ContactForm|null Contact form object. Null if unset.
	 */
	public static function get_instance( $post ) {
		$contact_form = null;

		if ( $post instanceof self ) {
			$contact_form = $post;
		} elseif ( ! empty( $post ) ) {
			$post = get_post( $post );

			if ( isset( $post ) and self::post_type === get_post_type( $post ) ) {
				$contact_form = new self( $post );
			}
		}

		return self::$current = $contact_form;
	}


	/**
	 * Generates a "unit-tag" for the given contact form ID.
	 *
	 * @return string Unit-tag.
	 */
	private static function generate_unit_tag( $id = 0 ) {
		static $global_count = 0;

		$global_count += 1;

		if ( in_the_loop() ) {
			$unit_tag = sprintf( 'wpcf7-f%1$d-p%2$d-o%3$d',
				absint( $id ),
				get_the_ID(),
				$global_count
			);
		} else {
			$unit_tag = sprintf( 'wpcf7-f%1$d-o%2$d',
				absint( $id ),
				$global_count
			);
		}

		return $unit_tag;
	}


	/**
	 * Constructor.
	 */
	private function __construct( $post = null ) {
		$post = get_post( $post );

		if ( $post
		and self::post_type === get_post_type( $post ) ) {
			$this->id = $post->ID;
			$this->name = $post->post_name;
			$this->title = $post->post_title;
			$this->locale = get_post_meta( $post->ID, '_locale', true );
			$this->hash = get_post_meta( $post->ID, '_hash', true );

			$this->construct_properties( $post );
			$this->upgrade();
		} else {
			$this->construct_properties();
		}

		do_action( 'wpcf7_contact_form', $this );
	}


	/**
	 * Magic method for property overloading.
	 */
	public function __get( $name ) {
		$message = __( '<code>%1$s</code> property of a <code>WPCF7_ContactForm</code> object is <strong>no longer accessible</strong>. Use <code>%2$s</code> method instead.', 'contact-form-7' );

		if ( 'id' === $name ) {
			wp_trigger_error(
				'',
				sprintf( $message, 'id', 'id()' ),
				E_USER_DEPRECATED
			);

			return $this->id;
		} elseif ( 'title' === $name ) {
			wp_trigger_error(
				'',
				sprintf( $message, 'title', 'title()' ),
				E_USER_DEPRECATED
			);

			return $this->title;
		} elseif ( $prop = $this->prop( $name ) ) {
			wp_trigger_error(
				'',
				sprintf( $message, $name, 'prop(\'' . $name . '\')' ),
				E_USER_DEPRECATED
			);

			return $prop;
		}
	}


	/**
	 * Returns true if this contact form is not yet saved to the database.
	 */
	public function initial() {
		return empty( $this->id );
	}


	/**
	 * Constructs contact form properties. This is called only once
	 * from the constructor.
	 */
	private function construct_properties( $post = null ) {
		$builtin_properties = array(
			'form' => '',
			'mail' => array(),
			'mail_2' => array(),
			'messages' => array(),
			'additional_settings' => '',
		);

		$properties = apply_filters(
			'wpcf7_pre_construct_contact_form_properties',
			$builtin_properties, $this
		);

		// Filtering out properties with invalid name
		$properties = array_filter(
			$properties,
			static function ( $key ) {
				$sanitized_key = sanitize_key( $key );
				return $key === $sanitized_key;
			},
			ARRAY_FILTER_USE_KEY
		);

		foreach ( $properties as $name => $val ) {
			$prop = $this->retrieve_property( $name );

			if ( isset( $prop ) ) {
				$properties[$name] = $prop;
			}
		}

		$this->properties = $properties;

		foreach ( $properties as $name => $val ) {
			$properties[$name] = apply_filters(
				"wpcf7_contact_form_property_{$name}",
				$val, $this
			);
		}

		$this->properties = $properties;

		$properties = (array) apply_filters(
			'wpcf7_contact_form_properties',
			$properties, $this
		);

		$this->properties = $properties;
	}


	/**
	 * Retrieves contact form property of the specified name from the database.
	 *
	 * @param string $name Property name.
	 * @return array|string|null Property value. Null if property does not exist.
	 */
	private function retrieve_property( $name ) {
		$property = null;

		if ( ! $this->initial() ) {
			$post_id = $this->id;

			if ( metadata_exists( 'post', $post_id, '_' . $name ) ) {
				$property = get_post_meta( $post_id, '_' . $name, true );
			} elseif ( metadata_exists( 'post', $post_id, $name ) ) {
				$property = get_post_meta( $post_id, $name, true );
			}
		}

		return $property;
	}


	/**
	 * Returns the value for the given property name.
	 *
	 * @param string $name Property name.
	 * @return array|string|null Property value. Null if property does not exist.
	 */
	public function prop( $name ) {
		$props = $this->get_properties();
		return isset( $props[$name] ) ? $props[$name] : null;
	}


	/**
	 * Returns all the properties.
	 *
	 * @return array This contact form's properties.
	 */
	public function get_properties() {
		return (array) $this->properties;
	}


	/**
	 * Updates properties.
	 *
	 * @param array $properties New properties.
	 */
	public function set_properties( $properties ) {
		$defaults = $this->get_properties();

		$properties = wp_parse_args( $properties, $defaults );
		$properties = array_intersect_key( $properties, $defaults );

		$this->properties = $properties;
	}


	/**
	 * Returns ID of this contact form.
	 *
	 * @return int The ID.
	 */
	public function id() {
		return $this->id;
	}


	/**
	 * Returns unit-tag for this contact form.
	 *
	 * @return string Unit-tag.
	 */
	public function unit_tag() {
		return $this->unit_tag;
	}


	/**
	 * Returns name (slug) of this contact form.
	 *
	 * @return string Name.
	 */
	public function name() {
		return $this->name;
	}


	/**
	 * Returns title of this contact form.
	 *
	 * @return string Title.
	 */
	public function title() {
		return $this->title;
	}


	/**
	 * Set a title for this contact form.
	 *
	 * @param string $title Title.
	 */
	public function set_title( $title ) {
		$title = strip_tags( $title );
		$title = trim( $title );

		if ( '' === $title ) {
			$title = __( 'Untitled', 'contact-form-7' );
		}

		$this->title = $title;
	}


	/**
	 * Returns the locale code of this contact form.
	 *
	 * @return string Locale code. Empty string if no valid locale is set.
	 */
	public function locale() {
		if ( wpcf7_is_valid_locale( $this->locale ) ) {
			return $this->locale;
		} else {
			return '';
		}
	}


	/**
	 * Sets a locale for this contact form.
	 *
	 * @param string $locale Locale code.
	 */
	public function set_locale( $locale ) {
		$locale = trim( $locale );

		if ( wpcf7_is_valid_locale( $locale ) ) {
			$this->locale = $locale;
		} else {
			$this->locale = 'en_US';
		}
	}


	/**
	 * Retrieves the random hash string tied to this contact form.
	 *
	 * @param int $length Length of hash string.
	 * @return string Hash string unique to this contact form.
	 */
	public function hash( $length = 7 ) {
		return substr( $this->hash, 0, absint( $length ) );
	}


	/**
	 * Returns the specified shortcode attribute value.
	 *
	 * @param string $name Shortcode attribute name.
	 * @return string|null Attribute value. Null if the attribute does not exist.
	 */
	public function shortcode_attr( $name ) {
		if ( isset( $this->shortcode_atts[$name] ) ) {
			return (string) $this->shortcode_atts[$name];
		}
	}


	/**
	 * Returns true if this contact form is identical to the submitted one.
	 */
	public function is_posted() {
		if ( ! WPCF7_Submission::get_instance() ) {
			return false;
		}

		if ( empty( $_POST['_wpcf7_unit_tag'] ) ) {
			return false;
		}

		return $this->unit_tag() === $_POST['_wpcf7_unit_tag'];
	}


	/**
	 * Generates HTML that represents a form.
	 *
	 * @param string|array $options Optional. Form options.
	 * @return string HTML output.
	 */
	public function form_html( $options = '' ) {
		$options = wp_parse_args( $options, array(
			'html_id' => '',
			'html_name' => '',
			'html_title' => '',
			'html_class' => '',
			'output' => 'form',
		) );

		$this->shortcode_atts = $options;

		if ( 'raw_form' == $options['output'] ) {
			return sprintf(
				'<pre class="wpcf7-raw-form"><code>%s</code></pre>',
				esc_html( $this->prop( 'form' ) )
			);
		}

		if ( $this->is_true( 'subscribers_only' )
		and ! current_user_can( 'wpcf7_submit', $this->id() ) ) {
			$notice = __(
				"This contact form is available only for logged in users.",
				'contact-form-7'
			);

			$notice = sprintf(
				'<p class="wpcf7-subscribers-only">%s</p>',
				esc_html( $notice )
			);

			return apply_filters( 'wpcf7_subscribers_only_notice', $notice, $this );
		}

		$this->unit_tag = self::generate_unit_tag( $this->id );

		$action_url = wpcf7_get_request_uri();

		if ( $frag = strstr( $action_url, '#' ) ) {
			$action_url = substr( $action_url, 0, -strlen( $frag ) );
		}

		$action_url .= '#' . $this->unit_tag();

		$action_url = apply_filters( 'wpcf7_form_action_url', $action_url );

		if (
			str_starts_with( $action_url, '//' ) or
			! str_starts_with( $action_url, '/' ) and
			! str_starts_with( $action_url, home_url() )
		) {
			return sprintf(
				'<p class="wpcf7-invalid-action-url"><strong>%1$s</strong> %2$s</p>',
				esc_html( __( 'Error:', 'contact-form-7' ) ),
				esc_html( __( "Invalid action URL is detected.", 'contact-form-7' ) )
			);
		}

		$lang_tag = str_replace( '_', '-', $this->locale );

		if ( preg_match( '/^([a-z]+-[a-z]+)-/i', $lang_tag, $matches ) ) {
			$lang_tag = $matches[1];
		}

		$html = "\n" . sprintf( '<div %s>',
			wpcf7_format_atts( array(
				'class' => 'wpcf7 no-js',
				'id' => $this->unit_tag(),
				( get_option( 'html_type' ) == 'text/html' ) ? 'lang' : 'xml:lang'
					=> $lang_tag,
				'dir' => wpcf7_is_rtl( $this->locale ) ? 'rtl' : 'ltr',
				'data-wpcf7-id' => $this->id(),
			) )
		);

		$html .= "\n" . $this->screen_reader_response() . "\n";

		$id_attr = apply_filters( 'wpcf7_form_id_attr',
			preg_replace( '/[^A-Za-z0-9:._-]/', '', $options['html_id'] )
		);

		$name_attr = apply_filters( 'wpcf7_form_name_attr',
			preg_replace( '/[^A-Za-z0-9:._-]/', '', $options['html_name'] )
		);

		$title_attr = apply_filters( 'wpcf7_form_title_attr', $options['html_title'] );

		$class = 'wpcf7-form';

		if ( $this->is_posted() ) {
			$submission = WPCF7_Submission::get_instance();

			$data_status_attr = $this->form_status_class_name(
				$submission->get_status()
			);

			$class .= sprintf( ' %s', $data_status_attr );
		} else {
			$data_status_attr = 'init';
			$class .= ' init';
		}

		if ( $options['html_class'] ) {
			$class .= ' ' . $options['html_class'];
		}

		if ( $this->in_demo_mode() ) {
			$class .= ' demo';
		}

		$class = explode( ' ', $class );
		$class = array_map( 'sanitize_html_class', $class );
		$class = array_filter( $class );
		$class = array_unique( $class );
		$class = implode( ' ', $class );
		$class = apply_filters( 'wpcf7_form_class_attr', $class );

		$enctype = wpcf7_enctype_value( apply_filters( 'wpcf7_form_enctype', '' ) );
		$autocomplete = apply_filters( 'wpcf7_form_autocomplete', '' );

		$atts = array(
			'action' => esc_url( $action_url ),
			'method' => 'post',
			'class' => ( '' !== $class ) ? $class : null,
			'id' => ( '' !== $id_attr ) ? $id_attr : null,
			'name' => ( '' !== $name_attr ) ? $name_attr : null,
			'aria-label' => ( '' !== $title_attr )
				? $title_attr : __( 'Contact form', 'contact-form-7' ),
			'enctype' => ( '' !== $enctype ) ? $enctype : null,
			'autocomplete' => ( '' !== $autocomplete ) ? $autocomplete : null,
			'novalidate' => true,
			'data-status' => $data_status_attr,
		);

		$atts += (array) apply_filters( 'wpcf7_form_additional_atts', array() );

		$html .= sprintf( '<form %s>', wpcf7_format_atts( $atts ) ) . "\n";
		$html .= $this->form_hidden_fields();
		$html .= $this->form_elements();

		if ( ! $this->responses_count ) {
			$html .= $this->form_response_output();
		}

		$html .= "\n" . '</form>';
		$html .= "\n" . '</div>';

		return $html . "\n";
	}


	/**
	 * Returns the class name that matches the given form status.
	 */
	private function form_status_class_name( $status ) {
		switch ( $status ) {
			case 'init':
				$class = 'init';
				break;
			case 'validation_failed':
				$class = 'invalid';
				break;
			case 'acceptance_missing':
				$class = 'unaccepted';
				break;
			case 'spam':
				$class = 'spam';
				break;
			case 'aborted':
				$class = 'aborted';
				break;
			case 'mail_sent':
				$class = 'sent';
				break;
			case 'mail_failed':
				$class = 'failed';
				break;
			default:
				$class = sprintf(
					'custom-%s',
					preg_replace( '/[^0-9a-z]+/i', '-', $status )
				);
		}

		return $class;
	}


	/**
	 * Returns a set of hidden fields.
	 */
	private function form_hidden_fields() {
		$hidden_fields = array(
			'_wpcf7' => $this->id(),
			'_wpcf7_version' => WPCF7_VERSION,
			'_wpcf7_locale' => $this->locale(),
			'_wpcf7_unit_tag' => $this->unit_tag(),
			'_wpcf7_container_post' => 0,
			'_wpcf7_posted_data_hash' => '',
		);

		if ( in_the_loop() ) {
			$hidden_fields['_wpcf7_container_post'] = (int) get_the_ID();
		}

		if ( $this->nonce_is_active() and is_user_logged_in() ) {
			$hidden_fields['_wpnonce'] = wpcf7_create_nonce();
		}

		$hidden_fields += (array) apply_filters(
			'wpcf7_form_hidden_fields', array()
		);

		$content = '';

		foreach ( $hidden_fields as $name => $value ) {
			$content .= sprintf(
				'<input type="hidden" name="%1$s" value="%2$s" />',
				esc_attr( $name ),
				esc_attr( $value )
			) . "\n";
		}

		return '<div style="display: none;">' . "\n" . $content . '</div>' . "\n";
	}


	/**
	 * Returns the visible response output for a form submission.
	 */
	public function form_response_output() {
		$status = 'init';
		$class = 'wpcf7-response-output';
		$content = '';

		if ( $this->is_posted() ) { // Post response output for non-AJAX
			$submission = WPCF7_Submission::get_instance();
			$status = $submission->get_status();
			$content = $submission->get_response();
		}

		$atts = array(
			'class' => trim( $class ),
			'aria-hidden' => 'true',
		);

		$output = sprintf( '<div %1$s>%2$s</div>',
			wpcf7_format_atts( $atts ),
			esc_html( $content )
		);

		$output = apply_filters( 'wpcf7_form_response_output',
			$output, $class, $content, $this, $status
		);

		$this->responses_count += 1;

		return $output;
	}


	/**
	 * Returns the response output that is only accessible from screen readers.
	 */
	public function screen_reader_response() {
		$primary_response = '';
		$validation_errors = array();

		if ( $this->is_posted() ) { // Post response output for non-AJAX
			$submission = WPCF7_Submission::get_instance();
			$primary_response = $submission->get_response();

			if ( $invalid_fields = $submission->get_invalid_fields() ) {
				foreach ( (array) $invalid_fields as $name => $field ) {
					$list_item = esc_html( $field['reason'] );

					if ( $field['idref'] ) {
						$list_item = sprintf(
							'<a href="#%1$s">%2$s</a>',
							esc_attr( $field['idref'] ),
							$list_item
						);
					}

					$validation_error_id = wpcf7_get_validation_error_reference(
						$name,
						$this->unit_tag()
					);

					if ( $validation_error_id ) {
						$list_item = sprintf(
							'<li id="%1$s">%2$s</li>',
							esc_attr( $validation_error_id ),
							$list_item
						);

						$validation_errors[] = $list_item;
					}
				}
			}
		}

		$primary_response = sprintf(
			'<p role="status" aria-live="polite" aria-atomic="true">%s</p>',
			esc_html( $primary_response )
		);

		$validation_errors = sprintf(
			'<ul>%s</ul>',
			implode( "\n", $validation_errors )
		);

		$output = sprintf(
			'<div class="screen-reader-response">%1$s %2$s</div>',
			$primary_response,
			$validation_errors
		);

		return $output;
	}


	/**
	 * Returns a validation error for the specified input field.
	 *
	 * @param string $name Input field name.
	 */
	public function validation_error( $name ) {
		$error = '';

		if ( $this->is_posted() ) {
			$submission = WPCF7_Submission::get_instance();

			if ( $invalid_field = $submission->get_invalid_field( $name ) ) {
				$error = trim( $invalid_field['reason'] );
			}
		}

		if ( ! $error ) {
			return $error;
		}

		$atts = array(
			'class' => 'wpcf7-not-valid-tip',
			'aria-hidden' => 'true',
		);

		$error = sprintf(
			'<span %1$s>%2$s</span>',
			wpcf7_format_atts( $atts ),
			esc_html( $error )
		);

		return apply_filters( 'wpcf7_validation_error', $error, $name, $this );
	}


	/**
	 * Replaces all form-tags in the form template with corresponding HTML.
	 *
	 * @return string Replaced form content.
	 */
	public function replace_all_form_tags() {
		$manager = WPCF7_FormTagsManager::get_instance();
		$form = $this->prop( 'form' );

		if ( wpcf7_autop_or_not() ) {
			$form = $manager->replace_with_placeholders( $form );
			$form = wpcf7_autop( $form );
			$form = $manager->restore_from_placeholders( $form );
		}

		$form = $manager->replace_all( $form );
		$this->scanned_form_tags = $manager->get_scanned_tags();

		return $form;
	}


	/**
	 * Replaces all form-tags in the form template with corresponding HTML.
	 *
	 * @deprecated 4.6 Use replace_all_form_tags()
	 *
	 * @return string Replaced form content.
	 */
	public function form_do_shortcode() {
		wpcf7_deprecated_function( __METHOD__, '4.6',
			'WPCF7_ContactForm::replace_all_form_tags'
		);

		return $this->replace_all_form_tags();
	}


	/**
	 * Scans form-tags from the form template.
	 *
	 * @param string|array|null $cond Optional. Filters. Default null.
	 * @return array Form-tags matching the given filter conditions.
	 */
	public function scan_form_tags( $cond = null ) {
		$manager = WPCF7_FormTagsManager::get_instance();

		if ( empty( $this->scanned_form_tags ) ) {
			$this->scanned_form_tags = $manager->scan( $this->prop( 'form' ) );
		}

		$tags = $this->scanned_form_tags;

		return $manager->filter( $tags, $cond );
	}


	/**
	 * Scans form-tags from the form template.
	 *
	 * @deprecated 4.6 Use scan_form_tags()
	 *
	 * @param string|array|null $cond Optional. Filters. Default null.
	 * @return array Form-tags matching the given filter conditions.
	 */
	public function form_scan_shortcode( $cond = null ) {
		wpcf7_deprecated_function( __METHOD__, '4.6',
			'WPCF7_ContactForm::scan_form_tags'
		);

		return $this->scan_form_tags( $cond );
	}


	/**
	 * Replaces all form-tags in the form template with corresponding HTML.
	 *
	 * @return string Replaced form content. wpcf7_form_elements filters applied.
	 */
	public function form_elements() {
		return apply_filters( 'wpcf7_form_elements',
			$this->replace_all_form_tags()
		);
	}


	/**
	 * Collects mail-tags available for this contact form.
	 *
	 * @param string|array $options Optional. Search options.
	 * @return array Mail-tag names.
	 */
	public function collect_mail_tags( $options = '' ) {
		$manager = WPCF7_FormTagsManager::get_instance();

		$options = wp_parse_args( $options, array(
			'include' => array(),
			'exclude' => $manager->collect_tag_types( 'not-for-mail' ),
		) );

		$tags = $this->scan_form_tags();
		$mailtags = array();

		foreach ( (array) $tags as $tag ) {
			$type = $tag->basetype;

			if ( empty( $type ) ) {
				continue;
			} elseif ( ! empty( $options['include'] ) ) {
				if ( ! in_array( $type, $options['include'] ) ) {
					continue;
				}
			} elseif ( ! empty( $options['exclude'] ) ) {
				if ( in_array( $type, $options['exclude'] ) ) {
					continue;
				}
			}

			$mailtags[] = $tag->name;
		}

		$mailtags = array_unique( $mailtags );
		$mailtags = array_filter( $mailtags );
		$mailtags = array_values( $mailtags );

		return apply_filters( 'wpcf7_collect_mail_tags', $mailtags, $options, $this );
	}


	/**
	 * Prints a mail-tag suggestion list.
	 *
	 * @param string $template_name Optional. Mail template name. Default 'mail'.
	 */
	public function suggest_mail_tags( $template_name = 'mail' ) {
		$mail = wp_parse_args( $this->prop( $template_name ),
			array(
				'active' => false,
				'recipient' => '',
				'sender' => '',
				'subject' => '',
				'body' => '',
				'additional_headers' => '',
				'attachments' => '',
				'use_html' => false,
				'exclude_blank' => false,
			)
		);

		$mail = array_filter( $mail );

		foreach ( (array) $this->collect_mail_tags() as $mail_tag ) {
			$pattern = sprintf(
				'/\[(_[a-z]+_)?%s([ \t]+[^]]+)?\]/',
				preg_quote( $mail_tag, '/' )
			);

			$used = preg_grep( $pattern, $mail );

			echo sprintf(
				'<span class="%1$s">[%2$s]</span>',
				'mailtag code ' . ( $used ? 'used' : 'unused' ),
				esc_html( $mail_tag )
			);
		}
	}


	/**
	 * Submits this contact form.
	 *
	 * @param string|array $options Optional. Submission options. Default empty.
	 * @return array Result of submission.
	 */
	public function submit( $options = '' ) {
		$options = wp_parse_args( $options, array(
			'skip_mail' =>
				( $this->in_demo_mode()
				|| $this->is_true( 'skip_mail' )
				|| ! empty( $this->skip_mail ) ),
		) );

		if ( $this->is_true( 'subscribers_only' )
		and ! current_user_can( 'wpcf7_submit', $this->id() ) ) {
			$result = array(
				'contact_form_id' => $this->id(),
				'status' => 'error',
				'message' => __(
					"This contact form is available only for logged in users.",
					'contact-form-7'
				),
			);

			return $result;
		}

		$submission = WPCF7_Submission::get_instance( $this, array(
			'skip_mail' => $options['skip_mail'],
		) );

		$result = array(
			'contact_form_id' => $this->id(),
		);

		$result += $submission->get_result();

		if ( $this->in_demo_mode() ) {
			$result['demo_mode'] = true;
		}

		do_action( 'wpcf7_submit', $this, $result );

		return $result;
	}


	/**
	 * Returns message used for given status.
	 *
	 * @param string $status Status.
	 * @param bool $filter Optional. Whether filters are applied. Default true.
	 * @return string Message.
	 */
	public function message( $status, $filter = true ) {
		$messages = $this->prop( 'messages' );
		$message = isset( $messages[$status] ) ? $messages[$status] : '';

		if ( $filter ) {
			$message = $this->filter_message( $message, $status );
		}

		return $message;
	}


	/**
	 * Filters a message.
	 *
	 * @param string $message Message to filter.
	 * @param string $status Optional. Status. Default empty.
	 * @return string Filtered message.
	 */
	public function filter_message( $message, $status = '' ) {
		$message = wpcf7_mail_replace_tags( $message );
		$message = apply_filters( 'wpcf7_display_message', $message, $status );
		$message = wp_strip_all_tags( $message );

		return $message;
	}


	/**
	 * Returns the additional setting value searched by name.
	 *
	 * @param string $name Name of setting.
	 * @return string Additional setting value.
	 */
	public function pref( $name ) {
		$settings = $this->additional_setting( $name );

		if ( $settings ) {
			return $settings[0];
		}
	}


	/**
	 * Returns additional setting values searched by name.
	 *
	 * @param string $name Name of setting.
	 * @param int $max Maximum result item count.
	 * @return array Additional setting values.
	 */
	public function additional_setting( $name, $max = 1 ) {
		$settings = (array) explode( "\n", $this->prop( 'additional_settings' ) );

		$pattern = '/^([a-zA-Z0-9_]+)[\t ]*:(.*)$/';
		$count = 0;
		$values = array();

		foreach ( $settings as $setting ) {
			if ( preg_match( $pattern, $setting, $matches ) ) {
				if ( $matches[1] != $name ) {
					continue;
				}

				if ( ! $max or $count < (int) $max ) {
					$values[] = trim( $matches[2] );
					$count += 1;
				}
			}
		}

		return $values;
	}


	/**
	 * Returns true if the specified setting has a truthy string value.
	 *
	 * @param string $name Name of setting.
	 * @return bool True if the setting value is 'on', 'true', or '1'.
	 */
	public function is_true( $name ) {
		return in_array(
			$this->pref( $name ),
			array( 'on', 'true', '1' ),
			true
		);
	}


	/**
	 * Returns true if this contact form is in the demo mode.
	 */
	public function in_demo_mode() {
		return $this->is_true( 'demo_mode' );
	}


	/**
	 * Returns true if nonce is active for this contact form.
	 */
	public function nonce_is_active() {
		$is_active = WPCF7_VERIFY_NONCE;

		if ( $this->is_true( 'subscribers_only' ) ) {
			$is_active = true;
		}

		return (bool) apply_filters( 'wpcf7_verify_nonce', $is_active, $this );
	}


	/**
	 * Returns true if the specified setting has a falsey string value.
	 *
	 * @param string $name Name of setting.
	 * @return bool True if the setting value is 'off', 'false', or '0'.
	 */
	public function is_false( $name ) {
		return in_array(
			$this->pref( $name ),
			array( 'off', 'false', '0' ),
			true
		);
	}


	/**
	 * Upgrades this contact form properties.
	 */
	private function upgrade() {
		$mail = $this->prop( 'mail' );

		if ( is_array( $mail )
		and ! isset( $mail['recipient'] ) ) {
			$mail['recipient'] = get_option( 'admin_email' );
		}

		$this->properties['mail'] = $mail;

		$messages = $this->prop( 'messages' );

		if ( is_array( $messages ) ) {
			foreach ( wpcf7_messages() as $key => $arr ) {
				if ( ! isset( $messages[$key] ) ) {
					$messages[$key] = $arr['default'];
				}
			}
		}

		$this->properties['messages'] = $messages;
	}


	/**
	 * Stores this contact form properties to the database.
	 *
	 * @return int The post ID on success. The value 0 on failure.
	 */
	public function save() {
		$title = wp_slash( $this->title );
		$props = wp_slash( $this->get_properties() );

		$post_content = implode( "\n", wpcf7_array_flatten( $props ) );

		if ( $this->initial() ) {
			$post_id = wp_insert_post( array(
				'post_type' => self::post_type,
				'post_status' => 'publish',
				'post_title' => $title,
				'post_content' => trim( $post_content ),
			) );
		} else {
			$post_id = wp_update_post( array(
				'ID' => (int) $this->id,
				'post_status' => 'publish',
				'post_title' => $title,
				'post_content' => trim( $post_content ),
			) );
		}

		if ( $post_id ) {
			foreach ( $props as $prop => $value ) {
				update_post_meta( $post_id, '_' . $prop,
					wpcf7_normalize_newline_deep( $value )
				);
			}

			if ( wpcf7_is_valid_locale( $this->locale ) ) {
				update_post_meta( $post_id, '_locale', $this->locale );
			}

			add_post_meta( $post_id, '_hash',
				wpcf7_generate_contact_form_hash( $post_id ),
				true // Unique
			);

			if ( $this->initial() ) {
				$this->id = $post_id;
				do_action( 'wpcf7_after_create', $this );
			} else {
				do_action( 'wpcf7_after_update', $this );
			}

			do_action( 'wpcf7_after_save', $this );
		}

		return $post_id;
	}


	/**
	 * Makes a copy of this contact form.
	 *
	 * @return WPCF7_ContactForm New contact form object.
	 */
	public function copy() {
		$new = new self;
		$new->title = $this->title . '_copy';
		$new->locale = $this->locale;
		$new->properties = $this->properties;

		return apply_filters( 'wpcf7_copy', $new, $this );
	}


	/**
	 * Deletes this contact form.
	 *
	 * @return bool True if deletion succeeded, false otherwise.
	 */
	public function delete() {
		if ( $this->initial() ) {
			return false;
		}

		if ( wp_delete_post( $this->id, true ) ) {
			$this->id = 0;
			return true;
		}

		return false;
	}


	/**
	 * Returns a WordPress shortcode for this contact form.
	 */
	public function shortcode( $options = '' ) {
		$options = wp_parse_args( $options, array(
			'use_old_format' => false
		) );

		$title = str_replace( array( '"', '[', ']' ), '', $this->title );

		if ( $options['use_old_format'] ) {
			$old_unit_id = (int) get_post_meta( $this->id, '_old_cf7_unit_id', true );

			if ( $old_unit_id ) {
				$shortcode = sprintf(
					'[contact-form %1$d "%2$s"]',
					$old_unit_id,
					$title
				);
			} else {
				$shortcode = '';
			}
		} else {
			$shortcode = sprintf(
				'[contact-form-7 id="%1$s" title="%2$s"]',
				$this->hash(),
				$title
			);
		}

		return apply_filters( 'wpcf7_contact_form_shortcode',
			$shortcode, $options, $this
		);
	}
}
includes/pipe.php000064400000005076147510545420010037 0ustar00<?php
/**
 * Pipe-related classes.
 *
 * @link https://contactform7.com/selectable-recipient-with-pipes/
 */


/**
 * Class representing a pair of pipe.
 */
class WPCF7_Pipe {

	public $before = '';
	public $after = '';

	public function __construct( $text ) {
		$text = (string) $text;

		$pipe_pos = strpos( $text, '|' );

		if ( false === $pipe_pos ) {
			$this->before = $this->after = trim( $text );
		} else {
			$this->before = trim( substr( $text, 0, $pipe_pos ) );
			$this->after = trim( substr( $text, $pipe_pos + 1 ) );
		}
	}
}


/**
 * Class representing a list of pipes.
 */
class WPCF7_Pipes {

	private $pipes = array();

	public function __construct( $texts = null ) {
		foreach ( (array) $texts as $text ) {
			$this->add_pipe( $text );
		}
	}

	private function add_pipe( $text ) {
		$pipe = new WPCF7_Pipe( $text );
		$this->pipes[] = $pipe;
	}

	public function merge( self $another ) {
		$this->pipes = array_merge( $this->pipes, $another->pipes );
	}

	public function do_pipe( $input ) {
		$input_canonical = wpcf7_canonicalize( $input, array(
			'strto' => 'as-is',
		) );

		foreach ( $this->pipes as $pipe ) {
			$before_canonical = wpcf7_canonicalize( $pipe->before, array(
				'strto' => 'as-is',
			) );

			if ( $input_canonical === $before_canonical ) {
				return $pipe->after;
			}
		}

		return $input;
	}

	public function collect_befores() {
		$befores = array();

		foreach ( $this->pipes as $pipe ) {
			$befores[] = $pipe->before;
		}

		return $befores;
	}

	public function collect_afters() {
		$afters = array();

		foreach ( $this->pipes as $pipe ) {
			$afters[] = $pipe->after;
		}

		return $afters;
	}

	public function zero() {
		return empty( $this->pipes );
	}

	public function random_pipe() {
		if ( $this->zero() ) {
			return null;
		}

		return $this->pipes[array_rand( $this->pipes )];
	}

	public function to_array() {
		return array_map(
			static function ( WPCF7_Pipe $pipe ) {
				return array(
					$pipe->before,
					$pipe->after,
				);
			},
			$this->pipes
		);
	}
}


/**
 * Trait for classes that hold cross-tag WPCF7_Pipes object.
 */
trait WPCF7_PipesHolder {

	protected $pipes;

	public function get_pipes( $field_name ) {
		if ( isset( $this->pipes[$field_name] ) ) {
			return $this->pipes[$field_name];
		}

		$result = new WPCF7_Pipes;

		$tags = $this->scan_form_tags( array(
			'name' => $field_name,
		) );

		foreach ( $tags as $tag ) {
			if ( $tag->pipes instanceof WPCF7_Pipes ) {
				$result->merge( $tag->pipes );
			}
		}

		return $this->pipes[$field_name] = $result;
	}

	public function scan_form_tags() {
		return array();
	}

}
includes/css/styles.css000064400000005516147510545420011215 0ustar00.wpcf7 .screen-reader-response {
	position: absolute;
	overflow: hidden;
	clip: rect(1px, 1px, 1px, 1px);
	clip-path: inset(50%);
	height: 1px;
	width: 1px;
	margin: -1px;
	padding: 0;
	border: 0;
	word-wrap: normal !important;
}

.wpcf7 form .wpcf7-response-output {
	margin: 2em 0.5em 1em;
	padding: 0.2em 1em;
	border: 2px solid #00a0d2; /* Blue */
}

.wpcf7 form.init .wpcf7-response-output,
.wpcf7 form.resetting .wpcf7-response-output,
.wpcf7 form.submitting .wpcf7-response-output {
	display: none;
}

.wpcf7 form.sent .wpcf7-response-output {
	border-color: #46b450; /* Green */
}

.wpcf7 form.failed .wpcf7-response-output,
.wpcf7 form.aborted .wpcf7-response-output {
	border-color: #dc3232; /* Red */
}

.wpcf7 form.spam .wpcf7-response-output {
	border-color: #f56e28; /* Orange */
}

.wpcf7 form.invalid .wpcf7-response-output,
.wpcf7 form.unaccepted .wpcf7-response-output,
.wpcf7 form.payment-required .wpcf7-response-output {
	border-color: #ffb900; /* Yellow */
}

.wpcf7-form-control-wrap {
	position: relative;
}

.wpcf7-not-valid-tip {
	color: #dc3232; /* Red */
	font-size: 1em;
	font-weight: normal;
	display: block;
}

.use-floating-validation-tip .wpcf7-not-valid-tip {
	position: relative;
	top: -2ex;
	left: 1em;
	z-index: 100;
	border: 1px solid #dc3232;
	background: #fff;
	padding: .2em .8em;
	width: 24em;
}

.wpcf7-list-item {
	display: inline-block;
	margin: 0 0 0 1em;
}

.wpcf7-list-item-label::before,
.wpcf7-list-item-label::after {
	content: " ";
}

.wpcf7-spinner {
	visibility: hidden;
	display: inline-block;
	background-color: #23282d; /* Dark Gray 800 */
	opacity: 0.75;
	width: 24px;
	height: 24px;
	border: none;
	border-radius: 100%;
	padding: 0;
	margin: 0 24px;
	position: relative;
}

form.submitting .wpcf7-spinner {
	visibility: visible;
}

.wpcf7-spinner::before {
	content: '';
	position: absolute;
	background-color: #fbfbfc; /* Light Gray 100 */
	top: 4px;
	left: 4px;
	width: 6px;
	height: 6px;
	border: none;
	border-radius: 100%;
	transform-origin: 8px 8px;
	animation-name: spin;
	animation-duration: 1000ms;
	animation-timing-function: linear;
	animation-iteration-count: infinite;
}

@media (prefers-reduced-motion: reduce) {
	.wpcf7-spinner::before {
		animation-name: blink;
		animation-duration: 2000ms;
	}
}

@keyframes spin {
	from {
		transform: rotate(0deg);
	}

	to {
		transform: rotate(360deg);
	}
}

@keyframes blink {
	from {
		opacity: 0;
	}

	50% {
		opacity: 1;
	}

	to {
		opacity: 0;
	}
}

.wpcf7 [inert] {
	opacity: 0.5;
}

.wpcf7 input[type="file"] {
	cursor: pointer;
}

.wpcf7 input[type="file"]:disabled {
	cursor: default;
}

.wpcf7 .wpcf7-submit:disabled {
	cursor: not-allowed;
}

.wpcf7 input[type="url"],
.wpcf7 input[type="email"],
.wpcf7 input[type="tel"] {
	direction: ltr;
}

.wpcf7-reflection > output {
	display: list-item;
	list-style: none;
}

.wpcf7-reflection > output[hidden] {
	display: none;
}
includes/css/styles-rtl.css000064400000000230147510545420012000 0ustar00.wpcf7-not-valid-tip {
	direction: rtl;
}

.use-floating-validation-tip .wpcf7-not-valid-tip {
	right: 1em;
}

.wpcf7-list-item {
	margin: 0 1em 0 0;
}
includes/shortcodes.php000064400000005226147510545420011254 0ustar00<?php
/**
 * All the functions and classes in this file are deprecated.
 * You should not use them. The functions and classes will be
 * removed in a later version.
 */

function wpcf7_add_shortcode( $tag, $callback, $has_name = false ) {
	wpcf7_deprecated_function( __FUNCTION__, '4.6', 'wpcf7_add_form_tag' );

	return wpcf7_add_form_tag( $tag, $callback, $has_name );
}

function wpcf7_remove_shortcode( $tag ) {
	wpcf7_deprecated_function( __FUNCTION__, '4.6', 'wpcf7_remove_form_tag' );

	return wpcf7_remove_form_tag( $tag );
}

function wpcf7_do_shortcode( $content ) {
	wpcf7_deprecated_function( __FUNCTION__, '4.6',
		'wpcf7_replace_all_form_tags' );

	return wpcf7_replace_all_form_tags( $content );
}

function wpcf7_scan_shortcode( $cond = null ) {
	wpcf7_deprecated_function( __FUNCTION__, '4.6', 'wpcf7_scan_form_tags' );

	return wpcf7_scan_form_tags( $cond );
}

class WPCF7_ShortcodeManager {

	private static $form_tags_manager;

	private function __construct() {}

	public static function get_instance() {
		wpcf7_deprecated_function( __METHOD__, '4.6',
			'WPCF7_FormTagsManager::get_instance' );

		self::$form_tags_manager = WPCF7_FormTagsManager::get_instance();
		return new self;
	}

	public function get_scanned_tags() {
		wpcf7_deprecated_function( __METHOD__, '4.6',
			'WPCF7_FormTagsManager::get_scanned_tags' );

		return self::$form_tags_manager->get_scanned_tags();
	}

	public function add_shortcode( $tag, $callback, $has_name = false ) {
		wpcf7_deprecated_function( __METHOD__, '4.6',
			'WPCF7_FormTagsManager::add' );

		return self::$form_tags_manager->add( $tag, $callback, $has_name );
	}

	public function remove_shortcode( $tag ) {
		wpcf7_deprecated_function( __METHOD__, '4.6',
			'WPCF7_FormTagsManager::remove' );

		return self::$form_tags_manager->remove( $tag );
	}

	public function normalize_shortcode( $content ) {
		wpcf7_deprecated_function( __METHOD__, '4.6',
			'WPCF7_FormTagsManager::normalize' );

		return self::$form_tags_manager->normalize( $content );
	}

	public function do_shortcode( $content, $exec = true ) {
		wpcf7_deprecated_function( __METHOD__, '4.6',
			'WPCF7_FormTagsManager::replace_all' );

		if ( $exec ) {
			return self::$form_tags_manager->replace_all( $content );
		} else {
			return self::$form_tags_manager->scan( $content );
		}
	}

	public function scan_shortcode( $content ) {
		wpcf7_deprecated_function( __METHOD__, '4.6',
			'WPCF7_FormTagsManager::scan' );

		return self::$form_tags_manager->scan( $content );
	}
}

class WPCF7_Shortcode extends WPCF7_FormTag {

	public function __construct( $tag ) {
		wpcf7_deprecated_function( 'WPCF7_Shortcode', '4.6', 'WPCF7_FormTag' );

		parent::__construct( $tag );
	}
}
includes/special-mail-tags.php000064400000015005147510545420012367 0ustar00<?php
/**
** Special Mail Tags
** https://contactform7.com/special-mail-tags/
**/

add_filter( 'wpcf7_special_mail_tags', 'wpcf7_special_mail_tag', 10, 4 );

/**
 * Returns output string of a special mail-tag.
 *
 * @param string $output The string to be output.
 * @param string $name The tag name of the special mail-tag.
 * @param bool $html Whether the mail-tag is used in an HTML content.
 * @param WPCF7_MailTag $mail_tag An object representation of the mail-tag.
 * @return string Output of the given special mail-tag.
 */
function wpcf7_special_mail_tag( $output, $name, $html, $mail_tag = null ) {
	if ( ! $mail_tag instanceof WPCF7_MailTag ) {
		wpcf7_doing_it_wrong(
			sprintf( '%s()', __FUNCTION__ ),
			__( 'The fourth parameter ($mail_tag) must be an instance of the WPCF7_MailTag class.', 'contact-form-7' ),
			'5.2.2'
		);
	}

	$name = preg_replace( '/^wpcf7\./', '_', $name ); // for back-compat

	$submission = WPCF7_Submission::get_instance();

	if ( ! $submission ) {
		return $output;
	}

	if ( '_remote_ip' === $name ) {
		if ( $remote_ip = $submission->get_meta( 'remote_ip' ) ) {
			return $remote_ip;
		} else {
			return '';
		}
	}

	if ( '_user_agent' === $name ) {
		if ( $user_agent = $submission->get_meta( 'user_agent' ) ) {
			return $html ? esc_html( $user_agent ) : $user_agent;
		} else {
			return '';
		}
	}

	if ( '_url' === $name ) {
		if ( $url = $submission->get_meta( 'url' ) ) {
			return $url;
		} else {
			return '';
		}
	}

	if ( '_date' === $name or '_time' === $name ) {
		if ( $timestamp = $submission->get_meta( 'timestamp' ) ) {
			if ( '_date' === $name ) {
				return wp_date( get_option( 'date_format' ), $timestamp );
			}

			if ( '_time' === $name ) {
				return wp_date( get_option( 'time_format' ), $timestamp );
			}
		}

		return '';
	}

	if ( '_invalid_fields' === $name ) {
		return count( $submission->get_invalid_fields() );
	}

	if ( '_contact_form_title' === $name ) {
		$contact_form = $submission->get_contact_form();

		return $html
			? esc_html( $contact_form->title() )
			: $contact_form->title();
	}

	return $output;
}


add_filter( 'wpcf7_special_mail_tags', 'wpcf7_post_related_smt', 10, 4 );

/**
 * Returns output string of a special mail-tag.
 *
 * @param string $output The string to be output.
 * @param string $name The tag name of the special mail-tag.
 * @param bool $html Whether the mail-tag is used in an HTML content.
 * @param WPCF7_MailTag $mail_tag An object representation of the mail-tag.
 * @return string Output of the given special mail-tag.
 */
function wpcf7_post_related_smt( $output, $name, $html, $mail_tag = null ) {
	if ( ! $mail_tag instanceof WPCF7_MailTag ) {
		wpcf7_doing_it_wrong(
			sprintf( '%s()', __FUNCTION__ ),
			__( 'The fourth parameter ($mail_tag) must be an instance of the WPCF7_MailTag class.', 'contact-form-7' ),
			'5.2.2'
		);
	}

	if ( ! str_starts_with( $name, '_post_' ) ) {
		return $output;
	}

	$submission = WPCF7_Submission::get_instance();

	if ( ! $submission ) {
		return $output;
	}

	$post_id = (int) $submission->get_meta( 'container_post_id' );

	if ( ! $post_id or ! $post = get_post( $post_id ) ) {
		return '';
	}

	if ( '_post_id' === $name ) {
		return (string) $post->ID;
	}

	if ( '_post_name' === $name ) {
		return $post->post_name;
	}

	if ( '_post_title' === $name ) {
		return $html ? esc_html( $post->post_title ) : $post->post_title;
	}

	if ( '_post_url' === $name ) {
		return get_permalink( $post->ID );
	}

	$user = new WP_User( $post->post_author );

	if ( '_post_author' === $name ) {
		return $user->display_name;
	}

	if ( '_post_author_email' === $name ) {
		return $user->user_email;
	}

	return $output;
}


add_filter( 'wpcf7_special_mail_tags', 'wpcf7_site_related_smt', 10, 4 );

/**
 * Returns output string of a special mail-tag.
 *
 * @param string $output The string to be output.
 * @param string $name The tag name of the special mail-tag.
 * @param bool $html Whether the mail-tag is used in an HTML content.
 * @param WPCF7_MailTag $mail_tag An object representation of the mail-tag.
 * @return string Output of the given special mail-tag.
 */
function wpcf7_site_related_smt( $output, $name, $html, $mail_tag = null ) {
	if ( ! $mail_tag instanceof WPCF7_MailTag ) {
		wpcf7_doing_it_wrong(
			sprintf( '%s()', __FUNCTION__ ),
			__( 'The fourth parameter ($mail_tag) must be an instance of the WPCF7_MailTag class.', 'contact-form-7' ),
			'5.2.2'
		);
	}

	$filter = $html ? 'display' : 'raw';

	if ( '_site_title' === $name ) {
		$output = get_bloginfo( 'name', $filter );

		if ( ! $html ) {
			$output = wp_specialchars_decode( $output, ENT_QUOTES );
		}

		return $output;
	}

	if ( '_site_description' === $name ) {
		$output = get_bloginfo( 'description', $filter );

		if ( ! $html ) {
			$output = wp_specialchars_decode( $output, ENT_QUOTES );
		}

		return $output;
	}

	if ( '_site_url' === $name ) {
		return get_bloginfo( 'url', $filter );
	}

	if ( '_site_domain' === $name ) {
		$url = get_bloginfo( 'url', $filter );
		$host = wp_parse_url( $url, PHP_URL_HOST );

		if ( null === $host ) {
			return '';
		}

		if ( str_starts_with( $host, 'www.' ) ) {
			$host = substr( $host, 4 );
		}

		return $host;
	}

	if ( '_site_admin_email' === $name ) {
		return get_bloginfo( 'admin_email', $filter );
	}

	return $output;
}


add_filter( 'wpcf7_special_mail_tags', 'wpcf7_user_related_smt', 10, 4 );

/**
 * Returns output string of a special mail-tag.
 *
 * @param string $output The string to be output.
 * @param string $name The tag name of the special mail-tag.
 * @param bool $html Whether the mail-tag is used in an HTML content.
 * @param WPCF7_MailTag $mail_tag An object representation of the mail-tag.
 * @return string Output of the given special mail-tag.
 */
function wpcf7_user_related_smt( $output, $name, $html, $mail_tag = null ) {
	if ( ! $mail_tag instanceof WPCF7_MailTag ) {
		wpcf7_doing_it_wrong(
			sprintf( '%s()', __FUNCTION__ ),
			__( 'The fourth parameter ($mail_tag) must be an instance of the WPCF7_MailTag class.', 'contact-form-7' ),
			'5.2.2'
		);
	}

	if ( ! str_starts_with( $name, '_user_' ) or '_user_agent' === $name ) {
		return $output;
	}

	$submission = WPCF7_Submission::get_instance();

	if ( ! $submission ) {
		return $output;
	}

	$user_id = (int) $submission->get_meta( 'current_user_id' );

	if ( ! $user_id ) {
		return '';
	}

	$primary_props = array( 'user_login', 'user_email', 'user_url' );
	$opt = ltrim( $name, '_' );
	$opt = in_array( $opt, $primary_props ) ? $opt : substr( $opt, 5 );

	$user = new WP_User( $user_id );

	if ( $user->has_prop( $opt ) ) {
		return $user->get( $opt );
	}

	return '';
}
includes/capabilities.php000064400000001502147510545420011521 0ustar00<?php

add_filter( 'map_meta_cap', 'wpcf7_map_meta_cap', 10, 4 );

function wpcf7_map_meta_cap( $caps, $cap, $user_id, $args ) {
	$meta_caps = array(
		'wpcf7_edit_contact_form' => WPCF7_ADMIN_READ_WRITE_CAPABILITY,
		'wpcf7_edit_contact_forms' => WPCF7_ADMIN_READ_WRITE_CAPABILITY,
		'wpcf7_read_contact_form' => WPCF7_ADMIN_READ_CAPABILITY,
		'wpcf7_read_contact_forms' => WPCF7_ADMIN_READ_CAPABILITY,
		'wpcf7_delete_contact_form' => WPCF7_ADMIN_READ_WRITE_CAPABILITY,
		'wpcf7_delete_contact_forms' => WPCF7_ADMIN_READ_WRITE_CAPABILITY,
		'wpcf7_manage_integration' => 'manage_options',
		'wpcf7_submit' => 'read',
	);

	$meta_caps = apply_filters( 'wpcf7_map_meta_cap', $meta_caps );

	$caps = array_diff( $caps, array_keys( $meta_caps ) );

	if ( isset( $meta_caps[$cap] ) ) {
		$caps[] = $meta_caps[$cap];
	}

	return $caps;
}
includes/controller.php000064400000006305147510545420011261 0ustar00<?php
/**
 * Controller for front-end requests, scripts, and styles
 */


add_action(
	'parse_request',
	'wpcf7_control_init',
	20, 0
);

/**
 * Handles a submission in non-Ajax mode.
 */
function wpcf7_control_init() {
	if ( WPCF7_Submission::is_restful() ) {
		return;
	}

	if ( isset( $_POST['_wpcf7'] ) ) {
		$contact_form = wpcf7_contact_form( (int) $_POST['_wpcf7'] );

		if ( $contact_form ) {
			$contact_form->submit();
		}
	}
}


/**
 * Registers main scripts and styles.
 */
add_action(
	'wp_enqueue_scripts',
	static function () {
		$assets = include(
			wpcf7_plugin_path( 'includes/js/index.asset.php' )
		);

		$assets = wp_parse_args( $assets, array(
			'dependencies' => array(),
			'version' => WPCF7_VERSION,
		) );

		wp_register_script(
			'contact-form-7',
			wpcf7_plugin_url( 'includes/js/index.js' ),
			array_merge(
				$assets['dependencies'],
				array( 'swv' )
			),
			$assets['version'],
			array( 'in_footer' => true )
		);

		wp_set_script_translations( 'contact-form-7', 'contact-form-7' );

		wp_register_script(
			'contact-form-7-html5-fallback',
			wpcf7_plugin_url( 'includes/js/html5-fallback.js' ),
			array( 'jquery-ui-datepicker' ),
			WPCF7_VERSION,
			array( 'in_footer' => true )
		);

		if ( wpcf7_load_js() ) {
			wpcf7_enqueue_scripts();
		}

		wp_register_style(
			'contact-form-7',
			wpcf7_plugin_url( 'includes/css/styles.css' ),
			array(),
			WPCF7_VERSION,
			'all'
		);

		wp_register_style(
			'contact-form-7-rtl',
			wpcf7_plugin_url( 'includes/css/styles-rtl.css' ),
			array( 'contact-form-7' ),
			WPCF7_VERSION,
			'all'
		);

		wp_register_style(
			'jquery-ui-smoothness',
			wpcf7_plugin_url(
				'includes/js/jquery-ui/themes/smoothness/jquery-ui.min.css'
			),
			array(),
			'1.12.1',
			'screen'
		);

		if ( wpcf7_load_css() ) {
			wpcf7_enqueue_styles();
		}
	},
	10, 0
);


/**
 * Enqueues scripts.
 */
function wpcf7_enqueue_scripts() {
	wp_enqueue_script( 'contact-form-7' );

	$wpcf7_obj = array(
		'api' => array(
			'root' => sanitize_url( get_rest_url() ),
			'namespace' => 'contact-form-7/v1',
		),
	);

	if ( defined( 'WP_CACHE' ) and WP_CACHE ) {
		$wpcf7_obj = array_merge( $wpcf7_obj, array(
			'cached' => 1,
		) );
	}

	wp_add_inline_script( 'contact-form-7',
		sprintf(
			'var wpcf7 = %s;',
			wp_json_encode( $wpcf7_obj, JSON_PRETTY_PRINT )
		),
		'before'
	);

	do_action( 'wpcf7_enqueue_scripts' );
}


/**
 * Returns true if the main script is enqueued.
 */
function wpcf7_script_is() {
	return wp_script_is( 'contact-form-7' );
}


/**
 * Enqueues styles.
 */
function wpcf7_enqueue_styles() {
	wp_enqueue_style( 'contact-form-7' );

	if ( wpcf7_is_rtl() ) {
		wp_enqueue_style( 'contact-form-7-rtl' );
	}

	do_action( 'wpcf7_enqueue_styles' );
}


/**
 * Returns true if the main stylesheet is enqueued.
 */
function wpcf7_style_is() {
	return wp_style_is( 'contact-form-7' );
}


add_action(
	'wp_enqueue_scripts',
	'wpcf7_html5_fallback',
	20, 0
);

/**
 * Enqueues scripts and styles for the HTML5 fallback.
 */
function wpcf7_html5_fallback() {
	if ( ! wpcf7_support_html5_fallback() ) {
		return;
	}

	if ( wpcf7_script_is() ) {
		wp_enqueue_script( 'contact-form-7-html5-fallback' );
	}

	if ( wpcf7_style_is() ) {
		wp_enqueue_style( 'jquery-ui-smoothness' );
	}
}
includes/validation.php000064400000006341147510545420011230 0ustar00<?php

/**
 * Server-side user input validation manager.
 */
class WPCF7_Validation implements ArrayAccess {
	private $invalid_fields = array();
	private $container = array();

	public function __construct() {
		$this->container = array(
			'valid' => true,
			'reason' => array(),
			'idref' => array(),
		);
	}


	/**
	 * Marks a form control as an invalid field.
	 *
	 * @param WPCF7_FormTag|array|string $context Context representing the
	 *                                   target field.
	 * @param WP_Error|string $error The error of the field.
	 */
	public function invalidate( $context, $error ) {
		if ( $context instanceof WPCF7_FormTag ) {
			$tag = $context;
		} elseif ( is_array( $context ) ) {
			$tag = new WPCF7_FormTag( $context );
		} elseif ( is_string( $context ) ) {
			$tags = wpcf7_scan_form_tags( array( 'name' => trim( $context ) ) );
			$tag = $tags ? new WPCF7_FormTag( $tags[0] ) : null;
		}

		$name = ! empty( $tag ) ? $tag->name : null;

		if ( empty( $name )
		or ! wpcf7_is_name( $name ) ) {
			return;
		}

		if ( is_wp_error( $error ) ) {
			$message = $error->get_error_message();
		} else {
			$message = $error;
		}

		if ( $this->is_valid( $name ) ) {
			$id = $tag->get_id_option();

			if ( empty( $id )
			or ! wpcf7_is_name( $id ) ) {
				$id = null;
			}

			$this->invalid_fields[$name] = array(
				'reason' => (string) $message,
				'idref' => $id,
			);
		}
	}


	/**
	 * Returns true if the target field is valid.
	 *
	 * @param string|null $name Optional. If specified, this is the name of
	 *                    the target field. Default null.
	 * @return bool True if the target field has no error. If no target is
	 *              specified, returns true if all fields are valid.
	 *              Otherwise false.
	 */
	public function is_valid( $name = null ) {
		if ( ! empty( $name ) ) {
			return ! isset( $this->invalid_fields[$name] );
		} else {
			return empty( $this->invalid_fields );
		}
	}


	/**
	 * Retrieves an associative array of invalid fields.
	 *
	 * @return array The associative array of invalid fields.
	 */
	public function get_invalid_fields() {
		return $this->invalid_fields;
	}


	/**
	 * Assigns a value to the specified offset.
	 *
	 * @link https://www.php.net/manual/en/arrayaccess.offsetset.php
	 */
	#[ReturnTypeWillChange]
	public function offsetSet( $offset, $value ) {
		if ( isset( $this->container[$offset] ) ) {
			$this->container[$offset] = $value;
		}

		if ( 'reason' == $offset
		and is_array( $value ) ) {
			foreach ( $value as $k => $v ) {
				$this->invalidate( $k, $v );
			}
		}
	}


	/**
	 * Returns the value at specified offset.
	 *
	 * @link https://www.php.net/manual/en/arrayaccess.offsetget.php
	 */
	#[ReturnTypeWillChange]
	public function offsetGet( $offset ) {
		if ( isset( $this->container[$offset] ) ) {
			return $this->container[$offset];
		}
	}


	/**
	 * Returns true if the specified offset exists.
	 *
	 * @link https://www.php.net/manual/en/arrayaccess.offsetexists.php
	 */
	#[ReturnTypeWillChange]
	public function offsetExists( $offset ) {
		return isset( $this->container[$offset] );
	}


	/**
	 * Unsets an offset.
	 *
	 * @link https://www.php.net/manual/en/arrayaccess.offsetunset.php
	 */
	#[ReturnTypeWillChange]
	public function offsetUnset( $offset ) {
	}

}
includes/mail-tag.php000064400000010142147510545420010563 0ustar00<?php

/**
 * Class that represents a mail-tag.
 */
class WPCF7_MailTag {

	private $tag;
	private $tagname = '';
	private $name = '';
	private $options = array();
	private $values = array();
	private $form_tag = null;


	/**
	 * The constructor method.
	 */
	public function __construct( $tag, $tagname, $values ) {
		$this->tag = $tag;
		$this->name = $this->tagname = $tagname;

		$this->options = array(
			'do_not_heat' => false,
			'format' => '',
		);

		if ( ! empty( $values ) ) {
			preg_match_all( '/"[^"]*"|\'[^\']*\'/', $values, $matches );
			$this->values = wpcf7_strip_quote_deep( $matches[0] );
		}

		if ( preg_match( '/^_raw_(.+)$/', $tagname, $matches ) ) {
			$this->name = trim( $matches[1] );
			$this->options['do_not_heat'] = true;
		}

		if ( preg_match( '/^_format_(.+)$/', $tagname, $matches ) ) {
			$this->name = trim( $matches[1] );
			$this->options['format'] = $this->values[0];
		}
	}


	/**
	 * Returns the name part of this mail-tag.
	 */
	public function tag_name() {
		return $this->tagname;
	}


	/**
	 * Returns the form field name corresponding to this mail-tag.
	 */
	public function field_name() {
		return strtr( $this->name, '.', '_' );
	}


	/**
	 * Returns the value of the specified option.
	 */
	public function get_option( $option ) {
		return $this->options[$option];
	}


	/**
	 * Returns the values part of this mail-tag.
	 */
	public function values() {
		return $this->values;
	}


	/**
	 * Retrieves the WPCF7_FormTag object that corresponds to this mail-tag.
	 */
	public function corresponding_form_tag() {
		if ( $this->form_tag instanceof WPCF7_FormTag ) {
			return $this->form_tag;
		}

		if ( $submission = WPCF7_Submission::get_instance() ) {
			$contact_form = $submission->get_contact_form();
			$tags = $contact_form->scan_form_tags( array(
				'name' => $this->field_name(),
				'feature' => '! zero-controls-container',
			) );

			if ( $tags ) {
				$this->form_tag = $tags[0];
			}
		}

		return $this->form_tag;
	}

}


use Contactable\SWV;

/**
 * Mail-tag output calculator.
 */
class WPCF7_MailTag_OutputCalculator {

	const email = 0b100;
	const text = 0b010;
	const blank = 0b001;

	private $contact_form;

	public function __construct( WPCF7_ContactForm $contact_form ) {
		$this->contact_form = $contact_form;
	}

	public function calc_output( WPCF7_MailTag $mail_tag ) {
		return $this->calc_swv_result(
			$mail_tag,
			$this->contact_form->get_schema()
		);
	}

	private function calc_swv_result( WPCF7_MailTag $mail_tag, SWV\Rule $rule ) {

		if ( $rule instanceof SWV\AnyRule ) {
			$result = 0b000;

			foreach ( $rule->rules() as $child_rule ) {
				$result |= $this->calc_swv_result( $mail_tag, $child_rule );
			}

			return $result;
		}

		if ( $rule instanceof SWV\CompositeRule ) {
			$result = 0b111;

			foreach ( $rule->rules() as $child_rule ) {
				$result &= $this->calc_swv_result( $mail_tag, $child_rule );
			}

			return $result;
		}

		$field_prop = $rule->get_property( 'field' );

		if ( empty( $field_prop ) or $field_prop !== $mail_tag->field_name() ) {
			return self::email | self::text | self::blank;
		}

		if ( $rule instanceof SWV\RequiredRule ) {
			return ~ self::blank;
		}

		if ( $rule instanceof SWV\EmailRule ) {
			return self::email | self::blank;
		}

		if ( $rule instanceof SWV\EnumRule ) {
			$acceptable_values = (array) $rule->get_property( 'accept' );
			$acceptable_values = array_map( 'strval', $acceptable_values );
			$acceptable_values = array_filter( $acceptable_values );
			$acceptable_values = array_unique( $acceptable_values );

			if ( ! $mail_tag->get_option( 'do_not_heat' ) ) {
				$pipes = $this->contact_form->get_pipes(
					$mail_tag->field_name()
				);

				$acceptable_values = array_map(
					static function ( $val ) use ( $pipes ) {
						return $pipes->do_pipe( $val );
					},
					$acceptable_values
				);
			}

			$email_values = array_filter(
				$acceptable_values,
				'wpcf7_is_mailbox_list'
			);

			if ( count( $email_values ) === count( $acceptable_values ) ) {
				return self::email | self::blank;
			} else {
				return self::email | self::text | self::blank;
			}
		}

		return self::email | self::text | self::blank;
	}

}
includes/file.php000064400000024236147510545420010020 0ustar00<?php

/**
 * Validates uploaded files and moves them to the temporary directory.
 *
 * @param array $file An item of `$_FILES`.
 * @param string|array $options Optional. Options to control behavior.
 * @return array|WP_Error Array of file paths, or WP_Error if validation fails.
 */
function wpcf7_unship_uploaded_file( $file, $options = '' ) {
	$options = wp_parse_args( $options, array(
		'required' => false,
		'filetypes' => '',
		'limit' => MB_IN_BYTES,
	) );

	foreach ( array( 'name', 'size', 'tmp_name', 'error' ) as $key ) {
		if ( ! isset( $file[$key] ) ) {
			$file[$key] = array();
		}
	}

	$names = wpcf7_array_flatten( $file['name'] );
	$sizes = wpcf7_array_flatten( $file['size'] );
	$tmp_names = wpcf7_array_flatten( $file['tmp_name'] );
	$errors = wpcf7_array_flatten( $file['error'] );

	foreach ( $errors as $error ) {
		if ( ! empty( $error ) and UPLOAD_ERR_NO_FILE !== $error ) {
			return new WP_Error( 'wpcf7_upload_failed_php_error',
				wpcf7_get_message( 'upload_failed_php_error' )
			);
		}
	}

	if ( isset( $options['schema'] ) and isset( $options['name'] ) ) {
		$context = array(
			'file' => true,
			'field' => $options['name'],
		);

		foreach ( $options['schema']->validate( $context ) as $result ) {
			if ( is_wp_error( $result ) ) {
				return $result;
			}
		}
	}

	// Move uploaded file to tmp dir
	$uploads_dir = wpcf7_upload_tmp_dir();
	$uploads_dir = wpcf7_maybe_add_random_dir( $uploads_dir );

	$uploaded_files = array();

	foreach ( $names as $key => $name ) {
		$tmp_name = $tmp_names[$key];

		if ( empty( $tmp_name ) or ! is_uploaded_file( $tmp_name ) ) {
			continue;
		}

		$filename = $name;
		$filename = wpcf7_canonicalize( $filename, array( 'strto' => 'as-is' ) );
		$filename = wpcf7_antiscript_file_name( $filename );

		$filename = apply_filters( 'wpcf7_upload_file_name',
			$filename, $name, $options
		);

		$filename = wp_unique_filename( $uploads_dir, $filename );
		$new_file = path_join( $uploads_dir, $filename );

		if ( false === @move_uploaded_file( $tmp_name, $new_file ) ) {
			return new WP_Error( 'wpcf7_upload_failed',
				wpcf7_get_message( 'upload_failed' )
			);
		}

		// Make sure the uploaded file is only readable for the owner process
		chmod( $new_file, 0400 );

		$uploaded_files[] = $new_file;
	}

	return $uploaded_files;
}


add_filter(
	'wpcf7_messages',
	'wpcf7_file_messages',
	10, 1
);

/**
 * A wpcf7_messages filter callback that adds messages for
 * file-uploading fields.
 */
function wpcf7_file_messages( $messages ) {
	return array_merge( $messages, array(
		'upload_failed' => array(
			'description' => __( "Uploading a file fails for any reason", 'contact-form-7' ),
			'default' => __( "There was an unknown error uploading the file.", 'contact-form-7' ),
		),

		'upload_file_type_invalid' => array(
			'description' => __( "Uploaded file is not allowed for file type", 'contact-form-7' ),
			'default' => __( "You are not allowed to upload files of this type.", 'contact-form-7' ),
		),

		'upload_file_too_large' => array(
			'description' => __( "Uploaded file is too large", 'contact-form-7' ),
			'default' => __( "The uploaded file is too large.", 'contact-form-7' ),
		),

		'upload_failed_php_error' => array(
			'description' => __( "Uploading a file fails for PHP error", 'contact-form-7' ),
			'default' => __( "There was an error uploading the file.", 'contact-form-7' ),
		),
	) );
}


add_filter(
	'wpcf7_form_enctype',
	'wpcf7_file_form_enctype_filter',
	10, 1
);

/**
 * A wpcf7_form_enctype filter callback that sets the enctype attribute
 * to multipart/form-data if the form has file-uploading fields.
 */
function wpcf7_file_form_enctype_filter( $enctype ) {
	$multipart = (bool) wpcf7_scan_form_tags( array(
		'feature' => 'file-uploading',
	) );

	if ( $multipart ) {
		$enctype = 'multipart/form-data';
	}

	return $enctype;
}


/**
 * Converts a MIME type string to an array of corresponding file extensions.
 *
 * @param string $mime MIME type.
 *                     Wildcard (*) is available for the subtype part.
 * @return array Corresponding file extensions.
 */
function wpcf7_convert_mime_to_ext( $mime ) {
	static $mime_types = array();

	$mime_types = wp_get_mime_types();

	$results = array();

	if ( preg_match( '%^([a-z]+)/([*]|[a-z0-9.+-]+)$%i', $mime, $matches ) ) {
		foreach ( $mime_types as $key => $val ) {
			if ( '*' === $matches[2] and str_starts_with( $val, $matches[1] . '/' )
		 	or $val === $matches[0] ) {
				$results = array_merge( $results, explode( '|', $key ) );
			}
		}
	}

	$results = array_unique( $results );
	$results = array_filter( $results );
	$results = array_values( $results );

	return $results;
}


/**
 * Returns a formatted list of acceptable filetypes.
 *
 * @param string|array $types Optional. Array of filetypes.
 * @param string $format Optional. Pre-defined format designator.
 * @return string Formatted list of acceptable filetypes.
 */
function wpcf7_acceptable_filetypes( $types = 'default', $format = 'regex' ) {
	if ( 'default' === $types or empty( $types ) ) {
		$types = array(
			'audio/*',
			'video/*',
			'image/*',
		);
	} else {
		$types = array_map(
			static function ( $type ) {
				if ( is_string( $type ) ) {
					return preg_split( '/[\s|,]+/', strtolower( $type ) );
				}
			},
			(array) $types
		);

		$types = wpcf7_array_flatten( $types );
		$types = array_filter( array_unique( $types ) );
	}

	if ( 'attr' === $format or 'attribute' === $format ) {
		$types = array_map(
			static function ( $type ) {
				if ( false === strpos( $type, '/' ) ) {
					return sprintf( '.%s', trim( $type, '.' ) );
				} elseif ( preg_match( '%^([a-z]+)/[*]$%i', $type, $matches ) ) {
					if ( in_array( $matches[1], array( 'audio', 'video', 'image' ) ) ) {
						return $type;
					} else {
						return '';
					}
				} elseif ( wpcf7_convert_mime_to_ext( $type ) ) {
					return $type;
				}
			},
			$types
		);

		$types = array_filter( $types );

		return implode( ',', $types );

	} elseif ( 'regex' === $format ) {
		$types = array_map(
			static function ( $type ) {
				if ( false === strpos( $type, '/' ) ) {
					return preg_quote( trim( $type, '.' ) );
				} elseif ( $type = wpcf7_convert_mime_to_ext( $type ) ) {
					return $type;
				}
			},
			$types
		);

		$types = wpcf7_array_flatten( $types );
		$types = array_filter( array_unique( $types ) );

		return implode( '|', $types );
	}

	return '';
}


add_action(
	'wpcf7_init',
	'wpcf7_init_uploads',
	10, 0
);

/**
 * Initializes the temporary directory for uploaded files.
 */
function wpcf7_init_uploads() {
	$dir = wpcf7_upload_tmp_dir();

	if ( is_dir( $dir ) and is_writable( $dir ) ) {
		$htaccess_file = path_join( $dir, '.htaccess' );

		if ( file_exists( $htaccess_file ) ) {
			list( $first_line_comment ) = (array) file(
				$htaccess_file,
				FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES
			);

			if ( '# Apache 2.4+' === $first_line_comment ) {
				return;
			}
		}

		if ( $handle = @fopen( $htaccess_file, 'w' ) ) {
			fwrite( $handle, "# Apache 2.4+\n" );
			fwrite( $handle, "<IfModule authz_core_module>\n" );
			fwrite( $handle, "    Require all denied\n" );
			fwrite( $handle, "</IfModule>\n" );
			fwrite( $handle, "\n" );
			fwrite( $handle, "# Apache 2.2\n" );
			fwrite( $handle, "<IfModule !authz_core_module>\n" );
			fwrite( $handle, "    Deny from all\n" );
			fwrite( $handle, "</IfModule>\n" );

			fclose( $handle );
		}
	}
}


/**
 * Creates a child directory with a randomly generated name.
 *
 * @param string $dir The parent directory path.
 * @return string The child directory path if created, otherwise the parent.
 */
function wpcf7_maybe_add_random_dir( $dir ) {
	do {
		$rand_max = mt_getrandmax();
		$rand = zeroise( mt_rand( 0, $rand_max ), strlen( $rand_max ) );
		$dir_new = path_join( $dir, $rand );
	} while ( file_exists( $dir_new ) );

	if ( wp_mkdir_p( $dir_new ) ) {
		return $dir_new;
	}

	return $dir;
}


/**
 * Returns the directory path for uploaded files.
 *
 * @return string Directory path.
 */
function wpcf7_upload_tmp_dir() {
	if ( defined( 'WPCF7_UPLOADS_TMP_DIR' ) ) {
		$dir = path_join( WP_CONTENT_DIR, WPCF7_UPLOADS_TMP_DIR );
		wp_mkdir_p( $dir );

		if ( wpcf7_is_file_path_in_content_dir( $dir ) ) {
			return $dir;
		}
	}

	$dir = path_join( wpcf7_upload_dir( 'dir' ), 'wpcf7_uploads' );
	wp_mkdir_p( $dir );
	return $dir;
}


add_action(
	'shutdown',
	'wpcf7_cleanup_upload_files',
	20, 0
);

/**
 * Cleans up files in the temporary directory for uploaded files.
 *
 * @param int $seconds Files older than this are removed. Default 60.
 * @param int $max Maximum number of files to be removed in a function call.
 *                 Default 100.
 */
function wpcf7_cleanup_upload_files( $seconds = 60, $max = 100 ) {
	$dir = trailingslashit( wpcf7_upload_tmp_dir() );

	if ( ! is_dir( $dir )
	or ! is_readable( $dir )
	or ! wp_is_writable( $dir ) ) {
		return;
	}

	$seconds = absint( $seconds );
	$max = absint( $max );
	$count = 0;

	if ( $handle = opendir( $dir ) ) {
		while ( false !== ( $file = readdir( $handle ) ) ) {
			if ( '.' == $file
			or '..' == $file
			or '.htaccess' == $file ) {
				continue;
			}

			$mtime = @filemtime( path_join( $dir, $file ) );

			if ( $mtime and time() < $mtime + $seconds ) { // less than $seconds old
				continue;
			}

			wpcf7_rmdir_p( path_join( $dir, $file ) );
			$count += 1;

			if ( $max <= $count ) {
				break;
			}
		}

		closedir( $handle );
	}
}


add_action(
	'wpcf7_admin_warnings',
	'wpcf7_file_display_warning_message',
	10, 3
);

/**
 * Displays warning messages about file-uploading fields.
 */
function wpcf7_file_display_warning_message( $page, $action, $object ) {
	if ( $object instanceof WPCF7_ContactForm ) {
		$contact_form = $object;
	} else {
		return;
	}

	$has_tags = (bool) $contact_form->scan_form_tags( array(
		'feature' => 'file-uploading',
	) );

	if ( ! $has_tags ) {
		return;
	}

	$uploads_dir = wpcf7_upload_tmp_dir();

	if ( ! is_dir( $uploads_dir ) or ! wp_is_writable( $uploads_dir ) ) {
		$message = sprintf(
			/* translators: %s: the path of the temporary folder */
			__( 'This contact form has file uploading fields, but the temporary folder for the files (%s) does not exist or is not writable. You can create the folder or change its permission manually.', 'contact-form-7' ),
			$uploads_dir
		);

		wp_admin_notice( esc_html( $message ), 'type=warning' );
	}
}
includes/formatting.php000064400000033003147510545420011243 0ustar00<?php

/**
 * Replaces double line breaks with paragraph elements.
 *
 * @param string $input The text which has to be formatted.
 * @param bool $br Optional. If set, this will convert all remaining
 *             line breaks after paragraphing. Default true.
 * @return string Text which has been converted into correct paragraph tags.
 */
function wpcf7_autop( $input, $br = true ) {
	$placeholders = array();

	// Replace non-HTML embedded elements with placeholders.
	$input = preg_replace_callback(
		'/<(math|svg).*?<\/\1>/is',
		static function ( $matches ) use ( &$placeholders ) {
			$placeholder = sprintf(
				'<%1$s id="%2$s" />',
				WPCF7_HTMLFormatter::placeholder_inline,
				sha1( $matches[0] )
			);

			list( $placeholder ) =
				WPCF7_HTMLFormatter::normalize_start_tag( $placeholder );

			$placeholders[$placeholder] = $matches[0];

			return $placeholder;
		},
		$input
	);

	$formatter = new WPCF7_HTMLFormatter( array(
		'auto_br' => $br,
	) );

	$chunks = $formatter->separate_into_chunks( $input );

	$output = $formatter->format( $chunks );

	// Restore from placeholders.
	$output = str_replace(
		array_keys( $placeholders ),
		array_values( $placeholders ),
		$output
	);

	return $output;
}


/**
 * Newline preservation help function for wpcf7_autop().
 *
 * @deprecated 5.7 Unnecessary to use any more.
 *
 * @param array $matches preg_replace_callback() matches array.
 * @return string Text including newline placeholders.
 */
function wpcf7_autop_preserve_newline_callback( $matches ) {
	return str_replace( "\n", '<WPPreserveNewline />', $matches[0] );
}


/**
 * Sanitizes the query variables.
 *
 * @param string $text Query variable.
 * @return string Text sanitized.
 */
function wpcf7_sanitize_query_var( $text ) {
	$text = wp_unslash( $text );
	$text = wp_check_invalid_utf8( $text );

	if ( false !== strpos( $text, '<' ) ) {
		$text = wp_pre_kses_less_than( $text );
		$text = wp_strip_all_tags( $text );
	}

	$text = preg_replace( '/%[a-f0-9]{2}/i', '', $text );
	$text = preg_replace( '/ +/', ' ', $text );
	$text = trim( $text, ' ' );

	return $text;
}


/**
 * Strips quote characters surrounding the input.
 *
 * @param string $text Input text.
 * @return string Processed output.
 */
function wpcf7_strip_quote( $text ) {
	$text = trim( $text );

	if ( preg_match( '/^"(.*)"$/s', $text, $matches ) ) {
		$text = $matches[1];
	} elseif ( preg_match( "/^'(.*)'$/s", $text, $matches ) ) {
		$text = $matches[1];
	}

	return $text;
}


/**
 * Navigates through an array, object, or scalar, and
 * strips quote characters surrounding the each value.
 *
 * @param mixed $input The array or string to be processed.
 * @return mixed Processed value.
 */
function wpcf7_strip_quote_deep( $input ) {
	if ( is_string( $input ) ) {
		return wpcf7_strip_quote( $input );
	}

	if ( is_array( $input ) ) {
		$result = array();

		foreach ( $input as $key => $text ) {
			$result[$key] = wpcf7_strip_quote_deep( $text );
		}

		return $result;
	}
}


/**
 * Normalizes newline characters.
 *
 * @param string $text Input text.
 * @param string $to Optional. The newline character that is used in the output.
 * @return string Normalized text.
 */
function wpcf7_normalize_newline( $text, $to = "\n" ) {
	if ( ! is_string( $text ) ) {
		return $text;
	}

	$nls = array( "\r\n", "\r", "\n" );

	if ( ! in_array( $to, $nls ) ) {
		return $text;
	}

	return str_replace( $nls, $to, $text );
}


/**
 * Navigates through an array, object, or scalar, and
 * normalizes newline characters in the each value.
 *
 * @param mixed $input The array or string to be processed.
 * @param string $to Optional. The newline character that is used in the output.
 * @return mixed Processed value.
 */
function wpcf7_normalize_newline_deep( $input, $to = "\n" ) {
	if ( is_array( $input ) ) {
		$result = array();

		foreach ( $input as $key => $text ) {
			$result[$key] = wpcf7_normalize_newline_deep( $text, $to );
		}

		return $result;
	}

	return wpcf7_normalize_newline( $input, $to );
}


/**
 * Strips newline characters.
 *
 * @param string $text Input text.
 * @return string Processed one-line text.
 */
function wpcf7_strip_newline( $text ) {
	$text = (string) $text;
	$text = str_replace( array( "\r", "\n" ), '', $text );
	return trim( $text );
}


/**
 * Canonicalizes text.
 *
 * @param string $text Input text.
 * @param string|array|object $options Options.
 * @return string Canonicalized text.
 */
function wpcf7_canonicalize( $text, $options = '' ) {
	// for back-compat
	if ( is_string( $options ) and '' !== $options
	and false === strpos( $options, '=' ) ) {
		$options = array(
			'strto' => $options,
		);
	}

	$options = wp_parse_args( $options, array(
		'strto' => 'lower',
		'strip_separators' => false,
	) );

	static $charset = null;

	if ( ! isset( $charset ) ) {
		$charset = get_option( 'blog_charset' );

		$is_utf8 = in_array(
			$charset,
			array( 'utf8', 'utf-8', 'UTF8', 'UTF-8' )
		);

		if ( $is_utf8 ) {
			$charset = 'UTF-8';
		}
	}

	$text = html_entity_decode( $text, ENT_QUOTES | ENT_HTML5, $charset );

	if ( function_exists( 'mb_convert_kana' ) ) {
		$text = mb_convert_kana( $text, 'asKV', $charset );
	}

	if ( $options['strip_separators'] ) {
		$text = preg_replace( '/[\r\n\t ]+/', '', $text );
	} else {
		$text = preg_replace( '/[\r\n\t ]+/', ' ', $text );
	}

	if ( 'lower' == $options['strto'] ) {
		if ( function_exists( 'mb_strtolower' ) ) {
			$text = mb_strtolower( $text, $charset );
		} else {
			$text = strtolower( $text );
		}
	} elseif ( 'upper' == $options['strto'] ) {
		if ( function_exists( 'mb_strtoupper' ) ) {
			$text = mb_strtoupper( $text, $charset );
		} else {
			$text = strtoupper( $text );
		}
	}

	$text = trim( $text );
	return $text;
}


/**
 * Returns a canonical keyword usable for a name or an ID purposes.
 */
function wpcf7_canonicalize_name( $text ) {
	return preg_replace( '/[^0-9a-z]+/i', '-', $text );
}


/**
 * Sanitizes Contact Form 7's form unit-tag.
 *
 * @param string $tag Unit-tag.
 * @return string Sanitized unit-tag.
 */
function wpcf7_sanitize_unit_tag( $tag ) {
	$tag = preg_replace( '/[^A-Za-z0-9_-]/', '', (string) $tag );
	return $tag;
}


/**
 * Converts a file name to one that is not executable as a script.
 *
 * @param string $filename File name.
 * @return string Converted file name.
 */
function wpcf7_antiscript_file_name( $filename ) {
	$filename = wp_basename( $filename );

	// Apply part of protection logic from sanitize_file_name().
	$filename = str_replace(
		array(
			'?', '[', ']', '/', '\\', '=', '<', '>', ':', ';', ',', "'", '"',
			'&', '$', '#', '*', '(', ')', '|', '~', '`', '!', '{', '}',
			'%', '+', '’', '«', '»', '”', '“', chr( 0 )
		),
		'',
		$filename
	);

	$filename = preg_replace( '/[\r\n\t -]+/', '-', $filename );
	$filename = preg_replace( '/[\pC\pZ]+/iu', '', $filename );

	$parts = explode( '.', $filename );

	if ( count( $parts ) < 2 ) {
		return $filename;
	}

	$script_pattern = '/^(php|phtml|pl|py|rb|cgi|asp|aspx)\d?$/i';

	$filename = array_shift( $parts );
	$extension = array_pop( $parts );

	foreach ( (array) $parts as $part ) {
		if ( preg_match( $script_pattern, $part ) ) {
			$filename .= '.' . $part . '_';
		} else {
			$filename .= '.' . $part;
		}
	}

	if ( preg_match( $script_pattern, $extension ) ) {
		$filename .= '.' . $extension . '_.txt';
	} else {
		$filename .= '.' . $extension;
	}

	return $filename;
}


/**
 * Masks a password with asterisks (*).
 *
 * @param int $right Length of right-hand unmasked text. Default 0.
 * @param int $left Length of left-hand unmasked text. Default 0.
 * @return string Text of masked password.
 */
function wpcf7_mask_password( $text, $right = 0, $left = 0 ) {
	$length = strlen( $text );

	$right = absint( $right );
	$left = absint( $left );

	if ( $length < $right + $left ) {
		$right = $left = 0;
	}

	if ( $length <= 48 ) {
		$masked = str_repeat( '*', $length - ( $right + $left ) );
	} elseif ( $right + $left < 48 ) {
		$masked = str_repeat( '*', 48 - ( $right + $left ) );
	} else {
		$masked = '****';
	}

	$left_unmasked = $left ? substr( $text, 0, $left ) : '';
	$right_unmasked = $right ? substr( $text, -1 * $right ) : '';

	$text = $left_unmasked . $masked . $right_unmasked;

	return $text;
}


/**
 * Returns an array of allowed HTML tags and attributes for a given context.
 *
 * @param string $context Context used to decide allowed tags and attributes.
 * @return array Array of allowed HTML tags and their allowed attributes.
 */
function wpcf7_kses_allowed_html( $context = 'form' ) {
	static $allowed_tags = array();

	if ( isset( $allowed_tags[$context] ) ) {
		return apply_filters(
			'wpcf7_kses_allowed_html',
			$allowed_tags[$context],
			$context
		);
	}

	$allowed_tags[$context] = wp_kses_allowed_html( 'post' );

	if ( 'form' === $context ) {
		$additional_tags_for_form = array(
			'button' => array(
				'disabled' => true,
				'name' => true,
				'type' => true,
				'value' => true,
			),
			'datalist' => array(),
			'fieldset' => array(
				'disabled' => true,
				'name' => true,
			),
			'input' => array(
				'accept' => true,
				'alt' => true,
				'capture' => true,
				'checked' => true,
				'disabled' => true,
				'list' => true,
				'max' => true,
				'maxlength' => true,
				'min' => true,
				'minlength' => true,
				'multiple' => true,
				'name' => true,
				'placeholder' => true,
				'readonly' => true,
				'size' => true,
				'step' => true,
				'type' => true,
				'value' => true,
			),
			'label' => array(
				'for' => true,
			),
			'legend' => array(),
			'meter' => array(
				'value' => true,
				'min' => true,
				'max' => true,
				'low' => true,
				'high' => true,
				'optimum' => true,
			),
			'optgroup' => array(
				'disabled' => true,
				'label' => true,
			),
			'option' => array(
				'disabled' => true,
				'label' => true,
				'selected' => true,
				'value' => true,
			),
			'output' => array(
				'for' => true,
				'name' => true,
			),
			'progress' => array(
				'max' => true,
				'value' => true,
			),
			'select' => array(
				'disabled' => true,
				'multiple' => true,
				'name' => true,
				'size' => true,
			),
			'textarea' => array(
				'cols' => true,
				'disabled' => true,
				'maxlength' => true,
				'minlength' => true,
				'name' => true,
				'placeholder' => true,
				'readonly' => true,
				'rows' => true,
				'spellcheck' => true,
				'wrap' => true,
			),
		);

		$additional_tags_for_form = array_map(
			static function ( $elm ) {
				$global_attributes = array(
					'aria-atomic' => true,
					'aria-checked' => true,
					'aria-describedby' => true,
					'aria-details' => true,
					'aria-disabled' => true,
					'aria-hidden' => true,
					'aria-invalid' => true,
					'aria-label' => true,
					'aria-labelledby' => true,
					'aria-live' => true,
					'aria-relevant' => true,
					'aria-required' => true,
					'aria-selected' => true,
					'class' => true,
					'data-*' => true,
					'id' => true,
					'inputmode' => true,
					'role' => true,
					'style' => true,
					'tabindex' => true,
					'title' => true,
				);

				return array_merge( $global_attributes, (array) $elm );
			},
			$additional_tags_for_form
		);

		$allowed_tags[$context] = array_merge(
			$allowed_tags[$context],
			$additional_tags_for_form
		);
	}

	return apply_filters(
		'wpcf7_kses_allowed_html',
		$allowed_tags[$context],
		$context
	);
}


/**
 * Sanitizes content for allowed HTML tags for the specified context.
 *
 * @param string $input Content to filter.
 * @param string $context Context used to decide allowed tags and attributes.
 * @return string Filtered text with allowed HTML tags and attributes intact.
 */
function wpcf7_kses( $input, $context = 'form' ) {
	$output = wp_kses(
		$input,
		wpcf7_kses_allowed_html( $context )
	);

	return $output;
}


/**
 * Returns a formatted string of HTML attributes.
 *
 * @param array $atts Associative array of attribute name and value pairs.
 * @return string Formatted HTML attributes.
 */
function wpcf7_format_atts( $atts ) {
	$atts_filtered = array();

	foreach ( $atts as $name => $value ) {
		$name = strtolower( trim( $name ) );

		if ( ! preg_match( '/^[a-z_:][a-z_:.0-9-]*$/', $name ) ) {
			continue;
		}

		static $boolean_attributes = array(
			'checked',
			'disabled',
			'inert',
			'multiple',
			'readonly',
			'required',
			'selected',
		);

		if ( in_array( $name, $boolean_attributes ) and '' === $value ) {
			$value = false;
		}

		if ( is_numeric( $value ) ) {
			$value = (string) $value;
		}

		if ( null === $value or false === $value ) {
			unset( $atts_filtered[$name] );
		} elseif ( true === $value ) {
			$atts_filtered[$name] = $name; // boolean attribute
		} elseif ( is_string( $value ) ) {
			$atts_filtered[$name] = trim( $value );
		}
	}

	$output = '';

	foreach ( $atts_filtered as $name => $value ) {
		$output .= sprintf( ' %1$s="%2$s"', $name, esc_attr( $value ) );
	}

	return trim( $output );
}


/**
 * Strips surrounding whitespaces.
 *
 * @link https://contactform7.com/2024/07/13/consistent-handling-policy-of-surrounding-whitespaces/
 *
 * @param string|array $input Input text.
 * @return string|array Output text.
 */
function wpcf7_strip_whitespaces( $input ) {
	if ( is_array( $input ) ) {
		return array_map( 'wpcf7_strip_whitespaces', $input );
	}

	// https://www.unicode.org/Public/UCD/latest/ucd/PropList.txt
	// https://tc39.es/ecma262/multipage/ecmascript-language-lexical-grammar.html
	$whitespaces = '\x09-\x0D\x20\x85\xA0\x{1680}\x{2000}-\x{200A}\x{2028}\x{2029}\x{202F}\x{205F}\x{3000}\x{FEFF}';

	// Strip leading whitespaces
	$input = preg_replace(
		sprintf( '/^[%s]+/u', $whitespaces ),
		'',
		$input
	);

	// Strip trailing whitespaces
	$input = preg_replace(
		sprintf( '/[%s]+$/u', $whitespaces ),
		'',
		$input
	);

	return $input;
}
includes/functions.php000064400000037051147510545420011110 0ustar00<?php

/**
 * Returns path to a plugin file.
 *
 * @param string $path File path relative to the plugin root directory.
 * @return string Absolute file path.
 */
function wpcf7_plugin_path( $path = '' ) {
	return path_join( WPCF7_PLUGIN_DIR, trim( $path, '/' ) );
}


/**
 * Returns the URL to a plugin file.
 *
 * @param string $path File path relative to the plugin root directory.
 * @return string URL.
 */
function wpcf7_plugin_url( $path = '' ) {
	$url = plugins_url( $path, WPCF7_PLUGIN );

	if ( is_ssl()
	and 'http:' == substr( $url, 0, 5 ) ) {
		$url = 'https:' . substr( $url, 5 );
	}

	return $url;
}


/**
 * Include a file under WPCF7_PLUGIN_MODULES_DIR.
 *
 * @param string $path File path relative to the module dir.
 * @return bool True on success, false on failure.
 */
function wpcf7_include_module_file( $path ) {
	$dir = WPCF7_PLUGIN_MODULES_DIR;

	if ( empty( $dir ) or ! is_dir( $dir ) ) {
		return false;
	}

	$path = path_join( $dir, ltrim( $path, '/' ) );

	if ( file_exists( $path ) ) {
		include_once $path;
		return true;
	}

	return false;
}


/**
 * Retrieves uploads directory information.
 *
 * @param string|bool $type Optional. Type of output. Default false.
 * @return array|string Information about the upload directory.
 */
function wpcf7_upload_dir( $type = false ) {
	$uploads = wp_get_upload_dir();

	$uploads = apply_filters( 'wpcf7_upload_dir', array(
		'dir' => $uploads['basedir'],
		'url' => $uploads['baseurl'],
	) );

	if ( 'dir' == $type ) {
		return $uploads['dir'];
	} if ( 'url' == $type ) {
		return $uploads['url'];
	}

	return $uploads;
}


/**
 * Verifies that a correct security nonce was used with time limit.
 *
 * @param string $nonce Nonce value that was used for verification.
 * @param string $action Optional. Context to what is taking place.
 *                       Default 'wp_rest'.
 * @return int|bool 1 if the nonce is generated between 0-12 hours ago,
 *                  2 if the nonce is generated between 12-24 hours ago.
 *                  False if the nonce is invalid.
 */
function wpcf7_verify_nonce( $nonce, $action = 'wp_rest' ) {
	return wp_verify_nonce( $nonce, $action );
}


/**
 * Creates a cryptographic token tied to a specific action, user, user session,
 * and window of time.
 *
 * @param string $action Optional. Context to what is taking place.
 *                       Default 'wp_rest'.
 * @return string The token.
 */
function wpcf7_create_nonce( $action = 'wp_rest' ) {
	return wp_create_nonce( $action );
}


/**
 * Converts multi-dimensional array to a flat array.
 *
 * @param mixed $input Array or item of array.
 * @return array Flatten array.
 */
function wpcf7_array_flatten( $input ) {
	if ( ! is_array( $input ) ) {
		return array( $input );
	}

	$output = array();

	foreach ( $input as $value ) {
		$output = array_merge( $output, wpcf7_array_flatten( $value ) );
	}

	return $output;
}


/**
 * Excludes unset or blank text values from the given array.
 *
 * @param array $input The array.
 * @return array Array without blank text values.
 */
function wpcf7_exclude_blank( $input ) {
	$output = array_filter( $input,
		static function ( $i ) {
			return isset( $i ) && '' !== $i;
		}
	);

	return array_values( $output );
}


/**
 * Creates a comma-separated list from a multi-dimensional array.
 *
 * @param mixed $input Array or item of array.
 * @param string|array $options Optional. Output options.
 * @return string Comma-separated list.
 */
function wpcf7_flat_join( $input, $options = '' ) {
	$options = wp_parse_args( $options, array(
		'separator' => ', ',
	) );

	$input = wpcf7_array_flatten( $input );
	$output = array();

	foreach ( (array) $input as $value ) {
		if ( is_scalar( $value ) ) {
			$output[] = trim( (string) $value );
		}
	}

	return implode( $options['separator'], $output );
}


/**
 * Returns true if HTML5 is supported.
 */
function wpcf7_support_html5() {
	return (bool) wpcf7_apply_filters_deprecated(
		'wpcf7_support_html5',
		array( true ),
		'5.6',
		''
	);
}


/**
 * Returns true if HTML5 fallback is active.
 */
function wpcf7_support_html5_fallback() {
	return (bool) apply_filters( 'wpcf7_support_html5_fallback', false );
}


/**
 * Returns true if the Really Simple CAPTCHA plugin is used for contact forms.
 */
function wpcf7_use_really_simple_captcha() {
	return apply_filters( 'wpcf7_use_really_simple_captcha',
		WPCF7_USE_REALLY_SIMPLE_CAPTCHA
	);
}


/**
 * Returns true if config validation is active.
 */
function wpcf7_validate_configuration() {
	return apply_filters( 'wpcf7_validate_configuration',
		WPCF7_VALIDATE_CONFIGURATION
	);
}


/**
 * Returns true if wpcf7_autop() is applied.
 */
function wpcf7_autop_or_not( $options = '' ) {
	$options = wp_parse_args( $options, array(
		'for' => 'form',
	) );

	return (bool) apply_filters( 'wpcf7_autop_or_not', WPCF7_AUTOP, $options );
}


/**
 * Returns true if JavaScript for this plugin is loaded.
 */
function wpcf7_load_js() {
	return apply_filters( 'wpcf7_load_js', WPCF7_LOAD_JS );
}


/**
 * Returns true if CSS for this plugin is loaded.
 */
function wpcf7_load_css() {
	return apply_filters( 'wpcf7_load_css', WPCF7_LOAD_CSS );
}


/**
 * Builds an HTML anchor element.
 *
 * @param string $url Link URL.
 * @param string $anchor_text Anchor label text.
 * @param string|array $atts Optional. HTML attributes.
 * @return string Formatted anchor element.
 */
function wpcf7_link( $url, $anchor_text, $atts = '' ) {
	$atts = wp_parse_args( $atts, array(
		'id' => null,
		'class' => null,
	) );

	$atts = array_merge( $atts, array(
		'href' => esc_url( $url ),
	) );

	return sprintf(
		'<a %1$s>%2$s</a>',
		wpcf7_format_atts( $atts ),
		esc_html( $anchor_text )
	);
}


/**
 * Returns the current request URL.
 */
function wpcf7_get_request_uri() {
	static $request_uri = '';

	if ( empty( $request_uri ) ) {
		$request_uri = add_query_arg( array() );
		$request_uri = '/' . ltrim( $request_uri, '/' );
	}

	return sanitize_url( $request_uri );
}


/**
 * Registers post types used for this plugin.
 */
function wpcf7_register_post_types() {
	if ( class_exists( 'WPCF7_ContactForm' ) ) {
		WPCF7_ContactForm::register_post_type();
		return true;
	} else {
		return false;
	}
}


/**
 * Returns the version string of this plugin.
 *
 * @param string|array $options Optional. Output options.
 * @return string Version string.
 */
function wpcf7_version( $options = '' ) {
	$options = wp_parse_args( $options, array(
		'limit' => -1,
		'only_major' => false,
	) );

	if ( $options['only_major'] ) {
		$options['limit'] = 2;
	}

	$options['limit'] = (int) $options['limit'];

	$ver = WPCF7_VERSION;
	$ver = strtr( $ver, '_-+', '...' );
	$ver = preg_replace( '/[^0-9.]+/', ".$0.", $ver );
	$ver = preg_replace( '/[.]+/', ".", $ver );
	$ver = trim( $ver, '.' );
	$ver = explode( '.', $ver );

	if ( -1 < $options['limit'] ) {
		$ver = array_slice( $ver, 0, $options['limit'] );
	}

	$ver = implode( '.', $ver );

	return $ver;
}


/**
 * Returns array entries that match the given version.
 *
 * @param string $version The version to search for.
 * @param array $input Search target array.
 * @return array|bool Array of matched entries. False on failure.
 */
function wpcf7_version_grep( $version, array $input ) {
	$pattern = '/^' . preg_quote( (string) $version, '/' ) . '(?:\.|$)/';

	return preg_grep( $pattern, $input );
}


/**
 * Returns an enctype attribute value.
 *
 * @param string $enctype Enctype value.
 * @return string Enctype value. Empty if not a valid enctype.
 */
function wpcf7_enctype_value( $enctype ) {
	$enctype = trim( $enctype );

	if ( empty( $enctype ) ) {
		return '';
	}

	$valid_enctypes = array(
		'application/x-www-form-urlencoded',
		'multipart/form-data',
		'text/plain',
	);

	if ( in_array( $enctype, $valid_enctypes ) ) {
		return $enctype;
	}

	$pattern = '%^enctype="(' . implode( '|', $valid_enctypes ) . ')"$%';

	if ( preg_match( $pattern, $enctype, $matches ) ) {
		return $matches[1]; // for back-compat
	}

	return '';
}


/**
 * Removes directory recursively.
 *
 * @param string $dir Directory path.
 * @return bool True on success, false on failure.
 */
function wpcf7_rmdir_p( $dir ) {
	if ( is_file( $dir ) ) {
		$file = $dir;

		if ( @unlink( $file ) ) {
			return true;
		}

		$stat = stat( $file );

		if ( @chmod( $file, $stat['mode'] | 0200 ) ) { // add write for owner
			if ( @unlink( $file ) ) {
				return true;
			}

			@chmod( $file, $stat['mode'] );
		}

		return false;
	}

	if ( ! is_dir( $dir ) ) {
		return false;
	}

	if ( $handle = opendir( $dir ) ) {
		while ( false !== ( $file = readdir( $handle ) ) ) {
			if ( $file == "."
			or $file == ".." ) {
				continue;
			}

			wpcf7_rmdir_p( path_join( $dir, $file ) );
		}

		closedir( $handle );
	}

	if ( false !== ( $files = scandir( $dir ) )
	and ! array_diff( $files, array( '.', '..' ) ) ) {
		return rmdir( $dir );
	}

	return false;
}


/**
 * Builds a URL-encoded query string.
 *
 * @link https://developer.wordpress.org/reference/functions/_http_build_query/
 *
 * @param array $data URL query parameters.
 * @param string $key Optional. If specified, used to prefix key name.
 * @return string Query string.
 */
function wpcf7_build_query( $data, $key = '' ) {
	$sep = '&';
	$ret = array();

	foreach ( (array) $data as $k => $v ) {
		$k = urlencode( $k );

		if ( ! empty( $key ) ) {
			$k = $key . '%5B' . $k . '%5D';
		}

		if ( null === $v ) {
			continue;
		} elseif ( false === $v ) {
			$v = '0';
		}

		if ( is_array( $v ) or is_object( $v ) ) {
			array_push( $ret, wpcf7_build_query( $v, $k ) );
		} else {
			array_push( $ret, $k . '=' . urlencode( $v ) );
		}
	}

	return implode( $sep, $ret );
}


/**
 * Returns the number of code units in a string.
 *
 * @link http://www.w3.org/TR/html5/infrastructure.html#code-unit-length
 *
 * @param string $text Input string.
 * @return int|bool The number of code units, or false if
 *                  mb_convert_encoding is not available.
 */
function wpcf7_count_code_units( $text ) {
	static $use_mb = null;

	if ( is_null( $use_mb ) ) {
		$use_mb = function_exists( 'mb_convert_encoding' );
	}

	if ( ! $use_mb ) {
		return false;
	}

	$text = (string) $text;
	$text = str_replace( "\r\n", "\n", $text );

	$encoding = mb_detect_encoding( $text, mb_detect_order(), true );

	if ( $encoding ) {
		$text = mb_convert_encoding( $text, 'UTF-16', $encoding );
	} else {
		$text = mb_convert_encoding( $text, 'UTF-16', 'UTF-8' );
	}

	$byte_count = mb_strlen( $text, '8bit' );

	return floor( $byte_count / 2 );
}


/**
 * Returns true if WordPress is running on the localhost.
 */
function wpcf7_is_localhost() {
	$sitename = wp_parse_url( network_home_url(), PHP_URL_HOST );
	return in_array( strtolower( $sitename ), array( 'localhost', '127.0.0.1' ) );
}


/**
 * Marks a function as deprecated and informs when it has been used.
 *
 * @param string $function_name The function that was called.
 * @param string $version The version of Contact Form 7 that deprecated
 *                        the function.
 * @param string $replacement The function that should have been called.
 */
function wpcf7_deprecated_function( $function_name, $version, $replacement ) {

	if ( ! WP_DEBUG ) {
		return;
	}

	if ( function_exists( '__' ) ) {
		/* translators: 1: PHP function name, 2: version number, 3: alternative function name */
		$message = __( 'Function %1$s is <strong>deprecated</strong> since Contact Form 7 version %2$s! Use %3$s instead.', 'contact-form-7' );
	} else {
		$message = 'Function %1$s is <strong>deprecated</strong> since Contact Form 7 version %2$s! Use %3$s instead.';
	}

	$message = sprintf( $message, $function_name, $version, $replacement );

	wp_trigger_error( '', $message, E_USER_DEPRECATED );
}


/**
 * Fires functions attached to a deprecated filter hook.
 *
 * @param string $hook_name The name of the filter hook.
 * @param array $args Array of additional function arguments to be
 *                    passed to apply_filters().
 * @param string $version The version of Contact Form 7 that deprecated
 *                        the hook.
 * @param string $replacement The hook that should have been used.
 */
function wpcf7_apply_filters_deprecated( $hook_name, $args, $version, $replacement = '' ) {
	if ( ! has_filter( $hook_name ) ) {
		return $args[0];
	}

	if ( WP_DEBUG and apply_filters( 'deprecated_hook_trigger_error', true ) ) {
		if ( $replacement ) {
			wp_trigger_error(
				'',
				sprintf(
					/* translators: 1: WordPress hook name, 2: version number, 3: alternative hook name */
					__( 'Hook %1$s is <strong>deprecated</strong> since Contact Form 7 version %2$s! Use %3$s instead.', 'contact-form-7' ),
					$hook_name,
					$version,
					$replacement
				),
				E_USER_DEPRECATED
			);
		} else {
			wp_trigger_error(
				'',
				sprintf(
					/* translators: 1: WordPress hook name, 2: version number */
					__( 'Hook %1$s is <strong>deprecated</strong> since Contact Form 7 version %2$s with no alternative available.', 'contact-form-7' ),
					$hook_name,
					$version
				),
				E_USER_DEPRECATED
			);
		}
	}

	return apply_filters_ref_array( $hook_name, $args );
}


/**
 * Marks something as being incorrectly called.
 *
 * @param string $function_name The function that was called.
 * @param string $message A message explaining what has been done incorrectly.
 * @param string $version The version of Contact Form 7 where the message
 *                        was added.
 */
function wpcf7_doing_it_wrong( $function_name, $message, $version ) {

	if ( ! WP_DEBUG ) {
		return;
	}

	if ( function_exists( '__' ) ) {
		if ( $version ) {
			$version = sprintf(
				/* translators: %s: Contact Form 7 version number. */
				__( '(This message was added in Contact Form 7 version %s.)', 'contact-form-7' ),
				$version
			);
		}

		wp_trigger_error(
			'',
			sprintf(
				/* translators: Developer debugging message. 1: PHP function name, 2: Explanatory message, 3: Contact Form 7 version number. */
				__( 'Function %1$s was called incorrectly. %2$s %3$s', 'contact-form-7' ),
				$function_name,
				$message,
				$version
			),
			E_USER_NOTICE
		);
	} else {
		if ( $version ) {
			$version = sprintf(
				'(This message was added in Contact Form 7 version %s.)',
				$version
			);
		}

		wp_trigger_error(
			'',
			sprintf(
				'Function %1$s was called incorrectly. %2$s %3$s',
				$function_name,
				$message,
				$version
			),
			E_USER_NOTICE
		);
	}
}


/**
 * Triggers an error about a remote HTTP request and response.
 *
 * @param string $url The resource URL.
 * @param array $request Request arguments.
 * @param array|WP_Error $response The response or WP_Error on failure.
 */
function wpcf7_log_remote_request( $url, $request, $response ) {

	if ( ! WP_DEBUG ) {
		return;
	}

	$log = sprintf(
		/* translators: 1: response code, 2: message, 3: body, 4: URL */
		__( 'HTTP Response: %1$s %2$s %3$s from %4$s', 'contact-form-7' ),
		(int) wp_remote_retrieve_response_code( $response ),
		wp_remote_retrieve_response_message( $response ),
		wp_remote_retrieve_body( $response ),
		$url
	);

	$log = apply_filters( 'wpcf7_log_remote_request',
		$log, $url, $request, $response
	);

	if ( $log ) {
		wp_trigger_error( '', $log, E_USER_NOTICE );
	}
}


/**
 * Anonymizes an IP address by masking local part.
 *
 * @param string $ip_addr The original IP address.
 * @return string|bool Anonymized IP address, or false on failure.
 */
function wpcf7_anonymize_ip_addr( $ip_addr ) {
	if ( ! function_exists( 'inet_ntop' )
	or ! function_exists( 'inet_pton' ) ) {
		return $ip_addr;
	}

	$packed = inet_pton( $ip_addr );

	if ( false === $packed ) {
		return $ip_addr;
	}

	if ( 4 == strlen( $packed ) ) { // IPv4
		$mask = '255.255.255.0';
	} elseif ( 16 == strlen( $packed ) ) { // IPv6
		$mask = 'ffff:ffff:ffff:0000:0000:0000:0000:0000';
	} else {
		return $ip_addr;
	}

	return inet_ntop( $packed & inet_pton( $mask ) );
}
includes/form-tags-manager.php000064400000034354147510545420012412 0ustar00<?php

/**
 * Wrapper function of WPCF7_FormTagsManager::add().
 */
function wpcf7_add_form_tag( $tag_types, $callback, $features = '' ) {
	$manager = WPCF7_FormTagsManager::get_instance();

	return $manager->add( $tag_types, $callback, $features );
}


/**
 * Wrapper function of WPCF7_FormTagsManager::remove().
 */
function wpcf7_remove_form_tag( $tag_type ) {
	$manager = WPCF7_FormTagsManager::get_instance();

	return $manager->remove( $tag_type );
}


/**
 * Wrapper function of WPCF7_FormTagsManager::replace_all().
 */
function wpcf7_replace_all_form_tags( $content ) {
	$manager = WPCF7_FormTagsManager::get_instance();

	return $manager->replace_all( $content );
}


/**
 * Wrapper function of WPCF7_ContactForm::scan_form_tags().
 */
function wpcf7_scan_form_tags( $cond = null ) {
	$contact_form = WPCF7_ContactForm::get_current();

	if ( $contact_form ) {
		return $contact_form->scan_form_tags( $cond );
	}

	return array();
}


/**
 * Wrapper function of WPCF7_FormTagsManager::tag_type_supports().
 */
function wpcf7_form_tag_supports( $tag_type, $feature ) {
	$manager = WPCF7_FormTagsManager::get_instance();

	return $manager->tag_type_supports( $tag_type, $feature );
}


/**
 * The singleton instance of this class manages the collection of form-tags.
 */
class WPCF7_FormTagsManager {

	private static $instance;

	private $tag_types = array();
	private $scanned_tags = null; // Tags scanned at the last time of scan()
	private $placeholders = array();

	private function __construct() {}


	/**
	 * Returns the singleton instance.
	 *
	 * @return WPCF7_FormTagsManager The singleton manager.
	 */
	public static function get_instance() {
		if ( empty( self::$instance ) ) {
			self::$instance = new self;
		}

		return self::$instance;
	}


	/**
	 * Returns scanned form-tags.
	 *
	 * @return array Array of WPCF7_FormTag objects.
	 */
	public function get_scanned_tags() {
		return $this->scanned_tags;
	}


	/**
	 * Registers form-tag types to the manager.
	 *
	 * @param string|array $tag_types The name of the form-tag type or
	 *                     an array of the names.
	 * @param callable $callback The callback to generates a form control HTML
	 *                 for a form-tag in this type.
	 * @param string|array $features Optional. Features a form-tag
	 *                     in this type supports.
	 */
	public function add( $tag_types, $callback, $features = '' ) {
		if ( ! is_callable( $callback ) ) {
			return;
		}

		if ( true === $features ) { // for back-compat
			$features = array( 'name-attr' => true );
		}

		$features = wp_parse_args( $features, array() );

		$tag_types = array_filter( array_unique( (array) $tag_types ) );

		foreach ( $tag_types as $tag_type ) {
			$tag_type = $this->sanitize_tag_type( $tag_type );

			if ( ! $this->tag_type_exists( $tag_type ) ) {
				$this->tag_types[$tag_type] = array(
					'function' => $callback,
					'features' => $features,
				);
			}
		}
	}


	/**
	 * Returns true if the given tag type exists.
	 */
	public function tag_type_exists( $tag_type ) {
		return isset( $this->tag_types[$tag_type] );
	}


	/**
	 * Returns true if the tag type supports the features.
	 *
	 * @param string $tag_type The name of the form-tag type.
	 * @param array|string $features The feature to check or an array of features.
	 * @return bool True if the form-tag type supports at least one of
	 *              the given features, false otherwise.
	 */
	public function tag_type_supports( $tag_type, $features ) {
		$features = array_filter( (array) $features );

		if ( isset( $this->tag_types[$tag_type]['features'] ) ) {
			return (bool) array_intersect(
				array_keys( array_filter( $this->tag_types[$tag_type]['features'] ) ),
				$features
			);
		}

		return false;
	}


	/**
	 * Returns form-tag types that support the given features.
	 *
	 * @param array|string $features Optional. The feature to check or
	 *                     an array of features. Default empty array.
	 * @param bool $invert Optional. If this value is true, returns form-tag
	 *             types that do not support the given features. Default false.
	 * @return array An array of form-tag types. If the $features param is empty,
	 *               returns all form-tag types that have been registered.
	 */
	public function collect_tag_types( $features = array(), $invert = false ) {
		$tag_types = array_keys( $this->tag_types );

		if ( empty( $features ) ) {
			return $tag_types;
		}

		$output = array();

		foreach ( $tag_types as $tag_type ) {
			if ( ! $invert && $this->tag_type_supports( $tag_type, $features )
			|| $invert && ! $this->tag_type_supports( $tag_type, $features ) ) {
				$output[] = $tag_type;
			}
		}

		return $output;
	}


	/**
	 * Sanitizes the form-tag type name.
	 */
	private function sanitize_tag_type( $tag_type ) {
		$tag_type = preg_replace( '/[^a-zA-Z0-9_*]+/', '_', $tag_type );
		$tag_type = rtrim( $tag_type, '_' );
		$tag_type = strtolower( $tag_type );
		return $tag_type;
	}


	/**
	 * Deregisters the form-tag type.
	 */
	public function remove( $tag_type ) {
		unset( $this->tag_types[$tag_type] );
	}


	/**
	 * Normalizes the text content that includes form-tags.
	 */
	public function normalize( $content ) {
		if ( empty( $this->tag_types ) ) {
			return $content;
		}

		$content = preg_replace_callback(
			'/' . $this->tag_regex() . '/s',
			array( $this, 'normalize_callback' ),
			$content
		);

		return $content;
	}


	/**
	 * The callback function used within normalize().
	 */
	private function normalize_callback( $matches ) {
		// allow [[foo]] syntax for escaping a tag
		if ( $matches[1] == '['
		and $matches[6] == ']' ) {
			return $matches[0];
		}

		$tag = $matches[2];

		$attr = trim( preg_replace( '/[\r\n\t ]+/', ' ', $matches[3] ) );
		$attr = strtr( $attr, array( '<' => '&lt;', '>' => '&gt;' ) );

		$content = trim( $matches[5] );
		$content = str_replace( "\n", '<WPPreserveNewline />', $content );

		$result = $matches[1] . '[' . $tag
			. ( $attr ? ' ' . $attr : '' )
			. ( $matches[4] ? ' ' . $matches[4] : '' )
			. ']'
			. ( $content ? $content . '[/' . $tag . ']' : '' )
			. $matches[6];

		return $result;
	}


	/**
	 * Replace all form-tags in the given text with placeholders.
	 */
	public function replace_with_placeholders( $content ) {
		if ( empty( $this->tag_types ) ) {
			return $content;
		}

		$this->placeholders = array();

		$callback = function ( $matches ) {
			// Allow [[foo]] syntax for escaping a tag.
			if ( '[' === $matches[1] and ']' === $matches[6] ) {
				return $matches[0];
			}

			$tag = $matches[0];
			$tag_type = $matches[2];

			$block_or_hidden = $this->tag_type_supports(
				$tag_type,
				array( 'display-block', 'display-hidden' )
			);

			if ( $block_or_hidden ) {
				$placeholder_tag_name = WPCF7_HTMLFormatter::placeholder_block;
			} else {
				$placeholder_tag_name = WPCF7_HTMLFormatter::placeholder_inline;
			}

			$placeholder = sprintf(
				'<%1$s id="%2$s" />',
				$placeholder_tag_name,
				sha1( $tag )
			);

			list( $placeholder ) =
				WPCF7_HTMLFormatter::normalize_start_tag( $placeholder );

			$this->placeholders[$placeholder] = $tag;

			return $placeholder;
		};

		return preg_replace_callback(
			'/' . $this->tag_regex() . '/s',
			$callback,
			$content
		);
	}


	/**
	 * Replace placeholders in the given text with original form-tags.
	 */
	public function restore_from_placeholders( $content ) {
		return str_replace(
			array_keys( $this->placeholders ),
			array_values( $this->placeholders ),
			$content
		);
	}


	/**
	 * Replaces all form-tags in the text content.
	 *
	 * @param string $content The text content including form-tags.
	 * @return string The result of replacements.
	 */
	public function replace_all( $content ) {
		return $this->scan( $content, true );
	}


	/**
	 * Scans form-tags in the text content.
	 *
	 * @param string $content The text content including form-tags.
	 * @param bool $replace Optional. Whether scanned form-tags will be
	 *             replaced. Default false.
	 * @return array|string An array of scanned form-tags if $replace is false.
	 *                      Otherwise text that scanned form-tags are replaced.
	 */
	public function scan( $content, $replace = false ) {
		$this->scanned_tags = array();

		if ( empty( $this->tag_types ) ) {
			if ( $replace ) {
				return $content;
			} else {
				return $this->scanned_tags;
			}
		}

		if ( $replace ) {
			$content = preg_replace_callback(
				'/' . $this->tag_regex() . '/s',
				array( $this, 'replace_callback' ),
				$content
			);

			return $content;
		} else {
			preg_replace_callback(
				'/' . $this->tag_regex() . '/s',
				array( $this, 'scan_callback' ),
				$content
			);

			return $this->scanned_tags;
		}
	}


	/**
	 * Filters form-tags based on a condition array argument.
	 *
	 * @param array|string $input The original form-tags collection.
	 *                     If it is a string, scans form-tags from it.
	 * @param array $cond The conditions that filtering will be based on.
	 * @return array The filtered form-tags collection.
	 */
	public function filter( $input, $cond ) {
		if ( is_array( $input ) ) {
			$tags = $input;
		} elseif ( is_string( $input ) ) {
			$tags = $this->scan( $input );
		} else {
			$tags = $this->scanned_tags;
		}

		$cond = wp_parse_args( $cond, array(
			'type' => array(),
			'basetype' => array(),
			'name' => array(),
			'feature' => array(),
		) );

		$cond = array_map( static function ( $c ) {
			return array_filter( array_map( 'trim', (array) $c ) );
		}, $cond );

		$tags = array_filter(
			(array) $tags,
			function ( $tag ) use ( $cond ) {
				$tag = new WPCF7_FormTag( $tag );

				if ( $cond['type']
				and ! in_array( $tag->type, $cond['type'], true ) ) {
					return false;
				}

				if ( $cond['basetype']
				and ! in_array( $tag->basetype, $cond['basetype'], true ) ) {
					return false;
				}

				if ( $cond['name']
				and ! in_array( $tag->name, $cond['name'], true ) ) {
					return false;
				}

				foreach ( $cond['feature'] as $feature ) {
					if ( '!' === substr( $feature, 0, 1 ) ) { // Negation
						$feature = trim( substr( $feature, 1 ) );

						if ( $this->tag_type_supports( $tag->type, $feature ) ) {
							return false;
						}
					} else {
						if ( ! $this->tag_type_supports( $tag->type, $feature ) ) {
							return false;
						}
					}
				}

				return true;
			}
		);

		return array_values( $tags );
	}


	/**
	 * Returns the regular expression for a form-tag.
	 */
	private function tag_regex() {
		$tagnames = array_keys( $this->tag_types );
		$tagregexp = implode( '|', array_map( 'preg_quote', $tagnames ) );

		return '(\[?)'
			. '\[(' . $tagregexp . ')(?:[\r\n\t ](.*?))?(?:[\r\n\t ](\/))?\]'
			. '(?:([^[]*?)\[\/\2\])?'
			. '(\]?)';
	}


	/**
	 * The callback function for the form-tag replacement.
	 */
	private function replace_callback( $matches ) {
		return $this->scan_callback( $matches, true );
	}


	/**
	 * The callback function for the form-tag scanning.
	 */
	private function scan_callback( $matches, $replace = false ) {
		// allow [[foo]] syntax for escaping a tag
		if ( $matches[1] == '['
		and $matches[6] == ']' ) {
			return substr( $matches[0], 1, -1 );
		}

		$tag_type = $matches[2];
		$tag_basetype = trim( $tag_type, '*' );
		$attr = $this->parse_atts( $matches[3] );

		$scanned_tag = array(
			'type' => $tag_type,
			'basetype' => $tag_basetype,
			'raw_name' => '',
			'name' => '',
			'options' => array(),
			'raw_values' => array(),
			'values' => array(),
			'pipes' => null,
			'labels' => array(),
			'attr' => '',
			'content' => '',
		);

		if ( $this->tag_type_supports( $tag_type, 'singular' ) ) {
			$tags_in_same_basetype = $this->filter(
				$this->scanned_tags,
				array( 'basetype' => $tag_basetype )
			);

			if ( $tags_in_same_basetype ) {
				// Another tag in the same base type already exists. Ignore this one.
				return $matches[0];
			}
		}

		if ( $this->tag_type_supports( $tag_type, 'name-attr' ) ) {
			if ( ! is_array( $attr ) ) {
				return $matches[0]; // Invalid form-tag.
			}

			$scanned_tag['raw_name'] = (string) array_shift( $attr['options'] );

			if ( ! wpcf7_is_name( $scanned_tag['raw_name'] ) ) {
				return $matches[0]; // Invalid name is used. Ignore this tag.
			}

			$scanned_tag['name'] = strtr( $scanned_tag['raw_name'], '.', '_' );
		}

		if ( is_array( $attr ) ) {
			$scanned_tag['options'] = (array) $attr['options'];
			$scanned_tag['raw_values'] = (array) $attr['values'];

			if ( WPCF7_USE_PIPE ) {
				$pipes = new WPCF7_Pipes( $scanned_tag['raw_values'] );
				$scanned_tag['values'] = $pipes->collect_befores();
				$scanned_tag['pipes'] = $pipes;
			} else {
				$scanned_tag['values'] = $scanned_tag['raw_values'];
			}

			$scanned_tag['labels'] = $scanned_tag['values'];

		} else {
			$scanned_tag['attr'] = $attr;
		}

		$scanned_tag['values'] = array_map( 'trim', $scanned_tag['values'] );
		$scanned_tag['labels'] = array_map( 'trim', $scanned_tag['labels'] );

		$content = trim( $matches[5] );
		$content = preg_replace( "/<br[\r\n\t ]*\/?>$/m", '', $content );
		$scanned_tag['content'] = $content;

		$scanned_tag = apply_filters( 'wpcf7_form_tag', $scanned_tag, $replace );

		$scanned_tag = new WPCF7_FormTag( $scanned_tag );

		$this->scanned_tags[] = $scanned_tag;

		if ( $replace ) {
			$callback = $this->tag_types[$tag_type]['function'];
			return $matches[1] . call_user_func( $callback, $scanned_tag ) . $matches[6];
		} else {
			return $matches[0];
		}
	}


	/**
	 * Parses the attributes of a form-tag to extract the name,
	 * options, and values.
	 *
	 * @param string $text Attributes of a form-tag.
	 * @return array|string An associative array of the options and values
	 *                      if the input is in the correct syntax,
	 *                      otherwise the input text itself.
	 */
	private function parse_atts( $text ) {
		$atts = array( 'options' => array(), 'values' => array() );
		$text = preg_replace( "/[\x{00a0}\x{200b}]+/u", " ", $text );
		$text = trim( $text );

		$pattern = '%^([-+*=0-9a-zA-Z:.!?#$&@_/|\%\r\n\t ]*?)((?:[\r\n\t ]*"[^"]*"|[\r\n\t ]*\'[^\']*\')*)$%';

		if ( preg_match( $pattern, $text, $matches ) ) {
			if ( ! empty( $matches[1] ) ) {
				$atts['options'] = preg_split( '/[\r\n\t ]+/', trim( $matches[1] ) );
			}

			if ( ! empty( $matches[2] ) ) {
				preg_match_all( '/"[^"]*"|\'[^\']*\'/', $matches[2], $matched_values );
				$atts['values'] = wpcf7_strip_quote_deep( $matched_values[0] );
			}
		} else {
			$atts = $text;
		}

		return $atts;
	}

}
includes/pocket-holder.php000064400000000505147510545420011632 0ustar00<?php

/**
 * Handy trait provides methods to handle dynamic properties.
 */
trait WPCF7_PocketHolder {

	protected $pocket = array();

	public function pull( $key ) {
		if ( isset( $this->pocket[$key] ) ) {
			return $this->pocket[$key];
		}
	}

	public function push( $key, $value ) {
		$this->pocket[$key] = $value;
	}

}
includes/submission.php000064400000050475147510545420011300 0ustar00<?php

/**
 * Class representing contact form submission.
 */
class WPCF7_Submission {

	use WPCF7_PocketHolder;

	private static $instance;

	private $contact_form;
	private $status = 'init';
	private $posted_data = array();
	private $posted_data_hash = null;
	private $skip_spam_check = false;
	private $uploaded_files = array();
	private $extra_attachments = array();
	private $skip_mail = false;
	private $response = '';
	private $invalid_fields = array();
	private $meta = array();
	private $consent = array();
	private $spam_log = array();
	private $result_props = array();


	/**
	 * Returns the singleton instance of this class.
	 */
	public static function get_instance( $contact_form = null, $options = '' ) {
		if ( $contact_form instanceof WPCF7_ContactForm ) {
			if ( empty( self::$instance ) ) {
				self::$instance = new self( $contact_form, $options );
				self::$instance->proceed();
				return self::$instance;
			} else {
				return null;
			}
		} else {
			if ( empty( self::$instance ) ) {
				return null;
			} else {
				return self::$instance;
			}
		}
	}


	/**
	 * Returns true if this submission is created via WP REST API.
	 */
	public static function is_restful() {
		return wp_is_serving_rest_request();
	}


	/**
	 * Constructor.
	 */
	private function __construct( WPCF7_ContactForm $contact_form, $options = '' ) {
		$options = wp_parse_args( $options, array(
			'skip_mail' => false,
		) );

		$this->contact_form = $contact_form;
		$this->skip_mail = (bool) $options['skip_mail'];
	}


	/**
	 * Destructor.
	 */
	public function __destruct() {
		$this->remove_uploaded_files();
	}


	/**
	 * The main logic of submission.
	 */
	private function proceed() {

		$callback = function () {
			$contact_form = $this->contact_form;

			$this->setup_meta_data();
			$this->setup_posted_data();

			if ( $this->is( 'init' ) and ! $this->validate() ) {
				$this->set_status( 'validation_failed' );
				$this->set_response( $contact_form->message( 'validation_error' ) );
			}

			if ( $this->is( 'init' ) and ! $this->accepted() ) {
				$this->set_status( 'acceptance_missing' );
				$this->set_response( $contact_form->message( 'accept_terms' ) );
			}

			if ( $this->is( 'init' ) and $this->spam() ) {
				$this->set_status( 'spam' );
				$this->set_response( $contact_form->message( 'spam' ) );
			}

			if ( $this->is( 'init' ) and ! $this->unship_uploaded_files() ) {
				$this->set_status( 'validation_failed' );
				$this->set_response( $contact_form->message( 'validation_error' ) );
			}

			if ( $this->is( 'init' ) ) {
				$abort = ! $this->before_send_mail();

				if ( $abort ) {
					if ( $this->is( 'init' ) ) {
						$this->set_status( 'aborted' );
					}

					if ( '' === $this->get_response() ) {
						$this->set_response( $contact_form->filter_message(
							__( "Sending mail has been aborted.", 'contact-form-7' ) )
						);
					}
				} elseif ( $this->mail() ) {
					$this->set_status( 'mail_sent' );
					$this->set_response( $contact_form->message( 'mail_sent_ok' ) );

					do_action( 'wpcf7_mail_sent', $contact_form );
				} else {
					$this->set_status( 'mail_failed' );
					$this->set_response( $contact_form->message( 'mail_sent_ng' ) );

					do_action( 'wpcf7_mail_failed', $contact_form );
				}
			}
		};

		wpcf7_switch_locale( $this->contact_form->locale(), $callback );
	}


	/**
	 * Returns the current status property.
	 */
	public function get_status() {
		return $this->status;
	}


	/**
	 * Sets the status property.
	 *
	 * @param string $status The status.
	 */
	public function set_status( $status ) {
		if ( preg_match( '/^[a-z][0-9a-z_]+$/', $status ) ) {
			$this->status = $status;
			return true;
		}

		return false;
	}


	/**
	 * Returns true if the specified status is identical to the current
	 * status property.
	 *
	 * @param string $status The status to compare.
	 */
	public function is( $status ) {
		return $this->status === $status;
	}


	/**
	 * Returns an associative array of submission result properties.
	 *
	 * @return array Submission result properties.
	 */
	public function get_result() {
		$result = array_merge( $this->result_props, array(
			'status' => $this->get_status(),
			'message' => $this->get_response(),
		) );

		if ( $this->is( 'validation_failed' ) ) {
			$result['invalid_fields'] = $this->get_invalid_fields();
		}

		switch ( $this->get_status() ) {
			case 'init':
			case 'validation_failed':
			case 'acceptance_missing':
			case 'spam':
				$result['posted_data_hash'] = '';
				break;
			default:
				$result['posted_data_hash'] = $this->get_posted_data_hash();
				break;
		}

		$result = apply_filters( 'wpcf7_submission_result', $result, $this );

		return $result;
	}


	/**
	 * Adds items to the array of submission result properties.
	 *
	 * @param string|array|object $data Value to add to result properties.
	 * @return array Added result properties.
	 */
	public function add_result_props( $data = '' ) {
		$data = wp_parse_args( $data, array() );

		$this->result_props = array_merge( $this->result_props, $data );

		return $data;
	}


	/**
	 * Retrieves the response property.
	 *
	 * @return string The current response property value.
	 */
	public function get_response() {
		return $this->response;
	}


	/**
	 * Sets the response property.
	 *
	 * @param string $response New response property value.
	 */
	public function set_response( $response ) {
		$this->response = $response;
		return true;
	}


	/**
	 * Retrieves the contact form property.
	 *
	 * @return WPCF7_ContactForm A contact form object.
	 */
	public function get_contact_form() {
		return $this->contact_form;
	}


	/**
	 * Search an invalid field by field name.
	 *
	 * @param string $name The field name.
	 * @return array|bool An associative array of validation error
	 *                    or false when no invalid field.
	 */
	public function get_invalid_field( $name ) {
		return $this->invalid_fields[$name] ?? false;
	}


	/**
	 * Retrieves all invalid fields.
	 *
	 * @return array Invalid fields.
	 */
	public function get_invalid_fields() {
		return $this->invalid_fields;
	}


	/**
	 * Retrieves meta information.
	 *
	 * @param string $name Name of the meta information.
	 * @return string|null The meta information of the given name if it exists,
	 *                     null otherwise.
	 */
	public function get_meta( $name ) {
		return $this->meta[$name] ?? null;
	}


	/**
	 * Collects meta information about this submission.
	 */
	private function setup_meta_data() {
		$this->meta = array(
			'timestamp' => time(),
			'remote_ip' => $this->get_remote_ip_addr(),
			'remote_port' => $_SERVER['REMOTE_PORT'] ?? '',
			'user_agent' => substr( $_SERVER['HTTP_USER_AGENT'] ?? '', 0, 254 ),
			'url' => $this->get_request_url(),
			'unit_tag' => wpcf7_sanitize_unit_tag( $_POST['_wpcf7_unit_tag'] ?? '' ),
			'container_post_id' => absint( $_POST['_wpcf7_container_post'] ?? 0 ),
			'current_user_id' => get_current_user_id(),
			'do_not_store' => $this->contact_form->is_true( 'do_not_store' ),
		);

		return $this->meta;
	}


	/**
	 * Retrieves user input data through this submission.
	 *
	 * @param string $name Optional field name.
	 * @return string|array|null The user input of the field, or array of all
	 *                           fields values if no field name specified.
	 */
	public function get_posted_data( $name = '' ) {
		if ( ! empty( $name ) ) {
			return $this->posted_data[$name] ?? null;
		}

		return $this->posted_data;
	}


	/**
	 * Retrieves a user input string value through the specified field.
	 *
	 * @param string $name Field name.
	 * @return string The user input. If the input is an array,
	 *                the first item in the array.
	 */
	public function get_posted_string( $name ) {
		$data = $this->get_posted_data( $name );
		$data = wpcf7_array_flatten( $data );

		if ( empty( $data ) ) {
			return '';
		}

		// Returns the first array item.
		return trim( reset( $data ) );
	}


	/**
	 * Constructs posted data property based on user input values.
	 */
	private function setup_posted_data() {
		$posted_data = array_filter(
			(array) $_POST,
			static function ( $key ) {
				return ! str_starts_with( $key, '_' );
			},
			ARRAY_FILTER_USE_KEY
		);

		$posted_data = wp_unslash( $posted_data );
		$posted_data = $this->sanitize_posted_data( $posted_data );

		$tags = $this->contact_form->scan_form_tags( array(
			'feature' => array(
				'name-attr',
				'! not-for-mail',
			),
		) );

		$tags = array_reduce( $tags, static function ( $carry, $tag ) {
			if ( $tag->name and ! isset( $carry[$tag->name] ) ) {
				$carry[$tag->name] = $tag;
			}

			return $carry;
		}, array() );

		foreach ( $tags as $tag ) {
			$value_orig = $value = $posted_data[$tag->name] ?? '';

			if ( wpcf7_form_tag_supports( $tag->type, 'selectable-values' ) ) {
				$value = ( '' === $value ) ? array() : (array) $value;

				if ( WPCF7_USE_PIPE ) {
					$pipes = $this->contact_form->get_pipes( $tag->name );

					$value = array_map( static function ( $value ) use ( $pipes ) {
						return $pipes->do_pipe( $value );
					}, $value );
				}
			}

			$value = apply_filters( "wpcf7_posted_data_{$tag->type}",
				$value,
				$value_orig,
				$tag
			);

			$posted_data[$tag->name] = $value;

			if ( $tag->has_option( 'consent_for:storage' ) and empty( $value ) ) {
				$this->meta['do_not_store'] = true;
			}
		}

		$this->posted_data = apply_filters( 'wpcf7_posted_data', $posted_data );

		$this->posted_data_hash = $this->create_posted_data_hash();

		return $this->posted_data;
	}


	/**
	 * Sanitizes user input data.
	 */
	private function sanitize_posted_data( $value ) {
		if ( is_array( $value ) ) {
			$value = array_map( array( $this, 'sanitize_posted_data' ), $value );
		} elseif ( is_string( $value ) ) {
			$value = wp_check_invalid_utf8( $value );
			$value = wp_kses_no_null( $value );
			$value = wpcf7_strip_whitespaces( $value );
		}

		return $value;
	}


	/**
	 * Returns the time-dependent variable for hash creation.
	 *
	 * @return float Float value rounded up to the next highest integer.
	 */
	private function posted_data_hash_tick() {
		return ceil( time() / ( HOUR_IN_SECONDS / 2 ) );
	}


	/**
	 * Creates a hash string based on posted data, the remote IP address,
	 * contact form location, and window of time.
	 *
	 * @param string $tick Optional. If not specified, result of
	 *               posted_data_hash_tick() will be used.
	 * @return string The hash.
	 */
	private function create_posted_data_hash( $tick = '' ) {
		if ( '' === $tick ) {
			$tick = $this->posted_data_hash_tick();
		}

		$hash = wp_hash(
			wpcf7_flat_join( array_merge(
				array(
					$tick,
					$this->get_meta( 'remote_ip' ),
					$this->get_meta( 'unit_tag' ),
				),
				$this->posted_data
			) ),
			'wpcf7_submission'
		);

		return $hash;
	}


	/**
	 * Returns the hash string created for this submission.
	 *
	 * @return string The current hash for the submission.
	 */
	public function get_posted_data_hash() {
		return $this->posted_data_hash;
	}


	/**
	 * Verifies that the given string is equivalent to the posted data hash.
	 *
	 * @param string $hash Optional. This value will be compared to the
	 *               current posted data hash for the submission. If not
	 *               specified, the value of $_POST['_wpcf7_posted_data_hash']
	 *               will be used.
	 * @return int|bool 1 if $hash is created 0-30 minutes ago,
	 *                  2 if $hash is created 30-60 minutes ago,
	 *                  false if $hash is invalid.
	 */
	public function verify_posted_data_hash( $hash = '' ) {
		if ( '' === $hash and ! empty( $_POST['_wpcf7_posted_data_hash'] ) ) {
			$hash = trim( $_POST['_wpcf7_posted_data_hash'] );
		}

		if ( '' === $hash ) {
			return false;
		}

		$tick = $this->posted_data_hash_tick();

		// Hash created 0-30 minutes ago.
		$expected_1 = $this->create_posted_data_hash( $tick );

		if ( hash_equals( $expected_1, $hash ) ) {
			return 1;
		}

		// Hash created 30-60 minutes ago.
		$expected_2 = $this->create_posted_data_hash( $tick - 1 );

		if ( hash_equals( $expected_2, $hash ) ) {
			return 2;
		}

		return false;
	}


	/**
	 * Retrieves the remote IP address of this submission.
	 */
	private function get_remote_ip_addr() {
		$ip_addr = '';

		if ( isset( $_SERVER['REMOTE_ADDR'] )
		and WP_Http::is_ip_address( $_SERVER['REMOTE_ADDR'] ) ) {
			$ip_addr = $_SERVER['REMOTE_ADDR'];
		}

		return apply_filters( 'wpcf7_remote_ip_addr', $ip_addr );
	}


	/**
	 * Retrieves the request URL of this submission.
	 */
	private function get_request_url() {
		$home_url = untrailingslashit( home_url() );

		if ( self::is_restful() ) {
			$referer = trim( $_SERVER['HTTP_REFERER'] ?? '' );

			if ( $referer and str_starts_with( $referer, $home_url ) ) {
				return sanitize_url( $referer );
			}
		}

		$url = preg_replace( '%(?<!:|/)/.*$%', '', $home_url )
			. wpcf7_get_request_uri();

		return $url;
	}


	/**
	 * Runs user input validation.
	 *
	 * @return bool True if no invalid field is found.
	 */
	private function validate() {
		if ( $this->invalid_fields ) {
			return false;
		}

		$result = new WPCF7_Validation();

		$this->contact_form->validate_schema(
			array(
				'text' => true,
				'file' => false,
				'field' => array(),
			),
			$result
		);

		$tags = $this->contact_form->scan_form_tags( array(
		  'feature' => '! file-uploading',
		) );

		foreach ( $tags as $tag ) {
			$type = $tag->type;
			$result = apply_filters( "wpcf7_validate_{$type}", $result, $tag );
		}

		$result = apply_filters( 'wpcf7_validate', $result, $tags );

		$this->invalid_fields = $result->get_invalid_fields();

		return $result->is_valid();
	}


	/**
	 * Returns true if user consent is obtained.
	 */
	private function accepted() {
		return apply_filters( 'wpcf7_acceptance', true, $this );
	}


	/**
	 * Adds user consent data to this submission.
	 *
	 * @param string $name Field name.
	 * @param string $conditions Conditions of consent.
	 */
	public function add_consent( $name, $conditions ) {
		$this->consent[$name] = $conditions;
		return true;
	}


	/**
	 * Collects user consent data.
	 *
	 * @return array User consent data.
	 */
	public function collect_consent() {
		return (array) $this->consent;
	}


	/**
	 * Executes spam protections.
	 *
	 * @return bool True if spam captured.
	 */
	private function spam() {
		$spam = false;

		$skip_spam_check = apply_filters( 'wpcf7_skip_spam_check',
			$this->skip_spam_check,
			$this
		);

		if ( $skip_spam_check ) {
			return $spam;
		}

		if ( $this->contact_form->is_true( 'subscribers_only' )
		and current_user_can( 'wpcf7_submit', $this->contact_form->id() ) ) {
			return $spam;
		}

		$user_agent = (string) $this->get_meta( 'user_agent' );

		if ( strlen( $user_agent ) < 2 ) {
			$spam = true;

			$this->add_spam_log( array(
				'agent' => 'wpcf7',
				'reason' => __( "User-Agent string is unnaturally short.", 'contact-form-7' ),
			) );
		}

		if ( ! $this->verify_nonce() ) {
			$spam = true;

			$this->add_spam_log( array(
				'agent' => 'wpcf7',
				'reason' => __( "Submitted nonce is invalid.", 'contact-form-7' ),
			) );
		}

		return apply_filters( 'wpcf7_spam', $spam, $this );
	}


	/**
	 * Adds a spam log.
	 *
	 * @link https://contactform7.com/2019/05/31/why-is-this-message-marked-spam/
	 */
	public function add_spam_log( $data = '' ) {
		$data = wp_parse_args( $data, array(
			'agent' => '',
			'reason' => '',
		) );

		$this->spam_log[] = $data;
	}


	/**
	 * Retrieves the spam logging data.
	 *
	 * @return array Spam logging data.
	 */
	public function get_spam_log() {
		return $this->spam_log;
	}


	/**
	 * Verifies that a correct security nonce was used.
	 */
	private function verify_nonce() {
		if ( ! $this->contact_form->nonce_is_active() or ! is_user_logged_in() ) {
			return true;
		}

		$nonce = $_POST['_wpnonce'] ?? '';

		return wpcf7_verify_nonce( $nonce );
	}


	/**
	 * Function called just before sending email.
	 */
	private function before_send_mail() {
		$abort = false;

		do_action_ref_array( 'wpcf7_before_send_mail', array(
			$this->contact_form,
			&$abort,
			$this,
		) );

		return ! $abort;
	}


	/**
	 * Sends emails based on user input values and contact form email templates.
	 */
	private function mail() {
		$contact_form = $this->contact_form;

		$skip_mail = apply_filters( 'wpcf7_skip_mail',
			$this->skip_mail, $contact_form
		);

		if ( $skip_mail ) {
			return true;
		}

		$result = WPCF7_Mail::send( $contact_form->prop( 'mail' ), 'mail' );

		if ( $result ) {
			$additional_mail = array();

			if ( $mail_2 = $contact_form->prop( 'mail_2' )
			and $mail_2['active'] ) {
				$additional_mail['mail_2'] = $mail_2;
			}

			$additional_mail = apply_filters( 'wpcf7_additional_mail',
				$additional_mail, $contact_form
			);

			foreach ( $additional_mail as $name => $template ) {
				WPCF7_Mail::send( $template, $name );
			}

			return true;
		}

		return false;
	}


	/**
	 * Retrieves files uploaded through this submission.
	 */
	public function uploaded_files() {
		return $this->uploaded_files;
	}


	/**
	 * Adds a file to the uploaded files array.
	 *
	 * @param string $name Field name.
	 * @param string|array $file_path File path or array of file paths.
	 */
	private function add_uploaded_file( $name, $file_path ) {
		if ( ! wpcf7_is_name( $name ) ) {
			return false;
		}

		$paths = (array) $file_path;
		$uploaded_files = array();
		$hash_strings = array();

		foreach ( $paths as $path ) {
			if ( @is_file( $path ) and @is_readable( $path ) ) {
				$uploaded_files[] = $path;
				$hash_strings[] = md5_file( $path );
			}
		}

		$this->uploaded_files[$name] = $uploaded_files;

		if ( empty( $this->posted_data[$name] ) ) {
			$this->posted_data[$name] = implode( ' ', $hash_strings );
		}
	}


	/**
	 * Removes uploaded files.
	 */
	private function remove_uploaded_files() {
		foreach ( (array) $this->uploaded_files as $file_path ) {
			$paths = (array) $file_path;

			foreach ( $paths as $path ) {
				wpcf7_rmdir_p( $path );

				if ( $dir = dirname( $path )
				and false !== ( $files = scandir( $dir ) )
				and ! array_diff( $files, array( '.', '..' ) ) ) {
					// remove parent dir if it's empty.
					rmdir( $dir );
				}
			}
		}
	}


	/**
	 * Moves uploaded files to the tmp directory and validates them.
	 *
	 * @return bool True if no invalid file is found.
	 */
	private function unship_uploaded_files() {
		$result = new WPCF7_Validation();

		$tags = $this->contact_form->scan_form_tags( array(
			'feature' => 'file-uploading',
		) );

		foreach ( $tags as $tag ) {
			if ( empty( $_FILES[$tag->name] ) ) {
				continue;
			}

			$file = $_FILES[$tag->name];

			$options = array(
				'tag' => $tag,
				'name' => $tag->name,
				'required' => $tag->is_required(),
				'filetypes' => $tag->get_option( 'filetypes' ),
				'limit' => $tag->get_limit_option(),
				'schema' => $this->contact_form->get_schema(),
			);

			$new_files = wpcf7_unship_uploaded_file( $file, $options );

			if ( is_wp_error( $new_files ) ) {
				$result->invalidate( $tag, $new_files );
			} else {
				$this->add_uploaded_file( $tag->name, $new_files );
			}

			$result = apply_filters(
				"wpcf7_validate_{$tag->type}",
				$result, $tag,
				array(
					'uploaded_files' => $new_files,
				)
			);
		}

		$this->invalid_fields = $result->get_invalid_fields();

		return $result->is_valid();
	}


	/**
	 * Adds extra email attachment files that are independent from form fields.
	 *
	 * @param string|array $file_path A file path or an array of file paths.
	 * @param string $template Optional. The name of the template to which
	 *                         the files are attached.
	 * @return bool True if it succeeds to attach a file at least,
	 *              or false otherwise.
	 */
	public function add_extra_attachments( $file_path, $template = 'mail' ) {
		if ( ! did_action( 'wpcf7_before_send_mail' ) ) {
			return false;
		}

		$extra_attachments = array();

		foreach ( (array) $file_path as $path ) {
			$path = path_join( WP_CONTENT_DIR, $path );

			if ( file_exists( $path ) ) {
				$extra_attachments[] = $path;
			}
		}

		if ( empty( $extra_attachments ) ) {
			return false;
		}

		if ( ! isset( $this->extra_attachments[$template] ) ) {
			$this->extra_attachments[$template] = array();
		}

		$this->extra_attachments[$template] = array_merge(
			$this->extra_attachments[$template],
			$extra_attachments
		);

		return true;
	}


	/**
	 * Returns extra email attachment files.
	 *
	 * @param string $template An email template name.
	 * @return array Array of file paths.
	 */
	public function extra_attachments( $template ) {
		if ( isset( $this->extra_attachments[$template] ) ) {
			return (array) $this->extra_attachments[$template];
		}

		return array();
	}

}
includes/integration.php000064400000021373147510545420011423 0ustar00<?php
/**
 * Integration API
 *
 * @link https://contactform7.com/integration-with-external-apis/
 */

class WPCF7_Integration {

	private static $instance;

	private $services = array();
	private $categories = array();

	private function __construct() {}


	/**
	 * Returns initially supported service categories.
	 *
	 * @return array Service categories.
	 */
	public static function get_builtin_categories() {
		return array(
			'spam_protection' => __( 'Spam protection', 'contact-form-7' ),
			'email_marketing' => __( 'Email marketing', 'contact-form-7' ),
			'payments' => __( 'Payments', 'contact-form-7' ),
		);
	}


	/**
	 * Returns the singleton instance of this class.
	 *
	 * @return WPCF7_Integration The instance.
	 */
	public static function get_instance() {
		if ( empty( self::$instance ) ) {
			self::$instance = new self;
			self::$instance->categories = self::get_builtin_categories();
		}

		return self::$instance;
	}


	/**
	 * Adds a service to the services list.
	 */
	public function add_service( $name, WPCF7_Service $service ) {
		$name = sanitize_key( $name );

		if ( empty( $name )
		or isset( $this->services[$name] ) ) {
			return false;
		}

		$this->services[$name] = $service;
	}


	/**
	 * Adds a service category to the categories list.
	 */
	public function add_category( $name, $title ) {
		$name = sanitize_key( $name );

		if ( empty( $name )
		or isset( $this->categories[$name] ) ) {
			return false;
		}

		$this->categories[$name] = $title;
	}


	/**
	 * Returns true if a service with the name exists in the services list.
	 *
	 * @param string $name The name of service to search.
	 */
	public function service_exists( $name = '' ) {
		if ( '' == $name ) {
			return (bool) count( $this->services );
		} else {
			return isset( $this->services[$name] );
		}
	}


	/**
	 * Returns a service object with the name.
	 *
	 * @param string $name The name of service.
	 * @return WPCF7_Service|bool The service object if it exists,
	 *                            false otherwise.
	 */
	public function get_service( $name ) {
		if ( $this->service_exists( $name ) ) {
			return $this->services[$name];
		} else {
			return false;
		}
	}


	/**
	 * Prints services list.
	 */
	public function list_services( $args = '' ) {
		$args = wp_parse_args( $args, array(
			'include' => array(),
		) );

		$singular = false;
		$services = (array) $this->services;

		if ( ! empty( $args['include'] ) ) {
			$services = array_intersect_key( $services,
				array_flip( (array) $args['include'] )
			);

			if ( 1 == count( $services ) ) {
				$singular = true;
			}
		}

		if ( empty( $services ) ) {
			return;
		}

		$action = wpcf7_current_action();

		foreach ( $services as $name => $service ) {
			$cats = array_intersect_key( $this->categories,
				array_flip( $service->get_categories() )
			);
?>
<div class="card<?php echo $service->is_active() ? ' active' : ''; ?>" id="<?php echo esc_attr( $name ); ?>">
<?php $service->icon(); ?>
<h2 class="title"><?php echo esc_html( $service->get_title() ); ?></h2>
<div class="infobox">
<?php echo esc_html( implode( ', ', $cats ) ); ?>
<br />
<?php $service->link(); ?>
</div>
<br class="clear" />

<div class="inside">
<?php
			if ( $singular ) {
				$service->display( $action );
			} else {
				$service->display();
			}
?>
</div>
</div>
<?php
		}
	}

}


/**
 * Abstract class for services.
 *
 * Only instances of this class's subclasses are allowed to be
 * listed on the Integration page.
 */
abstract class WPCF7_Service {

	abstract public function get_title();
	abstract public function is_active();


	public function get_categories() {
		return array();
	}


	public function icon() {
		return '';
	}


	public function link() {
		return '';
	}


	public function load( $action = '' ) {
	}


	public function display( $action = '' ) {
	}


	public function admin_notice( $message = '' ) {
	}

}


/**
 * Class for services that use OAuth.
 *
 * While this is not an abstract class, subclassing this class for
 * your aim is advised.
 */
class WPCF7_Service_OAuth2 extends WPCF7_Service {

	protected $client_id = '';
	protected $client_secret = '';
	protected $access_token = '';
	protected $refresh_token = '';
	protected $authorization_endpoint = 'https://example.com/authorization';
	protected $token_endpoint = 'https://example.com/token';


	public function get_title() {
		return '';
	}


	public function is_active() {
		return ! empty( $this->refresh_token );
	}


	protected function save_data() {
	}


	protected function reset_data() {
	}


	protected function get_redirect_uri() {
		return admin_url();
	}


	protected function menu_page_url( $args = '' ) {
		return menu_page_url( 'wpcf7-integration', false );
	}


	public function load( $action = '' ) {
		if ( 'auth_redirect' === $action ) {
			$code = $_GET['code'] ?? '';

			if ( $code ) {
				$this->request_token( $code );
			}

			if ( ! empty( $this->access_token ) ) {
				$message = 'success';
			} else {
				$message = 'failed';
			}

			wp_safe_redirect( $this->menu_page_url(
				array(
					'action' => 'setup',
					'message' => $message,
				)
			) );

			exit();
		}
	}


	protected function authorize( $scope = '' ) {
		$endpoint = add_query_arg(
			array(
				'response_type' => 'code',
				'client_id' => $this->client_id,
				'redirect_uri' => urlencode( $this->get_redirect_uri() ),
				'scope' => $scope,
			),
			$this->authorization_endpoint
		);

		if ( wp_redirect( sanitize_url( $endpoint ) ) ) {
			exit();
		}
	}


	protected function get_http_authorization_header( $scheme = 'basic' ) {
		$scheme = strtolower( trim( $scheme ) );

		switch ( $scheme ) {
			case 'bearer':
				return sprintf( 'Bearer %s', $this->access_token );
			case 'basic':
			default:
				return sprintf( 'Basic %s',
					base64_encode( $this->client_id . ':' . $this->client_secret )
				);
		}
	}


	protected function request_token( $authorization_code ) {
		$endpoint = add_query_arg(
			array(
				'code' => $authorization_code,
				'redirect_uri' => urlencode( $this->get_redirect_uri() ),
				'grant_type' => 'authorization_code',
			),
			$this->token_endpoint
		);

		$request = array(
			'headers' => array(
				'Authorization' => $this->get_http_authorization_header( 'basic' ),
			),
		);

		$response = wp_remote_post( sanitize_url( $endpoint ), $request );
		$response_code = (int) wp_remote_retrieve_response_code( $response );
		$response_body = wp_remote_retrieve_body( $response );
		$response_body = json_decode( $response_body, true );

		if ( WP_DEBUG and 400 <= $response_code ) {
			$this->log( $endpoint, $request, $response );
		}

		if ( 401 == $response_code ) { // Unauthorized
			$this->access_token = null;
			$this->refresh_token = null;
		} else {
			if ( isset( $response_body['access_token'] ) ) {
				$this->access_token = $response_body['access_token'];
			} else {
				$this->access_token = null;
			}

			if ( isset( $response_body['refresh_token'] ) ) {
				$this->refresh_token = $response_body['refresh_token'];
			} else {
				$this->refresh_token = null;
			}
		}

		$this->save_data();

		return $response;
	}


	protected function refresh_token() {
		$endpoint = add_query_arg(
			array(
				'refresh_token' => $this->refresh_token,
				'grant_type' => 'refresh_token',
			),
			$this->token_endpoint
		);

		$request = array(
			'headers' => array(
				'Authorization' => $this->get_http_authorization_header( 'basic' ),
			),
		);

		$response = wp_remote_post( sanitize_url( $endpoint ), $request );
		$response_code = (int) wp_remote_retrieve_response_code( $response );
		$response_body = wp_remote_retrieve_body( $response );
		$response_body = json_decode( $response_body, true );

		if ( WP_DEBUG and 400 <= $response_code ) {
			$this->log( $endpoint, $request, $response );
		}

		if ( 401 == $response_code ) { // Unauthorized
			$this->access_token = null;
			$this->refresh_token = null;
		} else {
			if ( isset( $response_body['access_token'] ) ) {
				$this->access_token = $response_body['access_token'];
			} else {
				$this->access_token = null;
			}

			if ( isset( $response_body['refresh_token'] ) ) {
				$this->refresh_token = $response_body['refresh_token'];
			}
		}

		$this->save_data();

		return $response;
	}


	protected function remote_request( $url, $request = array() ) {
		static $refreshed = false;

		$request = wp_parse_args( $request, array() );

		$request['headers'] = array_merge(
			$request['headers'],
			array(
				'Authorization' => $this->get_http_authorization_header( 'bearer' ),
			)
		);

		$response = wp_remote_request( sanitize_url( $url ), $request );

		if ( 401 === wp_remote_retrieve_response_code( $response )
		and ! $refreshed ) {
			$this->refresh_token();
			$refreshed = true;

			$response = $this->remote_request( $url, $request );
		}

		return $response;
	}


	protected function log( $url, $request, $response ) {
		wpcf7_log_remote_request( $url, $request, $response );
	}

}
includes/swv/schema-holder.php000064400000001726147510545420012432 0ustar00<?php

trait WPCF7_SWV_SchemaHolder {

	protected $schema;


	/**
	 * Retrieves SWV schema for this holder object (contact form).
	 *
	 * @return WPCF7_SWV_Schema The schema object.
	 */
	public function get_schema() {
		if ( isset( $this->schema ) ) {
			return $this->schema;
		}

		$schema = new WPCF7_SWV_Schema( array(
			'locale' => isset( $this->locale ) ? $this->locale : '',
		) );

		do_action( 'wpcf7_swv_create_schema', $schema, $this );

		return $this->schema = $schema;
	}


	/**
	 * Validates form inputs based on the schema and given context.
	 */
	public function validate_schema( $context, WPCF7_Validation $validity ) {
		$schema = $this->get_schema();

		foreach ( $schema->validate( $context ) as $result ) {
			if ( is_wp_error( $result ) ) {
				$rule = $result->get_error_data();
				$field = $rule->get_property( 'field' );

				if ( isset( $field ) and $validity->is_valid( $field ) ) {
					$validity->invalidate( $field, $result );
				}
			}
		}
	}

}
includes/swv/php/rules/file.php000064400000002437147510545420012557 0ustar00<?php

namespace Contactable\SWV;

class FileRule extends Rule {

	const rule_name = 'file';

	public function matches( $context ) {
		if ( false === parent::matches( $context ) ) {
			return false;
		}

		if ( empty( $context['file'] ) ) {
			return false;
		}

		return true;
	}

	public function validate( $context ) {
		$field = $this->get_property( 'field' );
		$input = $_FILES[$field]['name'] ?? '';
		$input = wpcf7_array_flatten( $input );
		$input = wpcf7_exclude_blank( $input );

		$acceptable_filetypes = array();

		foreach ( (array) $this->get_property( 'accept' ) as $accept ) {
			if ( preg_match( '/^\.[a-z0-9]+$/i', $accept ) ) {
				$acceptable_filetypes[] = strtolower( $accept );
			} else {
				foreach ( wpcf7_convert_mime_to_ext( $accept ) as $ext ) {
					$acceptable_filetypes[] = sprintf(
						'.%s',
						strtolower( trim( $ext, ' .' ) )
					);
				}
			}
		}

		$acceptable_filetypes = array_unique( $acceptable_filetypes );

		foreach ( $input as $i ) {
			$last_period_pos = strrpos( $i, '.' );

			if ( false === $last_period_pos ) { // no period
				return $this->create_error();
			}

			$suffix = strtolower( substr( $i, $last_period_pos ) );

			if ( ! in_array( $suffix, $acceptable_filetypes, true ) ) {
				return $this->create_error();
			}
		}

		return true;
	}

}
includes/swv/php/rules/maxlength.php000064400000001442147510545420013622 0ustar00<?php

namespace Contactable\SWV;

class MaxLengthRule extends Rule {

	const rule_name = 'maxlength';

	public function matches( $context ) {
		if ( false === parent::matches( $context ) ) {
			return false;
		}

		if ( empty( $context['text'] ) ) {
			return false;
		}

		return true;
	}

	public function validate( $context ) {
		$input = $this->get_default_input();
		$input = wpcf7_array_flatten( $input );
		$input = wpcf7_strip_whitespaces( $input );
		$input = wpcf7_exclude_blank( $input );

		if ( empty( $input ) ) {
			return true;
		}

		$total = 0;

		foreach ( $input as $i ) {
			$total += wpcf7_count_code_units( $i );
		}

		$threshold = (int) $this->get_property( 'threshold' );

		if ( $total <= $threshold ) {
			return true;
		} else {
			return $this->create_error();
		}
	}

}
includes/swv/php/rules/minfilesize.php000064400000001305147510545420014147 0ustar00<?php

namespace Contactable\SWV;

class MinFileSizeRule extends Rule {

	const rule_name = 'minfilesize';

	public function matches( $context ) {
		if ( false === parent::matches( $context ) ) {
			return false;
		}

		if ( empty( $context['file'] ) ) {
			return false;
		}

		return true;
	}

	public function validate( $context ) {
		$field = $this->get_property( 'field' );
		$input = $_FILES[$field]['size'] ?? '';
		$input = wpcf7_array_flatten( $input );
		$input = wpcf7_exclude_blank( $input );

		if ( empty( $input ) ) {
			return true;
		}

		$threshold = $this->get_property( 'threshold' );

		if ( array_sum( $input ) < $threshold ) {
			return $this->create_error();
		}

		return true;
	}

}
includes/swv/php/rules/minlength.php000064400000001442147510545420013620 0ustar00<?php

namespace Contactable\SWV;

class MinLengthRule extends Rule {

	const rule_name = 'minlength';

	public function matches( $context ) {
		if ( false === parent::matches( $context ) ) {
			return false;
		}

		if ( empty( $context['text'] ) ) {
			return false;
		}

		return true;
	}

	public function validate( $context ) {
		$input = $this->get_default_input();
		$input = wpcf7_array_flatten( $input );
		$input = wpcf7_strip_whitespaces( $input );
		$input = wpcf7_exclude_blank( $input );

		if ( empty( $input ) ) {
			return true;
		}

		$total = 0;

		foreach ( $input as $i ) {
			$total += wpcf7_count_code_units( $i );
		}

		$threshold = (int) $this->get_property( 'threshold' );

		if ( $threshold <= $total ) {
			return true;
		} else {
			return $this->create_error();
		}
	}

}
includes/swv/php/rules/stepnumber.php000064400000001671147510545420014023 0ustar00<?php

namespace Contactable\SWV;

class StepNumberRule extends Rule {

	const rule_name = 'stepnumber';

	public function matches( $context ) {
		if ( false === parent::matches( $context ) ) {
			return false;
		}

		if ( empty( $context['text'] ) ) {
			return false;
		}

		return true;
	}

	public function validate( $context ) {
		$input = $this->get_default_input();
		$input = wpcf7_array_flatten( $input );
		$input = wpcf7_strip_whitespaces( $input );
		$input = wpcf7_exclude_blank( $input );

		$base = floatval( $this->get_property( 'base' ) );
		$interval = floatval( $this->get_property( 'interval' ) );

		if ( ! ( 0 < $interval ) ) {
			return true;
		}

		foreach ( $input as $i ) {
			$remainder = fmod( floatval( $i ) - $base, $interval );

			if (
				0.0 === round( abs( $remainder ), 6 ) or
				0.0 === round( abs( $remainder - $interval ), 6 )
			) {
				continue;
			}

			return $this->create_error();
		}

		return true;
	}

}
includes/swv/php/rules/minitems.php000064400000001321147510545420013454 0ustar00<?php

namespace Contactable\SWV;

class MinItemsRule extends Rule {

	const rule_name = 'minitems';

	public function matches( $context ) {
		if ( false === parent::matches( $context ) ) {
			return false;
		}

		if ( empty( $context['text'] ) ) {
			return false;
		}

		return true;
	}

	public function validate( $context ) {
		$input = $this->get_default_input();
		$input = wpcf7_array_flatten( $input );
		$input = wpcf7_strip_whitespaces( $input );
		$input = wpcf7_exclude_blank( $input );

		$threshold = $this->get_property( 'threshold' );

		if ( ! wpcf7_is_number( $threshold ) ) {
			return true;
		}

		if ( count( $input ) < (int) $threshold ) {
			return $this->create_error();
		}

		return true;
	}

}
includes/swv/php/rules/required.php000064400000001112147510545420013445 0ustar00<?php

namespace Contactable\SWV;

class RequiredRule extends Rule {

	const rule_name = 'required';

	public function matches( $context ) {
		if ( false === parent::matches( $context ) ) {
			return false;
		}

		if ( empty( $context['text'] ) ) {
			return false;
		}

		return true;
	}

	public function validate( $context ) {
		$input = $this->get_default_input();
		$input = wpcf7_array_flatten( $input );
		$input = wpcf7_strip_whitespaces( $input );
		$input = wpcf7_exclude_blank( $input );

		if ( empty( $input ) ) {
			return $this->create_error();
		}

		return true;
	}

}
includes/swv/php/rules/all.php000064400000001114147510545420012377 0ustar00<?php

namespace Contactable\SWV;

class AllRule extends CompositeRule {

	const rule_name = 'all';

	public function matches( $context ) {
		if ( false === parent::matches( $context ) ) {
			return false;
		}

		return true;
	}

	public function validate( $context ) {
		foreach ( $this->rules() as $rule ) {
			if ( $rule->matches( $context ) ) {
				$result = $rule->validate( $context );

				if ( is_wp_error( $result ) ) {
					if ( $result->get_error_message() ) {
						return $result;
					} else {
						return $this->create_error();
					}
				}
			}
		}

		return true;
	}

}
includes/swv/php/rules/mindate.php000064400000001366147510545420013261 0ustar00<?php

namespace Contactable\SWV;

class MinDateRule extends Rule {

	const rule_name = 'mindate';

	public function matches( $context ) {
		if ( false === parent::matches( $context ) ) {
			return false;
		}

		if ( empty( $context['text'] ) ) {
			return false;
		}

		return true;
	}

	public function validate( $context ) {
		$input = $this->get_default_input();
		$input = wpcf7_array_flatten( $input );
		$input = wpcf7_strip_whitespaces( $input );
		$input = wpcf7_exclude_blank( $input );

		$threshold = $this->get_property( 'threshold' );

		if ( ! wpcf7_is_date( $threshold ) ) {
			return true;
		}

		foreach ( $input as $i ) {
			if ( wpcf7_is_date( $i ) and $i < $threshold ) {
				return $this->create_error();
			}
		}

		return true;
	}

}
includes/swv/php/rules/maxitems.php000064400000001321147510545420013456 0ustar00<?php

namespace Contactable\SWV;

class MaxItemsRule extends Rule {

	const rule_name = 'maxitems';

	public function matches( $context ) {
		if ( false === parent::matches( $context ) ) {
			return false;
		}

		if ( empty( $context['text'] ) ) {
			return false;
		}

		return true;
	}

	public function validate( $context ) {
		$input = $this->get_default_input();
		$input = wpcf7_array_flatten( $input );
		$input = wpcf7_strip_whitespaces( $input );
		$input = wpcf7_exclude_blank( $input );

		$threshold = $this->get_property( 'threshold' );

		if ( ! wpcf7_is_number( $threshold ) ) {
			return true;
		}

		if ( (int) $threshold < count( $input ) ) {
			return $this->create_error();
		}

		return true;
	}

}
includes/swv/php/rules/enum.php000064400000002132147510545420012574 0ustar00<?php

namespace Contactable\SWV;

class EnumRule extends Rule {

	const rule_name = 'enum';

	public function matches( $context ) {
		if ( false === parent::matches( $context ) ) {
			return false;
		}

		if ( empty( $context['text'] ) ) {
			return false;
		}

		return true;
	}

	public function validate( $context ) {
		$input = $this->get_default_input();
		$input = wpcf7_array_flatten( $input );
		$input = wpcf7_strip_whitespaces( $input );
		$input = wpcf7_exclude_blank( $input );

		$acceptable_values = (array) $this->get_property( 'accept' );

		$acceptable_values = array_map(
			static function ( $val ) {
				$val = strval( $val );
				$val = wpcf7_normalize_newline( $val );
				return $val;
			},
			$acceptable_values
		);

		$acceptable_values = array_unique( $acceptable_values );

		$acceptable_values = array_filter( $acceptable_values,
			static function ( $val ) {
				return '' !== $val;
			}
		);

		foreach ( $input as $i ) {
			$i = wpcf7_normalize_newline( $i );

			if ( ! in_array( $i, $acceptable_values, true ) ) {
				return $this->create_error();
			}
		}

		return true;
	}

}
includes/swv/php/rules/tel.php000064400000001151147510545420012414 0ustar00<?php

namespace Contactable\SWV;

class TelRule extends Rule {

	const rule_name = 'tel';

	public function matches( $context ) {
		if ( false === parent::matches( $context ) ) {
			return false;
		}

		if ( empty( $context['text'] ) ) {
			return false;
		}

		return true;
	}

	public function validate( $context ) {
		$input = $this->get_default_input();
		$input = wpcf7_array_flatten( $input );
		$input = wpcf7_strip_whitespaces( $input );
		$input = wpcf7_exclude_blank( $input );

		foreach ( $input as $i ) {
			if ( ! wpcf7_is_tel( $i ) ) {
				return $this->create_error();
			}
		}

		return true;
	}

}
includes/swv/php/rules/dayofweek.php000064400000002026147510545420013610 0ustar00<?php

namespace Contactable\SWV;

class DayofweekRule extends Rule {

	const rule_name = 'dayofweek';

	public function matches( $context ) {
		if ( false === parent::matches( $context ) ) {
			return false;
		}

		if ( empty( $context['text'] ) ) {
			return false;
		}

		return true;
	}

	public function validate( $context ) {
		$input = $this->get_default_input();
		$input = wpcf7_array_flatten( $input );
		$input = wpcf7_strip_whitespaces( $input );
		$input = wpcf7_exclude_blank( $input );

		$acceptable_values = (array) $this->get_property( 'accept' );
		$acceptable_values = array_map( 'intval', $acceptable_values );
		$acceptable_values = array_filter( $acceptable_values );
		$acceptable_values = array_unique( $acceptable_values );

		foreach ( $input as $i ) {
			if ( wpcf7_is_date( $i ) ) {
				$datetime = date_create_immutable( $i, wp_timezone() );
				$dow = (int) $datetime->format( 'N' );

				if ( ! in_array( $dow, $acceptable_values, true ) ) {
					return $this->create_error();
				}
			}
		}

		return true;
	}

}
includes/swv/php/rules/requiredfile.php000064400000001126147510545420014312 0ustar00<?php

namespace Contactable\SWV;

class RequiredFileRule extends Rule {

	const rule_name = 'requiredfile';

	public function matches( $context ) {
		if ( false === parent::matches( $context ) ) {
			return false;
		}

		if ( empty( $context['file'] ) ) {
			return false;
		}

		return true;
	}

	public function validate( $context ) {
		$field = $this->get_property( 'field' );
		$input = $_FILES[$field]['tmp_name'] ?? '';
		$input = wpcf7_array_flatten( $input );
		$input = wpcf7_exclude_blank( $input );

		if ( empty( $input ) ) {
			return $this->create_error();
		}

		return true;
	}

}
includes/swv/php/rules/maxnumber.php000064400000001416147510545420013632 0ustar00<?php

namespace Contactable\SWV;

class MaxNumberRule extends Rule {

	const rule_name = 'maxnumber';

	public function matches( $context ) {
		if ( false === parent::matches( $context ) ) {
			return false;
		}

		if ( empty( $context['text'] ) ) {
			return false;
		}

		return true;
	}

	public function validate( $context ) {
		$input = $this->get_default_input();
		$input = wpcf7_array_flatten( $input );
		$input = wpcf7_strip_whitespaces( $input );
		$input = wpcf7_exclude_blank( $input );

		$threshold = $this->get_property( 'threshold' );

		if ( ! wpcf7_is_number( $threshold ) ) {
			return true;
		}

		foreach ( $input as $i ) {
			if ( wpcf7_is_number( $i ) and (float) $threshold < (float) $i ) {
				return $this->create_error();
			}
		}

		return true;
	}

}
includes/swv/php/rules/url.php000064400000001151147510545420012432 0ustar00<?php

namespace Contactable\SWV;

class URLRule extends Rule {

	const rule_name = 'url';

	public function matches( $context ) {
		if ( false === parent::matches( $context ) ) {
			return false;
		}

		if ( empty( $context['text'] ) ) {
			return false;
		}

		return true;
	}

	public function validate( $context ) {
		$input = $this->get_default_input();
		$input = wpcf7_array_flatten( $input );
		$input = wpcf7_strip_whitespaces( $input );
		$input = wpcf7_exclude_blank( $input );

		foreach ( $input as $i ) {
			if ( ! wpcf7_is_url( $i ) ) {
				return $this->create_error();
			}
		}

		return true;
	}

}
includes/swv/php/rules/minnumber.php000064400000001416147510545420013630 0ustar00<?php

namespace Contactable\SWV;

class MinNumberRule extends Rule {

	const rule_name = 'minnumber';

	public function matches( $context ) {
		if ( false === parent::matches( $context ) ) {
			return false;
		}

		if ( empty( $context['text'] ) ) {
			return false;
		}

		return true;
	}

	public function validate( $context ) {
		$input = $this->get_default_input();
		$input = wpcf7_array_flatten( $input );
		$input = wpcf7_strip_whitespaces( $input );
		$input = wpcf7_exclude_blank( $input );

		$threshold = $this->get_property( 'threshold' );

		if ( ! wpcf7_is_number( $threshold ) ) {
			return true;
		}

		foreach ( $input as $i ) {
			if ( wpcf7_is_number( $i ) and (float) $i < (float) $threshold ) {
				return $this->create_error();
			}
		}

		return true;
	}

}
includes/swv/php/rules/number.php000064400000001162147510545420013122 0ustar00<?php

namespace Contactable\SWV;

class NumberRule extends Rule {

	const rule_name = 'number';

	public function matches( $context ) {
		if ( false === parent::matches( $context ) ) {
			return false;
		}

		if ( empty( $context['text'] ) ) {
			return false;
		}

		return true;
	}

	public function validate( $context ) {
		$input = $this->get_default_input();
		$input = wpcf7_array_flatten( $input );
		$input = wpcf7_strip_whitespaces( $input );
		$input = wpcf7_exclude_blank( $input );

		foreach ( $input as $i ) {
			if ( ! wpcf7_is_number( $i ) ) {
				return $this->create_error();
			}
		}

		return true;
	}

}
includes/swv/php/rules/date.php000064400000001154147510545420012550 0ustar00<?php

namespace Contactable\SWV;

class DateRule extends Rule {

	const rule_name = 'date';

	public function matches( $context ) {
		if ( false === parent::matches( $context ) ) {
			return false;
		}

		if ( empty( $context['text'] ) ) {
			return false;
		}

		return true;
	}

	public function validate( $context ) {
		$input = $this->get_default_input();
		$input = wpcf7_array_flatten( $input );
		$input = wpcf7_strip_whitespaces( $input );
		$input = wpcf7_exclude_blank( $input );

		foreach ( $input as $i ) {
			if ( ! wpcf7_is_date( $i ) ) {
				return $this->create_error();
			}
		}

		return true;
	}

}
includes/swv/php/rules/maxdate.php000064400000001366147510545420013263 0ustar00<?php

namespace Contactable\SWV;

class MaxDateRule extends Rule {

	const rule_name = 'maxdate';

	public function matches( $context ) {
		if ( false === parent::matches( $context ) ) {
			return false;
		}

		if ( empty( $context['text'] ) ) {
			return false;
		}

		return true;
	}

	public function validate( $context ) {
		$input = $this->get_default_input();
		$input = wpcf7_array_flatten( $input );
		$input = wpcf7_strip_whitespaces( $input );
		$input = wpcf7_exclude_blank( $input );

		$threshold = $this->get_property( 'threshold' );

		if ( ! wpcf7_is_date( $threshold ) ) {
			return true;
		}

		foreach ( $input as $i ) {
			if ( wpcf7_is_date( $i ) and $threshold < $i ) {
				return $this->create_error();
			}
		}

		return true;
	}

}
includes/swv/php/rules/maxfilesize.php000064400000001305147510545420014151 0ustar00<?php

namespace Contactable\SWV;

class MaxFileSizeRule extends Rule {

	const rule_name = 'maxfilesize';

	public function matches( $context ) {
		if ( false === parent::matches( $context ) ) {
			return false;
		}

		if ( empty( $context['file'] ) ) {
			return false;
		}

		return true;
	}

	public function validate( $context ) {
		$field = $this->get_property( 'field' );
		$input = $_FILES[$field]['size'] ?? '';
		$input = wpcf7_array_flatten( $input );
		$input = wpcf7_exclude_blank( $input );

		if ( empty( $input ) ) {
			return true;
		}

		$threshold = $this->get_property( 'threshold' );

		if ( $threshold < array_sum( $input ) ) {
			return $this->create_error();
		}

		return true;
	}

}
includes/swv/php/rules/time.php000064400000001154147510545420012571 0ustar00<?php

namespace Contactable\SWV;

class TimeRule extends Rule {

	const rule_name = 'time';

	public function matches( $context ) {
		if ( false === parent::matches( $context ) ) {
			return false;
		}

		if ( empty( $context['text'] ) ) {
			return false;
		}

		return true;
	}

	public function validate( $context ) {
		$input = $this->get_default_input();
		$input = wpcf7_array_flatten( $input );
		$input = wpcf7_strip_whitespaces( $input );
		$input = wpcf7_exclude_blank( $input );

		foreach ( $input as $i ) {
			if ( ! wpcf7_is_time( $i ) ) {
				return $this->create_error();
			}
		}

		return true;
	}

}
includes/swv/php/rules/email.php000064400000001157147510545420012725 0ustar00<?php

namespace Contactable\SWV;

class EmailRule extends Rule {

	const rule_name = 'email';

	public function matches( $context ) {
		if ( false === parent::matches( $context ) ) {
			return false;
		}

		if ( empty( $context['text'] ) ) {
			return false;
		}

		return true;
	}

	public function validate( $context ) {
		$input = $this->get_default_input();
		$input = wpcf7_array_flatten( $input );
		$input = wpcf7_strip_whitespaces( $input );
		$input = wpcf7_exclude_blank( $input );

		foreach ( $input as $i ) {
			if ( ! wpcf7_is_email( $i ) ) {
				return $this->create_error();
			}
		}

		return true;
	}

}
includes/swv/php/rules/any.php000064400000000767147510545420012433 0ustar00<?php

namespace Contactable\SWV;

class AnyRule extends CompositeRule {

	const rule_name = 'any';

	public function matches( $context ) {
		if ( false === parent::matches( $context ) ) {
			return false;
		}

		return true;
	}

	public function validate( $context ) {
		foreach ( $this->rules() as $rule ) {
			if ( $rule->matches( $context ) ) {
				$result = $rule->validate( $context );

				if ( ! is_wp_error( $result ) ) {
					return true;
				}
			}
		}

		return $this->create_error();
	}

}
includes/swv/php/abstract-rules.php000064400000006407147510545420013442 0ustar00<?php

namespace Contactable\SWV;

use WP_Error;

/**
 * The base class of SWV rules.
 */
abstract class Rule {

	protected $properties = array();

	public function __construct( $properties = '' ) {
		$this->properties = wp_parse_args( $properties, array() );
	}


	/**
	 * Returns true if this rule matches the given context.
	 *
	 * @param array $context Context.
	 */
	public function matches( $context ) {
		$field = $this->get_property( 'field' );

		if ( ! empty( $context['field'] ) ) {
			if ( $field and ! in_array( $field, (array) $context['field'], true ) ) {
				return false;
			}
		}

		return true;
	}


	/**
	 * Validates with this rule's logic.
	 *
	 * @param array $context Context.
	 */
	public function validate( $context ) {
		return true;
	}


	/**
	 * Converts the properties to an array.
	 *
	 * @return array Array of properties.
	 */
	public function to_array() {
		$properties = (array) $this->properties;

		if ( defined( 'static::rule_name' ) and static::rule_name ) {
			$properties = array( 'rule' => static::rule_name ) + $properties;
		}

		return $properties;
	}


	/**
	 * Returns the property value specified by the given property name.
	 *
	 * @param string $name Property name.
	 * @return mixed Property value.
	 */
	public function get_property( $name ) {
		if ( isset( $this->properties[$name] ) ) {
			return $this->properties[$name];
		}
	}


	/**
	 * Returns the default user input value from $_POST.
	 *
	 * @return mixed Default user input value.
	 */
	public function get_default_input() {
		$field = $this->get_property( 'field' );

		if ( isset( $_POST[$field] ) ) {
			return wp_unslash( $_POST[$field] );
		}

		return '';
	}


	/**
	 * Creates an error object. Returns false if the error property is omitted.
	 */
	protected function create_error() {
		$error_code = defined( 'static::rule_name' )
			? sprintf( 'swv_%s', static::rule_name )
			: 'swv';

		return new WP_Error(
			$error_code,
			(string) $this->get_property( 'error' ),
			$this
		);
	}

}


/**
 * The base class of SWV composite rules.
 */
abstract class CompositeRule extends Rule {

	protected $rules = array();


	/**
	 * Adds a sub-rule to this composite rule.
	 *
	 * @param Rule $rule Sub-rule to be added.
	 */
	public function add_rule( $rule ) {
		if ( $rule instanceof Rule ) {
			$this->rules[] = $rule;
		}
	}


	/**
	 * Returns an iterator of sub-rules.
	 */
	public function rules() {
		foreach ( $this->rules as $rule ) {
			yield $rule;
		}
	}


	/**
	 * Returns true if this rule matches the given context.
	 *
	 * @param array $context Context.
	 */
	public function matches( $context ) {
		return true;
	}


	/**
	 * Validates with this rule's logic.
	 *
	 * @param array $context Context.
	 */
	public function validate( $context ) {
		foreach ( $this->rules() as $rule ) {
			if ( $rule->matches( $context ) ) {
				$result = $rule->validate( $context );

				if ( is_wp_error( $result ) ) {
					return $result;
				}
			}
		}

		return true;
	}


	/**
	 * Converts the properties to an array.
	 *
	 * @return array Array of properties.
	 */
	public function to_array() {
		$rules_arrays = array_map(
			static function ( $rule ) {
				return $rule->to_array();
			},
			$this->rules
		);

		return array_merge(
			parent::to_array(),
			array(
				'rules' => $rules_arrays,
			)
		);
	}

}
includes/swv/swv.php000064400000010224147510545420010527 0ustar00<?php
/**
 * Schema-Woven Validation API
 */

require_once WPCF7_PLUGIN_DIR . '/includes/swv/schema-holder.php';
require_once WPCF7_PLUGIN_DIR . '/includes/swv/script-loader.php';
require_once WPCF7_PLUGIN_DIR . '/includes/swv/php/abstract-rules.php';


/**
 * Returns an associative array of SWV rules.
 */
function wpcf7_swv_available_rules() {
	$rules = array(
		'required' => 'Contactable\SWV\RequiredRule',
		'requiredfile' => 'Contactable\SWV\RequiredFileRule',
		'email' => 'Contactable\SWV\EmailRule',
		'url' => 'Contactable\SWV\URLRule',
		'tel' => 'Contactable\SWV\TelRule',
		'number' => 'Contactable\SWV\NumberRule',
		'date' => 'Contactable\SWV\DateRule',
		'time' => 'Contactable\SWV\TimeRule',
		'file' => 'Contactable\SWV\FileRule',
		'enum' => 'Contactable\SWV\EnumRule',
		'dayofweek' => 'Contactable\SWV\DayofweekRule',
		'minitems' => 'Contactable\SWV\MinItemsRule',
		'maxitems' => 'Contactable\SWV\MaxItemsRule',
		'minlength' => 'Contactable\SWV\MinLengthRule',
		'maxlength' => 'Contactable\SWV\MaxLengthRule',
		'minnumber' => 'Contactable\SWV\MinNumberRule',
		'maxnumber' => 'Contactable\SWV\MaxNumberRule',
		'mindate' => 'Contactable\SWV\MinDateRule',
		'maxdate' => 'Contactable\SWV\MaxDateRule',
		'minfilesize' => 'Contactable\SWV\MinFileSizeRule',
		'maxfilesize' => 'Contactable\SWV\MaxFileSizeRule',
		'stepnumber' => 'Contactable\SWV\StepNumberRule',
		'all' => 'Contactable\SWV\AllRule',
		'any' => 'Contactable\SWV\AnyRule',
	);

	return apply_filters( 'wpcf7_swv_available_rules', $rules );
}


add_action( 'wpcf7_init', 'wpcf7_swv_load_rules', 10, 0 );

/**
 * Loads SWV fules.
 */
function wpcf7_swv_load_rules() {
	$rules = wpcf7_swv_available_rules();

	foreach ( array_keys( $rules ) as $rule ) {
		$file = sprintf( '%s.php', $rule );
		$path = path_join( WPCF7_PLUGIN_DIR . '/includes/swv/php/rules', $file );

		if ( file_exists( $path ) ) {
			include_once $path;
		}
	}
}


/**
 * Creates an SWV rule object.
 *
 * @param string $rule_name Rule name.
 * @param string|array $properties Optional. Rule properties.
 * @return \Contactable\SWV\Rule|null The rule object, or null if it failed.
 */
function wpcf7_swv_create_rule( $rule_name, $properties = '' ) {
	$rules = wpcf7_swv_available_rules();

	if ( isset( $rules[$rule_name] ) ) {
		return new $rules[$rule_name]( $properties );
	}
}


/**
 * Returns an associative array of JSON Schema for Contact Form 7 SWV.
 */
function wpcf7_swv_get_meta_schema() {
	return array(
		'$schema' => 'https://json-schema.org/draft/2020-12/schema',
		'title' => 'Contact Form 7 SWV',
		'description' => 'Contact Form 7 SWV meta-schema',
		'type' => 'object',
		'properties' => array(
			'version' => array(
				'type' => 'string',
			),
			'locale' => array(
				'type' => 'string',
			),
			'rules' => array(
				'type' => 'array',
				'items' => array(
					'type' => 'object',
					'properties' => array(
						'rule' => array(
							'type' => 'string',
							'enum' => array_keys( wpcf7_swv_available_rules() ),
						),
						'field' => array(
							'type' => 'string',
							'pattern' => '^[A-Za-z][-A-Za-z0-9_:]*$',
						),
						'error' => array(
							'type' => 'string',
						),
						'accept' => array(
							'type' => 'array',
							'items' => array(
								'type' => 'string',
							),
						),
						'base' => array(
							'type' => 'string',
						),
						'interval' => array(
							'type' => 'number',
							'minimum' => 0,
						),
						'threshold' => array(
							'type' => 'string',
						),
					),
					'required' => array( 'rule' ),
				),
			),
		),
	);
}


/**
 * The schema class as a composite rule.
 */
class WPCF7_SWV_Schema extends \Contactable\SWV\CompositeRule {

	/**
	 * The human-readable version of the schema.
	 */
	const version = 'Contact Form 7 SWV Schema 2024-10';


	/**
	 * Constructor.
	 */
	public function __construct( $properties = '' ) {
		$this->properties = wp_parse_args( $properties, array(
			'version' => self::version,
		) );
	}


	/**
	 * Validates with this schema.
	 *
	 * @param array $context Context.
	 */
	public function validate( $context ) {
		foreach ( $this->rules() as $rule ) {
			if ( $rule->matches( $context ) ) {
				yield $rule->validate( $context );
			}
		}
	}

}
includes/swv/script-loader.php000064400000001024147510545420012456 0ustar00<?php

add_action(
	'wp_enqueue_scripts',
	static function () {
		$assets = array();
		$asset_file = wpcf7_plugin_path( 'includes/swv/js/index.asset.php' );

		if ( file_exists( $asset_file ) ) {
			$assets = include( $asset_file );
		}

		$assets = wp_parse_args( $assets, array(
			'dependencies' => array(),
			'version' => WPCF7_VERSION,
		) );

		wp_register_script( 'swv',
			wpcf7_plugin_url( 'includes/swv/js/index.js' ),
			$assets['dependencies'],
			$assets['version'],
			array( 'in_footer' => true )
		);
	},
	10, 0
);
includes/swv/js/index.asset.php000064400000000121147510545420012544 0ustar00<?php

return array(
	'dependencies' => array(),
	'version' => WPCF7_VERSION,
);
includes/swv/js/index.js000064400000030340147510545420011261 0ustar00(()=>{"use strict";var t={d:(e,i)=>{for(var s in i)t.o(i,s)&&!t.o(e,s)&&Object.defineProperty(e,s,{enumerable:!0,get:i[s]})},o:(t,e)=>Object.prototype.hasOwnProperty.call(t,e),r:t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})}},e={};function i(t){if(this.formData={},this.tree={},!(t instanceof FormData))return this;this.formData=t;const e=()=>{const t=new Map;return t.largestIndex=0,t.set=function(e,i){""===e?e=t.largestIndex++:/^[0-9]+$/.test(e)&&(e=parseInt(e),t.largestIndex<=e&&(t.largestIndex=e+1)),Map.prototype.set.call(t,e,i)},t};this.tree=e();const i=/^(?<name>[a-z][-a-z0-9_:]*)(?<array>(?:\[(?:[a-z][-a-z0-9_:]*|[0-9]*)\])*)/i;for(const[t,s]of this.formData){const o=t.match(i);if(o)if(""===o.groups.array)this.tree.set(o.groups.name,s);else{const t=[...o.groups.array.matchAll(/\[([a-z][-a-z0-9_:]*|[0-9]*)\]/gi)].map((([t,e])=>e));t.unshift(o.groups.name);const i=t.pop();t.reduce(((t,i)=>{if(/^[0-9]+$/.test(i)&&(i=parseInt(i)),t.get(i)instanceof Map)return t.get(i);const s=e();return t.set(i,s),s}),this.tree).set(i,s)}}}t.r(e),t.d(e,{all:()=>D,any:()=>M,date:()=>m,dayofweek:()=>u,email:()=>r,enum:()=>h,file:()=>d,maxdate:()=>z,maxfilesize:()=>j,maxitems:()=>v,maxlength:()=>x,maxnumber:()=>y,mindate:()=>A,minfilesize:()=>$,minitems:()=>w,minlength:()=>g,minnumber:()=>b,number:()=>c,required:()=>n,requiredfile:()=>a,stepnumber:()=>I,tel:()=>l,time:()=>f,url:()=>p}),i.prototype.entries=function(){return this.tree.entries()},i.prototype.get=function(t){return this.tree.get(t)},i.prototype.getAll=function(t){if(!this.has(t))return[];const e=t=>{const i=[];if(t instanceof Map)for(const[s,o]of t)i.push(...e(o));else""!==t&&i.push(t);return i};return e(this.get(t))},i.prototype.has=function(t){return this.tree.has(t)},i.prototype.keys=function(){return this.tree.keys()},i.prototype.values=function(){return this.tree.values()};const s=i;function o({rule:t,field:e,error:i,...s}){this.rule=t,this.field=e,this.error=i,this.properties=s}const n=function(t){if(0===t.getAll(this.field).map((t=>t.trim())).filter((t=>""!==t)).length)throw new o(this)},a=function(t){if(0===t.getAll(this.field).length)throw new o(this)},r=function(t){if(!t.getAll(this.field).map((t=>t.trim())).filter((t=>""!==t)).every((t=>{if(t.length<6)return!1;if(-1===t.indexOf("@",1))return!1;if(t.indexOf("@")!==t.lastIndexOf("@"))return!1;const[e,i]=t.split("@",2);if(!/^[a-zA-Z0-9!#$%&\'*+\/=?^_`{|}~\.-]+$/.test(e))return!1;if(/\.{2,}/.test(i))return!1;if(/(?:^[ \t\n\r\0\x0B.]|[ \t\n\r\0\x0B.]$)/.test(i))return!1;const s=i.split(".");if(s.length<2)return!1;for(const t of s){if(/(?:^[ \t\n\r\0\x0B-]|[ \t\n\r\0\x0B-]$)/.test(t))return!1;if(!/^[a-z0-9-]+$/i.test(t))return!1}return!0})))throw new o(this)},p=function(t){const e=t.getAll(this.field).map((t=>t.trim())).filter((t=>""!==t));if(!e.every((t=>{try{return(t=>-1!==["http","https","ftp","ftps","mailto","news","irc","irc6","ircs","gopher","nntp","feed","telnet","mms","rtsp","sms","svn","tel","fax","xmpp","webcal","urn"].indexOf(t))(new URL(t).protocol.replace(/:$/,""))}catch{return!1}})))throw new o(this)},l=function(t){if(!t.getAll(this.field).map((t=>t.trim())).filter((t=>""!==t)).every((t=>(((t=(t=t.replace(/[#*].*$/,"")).replaceAll(/[()/.*#\s-]+/g,"")).startsWith("+")||t.startsWith("00"))&&(t=`+${t.replace(/^[+0]+/,"")}`),!!/^[+]?[0-9]+$/.test(t)&&6<t.length&&t.length<16))))throw new o(this)},c=function(t){if(!t.getAll(this.field).map((t=>t.trim())).filter((t=>""!==t)).every((t=>!!/^[-]?[0-9]+(?:[eE][+-]?[0-9]+)?$/.test(t)||!!/^[-]?(?:[0-9]+)?[.][0-9]+(?:[eE][+-]?[0-9]+)?$/.test(t))))throw new o(this)},m=function(t){if(!t.getAll(this.field).map((t=>t.trim())).filter((t=>""!==t)).every((t=>{if(!/^[0-9]{4,}-[0-9]{2}-[0-9]{2}$/.test(t))return!1;const e=new Date(t);return!Number.isNaN(e.valueOf())})))throw new o(this)},f=function(t){if(!t.getAll(this.field).map((t=>t.trim())).filter((t=>""!==t)).every((t=>{const e=t.match(/^([0-9]{2})\:([0-9]{2})(?:\:([0-9]{2}))?$/);if(!e)return!1;const i=parseInt(e[1]),s=parseInt(e[2]),o=e[3]?parseInt(e[3]):0;return 0<=i&&i<=23&&0<=s&&s<=59&&0<=o&&o<=59})))throw new o(this)},d=function(t){if(!t.getAll(this.field).every((t=>t instanceof File&&this.accept?.some((e=>/^\.[a-z0-9]+$/i.test(e)?t.name.toLowerCase().endsWith(e.toLowerCase()):(t=>{const e=[],i=t.match(/^(?<toplevel>[a-z]+)\/(?<sub>[*]|[a-z0-9.+-]+)$/i);if(i){const t=i.groups.toplevel.toLowerCase(),s=i.groups.sub.toLowerCase();for(const[o,n]of(()=>{const t=new Map;return t.set("jpg|jpeg|jpe","image/jpeg"),t.set("gif","image/gif"),t.set("png","image/png"),t.set("bmp","image/bmp"),t.set("tiff|tif","image/tiff"),t.set("webp","image/webp"),t.set("ico","image/x-icon"),t.set("heic","image/heic"),t.set("asf|asx","video/x-ms-asf"),t.set("wmv","video/x-ms-wmv"),t.set("wmx","video/x-ms-wmx"),t.set("wm","video/x-ms-wm"),t.set("avi","video/avi"),t.set("divx","video/divx"),t.set("flv","video/x-flv"),t.set("mov|qt","video/quicktime"),t.set("mpeg|mpg|mpe","video/mpeg"),t.set("mp4|m4v","video/mp4"),t.set("ogv","video/ogg"),t.set("webm","video/webm"),t.set("mkv","video/x-matroska"),t.set("3gp|3gpp","video/3gpp"),t.set("3g2|3gp2","video/3gpp2"),t.set("txt|asc|c|cc|h|srt","text/plain"),t.set("csv","text/csv"),t.set("tsv","text/tab-separated-values"),t.set("ics","text/calendar"),t.set("rtx","text/richtext"),t.set("css","text/css"),t.set("htm|html","text/html"),t.set("vtt","text/vtt"),t.set("dfxp","application/ttaf+xml"),t.set("mp3|m4a|m4b","audio/mpeg"),t.set("aac","audio/aac"),t.set("ra|ram","audio/x-realaudio"),t.set("wav","audio/wav"),t.set("ogg|oga","audio/ogg"),t.set("flac","audio/flac"),t.set("mid|midi","audio/midi"),t.set("wma","audio/x-ms-wma"),t.set("wax","audio/x-ms-wax"),t.set("mka","audio/x-matroska"),t.set("rtf","application/rtf"),t.set("js","application/javascript"),t.set("pdf","application/pdf"),t.set("swf","application/x-shockwave-flash"),t.set("class","application/java"),t.set("tar","application/x-tar"),t.set("zip","application/zip"),t.set("gz|gzip","application/x-gzip"),t.set("rar","application/rar"),t.set("7z","application/x-7z-compressed"),t.set("exe","application/x-msdownload"),t.set("psd","application/octet-stream"),t.set("xcf","application/octet-stream"),t.set("doc","application/msword"),t.set("pot|pps|ppt","application/vnd.ms-powerpoint"),t.set("wri","application/vnd.ms-write"),t.set("xla|xls|xlt|xlw","application/vnd.ms-excel"),t.set("mdb","application/vnd.ms-access"),t.set("mpp","application/vnd.ms-project"),t.set("docx","application/vnd.openxmlformats-officedocument.wordprocessingml.document"),t.set("docm","application/vnd.ms-word.document.macroEnabled.12"),t.set("dotx","application/vnd.openxmlformats-officedocument.wordprocessingml.template"),t.set("dotm","application/vnd.ms-word.template.macroEnabled.12"),t.set("xlsx","application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"),t.set("xlsm","application/vnd.ms-excel.sheet.macroEnabled.12"),t.set("xlsb","application/vnd.ms-excel.sheet.binary.macroEnabled.12"),t.set("xltx","application/vnd.openxmlformats-officedocument.spreadsheetml.template"),t.set("xltm","application/vnd.ms-excel.template.macroEnabled.12"),t.set("xlam","application/vnd.ms-excel.addin.macroEnabled.12"),t.set("pptx","application/vnd.openxmlformats-officedocument.presentationml.presentation"),t.set("pptm","application/vnd.ms-powerpoint.presentation.macroEnabled.12"),t.set("ppsx","application/vnd.openxmlformats-officedocument.presentationml.slideshow"),t.set("ppsm","application/vnd.ms-powerpoint.slideshow.macroEnabled.12"),t.set("potx","application/vnd.openxmlformats-officedocument.presentationml.template"),t.set("potm","application/vnd.ms-powerpoint.template.macroEnabled.12"),t.set("ppam","application/vnd.ms-powerpoint.addin.macroEnabled.12"),t.set("sldx","application/vnd.openxmlformats-officedocument.presentationml.slide"),t.set("sldm","application/vnd.ms-powerpoint.slide.macroEnabled.12"),t.set("onetoc|onetoc2|onetmp|onepkg","application/onenote"),t.set("oxps","application/oxps"),t.set("xps","application/vnd.ms-xpsdocument"),t.set("odt","application/vnd.oasis.opendocument.text"),t.set("odp","application/vnd.oasis.opendocument.presentation"),t.set("ods","application/vnd.oasis.opendocument.spreadsheet"),t.set("odg","application/vnd.oasis.opendocument.graphics"),t.set("odc","application/vnd.oasis.opendocument.chart"),t.set("odb","application/vnd.oasis.opendocument.database"),t.set("odf","application/vnd.oasis.opendocument.formula"),t.set("wp|wpd","application/wordperfect"),t.set("key","application/vnd.apple.keynote"),t.set("numbers","application/vnd.apple.numbers"),t.set("pages","application/vnd.apple.pages"),t})())("*"===s&&n.startsWith(t+"/")||n===i[0])&&e.push(...o.split("|"))}return e})(e).some((e=>(e="."+e.trim(),t.name.toLowerCase().endsWith(e.toLowerCase())))))))))throw new o(this)},h=function(t){if(!t.getAll(this.field).map((t=>t.trim())).filter((t=>""!==t)).every((t=>this.accept?.some((e=>t===String(e))))))throw new o(this)},u=function(t){if(!t.getAll(this.field).map((t=>t.trim())).filter((t=>""!==t)).every((t=>{const e=0===(i=new Date(t).getDay())?7:i;var i;return this.accept?.some((t=>e===parseInt(t)))})))throw new o(this)},w=function(t){if(t.getAll(this.field).map((t=>t.trim())).filter((t=>""!==t)).length<parseInt(this.threshold))throw new o(this)},v=function(t){const e=t.getAll(this.field).map((t=>t.trim())).filter((t=>""!==t));if(parseInt(this.threshold)<e.length)throw new o(this)},g=function(t){const e=t.getAll(this.field).map((t=>t.trim())).filter((t=>""!==t));let i=0;if(e.forEach((t=>{"string"==typeof t&&(i+=t.length)})),0!==i&&i<parseInt(this.threshold))throw new o(this)},x=function(t){const e=t.getAll(this.field).map((t=>t.trim())).filter((t=>""!==t));let i=0;if(e.forEach((t=>{"string"==typeof t&&(i+=t.length)})),parseInt(this.threshold)<i)throw new o(this)},b=function(t){if(!t.getAll(this.field).map((t=>t.trim())).filter((t=>""!==t)).every((t=>!(parseFloat(t)<parseFloat(this.threshold)))))throw new o(this)},y=function(t){if(!t.getAll(this.field).map((t=>t.trim())).filter((t=>""!==t)).every((t=>!(parseFloat(this.threshold)<parseFloat(t)))))throw new o(this)},A=function(t){if(!t.getAll(this.field).map((t=>t.trim())).filter((t=>""!==t)).every((t=>!(/^[0-9]{4,}-[0-9]{2}-[0-9]{2}$/.test(t)&&/^[0-9]{4,}-[0-9]{2}-[0-9]{2}$/.test(this.threshold)&&t<this.threshold))))throw new o(this)},z=function(t){if(!t.getAll(this.field).map((t=>t.trim())).filter((t=>""!==t)).every((t=>!(/^[0-9]{4,}-[0-9]{2}-[0-9]{2}$/.test(t)&&/^[0-9]{4,}-[0-9]{2}-[0-9]{2}$/.test(this.threshold)&&this.threshold<t))))throw new o(this)},$=function(t){const e=t.getAll(this.field);let i=0;if(e.forEach((t=>{t instanceof File&&(i+=t.size)})),i<parseInt(this.threshold))throw new o(this)},j=function(t){const e=t.getAll(this.field);let i=0;if(e.forEach((t=>{t instanceof File&&(i+=t.size)})),parseInt(this.threshold)<i)throw new o(this)},I=function(t){const e=t.getAll(this.field).map((t=>t.trim())).filter((t=>""!==t)),i=parseFloat(this.base),s=parseFloat(this.interval);if(!(0<s))return!0;if(!e.every((t=>{const e=(parseFloat(t)-i)%s;return"0.000000"===Math.abs(e).toFixed(6)||"0.000000"===Math.abs(e-s).toFixed(6)})))throw new o(this)},O=({ruleObj:t,options:i})=>{const{rule:s,...o}=t;return"function"==typeof e[s]&&("function"!=typeof e[s].matches||e[s].matches(o,i))},E=({ruleObj:t,formDataTree:i,options:s})=>{const{rule:o}=t;e[o].call(t,i,s)},k=[],F=t=>[...k].reduce(((t,e)=>i=>e(i,t)),t),D=function(t,e={}){const i=(this.rules??[]).filter((t=>O({ruleObj:t,options:e}))),s=F(E);if(!i.every((i=>{try{s({ruleObj:i,formDataTree:t,options:e})}catch(t){if(!(t instanceof o))throw t;if(void 0!==t.error)throw t;return!1}return!0})))throw new o(this)},M=function(t,e={}){const i=(this.rules??[]).filter((t=>O({ruleObj:t,options:e}))),s=F(E);if(!i.some((i=>{try{s({ruleObj:i,formDataTree:t,options:e})}catch(t){if(!(t instanceof o))throw t;return!1}return!0})))throw new o(this)};var L;window.swv={validators:e,validate:(t,e,i={})=>{const n=(t.rules??[]).filter((t=>O({ruleObj:t,options:i})));if(!n.length)return new Map;const a=F(E),r=new s(e),p=n.reduce(((t,e)=>{try{a({ruleObj:e,formDataTree:r,options:i})}catch(e){if(!(e instanceof o))throw e;if(void 0!==e.field&&!t.has(e.field)&&void 0!==e.error)return t.set(e.field,e)}return t}),new Map);for(const t of r.keys())p.has(t)||p.set(t,{validInputs:r.getAll(t)});return p},use:t=>{k.push(t)},...null!==(L=window.swv)&&void 0!==L?L:{}}})();includes/js/html5-fallback.js000064400000001203147510545420012115 0ustar00( function( $ ) {
	$( function() {
		var supportHtml5 = ( function() {
			var features = {};
			var input = document.createElement( 'input' );
			var inputTypes = [ 'date' ];

			$.each( inputTypes, function( index, value ) {
				input.setAttribute( 'type', value );
				features[ value ] = input.type !== 'text';
			} );

			return features;
		} )();

		if ( ! supportHtml5.date ) {
			$( 'input.wpcf7-date[type="date"]' ).each( function() {
				$( this ).datepicker( {
					dateFormat: 'yy-mm-dd',
					minDate: new Date( $( this ).attr( 'min' ) ),
					maxDate: new Date( $( this ).attr( 'max' ) )
				} );
			} );
		}
	} );
} )( jQuery );
includes/js/jquery-ui/themes/smoothness/jquery-ui.css000064400000107270147510545420017071 0ustar00/*! jQuery UI - v1.12.1 - 2016-09-14
* http://jqueryui.com
* Includes: core.css, accordion.css, autocomplete.css, menu.css, button.css, controlgroup.css, checkboxradio.css, datepicker.css, dialog.css, draggable.css, resizable.css, progressbar.css, selectable.css, selectmenu.css, slider.css, sortable.css, spinner.css, tabs.css, tooltip.css, theme.css
* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana%2CArial%2Csans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=highlight_soft&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=flat&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=glass&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=glass&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=glass&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=glass&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=glass&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=flat&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=flat&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
* Copyright jQuery Foundation and other contributors; Licensed MIT */

/* Layout helpers
----------------------------------*/
.ui-helper-hidden {
	display: none;
}
.ui-helper-hidden-accessible {
	border: 0;
	clip: rect(0 0 0 0);
	height: 1px;
	margin: -1px;
	overflow: hidden;
	padding: 0;
	position: absolute;
	width: 1px;
}
.ui-helper-reset {
	margin: 0;
	padding: 0;
	border: 0;
	outline: 0;
	line-height: 1.3;
	text-decoration: none;
	font-size: 100%;
	list-style: none;
}
.ui-helper-clearfix:before,
.ui-helper-clearfix:after {
	content: "";
	display: table;
	border-collapse: collapse;
}
.ui-helper-clearfix:after {
	clear: both;
}
.ui-helper-zfix {
	width: 100%;
	height: 100%;
	top: 0;
	left: 0;
	position: absolute;
	opacity: 0;
	filter:Alpha(Opacity=0); /* support: IE8 */
}

.ui-front {
	z-index: 100;
}


/* Interaction Cues
----------------------------------*/
.ui-state-disabled {
	cursor: default !important;
	pointer-events: none;
}


/* Icons
----------------------------------*/
.ui-icon {
	display: inline-block;
	vertical-align: middle;
	margin-top: -.25em;
	position: relative;
	text-indent: -99999px;
	overflow: hidden;
	background-repeat: no-repeat;
}

.ui-widget-icon-block {
	left: 50%;
	margin-left: -8px;
	display: block;
}

/* Misc visuals
----------------------------------*/

/* Overlays */
.ui-widget-overlay {
	position: fixed;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
}
.ui-accordion .ui-accordion-header {
	display: block;
	cursor: pointer;
	position: relative;
	margin: 2px 0 0 0;
	padding: .5em .5em .5em .7em;
	font-size: 100%;
}
.ui-accordion .ui-accordion-content {
	padding: 1em 2.2em;
	border-top: 0;
	overflow: auto;
}
.ui-autocomplete {
	position: absolute;
	top: 0;
	left: 0;
	cursor: default;
}
.ui-menu {
	list-style: none;
	padding: 0;
	margin: 0;
	display: block;
	outline: 0;
}
.ui-menu .ui-menu {
	position: absolute;
}
.ui-menu .ui-menu-item {
	margin: 0;
	cursor: pointer;
	/* support: IE10, see #8844 */
	list-style-image: url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7");
}
.ui-menu .ui-menu-item-wrapper {
	position: relative;
	padding: 3px 1em 3px .4em;
}
.ui-menu .ui-menu-divider {
	margin: 5px 0;
	height: 0;
	font-size: 0;
	line-height: 0;
	border-width: 1px 0 0 0;
}
.ui-menu .ui-state-focus,
.ui-menu .ui-state-active {
	margin: -1px;
}

/* icon support */
.ui-menu-icons {
	position: relative;
}
.ui-menu-icons .ui-menu-item-wrapper {
	padding-left: 2em;
}

/* left-aligned */
.ui-menu .ui-icon {
	position: absolute;
	top: 0;
	bottom: 0;
	left: .2em;
	margin: auto 0;
}

/* right-aligned */
.ui-menu .ui-menu-icon {
	left: auto;
	right: 0;
}
.ui-button {
	padding: .4em 1em;
	display: inline-block;
	position: relative;
	line-height: normal;
	margin-right: .1em;
	cursor: pointer;
	vertical-align: middle;
	text-align: center;
	-webkit-user-select: none;
	-moz-user-select: none;
	-ms-user-select: none;
	user-select: none;

	/* Support: IE <= 11 */
	overflow: visible;
}

.ui-button,
.ui-button:link,
.ui-button:visited,
.ui-button:hover,
.ui-button:active {
	text-decoration: none;
}

/* to make room for the icon, a width needs to be set here */
.ui-button-icon-only {
	width: 2em;
	box-sizing: border-box;
	text-indent: -9999px;
	white-space: nowrap;
}

/* no icon support for input elements */
input.ui-button.ui-button-icon-only {
	text-indent: 0;
}

/* button icon element(s) */
.ui-button-icon-only .ui-icon {
	position: absolute;
	top: 50%;
	left: 50%;
	margin-top: -8px;
	margin-left: -8px;
}

.ui-button.ui-icon-notext .ui-icon {
	padding: 0;
	width: 2.1em;
	height: 2.1em;
	text-indent: -9999px;
	white-space: nowrap;

}

input.ui-button.ui-icon-notext .ui-icon {
	width: auto;
	height: auto;
	text-indent: 0;
	white-space: normal;
	padding: .4em 1em;
}

/* workarounds */
/* Support: Firefox 5 - 40 */
input.ui-button::-moz-focus-inner,
button.ui-button::-moz-focus-inner {
	border: 0;
	padding: 0;
}
.ui-controlgroup {
	vertical-align: middle;
	display: inline-block;
}
.ui-controlgroup > .ui-controlgroup-item {
	float: left;
	margin-left: 0;
	margin-right: 0;
}
.ui-controlgroup > .ui-controlgroup-item:focus,
.ui-controlgroup > .ui-controlgroup-item.ui-visual-focus {
	z-index: 9999;
}
.ui-controlgroup-vertical > .ui-controlgroup-item {
	display: block;
	float: none;
	width: 100%;
	margin-top: 0;
	margin-bottom: 0;
	text-align: left;
}
.ui-controlgroup-vertical .ui-controlgroup-item {
	box-sizing: border-box;
}
.ui-controlgroup .ui-controlgroup-label {
	padding: .4em 1em;
}
.ui-controlgroup .ui-controlgroup-label span {
	font-size: 80%;
}
.ui-controlgroup-horizontal .ui-controlgroup-label + .ui-controlgroup-item {
	border-left: none;
}
.ui-controlgroup-vertical .ui-controlgroup-label + .ui-controlgroup-item {
	border-top: none;
}
.ui-controlgroup-horizontal .ui-controlgroup-label.ui-widget-content {
	border-right: none;
}
.ui-controlgroup-vertical .ui-controlgroup-label.ui-widget-content {
	border-bottom: none;
}

/* Spinner specific style fixes */
.ui-controlgroup-vertical .ui-spinner-input {

	/* Support: IE8 only, Android < 4.4 only */
	width: 75%;
	width: calc( 100% - 2.4em );
}
.ui-controlgroup-vertical .ui-spinner .ui-spinner-up {
	border-top-style: solid;
}

.ui-checkboxradio-label .ui-icon-background {
	box-shadow: inset 1px 1px 1px #ccc;
	border-radius: .12em;
	border: none;
}
.ui-checkboxradio-radio-label .ui-icon-background {
	width: 16px;
	height: 16px;
	border-radius: 1em;
	overflow: visible;
	border: none;
}
.ui-checkboxradio-radio-label.ui-checkboxradio-checked .ui-icon,
.ui-checkboxradio-radio-label.ui-checkboxradio-checked:hover .ui-icon {
	background-image: none;
	width: 8px;
	height: 8px;
	border-width: 4px;
	border-style: solid;
}
.ui-checkboxradio-disabled {
	pointer-events: none;
}
.ui-datepicker {
	width: 17em;
	padding: .2em .2em 0;
	display: none;
}
.ui-datepicker .ui-datepicker-header {
	position: relative;
	padding: .2em 0;
}
.ui-datepicker .ui-datepicker-prev,
.ui-datepicker .ui-datepicker-next {
	position: absolute;
	top: 2px;
	width: 1.8em;
	height: 1.8em;
}
.ui-datepicker .ui-datepicker-prev-hover,
.ui-datepicker .ui-datepicker-next-hover {
	top: 1px;
}
.ui-datepicker .ui-datepicker-prev {
	left: 2px;
}
.ui-datepicker .ui-datepicker-next {
	right: 2px;
}
.ui-datepicker .ui-datepicker-prev-hover {
	left: 1px;
}
.ui-datepicker .ui-datepicker-next-hover {
	right: 1px;
}
.ui-datepicker .ui-datepicker-prev span,
.ui-datepicker .ui-datepicker-next span {
	display: block;
	position: absolute;
	left: 50%;
	margin-left: -8px;
	top: 50%;
	margin-top: -8px;
}
.ui-datepicker .ui-datepicker-title {
	margin: 0 2.3em;
	line-height: 1.8em;
	text-align: center;
}
.ui-datepicker .ui-datepicker-title select {
	font-size: 1em;
	margin: 1px 0;
}
.ui-datepicker select.ui-datepicker-month,
.ui-datepicker select.ui-datepicker-year {
	width: 45%;
}
.ui-datepicker table {
	width: 100%;
	font-size: .9em;
	border-collapse: collapse;
	margin: 0 0 .4em;
}
.ui-datepicker th {
	padding: .7em .3em;
	text-align: center;
	font-weight: bold;
	border: 0;
}
.ui-datepicker td {
	border: 0;
	padding: 1px;
}
.ui-datepicker td span,
.ui-datepicker td a {
	display: block;
	padding: .2em;
	text-align: right;
	text-decoration: none;
}
.ui-datepicker .ui-datepicker-buttonpane {
	background-image: none;
	margin: .7em 0 0 0;
	padding: 0 .2em;
	border-left: 0;
	border-right: 0;
	border-bottom: 0;
}
.ui-datepicker .ui-datepicker-buttonpane button {
	float: right;
	margin: .5em .2em .4em;
	cursor: pointer;
	padding: .2em .6em .3em .6em;
	width: auto;
	overflow: visible;
}
.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current {
	float: left;
}

/* with multiple calendars */
.ui-datepicker.ui-datepicker-multi {
	width: auto;
}
.ui-datepicker-multi .ui-datepicker-group {
	float: left;
}
.ui-datepicker-multi .ui-datepicker-group table {
	width: 95%;
	margin: 0 auto .4em;
}
.ui-datepicker-multi-2 .ui-datepicker-group {
	width: 50%;
}
.ui-datepicker-multi-3 .ui-datepicker-group {
	width: 33.3%;
}
.ui-datepicker-multi-4 .ui-datepicker-group {
	width: 25%;
}
.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,
.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header {
	border-left-width: 0;
}
.ui-datepicker-multi .ui-datepicker-buttonpane {
	clear: left;
}
.ui-datepicker-row-break {
	clear: both;
	width: 100%;
	font-size: 0;
}

/* RTL support */
.ui-datepicker-rtl {
	direction: rtl;
}
.ui-datepicker-rtl .ui-datepicker-prev {
	right: 2px;
	left: auto;
}
.ui-datepicker-rtl .ui-datepicker-next {
	left: 2px;
	right: auto;
}
.ui-datepicker-rtl .ui-datepicker-prev:hover {
	right: 1px;
	left: auto;
}
.ui-datepicker-rtl .ui-datepicker-next:hover {
	left: 1px;
	right: auto;
}
.ui-datepicker-rtl .ui-datepicker-buttonpane {
	clear: right;
}
.ui-datepicker-rtl .ui-datepicker-buttonpane button {
	float: left;
}
.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,
.ui-datepicker-rtl .ui-datepicker-group {
	float: right;
}
.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,
.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header {
	border-right-width: 0;
	border-left-width: 1px;
}

/* Icons */
.ui-datepicker .ui-icon {
	display: block;
	text-indent: -99999px;
	overflow: hidden;
	background-repeat: no-repeat;
	left: .5em;
	top: .3em;
}
.ui-dialog {
	position: absolute;
	top: 0;
	left: 0;
	padding: .2em;
	outline: 0;
}
.ui-dialog .ui-dialog-titlebar {
	padding: .4em 1em;
	position: relative;
}
.ui-dialog .ui-dialog-title {
	float: left;
	margin: .1em 0;
	white-space: nowrap;
	width: 90%;
	overflow: hidden;
	text-overflow: ellipsis;
}
.ui-dialog .ui-dialog-titlebar-close {
	position: absolute;
	right: .3em;
	top: 50%;
	width: 20px;
	margin: -10px 0 0 0;
	padding: 1px;
	height: 20px;
}
.ui-dialog .ui-dialog-content {
	position: relative;
	border: 0;
	padding: .5em 1em;
	background: none;
	overflow: auto;
}
.ui-dialog .ui-dialog-buttonpane {
	text-align: left;
	border-width: 1px 0 0 0;
	background-image: none;
	margin-top: .5em;
	padding: .3em 1em .5em .4em;
}
.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset {
	float: right;
}
.ui-dialog .ui-dialog-buttonpane button {
	margin: .5em .4em .5em 0;
	cursor: pointer;
}
.ui-dialog .ui-resizable-n {
	height: 2px;
	top: 0;
}
.ui-dialog .ui-resizable-e {
	width: 2px;
	right: 0;
}
.ui-dialog .ui-resizable-s {
	height: 2px;
	bottom: 0;
}
.ui-dialog .ui-resizable-w {
	width: 2px;
	left: 0;
}
.ui-dialog .ui-resizable-se,
.ui-dialog .ui-resizable-sw,
.ui-dialog .ui-resizable-ne,
.ui-dialog .ui-resizable-nw {
	width: 7px;
	height: 7px;
}
.ui-dialog .ui-resizable-se {
	right: 0;
	bottom: 0;
}
.ui-dialog .ui-resizable-sw {
	left: 0;
	bottom: 0;
}
.ui-dialog .ui-resizable-ne {
	right: 0;
	top: 0;
}
.ui-dialog .ui-resizable-nw {
	left: 0;
	top: 0;
}
.ui-draggable .ui-dialog-titlebar {
	cursor: move;
}
.ui-draggable-handle {
	-ms-touch-action: none;
	touch-action: none;
}
.ui-resizable {
	position: relative;
}
.ui-resizable-handle {
	position: absolute;
	font-size: 0.1px;
	display: block;
	-ms-touch-action: none;
	touch-action: none;
}
.ui-resizable-disabled .ui-resizable-handle,
.ui-resizable-autohide .ui-resizable-handle {
	display: none;
}
.ui-resizable-n {
	cursor: n-resize;
	height: 7px;
	width: 100%;
	top: -5px;
	left: 0;
}
.ui-resizable-s {
	cursor: s-resize;
	height: 7px;
	width: 100%;
	bottom: -5px;
	left: 0;
}
.ui-resizable-e {
	cursor: e-resize;
	width: 7px;
	right: -5px;
	top: 0;
	height: 100%;
}
.ui-resizable-w {
	cursor: w-resize;
	width: 7px;
	left: -5px;
	top: 0;
	height: 100%;
}
.ui-resizable-se {
	cursor: se-resize;
	width: 12px;
	height: 12px;
	right: 1px;
	bottom: 1px;
}
.ui-resizable-sw {
	cursor: sw-resize;
	width: 9px;
	height: 9px;
	left: -5px;
	bottom: -5px;
}
.ui-resizable-nw {
	cursor: nw-resize;
	width: 9px;
	height: 9px;
	left: -5px;
	top: -5px;
}
.ui-resizable-ne {
	cursor: ne-resize;
	width: 9px;
	height: 9px;
	right: -5px;
	top: -5px;
}
.ui-progressbar {
	height: 2em;
	text-align: left;
	overflow: hidden;
}
.ui-progressbar .ui-progressbar-value {
	margin: -1px;
	height: 100%;
}
.ui-progressbar .ui-progressbar-overlay {
	background: url("data:image/gif;base64,R0lGODlhKAAoAIABAAAAAP///yH/C05FVFNDQVBFMi4wAwEAAAAh+QQJAQABACwAAAAAKAAoAAACkYwNqXrdC52DS06a7MFZI+4FHBCKoDeWKXqymPqGqxvJrXZbMx7Ttc+w9XgU2FB3lOyQRWET2IFGiU9m1frDVpxZZc6bfHwv4c1YXP6k1Vdy292Fb6UkuvFtXpvWSzA+HycXJHUXiGYIiMg2R6W459gnWGfHNdjIqDWVqemH2ekpObkpOlppWUqZiqr6edqqWQAAIfkECQEAAQAsAAAAACgAKAAAApSMgZnGfaqcg1E2uuzDmmHUBR8Qil95hiPKqWn3aqtLsS18y7G1SzNeowWBENtQd+T1JktP05nzPTdJZlR6vUxNWWjV+vUWhWNkWFwxl9VpZRedYcflIOLafaa28XdsH/ynlcc1uPVDZxQIR0K25+cICCmoqCe5mGhZOfeYSUh5yJcJyrkZWWpaR8doJ2o4NYq62lAAACH5BAkBAAEALAAAAAAoACgAAAKVDI4Yy22ZnINRNqosw0Bv7i1gyHUkFj7oSaWlu3ovC8GxNso5fluz3qLVhBVeT/Lz7ZTHyxL5dDalQWPVOsQWtRnuwXaFTj9jVVh8pma9JjZ4zYSj5ZOyma7uuolffh+IR5aW97cHuBUXKGKXlKjn+DiHWMcYJah4N0lYCMlJOXipGRr5qdgoSTrqWSq6WFl2ypoaUAAAIfkECQEAAQAsAAAAACgAKAAAApaEb6HLgd/iO7FNWtcFWe+ufODGjRfoiJ2akShbueb0wtI50zm02pbvwfWEMWBQ1zKGlLIhskiEPm9R6vRXxV4ZzWT2yHOGpWMyorblKlNp8HmHEb/lCXjcW7bmtXP8Xt229OVWR1fod2eWqNfHuMjXCPkIGNileOiImVmCOEmoSfn3yXlJWmoHGhqp6ilYuWYpmTqKUgAAIfkECQEAAQAsAAAAACgAKAAAApiEH6kb58biQ3FNWtMFWW3eNVcojuFGfqnZqSebuS06w5V80/X02pKe8zFwP6EFWOT1lDFk8rGERh1TTNOocQ61Hm4Xm2VexUHpzjymViHrFbiELsefVrn6XKfnt2Q9G/+Xdie499XHd2g4h7ioOGhXGJboGAnXSBnoBwKYyfioubZJ2Hn0RuRZaflZOil56Zp6iioKSXpUAAAh+QQJAQABACwAAAAAKAAoAAACkoQRqRvnxuI7kU1a1UU5bd5tnSeOZXhmn5lWK3qNTWvRdQxP8qvaC+/yaYQzXO7BMvaUEmJRd3TsiMAgswmNYrSgZdYrTX6tSHGZO73ezuAw2uxuQ+BbeZfMxsexY35+/Qe4J1inV0g4x3WHuMhIl2jXOKT2Q+VU5fgoSUI52VfZyfkJGkha6jmY+aaYdirq+lQAACH5BAkBAAEALAAAAAAoACgAAAKWBIKpYe0L3YNKToqswUlvznigd4wiR4KhZrKt9Upqip61i9E3vMvxRdHlbEFiEXfk9YARYxOZZD6VQ2pUunBmtRXo1Lf8hMVVcNl8JafV38aM2/Fu5V16Bn63r6xt97j09+MXSFi4BniGFae3hzbH9+hYBzkpuUh5aZmHuanZOZgIuvbGiNeomCnaxxap2upaCZsq+1kAACH5BAkBAAEALAAAAAAoACgAAAKXjI8By5zf4kOxTVrXNVlv1X0d8IGZGKLnNpYtm8Lr9cqVeuOSvfOW79D9aDHizNhDJidFZhNydEahOaDH6nomtJjp1tutKoNWkvA6JqfRVLHU/QUfau9l2x7G54d1fl995xcIGAdXqMfBNadoYrhH+Mg2KBlpVpbluCiXmMnZ2Sh4GBqJ+ckIOqqJ6LmKSllZmsoq6wpQAAAh+QQJAQABACwAAAAAKAAoAAAClYx/oLvoxuJDkU1a1YUZbJ59nSd2ZXhWqbRa2/gF8Gu2DY3iqs7yrq+xBYEkYvFSM8aSSObE+ZgRl1BHFZNr7pRCavZ5BW2142hY3AN/zWtsmf12p9XxxFl2lpLn1rseztfXZjdIWIf2s5dItwjYKBgo9yg5pHgzJXTEeGlZuenpyPmpGQoKOWkYmSpaSnqKileI2FAAACH5BAkBAAEALAAAAAAoACgAAAKVjB+gu+jG4kORTVrVhRlsnn2dJ3ZleFaptFrb+CXmO9OozeL5VfP99HvAWhpiUdcwkpBH3825AwYdU8xTqlLGhtCosArKMpvfa1mMRae9VvWZfeB2XfPkeLmm18lUcBj+p5dnN8jXZ3YIGEhYuOUn45aoCDkp16hl5IjYJvjWKcnoGQpqyPlpOhr3aElaqrq56Bq7VAAAOw==");
	height: 100%;
	filter: alpha(opacity=25); /* support: IE8 */
	opacity: 0.25;
}
.ui-progressbar-indeterminate .ui-progressbar-value {
	background-image: none;
}
.ui-selectable {
	-ms-touch-action: none;
	touch-action: none;
}
.ui-selectable-helper {
	position: absolute;
	z-index: 100;
	border: 1px dotted black;
}
.ui-selectmenu-menu {
	padding: 0;
	margin: 0;
	position: absolute;
	top: 0;
	left: 0;
	display: none;
}
.ui-selectmenu-menu .ui-menu {
	overflow: auto;
	overflow-x: hidden;
	padding-bottom: 1px;
}
.ui-selectmenu-menu .ui-menu .ui-selectmenu-optgroup {
	font-size: 1em;
	font-weight: bold;
	line-height: 1.5;
	padding: 2px 0.4em;
	margin: 0.5em 0 0 0;
	height: auto;
	border: 0;
}
.ui-selectmenu-open {
	display: block;
}
.ui-selectmenu-text {
	display: block;
	margin-right: 20px;
	overflow: hidden;
	text-overflow: ellipsis;
}
.ui-selectmenu-button.ui-button {
	text-align: left;
	white-space: nowrap;
	width: 14em;
}
.ui-selectmenu-icon.ui-icon {
	float: right;
	margin-top: 0;
}
.ui-slider {
	position: relative;
	text-align: left;
}
.ui-slider .ui-slider-handle {
	position: absolute;
	z-index: 2;
	width: 1.2em;
	height: 1.2em;
	cursor: default;
	-ms-touch-action: none;
	touch-action: none;
}
.ui-slider .ui-slider-range {
	position: absolute;
	z-index: 1;
	font-size: .7em;
	display: block;
	border: 0;
	background-position: 0 0;
}

/* support: IE8 - See #6727 */
.ui-slider.ui-state-disabled .ui-slider-handle,
.ui-slider.ui-state-disabled .ui-slider-range {
	filter: inherit;
}

.ui-slider-horizontal {
	height: .8em;
}
.ui-slider-horizontal .ui-slider-handle {
	top: -.3em;
	margin-left: -.6em;
}
.ui-slider-horizontal .ui-slider-range {
	top: 0;
	height: 100%;
}
.ui-slider-horizontal .ui-slider-range-min {
	left: 0;
}
.ui-slider-horizontal .ui-slider-range-max {
	right: 0;
}

.ui-slider-vertical {
	width: .8em;
	height: 100px;
}
.ui-slider-vertical .ui-slider-handle {
	left: -.3em;
	margin-left: 0;
	margin-bottom: -.6em;
}
.ui-slider-vertical .ui-slider-range {
	left: 0;
	width: 100%;
}
.ui-slider-vertical .ui-slider-range-min {
	bottom: 0;
}
.ui-slider-vertical .ui-slider-range-max {
	top: 0;
}
.ui-sortable-handle {
	-ms-touch-action: none;
	touch-action: none;
}
.ui-spinner {
	position: relative;
	display: inline-block;
	overflow: hidden;
	padding: 0;
	vertical-align: middle;
}
.ui-spinner-input {
	border: none;
	background: none;
	color: inherit;
	padding: .222em 0;
	margin: .2em 0;
	vertical-align: middle;
	margin-left: .4em;
	margin-right: 2em;
}
.ui-spinner-button {
	width: 1.6em;
	height: 50%;
	font-size: .5em;
	padding: 0;
	margin: 0;
	text-align: center;
	position: absolute;
	cursor: default;
	display: block;
	overflow: hidden;
	right: 0;
}
/* more specificity required here to override default borders */
.ui-spinner a.ui-spinner-button {
	border-top-style: none;
	border-bottom-style: none;
	border-right-style: none;
}
.ui-spinner-up {
	top: 0;
}
.ui-spinner-down {
	bottom: 0;
}
.ui-tabs {
	position: relative;/* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
	padding: .2em;
}
.ui-tabs .ui-tabs-nav {
	margin: 0;
	padding: .2em .2em 0;
}
.ui-tabs .ui-tabs-nav li {
	list-style: none;
	float: left;
	position: relative;
	top: 0;
	margin: 1px .2em 0 0;
	border-bottom-width: 0;
	padding: 0;
	white-space: nowrap;
}
.ui-tabs .ui-tabs-nav .ui-tabs-anchor {
	float: left;
	padding: .5em 1em;
	text-decoration: none;
}
.ui-tabs .ui-tabs-nav li.ui-tabs-active {
	margin-bottom: -1px;
	padding-bottom: 1px;
}
.ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor,
.ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor,
.ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor {
	cursor: text;
}
.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor {
	cursor: pointer;
}
.ui-tabs .ui-tabs-panel {
	display: block;
	border-width: 0;
	padding: 1em 1.4em;
	background: none;
}
.ui-tooltip {
	padding: 8px;
	position: absolute;
	z-index: 9999;
	max-width: 300px;
}
body .ui-tooltip {
	border-width: 2px;
}
/* Component containers
----------------------------------*/
.ui-widget {
	font-family: Verdana,Arial,sans-serif;
	font-size: 1.1em;
}
.ui-widget .ui-widget {
	font-size: 1em;
}
.ui-widget input,
.ui-widget select,
.ui-widget textarea,
.ui-widget button {
	font-family: Verdana,Arial,sans-serif;
	font-size: 1em;
}
.ui-widget.ui-widget-content {
	border: 1px solid #d3d3d3;
}
.ui-widget-content {
	border: 1px solid #aaaaaa;
	background: #ffffff;
	color: #222222;
}
.ui-widget-content a {
	color: #222222;
}
.ui-widget-header {
	border: 1px solid #aaaaaa;
	background: #cccccc url("images/ui-bg_highlight-soft_75_cccccc_1x100.png") 50% 50% repeat-x;
	color: #222222;
	font-weight: bold;
}
.ui-widget-header a {
	color: #222222;
}

/* Interaction states
----------------------------------*/
.ui-state-default,
.ui-widget-content .ui-state-default,
.ui-widget-header .ui-state-default,
.ui-button,

/* We use html here because we need a greater specificity to make sure disabled
works properly when clicked or hovered */
html .ui-button.ui-state-disabled:hover,
html .ui-button.ui-state-disabled:active {
	border: 1px solid #d3d3d3;
	background: #e6e6e6 url("images/ui-bg_glass_75_e6e6e6_1x400.png") 50% 50% repeat-x;
	font-weight: normal;
	color: #555555;
}
.ui-state-default a,
.ui-state-default a:link,
.ui-state-default a:visited,
a.ui-button,
a:link.ui-button,
a:visited.ui-button,
.ui-button {
	color: #555555;
	text-decoration: none;
}
.ui-state-hover,
.ui-widget-content .ui-state-hover,
.ui-widget-header .ui-state-hover,
.ui-state-focus,
.ui-widget-content .ui-state-focus,
.ui-widget-header .ui-state-focus,
.ui-button:hover,
.ui-button:focus {
	border: 1px solid #999999;
	background: #dadada url("images/ui-bg_glass_75_dadada_1x400.png") 50% 50% repeat-x;
	font-weight: normal;
	color: #212121;
}
.ui-state-hover a,
.ui-state-hover a:hover,
.ui-state-hover a:link,
.ui-state-hover a:visited,
.ui-state-focus a,
.ui-state-focus a:hover,
.ui-state-focus a:link,
.ui-state-focus a:visited,
a.ui-button:hover,
a.ui-button:focus {
	color: #212121;
	text-decoration: none;
}

.ui-visual-focus {
	box-shadow: 0 0 3px 1px rgb(94, 158, 214);
}
.ui-state-active,
.ui-widget-content .ui-state-active,
.ui-widget-header .ui-state-active,
a.ui-button:active,
.ui-button:active,
.ui-button.ui-state-active:hover {
	border: 1px solid #aaaaaa;
	background: #ffffff url("images/ui-bg_glass_65_ffffff_1x400.png") 50% 50% repeat-x;
	font-weight: normal;
	color: #212121;
}
.ui-icon-background,
.ui-state-active .ui-icon-background {
	border: #aaaaaa;
	background-color: #212121;
}
.ui-state-active a,
.ui-state-active a:link,
.ui-state-active a:visited {
	color: #212121;
	text-decoration: none;
}

/* Interaction Cues
----------------------------------*/
.ui-state-highlight,
.ui-widget-content .ui-state-highlight,
.ui-widget-header .ui-state-highlight {
	border: 1px solid #fcefa1;
	background: #fbf9ee url("images/ui-bg_glass_55_fbf9ee_1x400.png") 50% 50% repeat-x;
	color: #363636;
}
.ui-state-checked {
	border: 1px solid #fcefa1;
	background: #fbf9ee;
}
.ui-state-highlight a,
.ui-widget-content .ui-state-highlight a,
.ui-widget-header .ui-state-highlight a {
	color: #363636;
}
.ui-state-error,
.ui-widget-content .ui-state-error,
.ui-widget-header .ui-state-error {
	border: 1px solid #cd0a0a;
	background: #fef1ec url("images/ui-bg_glass_95_fef1ec_1x400.png") 50% 50% repeat-x;
	color: #cd0a0a;
}
.ui-state-error a,
.ui-widget-content .ui-state-error a,
.ui-widget-header .ui-state-error a {
	color: #cd0a0a;
}
.ui-state-error-text,
.ui-widget-content .ui-state-error-text,
.ui-widget-header .ui-state-error-text {
	color: #cd0a0a;
}
.ui-priority-primary,
.ui-widget-content .ui-priority-primary,
.ui-widget-header .ui-priority-primary {
	font-weight: bold;
}
.ui-priority-secondary,
.ui-widget-content .ui-priority-secondary,
.ui-widget-header .ui-priority-secondary {
	opacity: .7;
	filter:Alpha(Opacity=70); /* support: IE8 */
	font-weight: normal;
}
.ui-state-disabled,
.ui-widget-content .ui-state-disabled,
.ui-widget-header .ui-state-disabled {
	opacity: .35;
	filter:Alpha(Opacity=35); /* support: IE8 */
	background-image: none;
}
.ui-state-disabled .ui-icon {
	filter:Alpha(Opacity=35); /* support: IE8 - See #6059 */
}

/* Icons
----------------------------------*/

/* states and images */
.ui-icon {
	width: 16px;
	height: 16px;
}
.ui-icon,
.ui-widget-content .ui-icon {
	background-image: url("images/ui-icons_222222_256x240.png");
}
.ui-widget-header .ui-icon {
	background-image: url("images/ui-icons_222222_256x240.png");
}
.ui-state-hover .ui-icon,
.ui-state-focus .ui-icon,
.ui-button:hover .ui-icon,
.ui-button:focus .ui-icon {
	background-image: url("images/ui-icons_454545_256x240.png");
}
.ui-state-active .ui-icon,
.ui-button:active .ui-icon {
	background-image: url("images/ui-icons_454545_256x240.png");
}
.ui-state-highlight .ui-icon,
.ui-button .ui-state-highlight.ui-icon {
	background-image: url("images/ui-icons_2e83ff_256x240.png");
}
.ui-state-error .ui-icon,
.ui-state-error-text .ui-icon {
	background-image: url("images/ui-icons_cd0a0a_256x240.png");
}
.ui-button .ui-icon {
	background-image: url("images/ui-icons_888888_256x240.png");
}

/* positioning */
.ui-icon-blank { background-position: 16px 16px; }
.ui-icon-caret-1-n { background-position: 0 0; }
.ui-icon-caret-1-ne { background-position: -16px 0; }
.ui-icon-caret-1-e { background-position: -32px 0; }
.ui-icon-caret-1-se { background-position: -48px 0; }
.ui-icon-caret-1-s { background-position: -65px 0; }
.ui-icon-caret-1-sw { background-position: -80px 0; }
.ui-icon-caret-1-w { background-position: -96px 0; }
.ui-icon-caret-1-nw { background-position: -112px 0; }
.ui-icon-caret-2-n-s { background-position: -128px 0; }
.ui-icon-caret-2-e-w { background-position: -144px 0; }
.ui-icon-triangle-1-n { background-position: 0 -16px; }
.ui-icon-triangle-1-ne { background-position: -16px -16px; }
.ui-icon-triangle-1-e { background-position: -32px -16px; }
.ui-icon-triangle-1-se { background-position: -48px -16px; }
.ui-icon-triangle-1-s { background-position: -65px -16px; }
.ui-icon-triangle-1-sw { background-position: -80px -16px; }
.ui-icon-triangle-1-w { background-position: -96px -16px; }
.ui-icon-triangle-1-nw { background-position: -112px -16px; }
.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
.ui-icon-arrow-1-n { background-position: 0 -32px; }
.ui-icon-arrow-1-ne { background-position: -16px -32px; }
.ui-icon-arrow-1-e { background-position: -32px -32px; }
.ui-icon-arrow-1-se { background-position: -48px -32px; }
.ui-icon-arrow-1-s { background-position: -65px -32px; }
.ui-icon-arrow-1-sw { background-position: -80px -32px; }
.ui-icon-arrow-1-w { background-position: -96px -32px; }
.ui-icon-arrow-1-nw { background-position: -112px -32px; }
.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
.ui-icon-arrowthick-1-n { background-position: 1px -48px; }
.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
.ui-icon-arrow-4 { background-position: 0 -80px; }
.ui-icon-arrow-4-diag { background-position: -16px -80px; }
.ui-icon-extlink { background-position: -32px -80px; }
.ui-icon-newwin { background-position: -48px -80px; }
.ui-icon-refresh { background-position: -64px -80px; }
.ui-icon-shuffle { background-position: -80px -80px; }
.ui-icon-transfer-e-w { background-position: -96px -80px; }
.ui-icon-transferthick-e-w { background-position: -112px -80px; }
.ui-icon-folder-collapsed { background-position: 0 -96px; }
.ui-icon-folder-open { background-position: -16px -96px; }
.ui-icon-document { background-position: -32px -96px; }
.ui-icon-document-b { background-position: -48px -96px; }
.ui-icon-note { background-position: -64px -96px; }
.ui-icon-mail-closed { background-position: -80px -96px; }
.ui-icon-mail-open { background-position: -96px -96px; }
.ui-icon-suitcase { background-position: -112px -96px; }
.ui-icon-comment { background-position: -128px -96px; }
.ui-icon-person { background-position: -144px -96px; }
.ui-icon-print { background-position: -160px -96px; }
.ui-icon-trash { background-position: -176px -96px; }
.ui-icon-locked { background-position: -192px -96px; }
.ui-icon-unlocked { background-position: -208px -96px; }
.ui-icon-bookmark { background-position: -224px -96px; }
.ui-icon-tag { background-position: -240px -96px; }
.ui-icon-home { background-position: 0 -112px; }
.ui-icon-flag { background-position: -16px -112px; }
.ui-icon-calendar { background-position: -32px -112px; }
.ui-icon-cart { background-position: -48px -112px; }
.ui-icon-pencil { background-position: -64px -112px; }
.ui-icon-clock { background-position: -80px -112px; }
.ui-icon-disk { background-position: -96px -112px; }
.ui-icon-calculator { background-position: -112px -112px; }
.ui-icon-zoomin { background-position: -128px -112px; }
.ui-icon-zoomout { background-position: -144px -112px; }
.ui-icon-search { background-position: -160px -112px; }
.ui-icon-wrench { background-position: -176px -112px; }
.ui-icon-gear { background-position: -192px -112px; }
.ui-icon-heart { background-position: -208px -112px; }
.ui-icon-star { background-position: -224px -112px; }
.ui-icon-link { background-position: -240px -112px; }
.ui-icon-cancel { background-position: 0 -128px; }
.ui-icon-plus { background-position: -16px -128px; }
.ui-icon-plusthick { background-position: -32px -128px; }
.ui-icon-minus { background-position: -48px -128px; }
.ui-icon-minusthick { background-position: -64px -128px; }
.ui-icon-close { background-position: -80px -128px; }
.ui-icon-closethick { background-position: -96px -128px; }
.ui-icon-key { background-position: -112px -128px; }
.ui-icon-lightbulb { background-position: -128px -128px; }
.ui-icon-scissors { background-position: -144px -128px; }
.ui-icon-clipboard { background-position: -160px -128px; }
.ui-icon-copy { background-position: -176px -128px; }
.ui-icon-contact { background-position: -192px -128px; }
.ui-icon-image { background-position: -208px -128px; }
.ui-icon-video { background-position: -224px -128px; }
.ui-icon-script { background-position: -240px -128px; }
.ui-icon-alert { background-position: 0 -144px; }
.ui-icon-info { background-position: -16px -144px; }
.ui-icon-notice { background-position: -32px -144px; }
.ui-icon-help { background-position: -48px -144px; }
.ui-icon-check { background-position: -64px -144px; }
.ui-icon-bullet { background-position: -80px -144px; }
.ui-icon-radio-on { background-position: -96px -144px; }
.ui-icon-radio-off { background-position: -112px -144px; }
.ui-icon-pin-w { background-position: -128px -144px; }
.ui-icon-pin-s { background-position: -144px -144px; }
.ui-icon-play { background-position: 0 -160px; }
.ui-icon-pause { background-position: -16px -160px; }
.ui-icon-seek-next { background-position: -32px -160px; }
.ui-icon-seek-prev { background-position: -48px -160px; }
.ui-icon-seek-end { background-position: -64px -160px; }
.ui-icon-seek-start { background-position: -80px -160px; }
/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
.ui-icon-seek-first { background-position: -80px -160px; }
.ui-icon-stop { background-position: -96px -160px; }
.ui-icon-eject { background-position: -112px -160px; }
.ui-icon-volume-off { background-position: -128px -160px; }
.ui-icon-volume-on { background-position: -144px -160px; }
.ui-icon-power { background-position: 0 -176px; }
.ui-icon-signal-diag { background-position: -16px -176px; }
.ui-icon-signal { background-position: -32px -176px; }
.ui-icon-battery-0 { background-position: -48px -176px; }
.ui-icon-battery-1 { background-position: -64px -176px; }
.ui-icon-battery-2 { background-position: -80px -176px; }
.ui-icon-battery-3 { background-position: -96px -176px; }
.ui-icon-circle-plus { background-position: 0 -192px; }
.ui-icon-circle-minus { background-position: -16px -192px; }
.ui-icon-circle-close { background-position: -32px -192px; }
.ui-icon-circle-triangle-e { background-position: -48px -192px; }
.ui-icon-circle-triangle-s { background-position: -64px -192px; }
.ui-icon-circle-triangle-w { background-position: -80px -192px; }
.ui-icon-circle-triangle-n { background-position: -96px -192px; }
.ui-icon-circle-arrow-e { background-position: -112px -192px; }
.ui-icon-circle-arrow-s { background-position: -128px -192px; }
.ui-icon-circle-arrow-w { background-position: -144px -192px; }
.ui-icon-circle-arrow-n { background-position: -160px -192px; }
.ui-icon-circle-zoomin { background-position: -176px -192px; }
.ui-icon-circle-zoomout { background-position: -192px -192px; }
.ui-icon-circle-check { background-position: -208px -192px; }
.ui-icon-circlesmall-plus { background-position: 0 -208px; }
.ui-icon-circlesmall-minus { background-position: -16px -208px; }
.ui-icon-circlesmall-close { background-position: -32px -208px; }
.ui-icon-squaresmall-plus { background-position: -48px -208px; }
.ui-icon-squaresmall-minus { background-position: -64px -208px; }
.ui-icon-squaresmall-close { background-position: -80px -208px; }
.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
.ui-icon-grip-diagonal-se { background-position: -80px -224px; }


/* Misc visuals
----------------------------------*/

/* Corner radius */
.ui-corner-all,
.ui-corner-top,
.ui-corner-left,
.ui-corner-tl {
	border-top-left-radius: 4px;
}
.ui-corner-all,
.ui-corner-top,
.ui-corner-right,
.ui-corner-tr {
	border-top-right-radius: 4px;
}
.ui-corner-all,
.ui-corner-bottom,
.ui-corner-left,
.ui-corner-bl {
	border-bottom-left-radius: 4px;
}
.ui-corner-all,
.ui-corner-bottom,
.ui-corner-right,
.ui-corner-br {
	border-bottom-right-radius: 4px;
}

/* Overlays */
.ui-widget-overlay {
	background: #aaaaaa;
	opacity: .3;
	filter: Alpha(Opacity=30); /* support: IE8 */
}
.ui-widget-shadow {
	-webkit-box-shadow: -8px -8px 8px #aaaaaa;
	box-shadow: -8px -8px 8px #aaaaaa;
}
includes/js/jquery-ui/themes/smoothness/theme.css000064400000042732147510545420016242 0ustar00/*!
 * jQuery UI CSS Framework 1.12.1
 * http://jqueryui.com
 *
 * Copyright jQuery Foundation and other contributors
 * Released under the MIT license.
 * http://jquery.org/license
 *
 * http://api.jqueryui.com/category/theming/
 *
 * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana%2CArial%2Csans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=highlight_soft&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=flat&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=glass&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=glass&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=glass&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=glass&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=glass&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=flat&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=flat&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
 */


/* Component containers
----------------------------------*/
.ui-widget {
	font-family: Verdana,Arial,sans-serif;
	font-size: 1.1em;
}
.ui-widget .ui-widget {
	font-size: 1em;
}
.ui-widget input,
.ui-widget select,
.ui-widget textarea,
.ui-widget button {
	font-family: Verdana,Arial,sans-serif;
	font-size: 1em;
}
.ui-widget.ui-widget-content {
	border: 1px solid #d3d3d3;
}
.ui-widget-content {
	border: 1px solid #aaaaaa;
	background: #ffffff;
	color: #222222;
}
.ui-widget-content a {
	color: #222222;
}
.ui-widget-header {
	border: 1px solid #aaaaaa;
	background: #cccccc url("images/ui-bg_highlight-soft_75_cccccc_1x100.png") 50% 50% repeat-x;
	color: #222222;
	font-weight: bold;
}
.ui-widget-header a {
	color: #222222;
}

/* Interaction states
----------------------------------*/
.ui-state-default,
.ui-widget-content .ui-state-default,
.ui-widget-header .ui-state-default,
.ui-button,

/* We use html here because we need a greater specificity to make sure disabled
works properly when clicked or hovered */
html .ui-button.ui-state-disabled:hover,
html .ui-button.ui-state-disabled:active {
	border: 1px solid #d3d3d3;
	background: #e6e6e6 url("images/ui-bg_glass_75_e6e6e6_1x400.png") 50% 50% repeat-x;
	font-weight: normal;
	color: #555555;
}
.ui-state-default a,
.ui-state-default a:link,
.ui-state-default a:visited,
a.ui-button,
a:link.ui-button,
a:visited.ui-button,
.ui-button {
	color: #555555;
	text-decoration: none;
}
.ui-state-hover,
.ui-widget-content .ui-state-hover,
.ui-widget-header .ui-state-hover,
.ui-state-focus,
.ui-widget-content .ui-state-focus,
.ui-widget-header .ui-state-focus,
.ui-button:hover,
.ui-button:focus {
	border: 1px solid #999999;
	background: #dadada url("images/ui-bg_glass_75_dadada_1x400.png") 50% 50% repeat-x;
	font-weight: normal;
	color: #212121;
}
.ui-state-hover a,
.ui-state-hover a:hover,
.ui-state-hover a:link,
.ui-state-hover a:visited,
.ui-state-focus a,
.ui-state-focus a:hover,
.ui-state-focus a:link,
.ui-state-focus a:visited,
a.ui-button:hover,
a.ui-button:focus {
	color: #212121;
	text-decoration: none;
}

.ui-visual-focus {
	box-shadow: 0 0 3px 1px rgb(94, 158, 214);
}
.ui-state-active,
.ui-widget-content .ui-state-active,
.ui-widget-header .ui-state-active,
a.ui-button:active,
.ui-button:active,
.ui-button.ui-state-active:hover {
	border: 1px solid #aaaaaa;
	background: #ffffff url("images/ui-bg_glass_65_ffffff_1x400.png") 50% 50% repeat-x;
	font-weight: normal;
	color: #212121;
}
.ui-icon-background,
.ui-state-active .ui-icon-background {
	border: #aaaaaa;
	background-color: #212121;
}
.ui-state-active a,
.ui-state-active a:link,
.ui-state-active a:visited {
	color: #212121;
	text-decoration: none;
}

/* Interaction Cues
----------------------------------*/
.ui-state-highlight,
.ui-widget-content .ui-state-highlight,
.ui-widget-header .ui-state-highlight {
	border: 1px solid #fcefa1;
	background: #fbf9ee url("images/ui-bg_glass_55_fbf9ee_1x400.png") 50% 50% repeat-x;
	color: #363636;
}
.ui-state-checked {
	border: 1px solid #fcefa1;
	background: #fbf9ee;
}
.ui-state-highlight a,
.ui-widget-content .ui-state-highlight a,
.ui-widget-header .ui-state-highlight a {
	color: #363636;
}
.ui-state-error,
.ui-widget-content .ui-state-error,
.ui-widget-header .ui-state-error {
	border: 1px solid #cd0a0a;
	background: #fef1ec url("images/ui-bg_glass_95_fef1ec_1x400.png") 50% 50% repeat-x;
	color: #cd0a0a;
}
.ui-state-error a,
.ui-widget-content .ui-state-error a,
.ui-widget-header .ui-state-error a {
	color: #cd0a0a;
}
.ui-state-error-text,
.ui-widget-content .ui-state-error-text,
.ui-widget-header .ui-state-error-text {
	color: #cd0a0a;
}
.ui-priority-primary,
.ui-widget-content .ui-priority-primary,
.ui-widget-header .ui-priority-primary {
	font-weight: bold;
}
.ui-priority-secondary,
.ui-widget-content .ui-priority-secondary,
.ui-widget-header .ui-priority-secondary {
	opacity: .7;
	filter:Alpha(Opacity=70); /* support: IE8 */
	font-weight: normal;
}
.ui-state-disabled,
.ui-widget-content .ui-state-disabled,
.ui-widget-header .ui-state-disabled {
	opacity: .35;
	filter:Alpha(Opacity=35); /* support: IE8 */
	background-image: none;
}
.ui-state-disabled .ui-icon {
	filter:Alpha(Opacity=35); /* support: IE8 - See #6059 */
}

/* Icons
----------------------------------*/

/* states and images */
.ui-icon {
	width: 16px;
	height: 16px;
}
.ui-icon,
.ui-widget-content .ui-icon {
	background-image: url("images/ui-icons_222222_256x240.png");
}
.ui-widget-header .ui-icon {
	background-image: url("images/ui-icons_222222_256x240.png");
}
.ui-state-hover .ui-icon,
.ui-state-focus .ui-icon,
.ui-button:hover .ui-icon,
.ui-button:focus .ui-icon {
	background-image: url("images/ui-icons_454545_256x240.png");
}
.ui-state-active .ui-icon,
.ui-button:active .ui-icon {
	background-image: url("images/ui-icons_454545_256x240.png");
}
.ui-state-highlight .ui-icon,
.ui-button .ui-state-highlight.ui-icon {
	background-image: url("images/ui-icons_2e83ff_256x240.png");
}
.ui-state-error .ui-icon,
.ui-state-error-text .ui-icon {
	background-image: url("images/ui-icons_cd0a0a_256x240.png");
}
.ui-button .ui-icon {
	background-image: url("images/ui-icons_888888_256x240.png");
}

/* positioning */
.ui-icon-blank { background-position: 16px 16px; }
.ui-icon-caret-1-n { background-position: 0 0; }
.ui-icon-caret-1-ne { background-position: -16px 0; }
.ui-icon-caret-1-e { background-position: -32px 0; }
.ui-icon-caret-1-se { background-position: -48px 0; }
.ui-icon-caret-1-s { background-position: -65px 0; }
.ui-icon-caret-1-sw { background-position: -80px 0; }
.ui-icon-caret-1-w { background-position: -96px 0; }
.ui-icon-caret-1-nw { background-position: -112px 0; }
.ui-icon-caret-2-n-s { background-position: -128px 0; }
.ui-icon-caret-2-e-w { background-position: -144px 0; }
.ui-icon-triangle-1-n { background-position: 0 -16px; }
.ui-icon-triangle-1-ne { background-position: -16px -16px; }
.ui-icon-triangle-1-e { background-position: -32px -16px; }
.ui-icon-triangle-1-se { background-position: -48px -16px; }
.ui-icon-triangle-1-s { background-position: -65px -16px; }
.ui-icon-triangle-1-sw { background-position: -80px -16px; }
.ui-icon-triangle-1-w { background-position: -96px -16px; }
.ui-icon-triangle-1-nw { background-position: -112px -16px; }
.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
.ui-icon-arrow-1-n { background-position: 0 -32px; }
.ui-icon-arrow-1-ne { background-position: -16px -32px; }
.ui-icon-arrow-1-e { background-position: -32px -32px; }
.ui-icon-arrow-1-se { background-position: -48px -32px; }
.ui-icon-arrow-1-s { background-position: -65px -32px; }
.ui-icon-arrow-1-sw { background-position: -80px -32px; }
.ui-icon-arrow-1-w { background-position: -96px -32px; }
.ui-icon-arrow-1-nw { background-position: -112px -32px; }
.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
.ui-icon-arrowthick-1-n { background-position: 1px -48px; }
.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
.ui-icon-arrow-4 { background-position: 0 -80px; }
.ui-icon-arrow-4-diag { background-position: -16px -80px; }
.ui-icon-extlink { background-position: -32px -80px; }
.ui-icon-newwin { background-position: -48px -80px; }
.ui-icon-refresh { background-position: -64px -80px; }
.ui-icon-shuffle { background-position: -80px -80px; }
.ui-icon-transfer-e-w { background-position: -96px -80px; }
.ui-icon-transferthick-e-w { background-position: -112px -80px; }
.ui-icon-folder-collapsed { background-position: 0 -96px; }
.ui-icon-folder-open { background-position: -16px -96px; }
.ui-icon-document { background-position: -32px -96px; }
.ui-icon-document-b { background-position: -48px -96px; }
.ui-icon-note { background-position: -64px -96px; }
.ui-icon-mail-closed { background-position: -80px -96px; }
.ui-icon-mail-open { background-position: -96px -96px; }
.ui-icon-suitcase { background-position: -112px -96px; }
.ui-icon-comment { background-position: -128px -96px; }
.ui-icon-person { background-position: -144px -96px; }
.ui-icon-print { background-position: -160px -96px; }
.ui-icon-trash { background-position: -176px -96px; }
.ui-icon-locked { background-position: -192px -96px; }
.ui-icon-unlocked { background-position: -208px -96px; }
.ui-icon-bookmark { background-position: -224px -96px; }
.ui-icon-tag { background-position: -240px -96px; }
.ui-icon-home { background-position: 0 -112px; }
.ui-icon-flag { background-position: -16px -112px; }
.ui-icon-calendar { background-position: -32px -112px; }
.ui-icon-cart { background-position: -48px -112px; }
.ui-icon-pencil { background-position: -64px -112px; }
.ui-icon-clock { background-position: -80px -112px; }
.ui-icon-disk { background-position: -96px -112px; }
.ui-icon-calculator { background-position: -112px -112px; }
.ui-icon-zoomin { background-position: -128px -112px; }
.ui-icon-zoomout { background-position: -144px -112px; }
.ui-icon-search { background-position: -160px -112px; }
.ui-icon-wrench { background-position: -176px -112px; }
.ui-icon-gear { background-position: -192px -112px; }
.ui-icon-heart { background-position: -208px -112px; }
.ui-icon-star { background-position: -224px -112px; }
.ui-icon-link { background-position: -240px -112px; }
.ui-icon-cancel { background-position: 0 -128px; }
.ui-icon-plus { background-position: -16px -128px; }
.ui-icon-plusthick { background-position: -32px -128px; }
.ui-icon-minus { background-position: -48px -128px; }
.ui-icon-minusthick { background-position: -64px -128px; }
.ui-icon-close { background-position: -80px -128px; }
.ui-icon-closethick { background-position: -96px -128px; }
.ui-icon-key { background-position: -112px -128px; }
.ui-icon-lightbulb { background-position: -128px -128px; }
.ui-icon-scissors { background-position: -144px -128px; }
.ui-icon-clipboard { background-position: -160px -128px; }
.ui-icon-copy { background-position: -176px -128px; }
.ui-icon-contact { background-position: -192px -128px; }
.ui-icon-image { background-position: -208px -128px; }
.ui-icon-video { background-position: -224px -128px; }
.ui-icon-script { background-position: -240px -128px; }
.ui-icon-alert { background-position: 0 -144px; }
.ui-icon-info { background-position: -16px -144px; }
.ui-icon-notice { background-position: -32px -144px; }
.ui-icon-help { background-position: -48px -144px; }
.ui-icon-check { background-position: -64px -144px; }
.ui-icon-bullet { background-position: -80px -144px; }
.ui-icon-radio-on { background-position: -96px -144px; }
.ui-icon-radio-off { background-position: -112px -144px; }
.ui-icon-pin-w { background-position: -128px -144px; }
.ui-icon-pin-s { background-position: -144px -144px; }
.ui-icon-play { background-position: 0 -160px; }
.ui-icon-pause { background-position: -16px -160px; }
.ui-icon-seek-next { background-position: -32px -160px; }
.ui-icon-seek-prev { background-position: -48px -160px; }
.ui-icon-seek-end { background-position: -64px -160px; }
.ui-icon-seek-start { background-position: -80px -160px; }
/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
.ui-icon-seek-first { background-position: -80px -160px; }
.ui-icon-stop { background-position: -96px -160px; }
.ui-icon-eject { background-position: -112px -160px; }
.ui-icon-volume-off { background-position: -128px -160px; }
.ui-icon-volume-on { background-position: -144px -160px; }
.ui-icon-power { background-position: 0 -176px; }
.ui-icon-signal-diag { background-position: -16px -176px; }
.ui-icon-signal { background-position: -32px -176px; }
.ui-icon-battery-0 { background-position: -48px -176px; }
.ui-icon-battery-1 { background-position: -64px -176px; }
.ui-icon-battery-2 { background-position: -80px -176px; }
.ui-icon-battery-3 { background-position: -96px -176px; }
.ui-icon-circle-plus { background-position: 0 -192px; }
.ui-icon-circle-minus { background-position: -16px -192px; }
.ui-icon-circle-close { background-position: -32px -192px; }
.ui-icon-circle-triangle-e { background-position: -48px -192px; }
.ui-icon-circle-triangle-s { background-position: -64px -192px; }
.ui-icon-circle-triangle-w { background-position: -80px -192px; }
.ui-icon-circle-triangle-n { background-position: -96px -192px; }
.ui-icon-circle-arrow-e { background-position: -112px -192px; }
.ui-icon-circle-arrow-s { background-position: -128px -192px; }
.ui-icon-circle-arrow-w { background-position: -144px -192px; }
.ui-icon-circle-arrow-n { background-position: -160px -192px; }
.ui-icon-circle-zoomin { background-position: -176px -192px; }
.ui-icon-circle-zoomout { background-position: -192px -192px; }
.ui-icon-circle-check { background-position: -208px -192px; }
.ui-icon-circlesmall-plus { background-position: 0 -208px; }
.ui-icon-circlesmall-minus { background-position: -16px -208px; }
.ui-icon-circlesmall-close { background-position: -32px -208px; }
.ui-icon-squaresmall-plus { background-position: -48px -208px; }
.ui-icon-squaresmall-minus { background-position: -64px -208px; }
.ui-icon-squaresmall-close { background-position: -80px -208px; }
.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
.ui-icon-grip-diagonal-se { background-position: -80px -224px; }


/* Misc visuals
----------------------------------*/

/* Corner radius */
.ui-corner-all,
.ui-corner-top,
.ui-corner-left,
.ui-corner-tl {
	border-top-left-radius: 4px;
}
.ui-corner-all,
.ui-corner-top,
.ui-corner-right,
.ui-corner-tr {
	border-top-right-radius: 4px;
}
.ui-corner-all,
.ui-corner-bottom,
.ui-corner-left,
.ui-corner-bl {
	border-bottom-left-radius: 4px;
}
.ui-corner-all,
.ui-corner-bottom,
.ui-corner-right,
.ui-corner-br {
	border-bottom-right-radius: 4px;
}

/* Overlays */
.ui-widget-overlay {
	background: #aaaaaa;
	opacity: .3;
	filter: Alpha(Opacity=30); /* support: IE8 */
}
.ui-widget-shadow {
	-webkit-box-shadow: -8px -8px 8px #aaaaaa;
	box-shadow: -8px -8px 8px #aaaaaa;
}
includes/js/jquery-ui/themes/smoothness/jquery-ui.min.css000064400000075066147510545420017662 0ustar00/*! jQuery UI - v1.12.1 - 2016-09-14
* http://jqueryui.com
* Includes: core.css, accordion.css, autocomplete.css, menu.css, button.css, controlgroup.css, checkboxradio.css, datepicker.css, dialog.css, draggable.css, resizable.css, progressbar.css, selectable.css, selectmenu.css, slider.css, sortable.css, spinner.css, tabs.css, tooltip.css, theme.css
* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana%2CArial%2Csans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=highlight_soft&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=flat&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=glass&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=glass&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=glass&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=glass&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=glass&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=flat&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=flat&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
* Copyright jQuery Foundation and other contributors; Licensed MIT */

.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important;pointer-events:none}.ui-icon{display:inline-block;vertical-align:middle;margin-top:-.25em;position:relative;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-icon-block{left:50%;margin-left:-8px;display:block}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-accordion .ui-accordion-header{display:block;cursor:pointer;position:relative;margin:2px 0 0 0;padding:.5em .5em .5em .7em;font-size:100%}.ui-accordion .ui-accordion-content{padding:1em 2.2em;border-top:0;overflow:auto}.ui-autocomplete{position:absolute;top:0;left:0;cursor:default}.ui-menu{list-style:none;padding:0;margin:0;display:block;outline:0}.ui-menu .ui-menu{position:absolute}.ui-menu .ui-menu-item{margin:0;cursor:pointer;list-style-image:url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7")}.ui-menu .ui-menu-item-wrapper{position:relative;padding:3px 1em 3px .4em}.ui-menu .ui-menu-divider{margin:5px 0;height:0;font-size:0;line-height:0;border-width:1px 0 0 0}.ui-menu .ui-state-focus,.ui-menu .ui-state-active{margin:-1px}.ui-menu-icons{position:relative}.ui-menu-icons .ui-menu-item-wrapper{padding-left:2em}.ui-menu .ui-icon{position:absolute;top:0;bottom:0;left:.2em;margin:auto 0}.ui-menu .ui-menu-icon{left:auto;right:0}.ui-button{padding:.4em 1em;display:inline-block;position:relative;line-height:normal;margin-right:.1em;cursor:pointer;vertical-align:middle;text-align:center;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;overflow:visible}.ui-button,.ui-button:link,.ui-button:visited,.ui-button:hover,.ui-button:active{text-decoration:none}.ui-button-icon-only{width:2em;box-sizing:border-box;text-indent:-9999px;white-space:nowrap}input.ui-button.ui-button-icon-only{text-indent:0}.ui-button-icon-only .ui-icon{position:absolute;top:50%;left:50%;margin-top:-8px;margin-left:-8px}.ui-button.ui-icon-notext .ui-icon{padding:0;width:2.1em;height:2.1em;text-indent:-9999px;white-space:nowrap}input.ui-button.ui-icon-notext .ui-icon{width:auto;height:auto;text-indent:0;white-space:normal;padding:.4em 1em}input.ui-button::-moz-focus-inner,button.ui-button::-moz-focus-inner{border:0;padding:0}.ui-controlgroup{vertical-align:middle;display:inline-block}.ui-controlgroup > .ui-controlgroup-item{float:left;margin-left:0;margin-right:0}.ui-controlgroup > .ui-controlgroup-item:focus,.ui-controlgroup > .ui-controlgroup-item.ui-visual-focus{z-index:9999}.ui-controlgroup-vertical > .ui-controlgroup-item{display:block;float:none;width:100%;margin-top:0;margin-bottom:0;text-align:left}.ui-controlgroup-vertical .ui-controlgroup-item{box-sizing:border-box}.ui-controlgroup .ui-controlgroup-label{padding:.4em 1em}.ui-controlgroup .ui-controlgroup-label span{font-size:80%}.ui-controlgroup-horizontal .ui-controlgroup-label + .ui-controlgroup-item{border-left:none}.ui-controlgroup-vertical .ui-controlgroup-label + .ui-controlgroup-item{border-top:none}.ui-controlgroup-horizontal .ui-controlgroup-label.ui-widget-content{border-right:none}.ui-controlgroup-vertical .ui-controlgroup-label.ui-widget-content{border-bottom:none}.ui-controlgroup-vertical .ui-spinner-input{width:75%;width:calc( 100% - 2.4em )}.ui-controlgroup-vertical .ui-spinner .ui-spinner-up{border-top-style:solid}.ui-checkboxradio-label .ui-icon-background{box-shadow:inset 1px 1px 1px #ccc;border-radius:.12em;border:none}.ui-checkboxradio-radio-label .ui-icon-background{width:16px;height:16px;border-radius:1em;overflow:visible;border:none}.ui-checkboxradio-radio-label.ui-checkboxradio-checked .ui-icon,.ui-checkboxradio-radio-label.ui-checkboxradio-checked:hover .ui-icon{background-image:none;width:8px;height:8px;border-width:4px;border-style:solid}.ui-checkboxradio-disabled{pointer-events:none}.ui-datepicker{width:17em;padding:.2em .2em 0;display:none}.ui-datepicker .ui-datepicker-header{position:relative;padding:.2em 0}.ui-datepicker .ui-datepicker-prev,.ui-datepicker .ui-datepicker-next{position:absolute;top:2px;width:1.8em;height:1.8em}.ui-datepicker .ui-datepicker-prev-hover,.ui-datepicker .ui-datepicker-next-hover{top:1px}.ui-datepicker .ui-datepicker-prev{left:2px}.ui-datepicker .ui-datepicker-next{right:2px}.ui-datepicker .ui-datepicker-prev-hover{left:1px}.ui-datepicker .ui-datepicker-next-hover{right:1px}.ui-datepicker .ui-datepicker-prev span,.ui-datepicker .ui-datepicker-next span{display:block;position:absolute;left:50%;margin-left:-8px;top:50%;margin-top:-8px}.ui-datepicker .ui-datepicker-title{margin:0 2.3em;line-height:1.8em;text-align:center}.ui-datepicker .ui-datepicker-title select{font-size:1em;margin:1px 0}.ui-datepicker select.ui-datepicker-month,.ui-datepicker select.ui-datepicker-year{width:45%}.ui-datepicker table{width:100%;font-size:.9em;border-collapse:collapse;margin:0 0 .4em}.ui-datepicker th{padding:.7em .3em;text-align:center;font-weight:bold;border:0}.ui-datepicker td{border:0;padding:1px}.ui-datepicker td span,.ui-datepicker td a{display:block;padding:.2em;text-align:right;text-decoration:none}.ui-datepicker .ui-datepicker-buttonpane{background-image:none;margin:.7em 0 0 0;padding:0 .2em;border-left:0;border-right:0;border-bottom:0}.ui-datepicker .ui-datepicker-buttonpane button{float:right;margin:.5em .2em .4em;cursor:pointer;padding:.2em .6em .3em .6em;width:auto;overflow:visible}.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current{float:left}.ui-datepicker.ui-datepicker-multi{width:auto}.ui-datepicker-multi .ui-datepicker-group{float:left}.ui-datepicker-multi .ui-datepicker-group table{width:95%;margin:0 auto .4em}.ui-datepicker-multi-2 .ui-datepicker-group{width:50%}.ui-datepicker-multi-3 .ui-datepicker-group{width:33.3%}.ui-datepicker-multi-4 .ui-datepicker-group{width:25%}.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header{border-left-width:0}.ui-datepicker-multi .ui-datepicker-buttonpane{clear:left}.ui-datepicker-row-break{clear:both;width:100%;font-size:0}.ui-datepicker-rtl{direction:rtl}.ui-datepicker-rtl .ui-datepicker-prev{right:2px;left:auto}.ui-datepicker-rtl .ui-datepicker-next{left:2px;right:auto}.ui-datepicker-rtl .ui-datepicker-prev:hover{right:1px;left:auto}.ui-datepicker-rtl .ui-datepicker-next:hover{left:1px;right:auto}.ui-datepicker-rtl .ui-datepicker-buttonpane{clear:right}.ui-datepicker-rtl .ui-datepicker-buttonpane button{float:left}.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,.ui-datepicker-rtl .ui-datepicker-group{float:right}.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header{border-right-width:0;border-left-width:1px}.ui-datepicker .ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat;left:.5em;top:.3em}.ui-dialog{position:absolute;top:0;left:0;padding:.2em;outline:0}.ui-dialog .ui-dialog-titlebar{padding:.4em 1em;position:relative}.ui-dialog .ui-dialog-title{float:left;margin:.1em 0;white-space:nowrap;width:90%;overflow:hidden;text-overflow:ellipsis}.ui-dialog .ui-dialog-titlebar-close{position:absolute;right:.3em;top:50%;width:20px;margin:-10px 0 0 0;padding:1px;height:20px}.ui-dialog .ui-dialog-content{position:relative;border:0;padding:.5em 1em;background:none;overflow:auto}.ui-dialog .ui-dialog-buttonpane{text-align:left;border-width:1px 0 0 0;background-image:none;margin-top:.5em;padding:.3em 1em .5em .4em}.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset{float:right}.ui-dialog .ui-dialog-buttonpane button{margin:.5em .4em .5em 0;cursor:pointer}.ui-dialog .ui-resizable-n{height:2px;top:0}.ui-dialog .ui-resizable-e{width:2px;right:0}.ui-dialog .ui-resizable-s{height:2px;bottom:0}.ui-dialog .ui-resizable-w{width:2px;left:0}.ui-dialog .ui-resizable-se,.ui-dialog .ui-resizable-sw,.ui-dialog .ui-resizable-ne,.ui-dialog .ui-resizable-nw{width:7px;height:7px}.ui-dialog .ui-resizable-se{right:0;bottom:0}.ui-dialog .ui-resizable-sw{left:0;bottom:0}.ui-dialog .ui-resizable-ne{right:0;top:0}.ui-dialog .ui-resizable-nw{left:0;top:0}.ui-draggable .ui-dialog-titlebar{cursor:move}.ui-draggable-handle{-ms-touch-action:none;touch-action:none}.ui-resizable{position:relative}.ui-resizable-handle{position:absolute;font-size:0.1px;display:block;-ms-touch-action:none;touch-action:none}.ui-resizable-disabled .ui-resizable-handle,.ui-resizable-autohide .ui-resizable-handle{display:none}.ui-resizable-n{cursor:n-resize;height:7px;width:100%;top:-5px;left:0}.ui-resizable-s{cursor:s-resize;height:7px;width:100%;bottom:-5px;left:0}.ui-resizable-e{cursor:e-resize;width:7px;right:-5px;top:0;height:100%}.ui-resizable-w{cursor:w-resize;width:7px;left:-5px;top:0;height:100%}.ui-resizable-se{cursor:se-resize;width:12px;height:12px;right:1px;bottom:1px}.ui-resizable-sw{cursor:sw-resize;width:9px;height:9px;left:-5px;bottom:-5px}.ui-resizable-nw{cursor:nw-resize;width:9px;height:9px;left:-5px;top:-5px}.ui-resizable-ne{cursor:ne-resize;width:9px;height:9px;right:-5px;top:-5px}.ui-progressbar{height:2em;text-align:left;overflow:hidden}.ui-progressbar .ui-progressbar-value{margin:-1px;height:100%}.ui-progressbar .ui-progressbar-overlay{background:url("data:image/gif;base64,R0lGODlhKAAoAIABAAAAAP///yH/C05FVFNDQVBFMi4wAwEAAAAh+QQJAQABACwAAAAAKAAoAAACkYwNqXrdC52DS06a7MFZI+4FHBCKoDeWKXqymPqGqxvJrXZbMx7Ttc+w9XgU2FB3lOyQRWET2IFGiU9m1frDVpxZZc6bfHwv4c1YXP6k1Vdy292Fb6UkuvFtXpvWSzA+HycXJHUXiGYIiMg2R6W459gnWGfHNdjIqDWVqemH2ekpObkpOlppWUqZiqr6edqqWQAAIfkECQEAAQAsAAAAACgAKAAAApSMgZnGfaqcg1E2uuzDmmHUBR8Qil95hiPKqWn3aqtLsS18y7G1SzNeowWBENtQd+T1JktP05nzPTdJZlR6vUxNWWjV+vUWhWNkWFwxl9VpZRedYcflIOLafaa28XdsH/ynlcc1uPVDZxQIR0K25+cICCmoqCe5mGhZOfeYSUh5yJcJyrkZWWpaR8doJ2o4NYq62lAAACH5BAkBAAEALAAAAAAoACgAAAKVDI4Yy22ZnINRNqosw0Bv7i1gyHUkFj7oSaWlu3ovC8GxNso5fluz3qLVhBVeT/Lz7ZTHyxL5dDalQWPVOsQWtRnuwXaFTj9jVVh8pma9JjZ4zYSj5ZOyma7uuolffh+IR5aW97cHuBUXKGKXlKjn+DiHWMcYJah4N0lYCMlJOXipGRr5qdgoSTrqWSq6WFl2ypoaUAAAIfkECQEAAQAsAAAAACgAKAAAApaEb6HLgd/iO7FNWtcFWe+ufODGjRfoiJ2akShbueb0wtI50zm02pbvwfWEMWBQ1zKGlLIhskiEPm9R6vRXxV4ZzWT2yHOGpWMyorblKlNp8HmHEb/lCXjcW7bmtXP8Xt229OVWR1fod2eWqNfHuMjXCPkIGNileOiImVmCOEmoSfn3yXlJWmoHGhqp6ilYuWYpmTqKUgAAIfkECQEAAQAsAAAAACgAKAAAApiEH6kb58biQ3FNWtMFWW3eNVcojuFGfqnZqSebuS06w5V80/X02pKe8zFwP6EFWOT1lDFk8rGERh1TTNOocQ61Hm4Xm2VexUHpzjymViHrFbiELsefVrn6XKfnt2Q9G/+Xdie499XHd2g4h7ioOGhXGJboGAnXSBnoBwKYyfioubZJ2Hn0RuRZaflZOil56Zp6iioKSXpUAAAh+QQJAQABACwAAAAAKAAoAAACkoQRqRvnxuI7kU1a1UU5bd5tnSeOZXhmn5lWK3qNTWvRdQxP8qvaC+/yaYQzXO7BMvaUEmJRd3TsiMAgswmNYrSgZdYrTX6tSHGZO73ezuAw2uxuQ+BbeZfMxsexY35+/Qe4J1inV0g4x3WHuMhIl2jXOKT2Q+VU5fgoSUI52VfZyfkJGkha6jmY+aaYdirq+lQAACH5BAkBAAEALAAAAAAoACgAAAKWBIKpYe0L3YNKToqswUlvznigd4wiR4KhZrKt9Upqip61i9E3vMvxRdHlbEFiEXfk9YARYxOZZD6VQ2pUunBmtRXo1Lf8hMVVcNl8JafV38aM2/Fu5V16Bn63r6xt97j09+MXSFi4BniGFae3hzbH9+hYBzkpuUh5aZmHuanZOZgIuvbGiNeomCnaxxap2upaCZsq+1kAACH5BAkBAAEALAAAAAAoACgAAAKXjI8By5zf4kOxTVrXNVlv1X0d8IGZGKLnNpYtm8Lr9cqVeuOSvfOW79D9aDHizNhDJidFZhNydEahOaDH6nomtJjp1tutKoNWkvA6JqfRVLHU/QUfau9l2x7G54d1fl995xcIGAdXqMfBNadoYrhH+Mg2KBlpVpbluCiXmMnZ2Sh4GBqJ+ckIOqqJ6LmKSllZmsoq6wpQAAAh+QQJAQABACwAAAAAKAAoAAAClYx/oLvoxuJDkU1a1YUZbJ59nSd2ZXhWqbRa2/gF8Gu2DY3iqs7yrq+xBYEkYvFSM8aSSObE+ZgRl1BHFZNr7pRCavZ5BW2142hY3AN/zWtsmf12p9XxxFl2lpLn1rseztfXZjdIWIf2s5dItwjYKBgo9yg5pHgzJXTEeGlZuenpyPmpGQoKOWkYmSpaSnqKileI2FAAACH5BAkBAAEALAAAAAAoACgAAAKVjB+gu+jG4kORTVrVhRlsnn2dJ3ZleFaptFrb+CXmO9OozeL5VfP99HvAWhpiUdcwkpBH3825AwYdU8xTqlLGhtCosArKMpvfa1mMRae9VvWZfeB2XfPkeLmm18lUcBj+p5dnN8jXZ3YIGEhYuOUn45aoCDkp16hl5IjYJvjWKcnoGQpqyPlpOhr3aElaqrq56Bq7VAAAOw==");height:100%;filter:alpha(opacity=25);opacity:0.25}.ui-progressbar-indeterminate .ui-progressbar-value{background-image:none}.ui-selectable{-ms-touch-action:none;touch-action:none}.ui-selectable-helper{position:absolute;z-index:100;border:1px dotted black}.ui-selectmenu-menu{padding:0;margin:0;position:absolute;top:0;left:0;display:none}.ui-selectmenu-menu .ui-menu{overflow:auto;overflow-x:hidden;padding-bottom:1px}.ui-selectmenu-menu .ui-menu .ui-selectmenu-optgroup{font-size:1em;font-weight:bold;line-height:1.5;padding:2px 0.4em;margin:0.5em 0 0 0;height:auto;border:0}.ui-selectmenu-open{display:block}.ui-selectmenu-text{display:block;margin-right:20px;overflow:hidden;text-overflow:ellipsis}.ui-selectmenu-button.ui-button{text-align:left;white-space:nowrap;width:14em}.ui-selectmenu-icon.ui-icon{float:right;margin-top:0}.ui-slider{position:relative;text-align:left}.ui-slider .ui-slider-handle{position:absolute;z-index:2;width:1.2em;height:1.2em;cursor:default;-ms-touch-action:none;touch-action:none}.ui-slider .ui-slider-range{position:absolute;z-index:1;font-size:.7em;display:block;border:0;background-position:0 0}.ui-slider.ui-state-disabled .ui-slider-handle,.ui-slider.ui-state-disabled .ui-slider-range{filter:inherit}.ui-slider-horizontal{height:.8em}.ui-slider-horizontal .ui-slider-handle{top:-.3em;margin-left:-.6em}.ui-slider-horizontal .ui-slider-range{top:0;height:100%}.ui-slider-horizontal .ui-slider-range-min{left:0}.ui-slider-horizontal .ui-slider-range-max{right:0}.ui-slider-vertical{width:.8em;height:100px}.ui-slider-vertical .ui-slider-handle{left:-.3em;margin-left:0;margin-bottom:-.6em}.ui-slider-vertical .ui-slider-range{left:0;width:100%}.ui-slider-vertical .ui-slider-range-min{bottom:0}.ui-slider-vertical .ui-slider-range-max{top:0}.ui-sortable-handle{-ms-touch-action:none;touch-action:none}.ui-spinner{position:relative;display:inline-block;overflow:hidden;padding:0;vertical-align:middle}.ui-spinner-input{border:none;background:none;color:inherit;padding:.222em 0;margin:.2em 0;vertical-align:middle;margin-left:.4em;margin-right:2em}.ui-spinner-button{width:1.6em;height:50%;font-size:.5em;padding:0;margin:0;text-align:center;position:absolute;cursor:default;display:block;overflow:hidden;right:0}.ui-spinner a.ui-spinner-button{border-top-style:none;border-bottom-style:none;border-right-style:none}.ui-spinner-up{top:0}.ui-spinner-down{bottom:0}.ui-tabs{position:relative;padding:.2em}.ui-tabs .ui-tabs-nav{margin:0;padding:.2em .2em 0}.ui-tabs .ui-tabs-nav li{list-style:none;float:left;position:relative;top:0;margin:1px .2em 0 0;border-bottom-width:0;padding:0;white-space:nowrap}.ui-tabs .ui-tabs-nav .ui-tabs-anchor{float:left;padding:.5em 1em;text-decoration:none}.ui-tabs .ui-tabs-nav li.ui-tabs-active{margin-bottom:-1px;padding-bottom:1px}.ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor,.ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor,.ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor{cursor:text}.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor{cursor:pointer}.ui-tabs .ui-tabs-panel{display:block;border-width:0;padding:1em 1.4em;background:none}.ui-tooltip{padding:8px;position:absolute;z-index:9999;max-width:300px}body .ui-tooltip{border-width:2px}.ui-widget{font-family:Verdana,Arial,sans-serif;font-size:1.1em}.ui-widget .ui-widget{font-size:1em}.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:Verdana,Arial,sans-serif;font-size:1em}.ui-widget.ui-widget-content{border:1px solid #d3d3d3}.ui-widget-content{border:1px solid #aaa;background:#fff;color:#222}.ui-widget-content a{color:#222}.ui-widget-header{border:1px solid #aaa;background:#ccc url("images/ui-bg_highlight-soft_75_cccccc_1x100.png") 50% 50% repeat-x;color:#222;font-weight:bold}.ui-widget-header a{color:#222}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default,.ui-button,html .ui-button.ui-state-disabled:hover,html .ui-button.ui-state-disabled:active{border:1px solid #d3d3d3;background:#e6e6e6 url("images/ui-bg_glass_75_e6e6e6_1x400.png") 50% 50% repeat-x;font-weight:normal;color:#555}.ui-state-default a,.ui-state-default a:link,.ui-state-default a:visited,a.ui-button,a:link.ui-button,a:visited.ui-button,.ui-button{color:#555;text-decoration:none}.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus,.ui-button:hover,.ui-button:focus{border:1px solid #999;background:#dadada url("images/ui-bg_glass_75_dadada_1x400.png") 50% 50% repeat-x;font-weight:normal;color:#212121}.ui-state-hover a,.ui-state-hover a:hover,.ui-state-hover a:link,.ui-state-hover a:visited,.ui-state-focus a,.ui-state-focus a:hover,.ui-state-focus a:link,.ui-state-focus a:visited,a.ui-button:hover,a.ui-button:focus{color:#212121;text-decoration:none}.ui-visual-focus{box-shadow:0 0 3px 1px rgb(94,158,214)}.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active,a.ui-button:active,.ui-button:active,.ui-button.ui-state-active:hover{border:1px solid #aaa;background:#fff url("images/ui-bg_glass_65_ffffff_1x400.png") 50% 50% repeat-x;font-weight:normal;color:#212121}.ui-icon-background,.ui-state-active .ui-icon-background{border:#aaa;background-color:#212121}.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#212121;text-decoration:none}.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:1px solid #fcefa1;background:#fbf9ee url("images/ui-bg_glass_55_fbf9ee_1x400.png") 50% 50% repeat-x;color:#363636}.ui-state-checked{border:1px solid #fcefa1;background:#fbf9ee}.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#363636}.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:1px solid #cd0a0a;background:#fef1ec url("images/ui-bg_glass_95_fef1ec_1x400.png") 50% 50% repeat-x;color:#cd0a0a}.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#cd0a0a}.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#cd0a0a}.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:bold}.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:normal}.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}.ui-state-disabled .ui-icon{filter:Alpha(Opacity=35)}.ui-icon{width:16px;height:16px}.ui-icon,.ui-widget-content .ui-icon{background-image:url("images/ui-icons_222222_256x240.png")}.ui-widget-header .ui-icon{background-image:url("images/ui-icons_222222_256x240.png")}.ui-state-hover .ui-icon,.ui-state-focus .ui-icon,.ui-button:hover .ui-icon,.ui-button:focus .ui-icon{background-image:url("images/ui-icons_454545_256x240.png")}.ui-state-active .ui-icon,.ui-button:active .ui-icon{background-image:url("images/ui-icons_454545_256x240.png")}.ui-state-highlight .ui-icon,.ui-button .ui-state-highlight.ui-icon{background-image:url("images/ui-icons_2e83ff_256x240.png")}.ui-state-error .ui-icon,.ui-state-error-text .ui-icon{background-image:url("images/ui-icons_cd0a0a_256x240.png")}.ui-button .ui-icon{background-image:url("images/ui-icons_888888_256x240.png")}.ui-icon-blank{background-position:16px 16px}.ui-icon-caret-1-n{background-position:0 0}.ui-icon-caret-1-ne{background-position:-16px 0}.ui-icon-caret-1-e{background-position:-32px 0}.ui-icon-caret-1-se{background-position:-48px 0}.ui-icon-caret-1-s{background-position:-65px 0}.ui-icon-caret-1-sw{background-position:-80px 0}.ui-icon-caret-1-w{background-position:-96px 0}.ui-icon-caret-1-nw{background-position:-112px 0}.ui-icon-caret-2-n-s{background-position:-128px 0}.ui-icon-caret-2-e-w{background-position:-144px 0}.ui-icon-triangle-1-n{background-position:0 -16px}.ui-icon-triangle-1-ne{background-position:-16px -16px}.ui-icon-triangle-1-e{background-position:-32px -16px}.ui-icon-triangle-1-se{background-position:-48px -16px}.ui-icon-triangle-1-s{background-position:-65px -16px}.ui-icon-triangle-1-sw{background-position:-80px -16px}.ui-icon-triangle-1-w{background-position:-96px -16px}.ui-icon-triangle-1-nw{background-position:-112px -16px}.ui-icon-triangle-2-n-s{background-position:-128px -16px}.ui-icon-triangle-2-e-w{background-position:-144px -16px}.ui-icon-arrow-1-n{background-position:0 -32px}.ui-icon-arrow-1-ne{background-position:-16px -32px}.ui-icon-arrow-1-e{background-position:-32px -32px}.ui-icon-arrow-1-se{background-position:-48px -32px}.ui-icon-arrow-1-s{background-position:-65px -32px}.ui-icon-arrow-1-sw{background-position:-80px -32px}.ui-icon-arrow-1-w{background-position:-96px -32px}.ui-icon-arrow-1-nw{background-position:-112px -32px}.ui-icon-arrow-2-n-s{background-position:-128px -32px}.ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.ui-icon-arrow-2-e-w{background-position:-160px -32px}.ui-icon-arrow-2-se-nw{background-position:-176px -32px}.ui-icon-arrowstop-1-n{background-position:-192px -32px}.ui-icon-arrowstop-1-e{background-position:-208px -32px}.ui-icon-arrowstop-1-s{background-position:-224px -32px}.ui-icon-arrowstop-1-w{background-position:-240px -32px}.ui-icon-arrowthick-1-n{background-position:1px -48px}.ui-icon-arrowthick-1-ne{background-position:-16px -48px}.ui-icon-arrowthick-1-e{background-position:-32px -48px}.ui-icon-arrowthick-1-se{background-position:-48px -48px}.ui-icon-arrowthick-1-s{background-position:-64px -48px}.ui-icon-arrowthick-1-sw{background-position:-80px -48px}.ui-icon-arrowthick-1-w{background-position:-96px -48px}.ui-icon-arrowthick-1-nw{background-position:-112px -48px}.ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.ui-icon-arrowreturn-1-w{background-position:-64px -64px}.ui-icon-arrowreturn-1-n{background-position:-80px -64px}.ui-icon-arrowreturn-1-e{background-position:-96px -64px}.ui-icon-arrowreturn-1-s{background-position:-112px -64px}.ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.ui-icon-arrow-4{background-position:0 -80px}.ui-icon-arrow-4-diag{background-position:-16px -80px}.ui-icon-extlink{background-position:-32px -80px}.ui-icon-newwin{background-position:-48px -80px}.ui-icon-refresh{background-position:-64px -80px}.ui-icon-shuffle{background-position:-80px -80px}.ui-icon-transfer-e-w{background-position:-96px -80px}.ui-icon-transferthick-e-w{background-position:-112px -80px}.ui-icon-folder-collapsed{background-position:0 -96px}.ui-icon-folder-open{background-position:-16px -96px}.ui-icon-document{background-position:-32px -96px}.ui-icon-document-b{background-position:-48px -96px}.ui-icon-note{background-position:-64px -96px}.ui-icon-mail-closed{background-position:-80px -96px}.ui-icon-mail-open{background-position:-96px -96px}.ui-icon-suitcase{background-position:-112px -96px}.ui-icon-comment{background-position:-128px -96px}.ui-icon-person{background-position:-144px -96px}.ui-icon-print{background-position:-160px -96px}.ui-icon-trash{background-position:-176px -96px}.ui-icon-locked{background-position:-192px -96px}.ui-icon-unlocked{background-position:-208px -96px}.ui-icon-bookmark{background-position:-224px -96px}.ui-icon-tag{background-position:-240px -96px}.ui-icon-home{background-position:0 -112px}.ui-icon-flag{background-position:-16px -112px}.ui-icon-calendar{background-position:-32px -112px}.ui-icon-cart{background-position:-48px -112px}.ui-icon-pencil{background-position:-64px -112px}.ui-icon-clock{background-position:-80px -112px}.ui-icon-disk{background-position:-96px -112px}.ui-icon-calculator{background-position:-112px -112px}.ui-icon-zoomin{background-position:-128px -112px}.ui-icon-zoomout{background-position:-144px -112px}.ui-icon-search{background-position:-160px -112px}.ui-icon-wrench{background-position:-176px -112px}.ui-icon-gear{background-position:-192px -112px}.ui-icon-heart{background-position:-208px -112px}.ui-icon-star{background-position:-224px -112px}.ui-icon-link{background-position:-240px -112px}.ui-icon-cancel{background-position:0 -128px}.ui-icon-plus{background-position:-16px -128px}.ui-icon-plusthick{background-position:-32px -128px}.ui-icon-minus{background-position:-48px -128px}.ui-icon-minusthick{background-position:-64px -128px}.ui-icon-close{background-position:-80px -128px}.ui-icon-closethick{background-position:-96px -128px}.ui-icon-key{background-position:-112px -128px}.ui-icon-lightbulb{background-position:-128px -128px}.ui-icon-scissors{background-position:-144px -128px}.ui-icon-clipboard{background-position:-160px -128px}.ui-icon-copy{background-position:-176px -128px}.ui-icon-contact{background-position:-192px -128px}.ui-icon-image{background-position:-208px -128px}.ui-icon-video{background-position:-224px -128px}.ui-icon-script{background-position:-240px -128px}.ui-icon-alert{background-position:0 -144px}.ui-icon-info{background-position:-16px -144px}.ui-icon-notice{background-position:-32px -144px}.ui-icon-help{background-position:-48px -144px}.ui-icon-check{background-position:-64px -144px}.ui-icon-bullet{background-position:-80px -144px}.ui-icon-radio-on{background-position:-96px -144px}.ui-icon-radio-off{background-position:-112px -144px}.ui-icon-pin-w{background-position:-128px -144px}.ui-icon-pin-s{background-position:-144px -144px}.ui-icon-play{background-position:0 -160px}.ui-icon-pause{background-position:-16px -160px}.ui-icon-seek-next{background-position:-32px -160px}.ui-icon-seek-prev{background-position:-48px -160px}.ui-icon-seek-end{background-position:-64px -160px}.ui-icon-seek-start{background-position:-80px -160px}.ui-icon-seek-first{background-position:-80px -160px}.ui-icon-stop{background-position:-96px -160px}.ui-icon-eject{background-position:-112px -160px}.ui-icon-volume-off{background-position:-128px -160px}.ui-icon-volume-on{background-position:-144px -160px}.ui-icon-power{background-position:0 -176px}.ui-icon-signal-diag{background-position:-16px -176px}.ui-icon-signal{background-position:-32px -176px}.ui-icon-battery-0{background-position:-48px -176px}.ui-icon-battery-1{background-position:-64px -176px}.ui-icon-battery-2{background-position:-80px -176px}.ui-icon-battery-3{background-position:-96px -176px}.ui-icon-circle-plus{background-position:0 -192px}.ui-icon-circle-minus{background-position:-16px -192px}.ui-icon-circle-close{background-position:-32px -192px}.ui-icon-circle-triangle-e{background-position:-48px -192px}.ui-icon-circle-triangle-s{background-position:-64px -192px}.ui-icon-circle-triangle-w{background-position:-80px -192px}.ui-icon-circle-triangle-n{background-position:-96px -192px}.ui-icon-circle-arrow-e{background-position:-112px -192px}.ui-icon-circle-arrow-s{background-position:-128px -192px}.ui-icon-circle-arrow-w{background-position:-144px -192px}.ui-icon-circle-arrow-n{background-position:-160px -192px}.ui-icon-circle-zoomin{background-position:-176px -192px}.ui-icon-circle-zoomout{background-position:-192px -192px}.ui-icon-circle-check{background-position:-208px -192px}.ui-icon-circlesmall-plus{background-position:0 -208px}.ui-icon-circlesmall-minus{background-position:-16px -208px}.ui-icon-circlesmall-close{background-position:-32px -208px}.ui-icon-squaresmall-plus{background-position:-48px -208px}.ui-icon-squaresmall-minus{background-position:-64px -208px}.ui-icon-squaresmall-close{background-position:-80px -208px}.ui-icon-grip-dotted-vertical{background-position:0 -224px}.ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.ui-icon-grip-solid-vertical{background-position:-32px -224px}.ui-icon-grip-solid-horizontal{background-position:-48px -224px}.ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.ui-icon-grip-diagonal-se{background-position:-80px -224px}.ui-corner-all,.ui-corner-top,.ui-corner-left,.ui-corner-tl{border-top-left-radius:4px}.ui-corner-all,.ui-corner-top,.ui-corner-right,.ui-corner-tr{border-top-right-radius:4px}.ui-corner-all,.ui-corner-bottom,.ui-corner-left,.ui-corner-bl{border-bottom-left-radius:4px}.ui-corner-all,.ui-corner-bottom,.ui-corner-right,.ui-corner-br{border-bottom-right-radius:4px}.ui-widget-overlay{background:#aaa;opacity:.3;filter:Alpha(Opacity=30)}.ui-widget-shadow{-webkit-box-shadow:-8px -8px 8px #aaa;box-shadow:-8px -8px 8px #aaa}includes/js/jquery-ui/themes/smoothness/images/ui-icons_222222_256x240.png000064400000015561147510545420021754 0ustar00�PNG


IHDR�E�r@gAMA���a cHRMz&�����u0�`:�p��Q<bKGD"�b�tIME�
%��'ETIDATx��m�%Uy�
$!,h ,�%�&���@�|I��EM�r�ݱ�D���2;�f��܉A^$5�Ƣj^�K�@U���-wW���D`�|�q��"�t>������ν3}�S���~�9}�<�>��<�yNp	M�)����`�	�px�h�t%��y�Y��D�^`�O��r�%`:
$%�{��0L�L��?��a|��6��܉�]A�����7P�'@/:�]5JH�&�ay���2���:�8t�y����@����#*'��?��t緝;�Ywגm׸������{�>|Dg7��\J�{�4�K�����3���tf�Z�ޱ�`�7�u7��Yɶ~f]�<��4m�*�<%%�{�^`����FR��
��	l8<O������h8<O������k�2�n6cL��`>�]=u������$��,`�&�+h��k�6��J_*|�K�0��?@�lx��do��m�]�L�3�ݞߌ0.;���T�E,;��4�����t���MO���mP�L�U�A&����e��+��`�8u�]�5�77~"���h8<O������h8<��]��C8�Y��s���Z��}i�A� �֠�)ȞsW.!m�.��
���z[�#��R�䨚��
\R��{���v�����
�r	����R�� ?˝#��[�|�f���`��������y��)�A-��Q�N
�4w���Ϯ:Kr{���河�3��ZP�!0t�{l�\�Y�wSn�P�IA.�Vm�-�R��
$y����sI����@;��eغX�.�v����Yv���B
��n]g������Wc�Vn�*�ôyT�=M�hpt
��+�3�
�'@��	�px4�
�'@��	�p��C�`���=x?��.�j�lk�]�R
��Q.�ޫ5@�P�,[��Z�j6�ƵK��ɟ�ڕ[ ,�P/5/�t�h��zG]Yn�!�wk�9څ��R��+��@���Ktťa.��mK�uD�<i�5Еc�n��[@z��@VmP���g�Q�O���c��:�Ӕ%�{%��܄.緯�ןߖ�F{�h'��@�{����"ȕ�.=>M篂��U�!Lg�K�\A�t�$���Vr�����X˒��`L�o���Me�/��R����+X.�X.]�L�]N��q�%e�7w��"�<
���ּ��p�뻴�ʩ����@	 ��uǤ
O���O7�
�'@��	�px4��� ��P���d�r��vM{w�Q�v�e�{Ȯ]�0�d1w�%L,v���Qwq�yyx`]�jW�.���!��W��W�l�/������D3�,v�܁6]����iZ<:IݯtM�~�9��U��P�i!�s�nS�!�����Q�yU緯lJ�Ț����!$(�7��-��/ޮB¤F[�^�)F�#���*U��$`7���\��!�OU���Ū3��ǐ�_��J�:𨃏ܽ�X6��X���!��|�.��!}t�$ePR�OQա�/P[Cm�b,�=�����X�A��!�th��o14]�Z���h��=O������h8<��#@k��eE�ٲM&��I�KѢ�&�b���04(.�%�t�h��tIH�2���>���D�g�ͳ��]ݢ��@�N����E]�h���ɟ|�T=��m5���@�.#���B���W��2w�Q׿¨a�lrv��E��b)n�#��ය݄��F���/N���6�%�t���]���KX���"�nz��"�t.���'��`[��A-<�d�#�]/\����#
��sDbVG��ӫ��
@�����u>y�-�L��T�i 	rgW=�����)�l�j&�˺;Y��e��F��,��6��C�G_0l;���y�1|��5�'@��	�px4�S�L�T_ʿ���ߐ�:�AD����V��\�cK�
!��e�8�L�}F�{�=.�y��0�������~w,ݭ9�^n�	���gH���<�s�ٌ�g�d���}ܠ):�$:�N��"��<�S!,��qg
駹��\���v��'�g��{;W3�p�I��m���bn��i�;J�����)��s<.$_�.�[5�{�I�V\ⷸ"�[$@d	Ke�%b!���Ѯ���F���n�0#l�§��8o���($���%�f)@6���[L�9�(?�K��o�?wjSl2�^�9�E�L���
�VH)0ͭ�!k@}Cn��U�:l�|�4���
2s���P�R�Q,Q�g�d�p6صp�Ki�*���B�?O�_1�?Ʒ����d��'%d�;��§\��k:�?r7p#��'�r�eL3��[[$꿟3D
�N��_��8�״)��<��z����'�i�>�]Y�,b���}H!��0L�a�4-�U��ڣ$�R|��c��r�Q�x�/a��_��s�e�R�mD��z�$V��\��
��3<ɔ�0㗹1�VD��<�n&�S	��L�C�4�*��5�O���`K�A����`�5�D$�n��}�5����Bf�"�GP��M	rU/���j"�$���!f+��{/��fjt�k�P�t쇘�S��ӹ�r�#��q>#��a��=���5���!*�,6�~ ���^#J�t
Wg{ȃ�s�d,�o9�X1�	��?������*u�u�B��,=�`�޻�'���1l$[�Gx4�
�'@��	���DΞ��-���z���)�E}:g˖���	���gÁ����yk��>��fi�Na~������ɏ�k`�.���7���3P���ȸҜ�;����+
�Zp�Ml�b�in��F�ݬ��L�����پȓ4� ��:�a�.0J���N�.p�k8�NP��x���\lh݅x2i�ǹ?O�H��5M�@�.K4p�\a���/�>a������y�%�^��z�U��������2�5�O'�0��V�Os�M��R�4�"0V���ܞ�����Fq�y�Y����E��L��0])PK~I��rx/��Q�s�*SL1�fn��>��������6U4�>i�#�����\��}cJ��j�rjo�_u8�n�,���JF�g����yFk6�a[0�y�|���k�S�\6����+�����)L*g�	E�D�خq|Y_���'-?Z";�<�W�ϼ=��
��[��\I�L}���‹�7Oq��X�������
���4<��z�7�=~����CP�6w��'ƟL~*?7ȳg����%�n�pM��B��C{��
�L�^�O������2;C!�<��n��$7��B5F&XQ�?̧��>��-��c%D�P]y���_�VaX1�uҗ���E�c��_��t'�[���PP>�`���������4B�� "�O�7��Ց�F���3
�����<�5��ϝ|B�.0�#���b�b���]�,ҥK{�/QW�����ܯ���d������0���~�.�����ꏜ���}��eK�
��Y@�3>?�_��"��X,�u5OԘ��(��x�sG4DI�
��4�
�'@��	�p4���X�N�IM�s(�,�ѡ�ކ<&���R=>@]���ZG�^
_���H�k����|��p7�rF��p��,�/�^>G�-�B���+�7��(z3�d�-��A���^'����qzj����
��z_`�I:L0��T��|��a��Ʉ�܇<S���I�U̅囌3I'.G���Ó��Ґl�{U���R��̌"�g�h.Gj�����,�N�Ui��0`��rƀ1�G�lK�TQ��zy��"?���or�>���'���/CT��S̤�
U��
�(�.����2����Rr ?<
aG�B�Ks�RƔ[�I���lc��yl�U��_�ɷx����O�	�QH1N�c��Ӻ#�?5f4ߣ��3lg��GA��<�aW�9�w@�I6����8��F�߮��U3���hC'��aQ�?m��*�w���\�����9$�;`[���6q��5e�(�|�E��"�8��ODHF+���~��S��m<���*��M�ʖ
._S�9<�ΐ�ҫ�Q�w �ʼn�W)p�?����
gW,
�
'�!pF�Q�8�_/�_z������{!��X�Z7&9�W�&�E��f���!��GU)�ŸY�:�l���{����`s6�������Ãl��d��,Gyx��IC�
_�k���Jw�iK��s8��8�����Mq,y��
��S��V�{�ycP��I�#ి��űo���os�:�*�i�@Z���8]�^��e�xt7�)�%��-T,)�O�\N�K��Q���|�0w�f���Kl.X�����ګ�=_���;fl⧅��;ϱ�m�� ]/�O�B����.y�S���W�/�)���)�xsp;�+��<��.p�ƴjq��I�CE��[���kO���y��
�'@�Q$��6^�=|;���6�������o\
|�ˤt_���⽃��G}�{����K����T���{���q�8b�
�� vK���"�kK���/n8�'@e��6e^���j��Ԫ�p؀�����l)l�㩻���7h��kdC�]�H�4�nnF�[:b�	l�[�ꑬ�'n�(���|[�Ƹ����4%�t�]�BF�h�%Z`%>�nj��Ԅ&����"\r'V�Z�v�D)y�kC���bW�;�I[‰�k�!�����fui�Q����*t�W�s�N_�~W<�
��g�)�'8}ږjHz��D6���6Dkx��3���?��x����Fy
�z��no���O+�v,��bcx���sLw���xt�n�G��ĝl�Nn2�ھ�I�O�ΐl��Ɵw�
�gkг��=�ޜl��Al)l��[�k��;�)"W2:��-�.H�٥��a�q�6���6$\0��o����qnj����cC�[O������h8<O�":F�@�j1Xg� d�b�ݖ��3<c�w��
�'ú��la��jd�iiK�[:�J�w@!? ����~iy��
�0\���]������#cY9%��&
�B�s�Q�@�6[�sJ8�NI���W�߭C'�QۥdFPMP�8a#$��Q(��+K	:��e�B�zi�X|�N�~<Ɯ��G�c̥��5P�\|t+ss(A[����P}��
���|-V���ܘ `�UZLh��v��$0���sƼyihH�� ��?K��Q`�a��#d�*���A��S#\j=��i�,]������6�
�'@��	�px4E���zl@dh���!M����U��c]"!@�n~�R�J%O2�!�E�a��h�=P�~`��$AG��S����r5�2r���b&ATZ�-J��C��-����W8�?�<��8ʽ��*[4�F�T�jG�p�8�&)�v�U<�U���j�i,~�|���?�=�lW��j�˻�RR�$�3�}�n�|TK5..�NQ�E���\�)�k������)ʿxS,��qE����������i�!�{q}�g�.��r
�g�U����Sq����s=W2^��)�.��[�AB�h��W�.��y�wȼ�=�}��0���6�O�8A���6�ϫ�
����O�
�'@��	�px4l�ԕ��T�
ž�����-���-��@]�-�\���A�+����õ��2���{]���$g�������-��h�"��M�M�-��|9�ZvY�?0䷕_,��m�o��9�	aa�.�I�����K�*V�J6[���B�:�n�.����a��P/0K�s����Զ_r�S�FOVh�	 �(��ɸ�����5���@Y����	P�}��x5y��o����E��Z���=����UJȯ|��?t�k3�=h���vn'SO��!`�Շ��]��~r	պpS�n=���ҝ/���A=�p�/c�����Nء�葜�&�(G)�JG�$6y�I�/�,�MP���%�P����(��i���CC~[�����v������W��B篾ꒈ�V���$˹�}��工�(�k&�
Z^�8�S�8>z�E�LHWW�����+�wx0�������-���pxk`��	�px4�
�'@��	�p�A�ܣDk�H��2u]���A��zwnP�E�x��Fy�A�u���m�	0F�0b�G:�1;L�6|�C�GI�C�H�R����ݿ6y��~˘�{�o}@���]�Q~"���h8<O������h8�/�~B�	P�-d����׻͒£"D�
��;R�򠫹 `�d]� a����{� �-�+�P�S#R������3@O z-�̒��
��¿r�vJ���Q��z��`W���_9�HG�x��\���E��A����2͌r��͠�&�~U�����>�w�S[�Σ��- `9�'C�~���C@�e�Cٹ�q�_��	��X�����z���N�%tEXtdate:create2016-09-14T13:32:39-04:00z��%tEXtdate:modify2015-06-01T10:37:21-04:00(An�tEXtSoftwareAdobe ImageReadyq�e<IEND�B`�includes/js/jquery-ui/themes/smoothness/images/ui-icons_cd0a0a_256x240.png000064400000011104147510545420022236 0ustar00�PNG


IHDR��IJ�gAMA���a cHRMz&�����u0�`:�p��Q<,PLTE�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�

�J�ctRNSXG|"2���wf�����ZNz�@@ef�S�F��ccaM�hmz�s��}�����䁎]����������b�p�
Ιi�8*�y�㧁Xȓ�د�͐����ǫ���bKGD�HtIME�
%��'E�IDATx��]c�޻�$,�'$h	��)$uZ7I_�B"H1i���R����kgg���d�l����>�ٽ��=Y���� �d�]ز��s:w/��	f@e�,!�A�$���HW�	��O�|��FM�Z ' ��1��d���9� ��v<�AAr�k�eN���
f����s��an�l�줰.�`�����vb���V��L�tm�)�u\vG(""""""��8sOp�~P¢5��{BK��F���|�lAH־QJ,`�4�.&�J�'�T�o2b���ؓlYQI<�E`	
6��-X�lֈ�VXH��|#j�`E��q��>B�:�qџ�C7�?���xt��v*��ݹ�8�P�6�_��d�Y���J�7��%�߾�A,�U�4��IGb�(��W�
��pB� �k.��b*X�&kVfvZ��?k�	y��Ya�R�o��ڨ�3D�O�HnoH��6ݩ�~
�q��c2""""""Ⲣ��ԎnFb9������ͷ�J
��y��j�Jxsj�Nev'`���dU�۷ķT_�`�����'yo-��/����jf>��%������p}��b�%g�l�:`O�2Lj��-6�.�`=��3��`�����f7ֽu�C�l�!�Q�8s0���x��	��v��I���i)��C۷�#��W	��3�{=`���DDDDDD�g��
yU�Rb��E�:h���������Z���~9јf��vv�_�촸�;�{������%0��}z	{�]	p��]$y>���a�W������,�����:�t�X�a�uO<��m��@R���HAb�!w�(xǰ�6� �=�b%����wzRS�	,:3�﷤�6�1!��!!»�\�a�)yc$������G]���������?�,n����7�s���V�u�����n ��R�(D�6C��e���j
)
��.��t~a�g�e��^��z���@I��R�@��l�s�R"S�Oa��е�b}+X�o��(	rX=�P�����l 9�+4��:X���u�	�pL�(jW,�)l�2[0��hw��3Ї��tE�#"""".2�'d��2�����
e�FC_�7�씮�KŌ&g~>��1�X\!��R��&��H�Z%���!r���
B
�h�O?���pj����lgk�J�{=�`����	z��*�&�� -��!dd�e���A��z_�q����~wY��p�7�|0���������TG$!	&��I�|��|�����@4z</��5o��_\�v��w��%@�.&�4)���6��5xM�i�Ju��u�����U?Zb+���!p�:3!o���Ȋ��I���w�$䂼�$�	
a���=��d@�	(�5� "�*}�f}᠜�:�'���!�����
‡P�����M�Y@�?�oz����Յd�Ƿ`��BCH^�U�P�0,`����T�Qbr��j�~��1�;cL���S`\�?vZ' 4pz9�M憀�l�����
�����X����*2���p`��?�����\�Y6-���c��K8;�Z���]��=�����������w���;�X�M�=��IS�tMvW���5�O�}��hkN.��6�?�4#�E���ّ]��4����L_�S��5���i2=��rW���h�+g.m���v���]��D�-���7o�_z:�9f~#��p�2y�3��������8����X
cC����m$��O��B��Wrmp��dg�i��+Mt�	(W�n�p�&Z6ʤ}g�?^~�_�
*ן�8�����O�V�|jo�v-�y`{S�A)�T�z��"�������-م-������tH,�X�������F�!G@9I5�-i��R���`�k(��&���>�_v�+O�B��T�������Ą1��-"��b�J|� ���R�C�~�9��`(F�H��D��D�I�~rmt�o�*y��nw5yj�=��@%c��]-+�o�;�yA���АE�;U��S@1�!��;��/�?�S�������&_�o��?��g�N�$j.��E~��eo"�>�'O���1(�C]:����7��``,�!���EDDDDlC�0�\98dy�_�ha��}�A����ߗ��|��|�����Ξҿ����
�wnܪ���
sYbHdz�	ި�4��p��`���b!Le]cm�d`I������.���)n�t#6e/YW���#]�L;zs�L��r����rZ�g�\-TB�^�7
@�7����P@>��'��FꝦb1
xHE�T�j_;S�1��j�7�T����%W����{ڢ����O�P�nS��L!w�@�Y��E@�2��&|^}|r��KM��_�%0�8
�"1�
 ��;X����<m2�Q�~��_��ld$z}�`��	5>Q���j��3S��xY`aׄA��|>7��l�c�X��p�xH<,�s�ɉx|2��8	�9��j�P��F8zK�w��/��1�*:@�^&}T�#�����	�`�cp�O�g���i趜L􂕜�T3Ə���}*�(�`��	���.�ŽV��3��+��I�f��u�?��o�c]D1kT� SKzY}`���}<~����*}�0F;l<#""":c�OG��NM1߽�v�6��/�z�~����+u�W‹򉣾k����ř�;y6+��u�hU�TTm�4���m�����m=�T��z�ϼ��!��
_G�S׃�'�rm��-R�^���ksw�5�I��B�F�f&xc��_o/�����t��{-��62̶H@^���M@N�<�q�Ӱ�6R�d���#�6�`6�m���
�	�e��RwcR�l��(_�)tx�	x�2�
pz�9`�����k�>�D
~:?���8�
�=8��S�#������V��Բ,<�a�}��jEDDDDD�#�xրqdVzC�vv���Ϟ i)ΐ�R��ȠB�Z�����mN|�%C�C�AL
Lʴ������8�@�E�`���00%�X��:Y��>W0#�Na�
q�?`%6h+�a��@��9`�O�ޱ�@�]? """"�r��EG�_?>Dg7��rt�>'W�G
?��}�q���E���?h+�K��$@��Ɋ�c��Y��뷓�����1�m��BF��Z��| �5Ƿan�gW2��@}
z��fչ�#}��SP�����ן�	$��P��K��J�W���PX��1��j^X���J4&�R�F�3p�μ�`t����7	�����_.G��.���Ky^�˷�#"""":����!��r���!�B2=F�Vn�^W9x����Udz���ܶ��r�W��Z>U��i%�Gi���T��W:���}�tu������w�t��u%��
>=Żá�<���[�t�{f�	F�O?�$�q���wz����øC,�`
������|R�>��3�,�~�Q(ؾ�B|p"J�W& <ԧo�1�����!%H~*KN��A�,�Z=	�I�NR@e��j�$i�t�5�k~\��Ħc]�m�06��tu���alڕ��J��#""""""<��3�{���$�_XA�'@�?z�o�I��7�L��]�-�����)�n$�������Aׄ�}�>#���@���I�uX�\�oZ@q���r�콙���v�j���;^�~l����ϯ�]-����)����h�Ϗ
-�
�������T�&�!�.%tEXtdate:create2016-09-14T13:32:39-04:00z��%tEXtdate:modify2015-06-01T10:37:21-04:00(An�tEXtSoftwareAdobe ImageReadyq�e<IEND�B`�includes/js/jquery-ui/themes/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png000064400000000504147510545420023013 0ustar00�PNG


IHDR���DgAMA���a cHRMz&�����u0�`:�p��Q<bKGD���1�tIME�	
"��!LIDAT8�cx���0�Fuógύ��ab���x���+�7&F&FN&�oL�_�3|dfbX��I��Ax�<���0:�� �%tEXtdate:create2016-09-14T13:34:08-04:00_Dn�%tEXtdate:modify2016-09-14T13:34:08-04:00.�IEND�B`�includes/js/jquery-ui/themes/smoothness/images/ui-icons_888888_256x240.png000064400000015707147510545420022022 0ustar00�PNG


IHDR�E�r@gAMA���a cHRMz&�����u0�`:�p��Q<bKGD�I�( tIME�
%��'E�IDATx��{�eE}�?H(bX�!�²[R�`����J�H��!w��M�b�ݱ�F�Ѩh����������ڥ�XT�#�D
T�;"ba�Rqw}�����G��)b����}N��9�νsO���sϯ�Ow�~�8�����<��3����@��@F����3��� ��
��$����	+�\���$��������	�����Ook�؞�0�Z	"���"`Jy��Qz�B7i��Q'.�����q���I�v�C���T���2��m�k��5e[7��������G�tͩ�k��!HL�^?3dJ��[��
f�Z���S0�Ms��}`�����T8�t��US�˴�����
��@1�a�`��fe��k���ï6^/
����@������px{�|�A��Q���"���i��O����=�]�}����=���\�z��\��mc�-��ܷ>���(�DЯ�'�L�6=�����;�����㴓l���������ۧ�=�����M/>��ڠ̓6�(�ڬ��0�����$%GI_�km��+�$�.q��
�W7~!����pxh8�4^/
�����ƐQG8�U��k���V��}��A� �栺*�s%�����~�aJYT}�-��c*v�ۭ.�J�=C
`+~�P}����\��=.�4���3���%4Ph�
�F,�_\���ֱWRЃ>4j"m�h��i�@I��zJҼ�y
ts�Y���@�ee'��C뱅r��jm܍��C�&��[�LM�%m{�e^�.�%��f��lN��źuѶd{��$�*�"n�K9(��u��f��c/ӯ<��-�!LU��i���{�&��0�l��W��W/
����@������pxh8�͡�������p��h�x��ѮO)�L��Q.�ޫU@�P--[��j��j6�ƵKǎ�ɟ���5�r	�7���p�h�ۊ{�]Zn�!�w��3ڹ��R���z�z[�t�a.��m[�uD�,i�9Хcw�nϹ�Cz�Ơ�� G�m,o}�R�f��NaÔ�
J�uˁ�
]�o�ۯ�-�M�u`f�]�g�J(��U@�E ��N=��Mϯ�,�U������ `z~S=����n0�o�粤=���	����̙�hJC,���K���J��s �/��&����޸咲C��9Uhua��v�^u9���&m�t�jc�(��0�H�@�ᗂ/
����@������kR�]y{L�*���k����,��CV��=�	&���*a����T��������W;�u�M��B��-����b��5���߮�`���b�p�]��Ӵy4t���tC�����lh�b���ٔއA���/(qW�\���;���Ȋ���G�'�+? ��U�@���낢�s�B����d *
�Ȱ�$�����=�����U!zӊUO�{���'�!`5͔��:���K�U�=�����Œ�@mRa��l�{IB%�b��5}�Z��ƀ��T7	셲��j��D�e�!��0��14]�F���h��4^/
����@�1|��E�f /n�l��&t��B��nȫؠ� 
ʹ�wS�L��O�DHZ�pU]�g���@�*�y�;i�-�JӅR�޽��HCt5�jN��ާ��r�	��L�s���_S>�ܵG]�������ϗ-
򩸹�h_�Y��=^�4Y	����kN��ջ��N�c��>BG��A"I՚L�@<4A��G����<�!s�"=;�a[@�ȼ��U�w0b?��X	=��0�H�j��r~z�V�(��U��&�v$��>�R�@P��骁�lO$���H!�`;p�dvY�$��4m����^�U��_��B����`ڑyP���0l'�z&m0�Oౡ��pxh8�4�$��J�l_ҿ����A�w��`\q����cM�
!OJ�e�8�|z=��=[K<.�i��Ǹ���"0k�ޘ�W�=������r)��0O�1%�^���q�&�l���
;���GX�)����[�ʝυ�c	��CU�rH�=Ž��1�e�q�3<�qm
����LZ��P�(DV�2�K~�,�y)���xQ@�e��z��RB���c�"~���߲D��ɔ��"2'���Z��o���|�8�8ۀW�a�5p��T�a�,i�1�Y�"@������)�?�ӆ��߻�!�b/�$y
rH��C*s��Y�+r����(󰍋x�!�i��{@�:>P�RN���������%���F���./T��D�UC��|��'ȔՇx� �;���w1w�s:�?r�^f��O��E�1�~6	���Y\��U��������h&(� 8��0h'yW����'�w(����:�*yMj�m�v/	����{��p�n�x�/�(�?_��i�Rz5^��z�,f�\��
�,Osx�YM`�/���*�6;x���g2Ë%s�W2i���al!ަ�)�9ϣ��ՕAE�~�5�]�f�"�G"�z
���^`[�[UE0C���!f �,h���5��c5C�m:�X@`�I��b�Sd���s�h���ye�Q�w���B~���+`$�;�\�l�<�A�����r�z$" ��D�/~?U�����e�����!���$�(�<*�@������px-<.�3� @�ac�.'o�aV�Q�t�ŷ����_޲�p�~X�\Q[��t�/X꧓[_(���f,��R�C|
l�e�W���x�1�L)չϰ8�K�*���w�D�/����n��-
}ߑ���B|W}|�·�z&�$u7@�}L�&����i��p=��
��g��jw)^LZ���/
@�H�V��=��5eO��~�7�)�����T�,�9�TA�'n�T=����~�E<�6���:�L����W8�~GIO��,Y�	�H�n�J�#\�x�A�X������N�S癫�E�ҥ���X�'9��!f�g7�\���b�˅|�K��6T��>c�#��%��V]���I%uB�5�9��ů9���\�
@��L��V���I��T�5lΜo�av�Y~�/�z�q�,�b�/쇗�/�&��o�MޮP��H����:`�oaLc��$1>���a_�~�EvQ�5��y��K
��wہ]�V�\MbL}��n�{�7_�$_f�@M�?g|vhЇO��iT=�wx9���6��M�R���D�?�P�d�3�����ddco�/����\��=��Zy����*N�֫�Ig/7��؜�(���8��6���~���bC2XS��ɇ��v>�G�[����UBu���S����f�������%&�?g��.n^�[$CA�9D�`}�O���&R5j�Q|O� c�]z@hd�}����
�vn�A�sw����$�S&�q�N��w��8BHH�.al�/�.uS�?�-¯[
��Q�ߍ�0���~�-��ӗ�쏌���}��dK���@�3>����Lb�,�㺪��k,Ox�AJL��
Q�
��4^/
����y��U�4�T���t�U����m`:���!��E�0ݮu\k��_A>�>��^�Ż���
1��y(�u.pn��f>Nȭ�J�ǹ���"o͐�g(�m!��dz��5p����휝�=���Nن~Y�/1��YP,�DO>��٩�E� {�Q\)|uz}��(�BO�U����#/������}W�H6����gvs!��Pf^��3dB����3u�B�J|��y���e0	,p%��dAN�ؙ���"���o��ԧ�E~��)�_�F�xq��/�O^�_��V=g�Ow���	V�.�+��"�����8<g''�d颹)c���RDz�I�Z�X��E�|�7�����F�(S�@;fqYw\�Sc^s��g�qƕ-v��E��}t�a;��K3�!yo`�1���0wUM�cʢ
���ò�Z���]��!��N�p�⿖����tz[8]�L.I��H⯀H�1E�����U���?~Ιl�6�ngs���9;��u�W0�������QK���|#�h'�_�i�D�u�����5F4x�V����F��t?��@T��C��7Cl����n6�p6��U��vE�9�V���9�rf��	1�k	���`[6����"���Av�E��'xx�h�Q������Js�9����9��8�_����Sq/�\��A��Lv����I�l��_D���N���3t�&�����c,���{��o����u�'p����2M�1>J��Z˿�5���F�-�?>o��ʅؖ�T^�r ZJ�����j�hF�n���m9��zޭν:���y����0c?��]��y�Um-��~�C/d�|l�7�?��
��e_>Dѡ���W���_ִ�%��X�Z�5��,�.�/
G�t�4^���������_��Agܣ7�����ˁ�sE!ܧ���W�*��Agޣ>���p9r��Nٟ�нQ��$�=f��?qb_fƅ�����d�����	&(�_�����5��q^��ϒ���`���_�Ƴ���CN��E�Ds���	@��X��d�������6����\�h�l^�͍��B,1��9�M�2�^�G
���-�W�C��f[X�.��I���!�n?����.3�_P�pǹ��@��}d�@'�������3d>�U�?R��I:}�]�k<`���\LXf�S����X� Y
� E���㶎��ho~sc�v=��C`�x+��!bc�;y�6�Si�qRN��, ����:���W�qUw;�9~�8�c�S�_�\�w'�^x��q'c�����:QFf�����߷�~����,%}ϠW'�;��[=���Z���6^�$�!E$'�-vs+�s�U�(�t�g�M���Á�,��Q�h<1c��X�Ixm`������pxh8�4^��X��o26��nQ��H�A�I�4�;F[��Ւa�A����*jd��Ҧ�a=�4tX/��,~���RJ*�o-O�]�U���ŪiS �+8³�*�d�ބC)^H~M?����f{�lC
��]�GG ���%П֡��Ψ��YT�O��	���Bٯ��yXR�	�>��F/X�����כ�I�,*��YS�/
�����(������`}��D,(��K�Xg�p��4���bZ�D�'OW��h�+RCC�MyЍ�Y���s'!����nJ�C��C#\r=��h�Lݔ���ï6^/
����@Ñ��[���9�3\�;4[C#=��G=6!h�Mݏ^NW��9��:,���s��o0�C�d!�8;�2�&�s\K�t��Žl�:�-�*��%���A$-�����G9�4?�B��8�=��:�5�F�T���cw�[8͖�?�kx�k��j��/~}�c���n"]�����o��.0x�+��>`/]ޭ5�.`+g(�"F�e�r�����s�"����b��ۍ+"xx�p���=����N�K���L�B���g�[y� E���?���Ga�*�J$s�u������̟2$J�LqW3�����[���7�7�C�D��0~ķx%�>1 �X�)Ϲ
G�`j�!�g�����F����o�p��r������pxh82��P����R�������
�^�[����~F:�.��f���~�o���8����\�#�u]��y��
�K�	����|���@4d���mS�Q\���WӣeW��C|[����V~[���OI�t�Mt1�R�D�U���͕l��w؃zwp��]���W��v���`��
�鑫���K�~����-�ְ|1�t4�0w��q>�Psߜ���Id�hE�%u]�\�1{�Θ���M`OpV�$� �/���#����=���65ك��|���S��~X�B�!�~��_1�j]�)}S���/��G" ��C@4	���F_&���D�xv��{\����(�r���ݯH�j�$�+�o�د~jIDpT�@���+yz;���6~h�oK?�B?���o˿)~�yUY: u��R�D����"GYN��K��.F�޶a�~�o�����s8�K�GY�/�pu�����}��l���4�2�AH�ᵁ
����@������pxh8De��t�a�{T��
O��)Cץ{�C@=���P���S��q�HO�3�`c�Ηw�����C�������鑇=B��_�nP�Q�!`�B*rls
�گM�<JBd����[@P漀a�{T�_j8�4^/
����@ñy���zY꯳��2�|�Y�@xT�,{�Ϡak��W��Q�,+$��	[���!\{��v�Sa�O���z1L���=�l��*+ʶ��O9��oOؿ�H_�s�^AS�'eM�)'�;�#]�B���e��A��@d��{���=@}؏p*��&�G)�[@�j�)B�~?����mVie�Ɲ~�ۣ&���c��<z��6���H�~�%tEXtdate:create2016-09-14T13:32:39-04:00z��%tEXtdate:modify2015-06-01T10:37:21-04:00(An�tEXtSoftwareAdobe ImageReadyq�e<IEND�B`�includes/js/jquery-ui/themes/smoothness/images/ui-bg_glass_65_ffffff_1x400.png000064400000000411147510545420023232 0ustar00�PNG


IHDR�G#7vgAMA���a cHRMz&�����u0�`:�p��Q<bKGD݊�tIME�	
"��!IDAT(�ch`��p��h��4�i%tEXtdate:create2016-09-14T13:34:08-04:00_Dn�%tEXtdate:modify2016-09-14T13:34:08-04:00.�IEND�B`�includes/js/jquery-ui/themes/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png000064400000000611147510545420023150 0ustar00�PNG


IHDR���A�gAMA���a cHRMz&�����u0�`:�p��Q<bKGD������	X��tIME�	
"��!�IDATH���!
A���bl����A1{�V�Y0i�x��x�v����D�K_��O��9�a�Ք��}��^�JaȌ�0b�vBA�$,�Q���"_44���=�Sqc�yE��I�W
<kA���i�0��<a$S��y.%tEXtdate:create2016-09-14T13:34:08-04:00_Dn�%tEXtdate:modify2016-09-14T13:34:08-04:00.�IEND�B`�includes/js/jquery-ui/themes/smoothness/images/ui-icons_2e83ff_256x240.png000064400000011104147510545420022203 0ustar00�PNG


IHDR��IJ�gAMA���a cHRMz&�����u0�`:�p��Q<,PLTE.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��.��)�:wctRNSXG|"2���wf�����ZNz�@@ef�S�F��ccaM�hmz�s��}�����䁎]����������b�p�
Ιi�8*�y�㧁Xȓ�د�͐����ǫ���bKGD�HtIME�
%��'E�IDATx��]c�޻�$,�'$h	��)$uZ7I_�B"H1i���R����kgg���d�l����>�ٽ��=Y���� �d�]ز��s:w/��	f@e�,!�A�$���HW�	��O�|��FM�Z ' ��1��d���9� ��v<�AAr�k�eN���
f����s��an�l�줰.�`�����vb���V��L�tm�)�u\vG(""""""��8sOp�~P¢5��{BK��F���|�lAH־QJ,`�4�.&�J�'�T�o2b���ؓlYQI<�E`	
6��-X�lֈ�VXH��|#j�`E��q��>B�:�qџ�C7�?���xt��v*��ݹ�8�P�6�_��d�Y���J�7��%�߾�A,�U�4��IGb�(��W�
��pB� �k.��b*X�&kVfvZ��?k�	y��Ya�R�o��ڨ�3D�O�HnoH��6ݩ�~
�q��c2""""""Ⲣ��ԎnFb9������ͷ�J
��y��j�Jxsj�Nev'`���dU�۷ķT_�`�����'yo-��/����jf>��%������p}��b�%g�l�:`O�2Lj��-6�.�`=��3��`�����f7ֽu�C�l�!�Q�8s0���x��	��v��I���i)��C۷�#��W	��3�{=`���DDDDDD�g��
yU�Rb��E�:h���������Z���~9јf��vv�_�촸�;�{������%0��}z	{�]	p��]$y>���a�W������,�����:�t�X�a�uO<��m��@R���HAb�!w�(xǰ�6� �=�b%����wzRS�	,:3�﷤�6�1!��!!»�\�a�)yc$������G]���������?�,n����7�s���V�u�����n ��R�(D�6C��e���j
)
��.��t~a�g�e��^��z���@I��R�@��l�s�R"S�Oa��е�b}+X�o��(	rX=�P�����l 9�+4��:X���u�	�pL�(jW,�)l�2[0��hw��3Ї��tE�#"""".2�'d��2�����
e�FC_�7�씮�KŌ&g~>��1�X\!��R��&��H�Z%���!r���
B
�h�O?���pj����lgk�J�{=�`����	z��*�&�� -��!dd�e���A��z_�q����~wY��p�7�|0���������TG$!	&��I�|��|�����@4z</��5o��_\�v��w��%@�.&�4)���6��5xM�i�Ju��u�����U?Zb+���!p�:3!o���Ȋ��I���w�$䂼�$�	
a���=��d@�	(�5� "�*}�f}᠜�:�'���!�����
‡P�����M�Y@�?�oz����Յd�Ƿ`��BCH^�U�P�0,`����T�Qbr��j�~��1�;cL���S`\�?vZ' 4pz9�M憀�l�����
�����X����*2���p`��?�����\�Y6-���c��K8;�Z���]��=�����������w���;�X�M�=��IS�tMvW���5�O�}��hkN.��6�?�4#�E���ّ]��4����L_�S��5���i2=��rW���h�+g.m���v���]��D�-���7o�_z:�9f~#��p�2y�3��������8����X
cC����m$��O��B��Wrmp��dg�i��+Mt�	(W�n�p�&Z6ʤ}g�?^~�_�
*ן�8�����O�V�|jo�v-�y`{S�A)�T�z��"�������-م-������tH,�X�������F�!G@9I5�-i��R���`�k(��&���>�_v�+O�B��T�������Ą1��-"��b�J|� ���R�C�~�9��`(F�H��D��D�I�~rmt�o�*y��nw5yj�=��@%c��]-+�o�;�yA���АE�;U��S@1�!��;��/�?�S�������&_�o��?��g�N�$j.��E~��eo"�>�'O���1(�C]:����7��``,�!���EDDDDlC�0�\98dy�_�ha��}�A����ߗ��|��|�����Ξҿ����
�wnܪ���
sYbHdz�	ި�4��p��`���b!Le]cm�d`I������.���)n�t#6e/YW���#]�L;zs�L��r����rZ�g�\-TB�^�7
@�7����P@>��'��FꝦb1
xHE�T�j_;S�1��j�7�T����%W����{ڢ����O�P�nS��L!w�@�Y��E@�2��&|^}|r��KM��_�%0�8
�"1�
 ��;X����<m2�Q�~��_��ld$z}�`��	5>Q���j��3S��xY`aׄA��|>7��l�c�X��p�xH<,�s�ɉx|2��8	�9��j�P��F8zK�w��/��1�*:@�^&}T�#�����	�`�cp�O�g���i趜L􂕜�T3Ə���}*�(�`��	���.�ŽV��3��+��I�f��u�?��o�c]D1kT� SKzY}`���}<~����*}�0F;l<#""":c�OG��NM1߽�v�6��/�z�~����+u�W‹򉣾k����ř�;y6+��u�hU�TTm�4���m�����m=�T��z�ϼ��!��
_G�S׃�'�rm��-R�^���ksw�5�I��B�F�f&xc��_o/�����t��{-��62̶H@^���M@N�<�q�Ӱ�6R�d���#�6�`6�m���
�	�e��RwcR�l��(_�)tx�	x�2�
pz�9`�����k�>�D
~:?���8�
�=8��S�#������V��Բ,<�a�}��jEDDDDD�#�xրqdVzC�vv���Ϟ i)ΐ�R��ȠB�Z�����mN|�%C�C�AL
Lʴ������8�@�E�`���00%�X��:Y��>W0#�Na�
q�?`%6h+�a��@��9`�O�ޱ�@�]? """"�r��EG�_?>Dg7��rt�>'W�G
?��}�q���E���?h+�K��$@��Ɋ�c��Y��뷓�����1�m��BF��Z��| �5Ƿan�gW2��@}
z��fչ�#}��SP�����ן�	$��P��K��J�W���PX��1��j^X���J4&�R�F�3p�μ�`t����7	�����_.G��.���Ky^�˷�#"""":����!��r���!�B2=F�Vn�^W9x����Udz���ܶ��r�W��Z>U��i%�Gi���T��W:���}�tu������w�t��u%��
>=Żá�<���[�t�{f�	F�O?�$�q���wz����øC,�`
������|R�>��3�,�~�Q(ؾ�B|p"J�W& <ԧo�1�����!%H~*KN��A�,�Z=	�I�NR@e��j�$i�t�5�k~\��Ħc]�m�06��tu���alڕ��J��#""""""<��3�{���$�_XA�'@�?z�o�I��7�L��]�-�����)�n$�������Aׄ�}�>#���@���I�uX�\�oZ@q���r�콙���v�j���;^�~l����ϯ�]-����)����h�Ϗ
-�
�������T�&�!�.%tEXtdate:create2016-09-14T13:32:39-04:00z��%tEXtdate:modify2015-06-01T10:37:21-04:00(An�tEXtSoftwareAdobe ImageReadyq�e<IEND�B`�includes/js/jquery-ui/themes/smoothness/images/ui-icons_454545_256x240.png000064400000015662147510545420021775 0ustar00�PNG


IHDR�E�r@gAMA���a cHRMz&�����u0�`:�p��Q<bKGDE�;�-tIME�
%��'E�IDATx��k�%Gu�m;���!�^�pl0�[�HXȹ�H��:w8;�������g1s����]�&��<�����������Clfq؅!,"�·�Wu׫��{�v�Gwn�>U�UuN=�ΩS��x4g
:�������6!�Agb3� �6+�J�D��0���&�s؇N�_�Bs&&�ڏ>~=��
c{v��j%�_�D����Y�E��F
qܸ�G���
�R�SơC���E�ہ!�'�NP)~��tϷ=;��wהme�BH{s�
S���&�S��6MCP6�z�̐!(�hnE�6�VjնcO��6�y7��iʶ~fK����jڬT0��<�2�����6+��^;�4~%����pxh8�4^/
�������:���2�n6eL�h`~��=u���p����r�n0s��Os횶����Wr��G��h �_
�C��mz�-��=�)w���Fi��#�@u-cթP���O{S�s˛^|B��A�'m	TQ���n`.[��ܫ�
|�Եt�7^�p�����@������pxh8�4^�s���C8�U��k���N��}��A� �栺*�s%�����~�aJYT}�-����1�pT��V�P%�%�?p(�>~�PA.E
�����]�1�^��(��[#��\���ֱWRЃ>4j"m�h��I�@I�>]���y�����ҙ�A6�������E:��q7����n�05A���uP��y
L�8�Pj���K�9
[��E�Z���.�Ȫ����.�L��u֛���L��;X�t�0Ua���2�9�@�às���_!�_	l8�4^/
����@����7���R�?�~¥\4����F�>�R�7F��{�V�C��l9w����T�.[�)�?}ڕk ��Po5o�t�h��z'���\C���V�g�s�kۥb�%��@���6��[�\ܩ۶`�6��Y��s�K���ݞs7��j�A��A�n�X�2G�?1�R6+�u
����W@P"�[�U��|��~��m�m`�3�` ��{H+���"Ȥ�N=��Mϯ�4�U������ `z~S=����n0�o�粤=���	����̙�hJ#[4�ٗ�v4�`5�@b�t
n0�w59��-���̩B���(X'�[����6�7i3�S�P�@	� ���Ĥ�����/7^/
����@�����:��6��U.Eo��w��sX����E{Ls�U�Xc��a��u7W�����v��R҅�l���~���٭��N�v]h���;І���i;M�GC'�{I7�9����J��*F���ͦ�>B\u}A���窞o��<�ȟ�Va���CHP"nLu�m߼]݅�����=e���MF�d�U�f;I��l�;:�D�C�ߪ�iŪ'Ƚǐ�_V�L�:p�s/5V��.�~�{3R[�I����AH�]$��fCT5����Pہ�(Ku��^([ݬ�N4]&��E@���.��`C�5o�J�����@������pxh8�4�'��Җ�:���6�lB'�.D��
��Р��xw�5��%��1\U��)F��:���Jm^�[u��R�d�T�wOt�I��&~|Uͩz��q;j~đ
��T�s�D�_S>�ܵ���	��������T��G4������m�������5'W�:m��" �VH�#t|dM‚��nz����:�um���?bG��A�-<[ez#�S/\���х��yD�V{���+��
@�����u6y�#�L����<"�<]5��d�	��l�j&�˺'Y�%i��F��b��g�J�AH�}������P�=o2�O౩��pxh8�4�$��J�l_ҿ����A�wp(��
UN�Q��߆�'$k��L�e>��Wƞ�%��ײ�:��Rf���Q�k����b½�?�.�u���x8��L���Pr�07j�N���װ�����OfX˼I��\�9���9T�n?���S�#��Z֙��kk@�g��?m�b�i��ʘ,������k�ċr�]��=
JO��E�*We~� 4�	-�E,dN�9�wuʬq�w>�c�3��e|�q���Ew��Kځ3%�,y ]�Y����$p��)C�Ǣ�����yR�<KۿK}�AHD`���!�@}En��evp�7��/
4shV��TʉX������J`ג�	~\#gᅑ./T����!�I�j|��*��<^�T���@+�]��uƜ��O�	��e��ә�"�O>������<Y\��U�����s�h&(� 8���0h'yW����ǣ��)����:�)yMj�m�v/	��୅{��Gy�N�h�/�(�?_��i�Rr5^��z�,b��\�S
�,Oqx�YM`�/���*�6�x���g2��
%sT2iW��6�B�E!S�r4�G-2-ՕAE�~�5Ν���f�Ӆ�^�f%��ؑ�VU� ڹ<��b2��a@`�F�^3�ڦ��D2�7	�\����9�F�U��K4�s�׼2t����;_E�!��|�P�D�N'W:�$n�|�XN�r`�b=b��?L���K3���ԍ�E
��2u�����sXf�0	��@0J��
��pxh8�4^F�e�N���1[��7�0�Ԩ�et�ŷ�C��_޲�H�~D�ܬ�|����O'��P����Xb���G�5�E�9`^a�����Gy�3�T�>�^�(/檜���}cݾ~�[��"�����ɯ�����x�·�z&�$u7@�L�&����i��r=G���g��jw)ZLZ�sܗ�~�M+�@�>�7p�Z��O�I��'y#�GSA��S�^z��U����K�!�;4�Og�0͂��_��]%=��e`�d
�ԣ��=K?RP��z��1�2�Ӎ�-���x9u��J�Z�[�Ԛ�[����@b�yvp#��a�i.�\�w���iC���#Y�.�ǵꚸ�M*�R��6ȩ�-~�����fZ���>�Ohզ:�as�|3����|��*��f��0S}a?���~�o�V�J�]@l,5���}c×%������E�SԸ��ՙ�_T����	�!co�����`_Xp����j�9�C�>|"qO�ꁾ�K������t��͝��i��'����
�t #{�P��&re���j�5���hv�^�M�8����G�E�����h��&��]@���X֔��Af����a���J�ɂH�*����_�VnX3�u�g��<}��h���r������PPv!�o��[@�[�D�F- 2��)�o���C��O�SP���{y��#\��_�.1�C���|ܼ���]�,�ҥKY단K���ss��ͅ�d
��w�2L)�߰O˾��e+������'HL�$�1�
�?��Ѽ�z>��!�0�r>��:x���Gt����b�*���h8�.����pxh8�4��6V��tU��9Oyw莇�!+�IT
���.Z��v��Z���F�
"�p������S�΃ѯ��?���!�p!�B|����5Cޞ�H��(zz����i8��[97Q{���
��z_b�:L��XTO>��٭�E� {�R\)|er}�o+�BO�����#/������}W�H6����gvs!��Pf^��3d"#Qg���h��8��la��0`X�J&�ɂ�`7�;a�	E
E���O�8��SҿL�D�_���:Z�Q�z�2��*T5�5�XQ{8!�Wf���S~����!�a�8�9�'J�HSle'�@��&3�Y�E,��_�ɷx�1��O�	�WP�1E�#��u�3j�k�E��y�g\iQ�bp��-���;��;�ť\���{�ǔ����U5e�)�6t����i,�U��J6���os&��X!���؉N���3�˔��A�!�
:�)��OFH*V��3��9g��[yT��,�FU���
&_C�<����ҫ�(_��?(����W1p�?����OW	�p�!�3J8Ҩ��o���W�d��'�`�9�MYa,���3�˳|�Cl�S�Ŧ���.׳wU!�ܟ��z�Bļ�:���b ؑ�r@j�����vx���_����	E�4�X�3|��8Wi�5gq�qp/�+�3v+��s�+Q7�]��.v��)����g�p
(6G���,(6G�?�Xd�� �o����u�'p����0M�:��n���C��f�F�/�?>m�O�΅ؑ�T^�r���R[M)<#���5Ќݤ�>;rZs��[�{u���Y����0c?��]��y�Um-��~��/d�|d�7�?�C
��e_>Dѡ���Wg���>�i�K��ݑX�8ƫ
"��J�fqvq�xh8��������p���_�]|-Y��w
:�����o\��+
�>%����W��7:������r.�\����+t�W��#��*�Oԃؗ��q!�TFQu�~rÁ���	&(�_�����=��q~�}�����`���_�Ƴ���CN%�E�Hs���
�h�k�Q��EϬ����6����\P�O6/���I
m!���ƹC�lg>��҅ 1�O 6X}G��.M�.��W�@@,��T�K�D���6���k,s?ofR"����vޣM�t�2'zlY�=@'�������Ӥ>�U�?R�ω;}�]q?k�o���)\LXf�Ӝ�4��X� ��j��JĽ�A���onLٮg��{�S�a���D���Vf���2��n�2���td�cj�˚k��$��O��ng��y���v'����C�4��6ާ�~4�=MI�3������d��F9�ݑ��W=	dH!�R����
�u�}�8�o�=�-�p`$��^���/O�e4V<F^�pxh8�4^/
��<:F�@Ǫ1�b�
@ȆEԻ#!�'x�H�m:VK�-������
OK�B��H��a� B��QЏH)�DP��<�wW���~��-���`���*�d�ބC)^H~M_T^th�S<ې�����@_.���UvFm��Ȋ�Z@}�M 6���B鯍�yXR�	�>��F/X������[�I�I
V=z�d1a�b�����X�C
:��oF��E,(�����`�p��4�l�bZ�D�'OW��A]4��RCC�-yЍ�i���s'/��U�S�$�C��C#\r=��h�Lݒ���ï6^/
����@��[�D*->
���M�k_��>��zlI�Т�������3,r���uX(�+d��<��d���B�qv�%^I�g��P�Y��=�:�-�*��%���]~�E�#g�r�bo��n�c���LE8����ȝ�6ΰ��O;�㚌�u5�����>�z�A��C���&�C�&����g��I����ZP�
�b�s�b/�p.�����o'G�+���o^�_��n\!�	�噻/�������fvq�=���fJ�>y�O���eĢH���ES|f���D<�`g�iz�I��>�7p5SZت!�{��y{�~�=4�@���#��˹���5�"p@y�U8ZS���q�	�?*6�6x{���ϖ/
����@Ñ
��<�����п�8����~�o���>U8/���yu�67s����|��W�ٿpo.P��<]ץ�Ɵ�/�D��oz��7hz
�! ����6�*�Uy�jr��6~`�oK?�B?���o˿9�iic�.���ͅ��%�w�vms%��]���\7}����U�]��7��%~��T�����_|���JOvh���務����Ѹ[��鄚�����{ [�@+r.����~�ٳ�u��ĭ����O"��2��#��f�`Ͽ=�MM���v�����7Q}�����WL�ZnJߔ����B��� &�����+�$��U��=	;T�=�����(�r����/K�j���+�o�د~jI8&e �1�Uyz;���6~h�oK?�B?���o˿)~�yUY: u��R��XX�
^���fN��K��)F�i޲i�~�o�����8�K���X�/�pu�97���:dس�~�o����!
��6^/
����@�����*�l��;ݣdm�xr��]��1t(�X�nM�^�
j��!!/6��n���t�1P��;FXQ��A^��qƍt�C������Tx�Dq���ۜB��k ���3|�|���9/`����/
����@������pl]h��^@���l!���=�mV$!���3h�Z�`�꠳9
�`�x_� akݞ�=�k�.|�!,��!ثØ�~��A+���l[�������������U?�d0���ğrB0_�S<ҥ�I_���~?������C�W��S|3ȇɲ_��>����N���ք�(�azX�>E����=�<�Y�=��ku��o��������	��U�X��0�%tEXtdate:create2016-09-14T13:32:39-04:00z��%tEXtdate:modify2015-06-01T10:37:21-04:00(An�tEXtSoftwareAdobe ImageReadyq�e<IEND�B`�includes/js/jquery-ui/themes/smoothness/images/ui-bg_glass_75_dadada_1x400.png000064400000000503147510545420023210 0ustar00�PNG


IHDR���DgAMA���a cHRMz&�����u0�`:�p��Q<bKGD���1�tIME�	
"��!KIDAT8�cx����a�"*���n{11�abgb4a����)���&�v�����1101�01�fb\�� 3�EC� _>o%tEXtdate:create2016-09-14T13:34:08-04:00_Dn�%tEXtdate:modify2016-09-14T13:34:08-04:00.�IEND�B`�includes/js/jquery-ui/themes/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png000064400000000505147510545420025021 0ustar00�PNG


IHDRd2��gAMA���a cHRMz&�����u0�`:�p��Q<bKGD���1�tIME�	
"��!MIDATӽΡ
�@џ���n�jn5�$@���(��'G��
i���D�7\��ƍ;N���p��
-ʜu���&����%tEXtdate:create2016-09-14T13:34:08-04:00_Dn�%tEXtdate:modify2016-09-14T13:34:08-04:00.�IEND�B`�includes/js/jquery-ui/themes/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png000064400000000606147510545420023151 0ustar00�PNG


IHDR���A�gAMA���a cHRMz&�����u0�`:�p��Q<bKGD������	X��tIME�	
"��!�IDATH��ϱ
a����\!V��J#X���ЋD}�
.f�>���>��P�կx���x���q��жuɚq���f+��6���[��\�‡����כW�T4r��6:]V:�,
(�Ŵ�8�yG-(d��	H%tEXtdate:create2016-09-14T13:34:08-04:00_Dn�%tEXtdate:modify2016-09-14T13:34:08-04:00.�IEND�B`�includes/js/index.js000064400000032214147510545420010444 0ustar00(()=>{"use strict";const e=window.wp.i18n,t=e=>Math.abs(parseInt(e,10)),a=(e,t,a)=>{const n=new CustomEvent(`wpcf7${t}`,{bubbles:!0,detail:a});"string"==typeof e&&(e=document.querySelector(e)),e.dispatchEvent(n)},n=(e,t)=>{const n=new Map([["init","init"],["validation_failed","invalid"],["acceptance_missing","unaccepted"],["spam","spam"],["aborted","aborted"],["mail_sent","sent"],["mail_failed","failed"],["submitting","submitting"],["resetting","resetting"],["validating","validating"],["payment_required","payment-required"]]);n.has(t)&&(t=n.get(t)),Array.from(n.values()).includes(t)||(t=`custom-${t=(t=t.replace(/[^0-9a-z]+/i," ").trim()).replace(/\s+/,"-")}`);const r=e.getAttribute("data-status");if(e.wpcf7.status=t,e.setAttribute("data-status",t),e.classList.add(t),r&&r!==t){e.classList.remove(r);const t={contactFormId:e.wpcf7.id,pluginVersion:e.wpcf7.pluginVersion,contactFormLocale:e.wpcf7.locale,unitTag:e.wpcf7.unitTag,containerPostId:e.wpcf7.containerPost,status:e.wpcf7.status,prevStatus:r};a(e,"statuschanged",t)}return t},r=e=>{const{root:t,namespace:a="contact-form-7/v1"}=wpcf7.api;return c.reduceRight(((e,t)=>a=>t(a,e)),(e=>{let n,r,{url:c,path:o,endpoint:s,headers:i,body:l,data:p,...d}=e;"string"==typeof s&&(n=a.replace(/^\/|\/$/g,""),r=s.replace(/^\//,""),o=r?n+"/"+r:n),"string"==typeof o&&(-1!==t.indexOf("?")&&(o=o.replace("?","&")),o=o.replace(/^\//,""),c=t+o),i={Accept:"application/json, */*;q=0.1",...i},delete i["X-WP-Nonce"],p&&(l=JSON.stringify(p),i["Content-Type"]="application/json");const f={code:"fetch_error",message:"You are probably offline."},u={code:"invalid_json",message:"The response is not a valid JSON response."};return window.fetch(c||o||window.location.href,{...d,headers:i,body:l}).then((e=>Promise.resolve(e).then((e=>{if(e.status>=200&&e.status<300)return e;throw e})).then((e=>{if(204===e.status)return null;if(e&&e.json)return e.json().catch((()=>{throw u}));throw u}))),(()=>{throw f}))}))(e)},c=[];function o(e,t={}){const{target:a,scope:r=e,...c}=t;if(void 0===e.wpcf7?.schema)return;const o={...e.wpcf7.schema};if(void 0!==a){if(!e.contains(a))return;if(!a.closest(".wpcf7-form-control-wrap[data-name]"))return;if(a.closest(".novalidate"))return}const p=r.querySelectorAll(".wpcf7-form-control-wrap"),d=Array.from(p).reduce(((e,t)=>(t.closest(".novalidate")||t.querySelectorAll(":where( input, textarea, select ):enabled").forEach((t=>{if(t.name)switch(t.type){case"button":case"image":case"reset":case"submit":break;case"checkbox":case"radio":t.checked&&e.append(t.name,t.value);break;case"select-multiple":for(const a of t.selectedOptions)e.append(t.name,a.value);break;case"file":for(const a of t.files)e.append(t.name,a);break;default:e.append(t.name,t.value)}})),e)),new FormData),f=e.getAttribute("data-status");Promise.resolve(n(e,"validating")).then((n=>{if(void 0!==swv){const n=swv.validate(o,d,t);for(const t of p){if(void 0===t.dataset.name)continue;const c=t.dataset.name;if(n.has(c)){const{error:t,validInputs:a}=n.get(c);i(e,c),void 0!==t&&s(e,c,t,{scope:r}),l(e,c,null!=a?a:[])}if(t.contains(a))break}}})).finally((()=>{n(e,f)}))}r.use=e=>{c.unshift(e)};const s=(e,t,a,n)=>{const{scope:r=e,...c}=null!=n?n:{},o=`${e.wpcf7?.unitTag}-ve-${t}`.replaceAll(/[^0-9a-z_-]+/gi,""),s=e.querySelector(`.wpcf7-form-control-wrap[data-name="${t}"] .wpcf7-form-control`);(()=>{const t=document.createElement("li");t.setAttribute("id",o),s&&s.id?t.insertAdjacentHTML("beforeend",`<a href="#${s.id}">${a}</a>`):t.insertAdjacentText("beforeend",a),e.wpcf7.parent.querySelector(".screen-reader-response ul").appendChild(t)})(),r.querySelectorAll(`.wpcf7-form-control-wrap[data-name="${t}"]`).forEach((e=>{const t=document.createElement("span");t.classList.add("wpcf7-not-valid-tip"),t.setAttribute("aria-hidden","true"),t.insertAdjacentText("beforeend",a),e.appendChild(t),e.querySelectorAll("[aria-invalid]").forEach((e=>{e.setAttribute("aria-invalid","true")})),e.querySelectorAll(".wpcf7-form-control").forEach((e=>{e.classList.add("wpcf7-not-valid"),e.setAttribute("aria-describedby",o),"function"==typeof e.setCustomValidity&&e.setCustomValidity(a),e.closest(".use-floating-validation-tip")&&(e.addEventListener("focus",(e=>{t.setAttribute("style","display: none")})),t.addEventListener("click",(e=>{t.setAttribute("style","display: none")})))}))}))},i=(e,t)=>{const a=`${e.wpcf7?.unitTag}-ve-${t}`.replaceAll(/[^0-9a-z_-]+/gi,"");e.wpcf7.parent.querySelector(`.screen-reader-response ul li#${a}`)?.remove(),e.querySelectorAll(`.wpcf7-form-control-wrap[data-name="${t}"]`).forEach((e=>{e.querySelector(".wpcf7-not-valid-tip")?.remove(),e.querySelectorAll("[aria-invalid]").forEach((e=>{e.setAttribute("aria-invalid","false")})),e.querySelectorAll(".wpcf7-form-control").forEach((e=>{e.removeAttribute("aria-describedby"),e.classList.remove("wpcf7-not-valid"),"function"==typeof e.setCustomValidity&&e.setCustomValidity("")}))}))},l=(e,t,a)=>{e.querySelectorAll(`[data-reflection-of="${t}"]`).forEach((e=>{if("output"===e.tagName.toLowerCase()){const t=e;0===a.length&&a.push(t.dataset.default),a.slice(0,1).forEach((e=>{e instanceof File&&(e=e.name),t.textContent=e}))}else e.querySelectorAll("output").forEach((e=>{e.hasAttribute("data-default")?0===a.length?e.removeAttribute("hidden"):e.setAttribute("hidden","hidden"):e.remove()})),a.forEach((a=>{a instanceof File&&(a=a.name);const n=document.createElement("output");n.setAttribute("name",t),n.textContent=a,e.appendChild(n)}))}))};function p(e,t={}){if(wpcf7.blocked)return d(e),void n(e,"submitting");const c=new FormData(e);t.submitter&&t.submitter.name&&c.append(t.submitter.name,t.submitter.value);const o={contactFormId:e.wpcf7.id,pluginVersion:e.wpcf7.pluginVersion,contactFormLocale:e.wpcf7.locale,unitTag:e.wpcf7.unitTag,containerPostId:e.wpcf7.containerPost,status:e.wpcf7.status,inputs:Array.from(c,(e=>{const t=e[0],a=e[1];return!t.match(/^_/)&&{name:t,value:a}})).filter((e=>!1!==e)),formData:c};r({endpoint:`contact-forms/${e.wpcf7.id}/feedback`,method:"POST",body:c,wpcf7:{endpoint:"feedback",form:e,detail:o}}).then((t=>{const r=n(e,t.status);return o.status=t.status,o.apiResponse=t,["invalid","unaccepted","spam","aborted"].includes(r)?a(e,r,o):["sent","failed"].includes(r)&&a(e,`mail${r}`,o),a(e,"submit",o),t})).then((t=>{t.posted_data_hash&&(e.querySelector('input[name="_wpcf7_posted_data_hash"]').value=t.posted_data_hash),"mail_sent"===t.status&&(e.reset(),e.wpcf7.resetOnMailSent=!0),t.invalid_fields&&t.invalid_fields.forEach((t=>{s(e,t.field,t.message)})),e.wpcf7.parent.querySelector('.screen-reader-response [role="status"]').insertAdjacentText("beforeend",t.message),e.querySelectorAll(".wpcf7-response-output").forEach((e=>{e.innerText=t.message}))})).catch((e=>console.error(e)))}r.use(((e,t)=>{if(e.wpcf7&&"feedback"===e.wpcf7.endpoint){const{form:t,detail:r}=e.wpcf7;d(t),a(t,"beforesubmit",r),n(t,"submitting")}return t(e)}));const d=e=>{e.querySelectorAll(".wpcf7-form-control-wrap").forEach((t=>{t.dataset.name&&i(e,t.dataset.name)})),e.wpcf7.parent.querySelector('.screen-reader-response [role="status"]').innerText="",e.querySelectorAll(".wpcf7-response-output").forEach((e=>{e.innerText=""}))};function f(e){const t=new FormData(e),c={contactFormId:e.wpcf7.id,pluginVersion:e.wpcf7.pluginVersion,contactFormLocale:e.wpcf7.locale,unitTag:e.wpcf7.unitTag,containerPostId:e.wpcf7.containerPost,status:e.wpcf7.status,inputs:Array.from(t,(e=>{const t=e[0],a=e[1];return!t.match(/^_/)&&{name:t,value:a}})).filter((e=>!1!==e)),formData:t};r({endpoint:`contact-forms/${e.wpcf7.id}/refill`,method:"GET",wpcf7:{endpoint:"refill",form:e,detail:c}}).then((t=>{e.wpcf7.resetOnMailSent?(delete e.wpcf7.resetOnMailSent,n(e,"mail_sent")):n(e,"init"),c.apiResponse=t,a(e,"reset",c)})).catch((e=>console.error(e)))}r.use(((e,t)=>{if(e.wpcf7&&"refill"===e.wpcf7.endpoint){const{form:t,detail:a}=e.wpcf7;d(t),n(t,"resetting")}return t(e)}));const u=(e,t)=>{for(const a in t){const n=t[a];e.querySelectorAll(`input[name="${a}"]`).forEach((e=>{e.value=""})),e.querySelectorAll(`img.wpcf7-captcha-${a.replaceAll(":","")}`).forEach((e=>{e.setAttribute("src",n)}));const r=/([0-9]+)\.(png|gif|jpeg)$/.exec(n);r&&e.querySelectorAll(`input[name="_wpcf7_captcha_challenge_${a}"]`).forEach((e=>{e.value=r[1]}))}},m=(e,t)=>{for(const a in t){const n=t[a][0],r=t[a][1];e.querySelectorAll(`.wpcf7-form-control-wrap[data-name="${a}"]`).forEach((e=>{e.querySelector(`input[name="${a}"]`).value="",e.querySelector(".wpcf7-quiz-label").textContent=n,e.querySelector(`input[name="_wpcf7_quiz_answer_${a}"]`).value=r}))}};function w(e){const a=new FormData(e);e.wpcf7={id:t(a.get("_wpcf7")),status:e.getAttribute("data-status"),pluginVersion:a.get("_wpcf7_version"),locale:a.get("_wpcf7_locale"),unitTag:a.get("_wpcf7_unit_tag"),containerPost:t(a.get("_wpcf7_container_post")),parent:e.closest(".wpcf7"),get schema(){return wpcf7.schemas.get(this.id)}},wpcf7.schemas.set(e.wpcf7.id,void 0),e.querySelectorAll(".has-spinner").forEach((e=>{e.insertAdjacentHTML("afterend",'<span class="wpcf7-spinner"></span>')})),(e=>{e.querySelectorAll(".wpcf7-exclusive-checkbox").forEach((t=>{t.addEventListener("change",(t=>{const a=t.target.getAttribute("name");e.querySelectorAll(`input[type="checkbox"][name="${a}"]`).forEach((e=>{e!==t.target&&(e.checked=!1)}))}))}))})(e),(e=>{e.querySelectorAll(".has-free-text").forEach((t=>{const a=t.querySelector("input.wpcf7-free-text"),n=t.querySelector('input[type="checkbox"], input[type="radio"]');a.disabled=!n.checked,e.addEventListener("change",(e=>{a.disabled=!n.checked,e.target===n&&n.checked&&a.focus()}))}))})(e),(e=>{e.querySelectorAll(".wpcf7-validates-as-url").forEach((e=>{e.addEventListener("change",(t=>{let a=e.value.trim();a&&!a.match(/^[a-z][a-z0-9.+-]*:/i)&&-1!==a.indexOf(".")&&(a=a.replace(/^\/+/,""),a="http://"+a),e.value=a}))}))})(e),(e=>{if(!e.querySelector(".wpcf7-acceptance")||e.classList.contains("wpcf7-acceptance-as-validation"))return;const t=()=>{let t=!0;e.querySelectorAll(".wpcf7-acceptance").forEach((e=>{if(!t||e.classList.contains("optional"))return;const a=e.querySelector('input[type="checkbox"]');(e.classList.contains("invert")&&a.checked||!e.classList.contains("invert")&&!a.checked)&&(t=!1)})),e.querySelectorAll(".wpcf7-submit").forEach((e=>{e.disabled=!t}))};t(),e.addEventListener("change",(e=>{t()})),e.addEventListener("wpcf7reset",(e=>{t()}))})(e),(e=>{const a=(e,a)=>{const n=t(e.getAttribute("data-starting-value")),r=t(e.getAttribute("data-maximum-value")),c=t(e.getAttribute("data-minimum-value")),o=e.classList.contains("down")?n-a.value.trim().length:a.value.trim().length;e.setAttribute("data-current-value",o),e.innerText=o,r&&r<a.value.length?e.classList.add("too-long"):e.classList.remove("too-long"),c&&a.value.length<c?e.classList.add("too-short"):e.classList.remove("too-short")},n=t=>{t={init:!1,...t},e.querySelectorAll(".wpcf7-character-count").forEach((n=>{const r=n.getAttribute("data-target-name"),c=e.querySelector(`[name="${r}"]`);c&&(c.value=c.defaultValue,a(n,c),t.init&&c.addEventListener("keyup",(e=>{a(n,c)})))}))};n({init:!0}),e.addEventListener("wpcf7reset",(e=>{n()}))})(e),window.addEventListener("load",(t=>{wpcf7.cached&&e.reset()})),e.addEventListener("reset",(t=>{wpcf7.reset(e)})),e.addEventListener("submit",(t=>{wpcf7.submit(e,{submitter:t.submitter}),t.preventDefault()})),e.addEventListener("wpcf7submit",(t=>{t.detail.apiResponse.captcha&&u(e,t.detail.apiResponse.captcha),t.detail.apiResponse.quiz&&m(e,t.detail.apiResponse.quiz)})),e.addEventListener("wpcf7reset",(t=>{t.detail.apiResponse.captcha&&u(e,t.detail.apiResponse.captcha),t.detail.apiResponse.quiz&&m(e,t.detail.apiResponse.quiz)})),e.addEventListener("change",(t=>{t.target.closest(".wpcf7-form-control")&&wpcf7.validate(e,{target:t.target})})),e.addEventListener("wpcf7statuschanged",(t=>{const a=t.detail.status;e.querySelectorAll(".active-on-any").forEach((e=>{e.removeAttribute("inert"),e.classList.remove("active-on-any")})),e.querySelectorAll(`.inert-on-${a}`).forEach((e=>{e.setAttribute("inert","inert"),e.classList.add("active-on-any")}))}))}document.addEventListener("DOMContentLoaded",(t=>{var a;if("undefined"!=typeof wpcf7)if(void 0!==wpcf7.api)if("function"==typeof window.fetch)if("function"==typeof window.FormData)if("function"==typeof NodeList.prototype.forEach)if("function"==typeof String.prototype.replaceAll){wpcf7={init:w,submit:p,reset:f,validate:o,schemas:new Map,...null!==(a=wpcf7)&&void 0!==a?a:{}},document.querySelectorAll("form .wpcf7[data-wpcf7-id]").forEach((t=>{const a=document.createElement("p");a.setAttribute("class","wpcf7-form-in-wrong-place");const n=document.createElement("strong");n.append((0,e.__)("Error:","contact-form-7"));const r=(0,e.__)("This contact form is placed in the wrong place.","contact-form-7");a.append(n," ",r),t.replaceWith(a)})),document.querySelectorAll(".wpcf7 > form").forEach((e=>{wpcf7.init(e),e.closest(".wpcf7").classList.replace("no-js","js")}));for(const e of wpcf7.schemas.keys())r({endpoint:`contact-forms/${e}/feedback/schema`,method:"GET"}).then((t=>{wpcf7.schemas.set(e,t)}))}else console.error("Your browser does not support String.replaceAll().");else console.error("Your browser does not support NodeList.forEach().");else console.error("Your browser does not support window.FormData().");else console.error("Your browser does not support window.fetch().");else console.error("wpcf7.api is not defined.");else console.error("wpcf7 is not defined.")}))})();includes/js/index.asset.php000064400000000140147510545420011726 0ustar00<?php

return array(
	'dependencies' => array(
		'wp-i18n',
	),
	'version' => WPCF7_VERSION,
);
includes/contact-form-template.php000064400000013302147510545420013276 0ustar00<?php

class WPCF7_ContactFormTemplate {

	public static function get_default( $prop = 'form' ) {
		if ( 'form' == $prop ) {
			$template = self::form();
		} elseif ( 'mail' == $prop ) {
			$template = self::mail();
		} elseif ( 'mail_2' == $prop ) {
			$template = self::mail_2();
		} elseif ( 'messages' == $prop ) {
			$template = self::messages();
		} else {
			$template = null;
		}

		return apply_filters( 'wpcf7_default_template', $template, $prop );
	}

	public static function form() {
		$template = sprintf(
			'
<label> %2$s
    [text* your-name autocomplete:name] </label>

<label> %3$s
    [email* your-email autocomplete:email] </label>

<label> %4$s
    [text* your-subject] </label>

<label> %5$s %1$s
    [textarea your-message] </label>

[submit "%6$s"]',
			__( '(optional)', 'contact-form-7' ),
			__( 'Your name', 'contact-form-7' ),
			__( 'Your email', 'contact-form-7' ),
			__( 'Subject', 'contact-form-7' ),
			__( 'Your message', 'contact-form-7' ),
			__( 'Submit', 'contact-form-7' )
		);

		return trim( $template );
	}

	public static function mail() {
		$template = array(
			'subject' => sprintf(
				/* translators: 1: blog name, 2: [your-subject] */
				_x( '%1$s "%2$s"', 'mail subject', 'contact-form-7' ),
				'[_site_title]',
				'[your-subject]'
			),
			'sender' => sprintf(
				'%s <%s>',
				'[_site_title]',
				self::from_email()
			),
			'body' =>
				sprintf(
					/* translators: %s: [your-name] [your-email] */
					__( 'From: %s', 'contact-form-7' ),
					'[your-name] [your-email]'
				) . "\n"
				. sprintf(
					/* translators: %s: [your-subject] */
					__( 'Subject: %s', 'contact-form-7' ),
					'[your-subject]'
				) . "\n\n"
				. __( 'Message Body:', 'contact-form-7' )
				. "\n" . '[your-message]' . "\n\n"
				. '-- ' . "\n"
				. sprintf(
					/* translators: 1: blog name, 2: blog URL */
					__( 'This is a notification that a contact form was submitted on your website (%1$s %2$s).', 'contact-form-7' ),
					'[_site_title]',
					'[_site_url]'
				),
			'recipient' => '[_site_admin_email]',
			'additional_headers' => 'Reply-To: [your-email]',
			'attachments' => '',
			'use_html' => 0,
			'exclude_blank' => 0,
		);

		return $template;
	}

	public static function mail_2() {
		$template = array(
			'active' => false,
			'subject' => sprintf(
				/* translators: 1: blog name, 2: [your-subject] */
				_x( '%1$s "%2$s"', 'mail subject', 'contact-form-7' ),
				'[_site_title]',
				'[your-subject]'
			),
			'sender' => sprintf(
				'%s <%s>',
				'[_site_title]',
				self::from_email()
			),
			'body' =>
				__( 'Message Body:', 'contact-form-7' )
				. "\n" . '[your-message]' . "\n\n"
				. '-- ' . "\n"
				. sprintf(
					/* translators: 1: blog name, 2: blog URL */
					__( 'This email is a receipt for your contact form submission on our website (%1$s %2$s) in which your email address was used. If that was not you, please ignore this message.', 'contact-form-7' ),
					'[_site_title]',
					'[_site_url]'
				),
			'recipient' => '[your-email]',
			'additional_headers' => sprintf(
				'Reply-To: %s',
				'[_site_admin_email]'
			),
			'attachments' => '',
			'use_html' => 0,
			'exclude_blank' => 0,
		);

		return $template;
	}

	public static function from_email() {
		$admin_email = get_option( 'admin_email' );

		if ( wpcf7_is_localhost() ) {
			return $admin_email;
		}

		$sitename = wp_parse_url( network_home_url(), PHP_URL_HOST );
		$sitename = strtolower( $sitename );

		if ( 'www.' === substr( $sitename, 0, 4 ) ) {
			$sitename = substr( $sitename, 4 );
		}

		if ( strpbrk( $admin_email, '@' ) === '@' . $sitename ) {
			return $admin_email;
		}

		return 'wordpress@' . $sitename;
	}

	public static function messages() {
		$messages = array();

		foreach ( wpcf7_messages() as $key => $arr ) {
			$messages[$key] = $arr['default'];
		}

		return $messages;
	}
}

function wpcf7_messages() {
	$messages = array(
		'mail_sent_ok' => array(
			'description'
				=> __( "Sender's message was sent successfully", 'contact-form-7' ),
			'default'
				=> __( "Thank you for your message. It has been sent.", 'contact-form-7' ),
		),

		'mail_sent_ng' => array(
			'description'
				=> __( "Sender's message failed to send", 'contact-form-7' ),
			'default'
				=> __( "There was an error trying to send your message. Please try again later.", 'contact-form-7' ),
		),

		'validation_error' => array(
			'description'
				=> __( "Validation errors occurred", 'contact-form-7' ),
			'default'
				=> __( "One or more fields have an error. Please check and try again.", 'contact-form-7' ),
		),

		'spam' => array(
			'description'
				=> __( "Submission was referred to as spam", 'contact-form-7' ),
			'default'
				=> __( "There was an error trying to send your message. Please try again later.", 'contact-form-7' ),
		),

		'accept_terms' => array(
			'description'
				=> __( "There are terms that the sender must accept", 'contact-form-7' ),
			'default'
				=> __( "You must accept the terms and conditions before sending your message.", 'contact-form-7' ),
		),

		'invalid_required' => array(
			'description'
				=> __( "There is a field that the sender must fill in", 'contact-form-7' ),
			'default'
				=> __( "Please fill out this field.", 'contact-form-7' ),
		),

		'invalid_too_long' => array(
			'description'
				=> __( "There is a field with input that is longer than the maximum allowed length", 'contact-form-7' ),
			'default'
				=> __( "This field has a too long input.", 'contact-form-7' ),
		),

		'invalid_too_short' => array(
			'description'
				=> __( "There is a field with input that is shorter than the minimum allowed length", 'contact-form-7' ),
			'default'
				=> __( "This field has a too short input.", 'contact-form-7' ),
		),
	);

	return apply_filters( 'wpcf7_messages', $messages );
}
includes/l10n.php000064400000006576147510545420007662 0ustar00<?php

/**
 * Retrieves an associative array of languages to which
 * this plugin is translated.
 *
 * @return array Array of languages.
 */
function wpcf7_l10n() {
	static $l10n = array();

	if ( ! empty( $l10n ) ) {
		return $l10n;
	}

	if ( ! is_admin() ) {
		return $l10n;
	}

	require_once( ABSPATH . 'wp-admin/includes/translation-install.php' );

	$api = translations_api( 'plugins', array(
		'slug' => 'contact-form-7',
		'version' => WPCF7_VERSION,
	) );

	if ( is_wp_error( $api )
	or empty( $api['translations'] ) ) {
		return $l10n;
	}

	foreach ( (array) $api['translations'] as $translation ) {
		if ( ! empty( $translation['language'] )
		and ! empty( $translation['english_name'] ) ) {
			$l10n[$translation['language']] = $translation['english_name'];
		}
	}

	return $l10n;
}


/**
 * Returns true if the given locale code looks valid.
 *
 * @param string $locale Locale code.
 */
function wpcf7_is_valid_locale( $locale ) {
	if ( ! is_string( $locale ) ) {
		return false;
	}

	$pattern = '/^[a-z]{2,3}(?:_[a-zA-Z_]{2,})?$/';
	return (bool) preg_match( $pattern, $locale );
}


/**
 * Returns true if the given locale is an RTL language.
 */
function wpcf7_is_rtl( $locale = '' ) {
	static $rtl_locales = array(
		'ar' => 'Arabic',
		'ary' => 'Moroccan Arabic',
		'azb' => 'South Azerbaijani',
		'fa_IR' => 'Persian',
		'haz' => 'Hazaragi',
		'he_IL' => 'Hebrew',
		'ps' => 'Pashto',
		'ug_CN' => 'Uighur',
	);

	if ( empty( $locale )
	and function_exists( 'is_rtl' ) ) {
		return is_rtl();
	}

	if ( empty( $locale ) ) {
		$locale = determine_locale();
	}

	return isset( $rtl_locales[$locale] );
}


/**
 * Loads a translation file into the plugin's text domain.
 *
 * @param string $locale Locale code.
 * @return bool True on success, false on failure.
 */
function wpcf7_load_textdomain( $locale = '' ) {
	$mofile = path_join(
		WP_LANG_DIR . '/plugins/',
		sprintf( '%s-%s.mo', WPCF7_TEXT_DOMAIN, $locale )
	);

	return load_textdomain( WPCF7_TEXT_DOMAIN, $mofile, $locale );
}


/**
 * Unloads translations for the plugin's text domain.
 *
 * @param bool $reloadable Whether the text domain can be loaded
 *             just-in-time again.
 * @return bool True on success, false on failure.
 */
function wpcf7_unload_textdomain( $reloadable = false ) {
	return unload_textdomain( WPCF7_TEXT_DOMAIN, $reloadable );
}


/**
 * Switches translation locale, calls the callback, then switches back
 * to the original locale.
 *
 * @param string $locale Locale code.
 * @param callable $callback The callable to be called.
 * @param mixed $args Parameters to be passed to the callback.
 * @return mixed The return value of the callback.
 */
function wpcf7_switch_locale( $locale, callable $callback, ...$args ) {
	static $available_locales = null;

	if ( ! isset( $available_locales ) ) {
		$available_locales = array_merge(
			array( 'en_US' ),
			get_available_languages()
		);
	}

	$previous_locale = determine_locale();

	$do_switch_locale = (
		$locale !== $previous_locale &&
		in_array( $locale, $available_locales, true ) &&
		in_array( $previous_locale, $available_locales, true )
	);

	if ( $do_switch_locale ) {
		wpcf7_unload_textdomain();
		switch_to_locale( $locale );
		wpcf7_load_textdomain( $locale );
	}

	$result = call_user_func( $callback, ...$args );

	if ( $do_switch_locale ) {
		wpcf7_unload_textdomain( true );
		restore_previous_locale();
		wpcf7_load_textdomain( $previous_locale );
	}

	return $result;
}
includes/html-formatter.php000064400000040511147510545420012040 0ustar00<?php

/**
 * Contact Form 7's class used for formatting HTML fragments.
 */
class WPCF7_HTMLFormatter {

	// HTML component types.
	const text = 0;
	const start_tag = 1;
	const end_tag = 2;
	const comment = 3;

	/**
	 * Tag name reserved for a custom HTML element used as a block placeholder.
	 */
	const placeholder_block = 'placeholder:block';

	/**
	 * Tag name reserved for a custom HTML element used as an inline placeholder.
	 */
	const placeholder_inline = 'placeholder:inline';

	/**
	 * The void elements in HTML.
	 *
	 * @link https://developer.mozilla.org/en-US/docs/Glossary/Void_element
	 */
	const void_elements = array(
		'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input',
		'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr',
		self::placeholder_block, self::placeholder_inline,
	);

	/**
	 * HTML elements that can contain flow content.
	 */
	const p_parent_elements = array(
		'address', 'article', 'aside', 'blockquote', 'body', 'caption',
		'dd', 'details', 'dialog', 'div', 'dt', 'fieldset', 'figcaption',
		'figure', 'footer', 'form', 'header', 'li', 'main', 'nav',
		'section', 'td', 'th',
	);

	/**
	 * HTML elements that can be neither the parent nor a child of
	 * a paragraph element.
	 */
	const p_nonparent_elements = array(
		'colgroup', 'dl', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head',
		'hgroup', 'html', 'legend', 'menu', 'ol', 'pre', 'style', 'summary',
		'table', 'tbody', 'template', 'tfoot', 'thead', 'title', 'tr', 'ul',
	);

	/**
	 * HTML elements in the phrasing content category, plus non-phrasing
	 * content elements that can be grandchildren of a paragraph element.
	 */
	const p_child_elements = array(
		'a', 'abbr', 'area', 'audio', 'b', 'bdi', 'bdo', 'br', 'button',
		'canvas', 'cite', 'code', 'data', 'datalist', 'del', 'dfn',
		'em', 'embed', 'i', 'iframe', 'img', 'input', 'ins', 'kbd',
		'keygen', 'label', 'link', 'map', 'mark', 'meta',
		'meter', 'noscript', 'object', 'output', 'picture', 'progress',
		'q', 'ruby', 's', 'samp', 'script', 'select', 'slot', 'small',
		'span', 'strong', 'sub', 'sup', 'textarea',
		'time', 'u', 'var', 'video', 'wbr',
		'optgroup', 'option', 'rp', 'rt', // non-phrasing grandchildren
		self::placeholder_inline,
	);

	/**
	 * HTML elements that can contain phrasing content.
	 */
	const br_parent_elements = array(
		'a', 'abbr', 'address', 'article', 'aside', 'audio', 'b', 'bdi',
		'bdo', 'blockquote', 'button', 'canvas', 'caption', 'cite', 'code',
		'data', 'datalist', 'dd', 'del', 'details', 'dfn', 'dialog', 'div',
		'dt', 'em', 'fieldset', 'figcaption', 'figure', 'footer', 'form',
		'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'header', 'i', 'ins', 'kbd',
		'label', 'legend', 'li', 'main', 'map', 'mark', 'meter', 'nav',
		'noscript', 'object', 'output', 'p', 'progress', 'q', 'rt',
		'ruby', 's', 'samp', 'section', 'slot', 'small', 'span', 'strong',
		'sub', 'summary', 'sup', 'td', 'th', 'time', 'u', 'var',
		'video',
	);


	// Properties.
	private $options = array();
	private $stacked_elements = array();
	private $output = '';


	/**
	 * Constructor.
	 */
	public function __construct( $options = '' ) {
		$this->options = wp_parse_args( $options, array(
			'auto_br' => true,
			'auto_indent' => true,
		) );
	}


	/**
	 * Separates the given text into chunks of HTML. Each chunk must be an
	 * associative array that includes 'position', 'type', and 'content' keys.
	 *
	 * @param string $input Text to be separated into chunks.
	 * @return iterable Iterable of chunks.
	 */
	public function separate_into_chunks( $input ) {
		$input_bytelength = strlen( $input );
		$position = 0;

		while ( $position < $input_bytelength ) {
			$next_tag = preg_match(
				'/(?:<!--.*?-->|<(?:\/?)[a-z].*?>)/is',
				$input,
				$matches,
				PREG_OFFSET_CAPTURE,
				$position
			);

			if ( ! $next_tag ) {
				yield array(
					'position' => $position,
					'type' => self::text,
					'content' => substr( $input, $position ),
				);

				break;
			}

			$next_tag = $matches[0][0];
			$next_tag_position = $matches[0][1];

			if ( $position < $next_tag_position ) {
				yield array(
					'position' => $position,
					'type' => self::text,
					'content' => substr(
						$input,
						$position,
						$next_tag_position - $position
					),
				);
			}

			if ( '<!' === substr( $next_tag, 0, 2 ) ) {
				$next_tag_type = self::comment;
			} elseif ( '</' === substr( $next_tag, 0, 2 ) ) {
				$next_tag_type = self::end_tag;
			} else {
				$next_tag_type = self::start_tag;
			}

			yield array(
				'position' => $next_tag_position,
				'type' => $next_tag_type,
				'content' => substr(
					$input,
					$next_tag_position,
					strlen( $next_tag )
				),
			);

			$position = $next_tag_position + strlen( $next_tag );
		}
	}


	/**
	 * Normalizes content in each chunk. This may change the type and position
	 * of the chunk.
	 *
	 * @param iterable $chunks The original chunks.
	 * @return iterable Normalized chunks.
	 */
	public function pre_format( $chunks ) {
		$position = 0;

		foreach ( $chunks as $chunk ) {
			$chunk['position'] = $position;

			// Standardize newline characters to "\n".
			$chunk['content'] = str_replace(
				array( "\r\n", "\r" ), "\n", $chunk['content']
			);

			if ( $chunk['type'] === self::start_tag ) {
				list( $chunk['content'] ) =
					self::normalize_start_tag( $chunk['content'] );

				// Replace <br /> by a line break.
				if (
					$this->options['auto_br'] and
					preg_match( '/^<br\s*\/?>$/i', $chunk['content'] )
				) {
					$chunk['type'] = self::text;
					$chunk['content'] = "\n";
				}
			}

			yield $chunk;
			$position = self::calc_next_position( $chunk );
		}
	}


	/**
	 * Concatenates neighboring text chunks to create a single chunk.
	 *
	 * @param iterable $chunks The original chunks.
	 * @return iterable Processed chunks.
	 */
	public function concatenate_texts( $chunks ) {
		$position = 0;
		$text_left = null;

		foreach ( $chunks as $chunk ) {
			$chunk['position'] = $position;

			if ( $chunk['type'] === self::text ) {
				if ( isset( $text_left ) ) {
					$text_left['content'] .= $chunk['content'];
				} else {
					$text_left = $chunk;
				}

				continue;
			}

			if ( isset( $text_left ) ) {
				yield $text_left;
				$chunk['position'] = self::calc_next_position( $text_left );
				$text_left = null;
			}

			yield $chunk;
			$position = self::calc_next_position( $chunk );
		}

		if ( isset( $text_left ) ) {
			yield $text_left;
		}
	}


	/**
	 * Outputs formatted HTML based on the given chunks.
	 *
	 * @param iterable $chunks The original chunks.
	 * @return string Formatted HTML.
	 */
	public function format( $chunks ) {
		$chunks = $this->pre_format( $chunks );
		$chunks = $this->concatenate_texts( $chunks );

		$this->output = '';
		$this->stacked_elements = array();

		foreach ( $chunks as $chunk ) {

			if ( $chunk['type'] === self::text ) {
				$this->append_text( $chunk['content'] );
			}

			if ( $chunk['type'] === self::start_tag ) {
				$this->start_tag( $chunk['content'] );
			}

			if ( $chunk['type'] === self::end_tag ) {
				$this->end_tag( $chunk['content'] );
			}

			if ( $chunk['type'] === self::comment ) {
				$this->append_comment( $chunk['content'] );
			}
		}

		// Close all remaining tags.
		$this->close_all_tags();

		return $this->output;
	}


	/**
	 * Appends a text node content to the output property.
	 *
	 * @param string $content Text node content.
	 */
	public function append_text( $content ) {
		if ( $this->is_inside( array( 'pre', 'template' ) ) ) {
			$this->output .= $content;
			return;
		}

		if (
			empty( $this->stacked_elements ) or
			$this->has_parent( 'p' ) or
			$this->has_parent( self::p_parent_elements )
		) {
			// Close <p> if the content starts with multiple line breaks.
			if ( preg_match( '/^\s*\n\s*\n\s*/', $content ) ) {
				$this->end_tag( 'p' );
			}

			// Split up the contents into paragraphs, separated by double line breaks.
			$paragraphs = preg_split( '/\s*\n\s*\n\s*/', $content );

			$paragraphs = array_filter( $paragraphs, static function ( $paragraph ) {
				return '' !== trim( $paragraph );
			} );

			$paragraphs = array_values( $paragraphs );

			if ( $paragraphs ) {
				if ( $this->is_inside( 'p' ) ) {
					$paragraph = array_shift( $paragraphs );

					$paragraph = self::normalize_paragraph(
						$paragraph,
						$this->options['auto_br']
					);

					$this->output .= $paragraph;
				}

				foreach ( $paragraphs as $paragraph ) {
					$this->start_tag( 'p' );

					$paragraph = ltrim( $paragraph );

					$paragraph = self::normalize_paragraph(
						$paragraph,
						$this->options['auto_br']
					);

					$this->output .= $paragraph;
				}
			}

			// Close <p> if the content ends with multiple line breaks.
			if ( preg_match( '/\s*\n\s*\n\s*$/', $content ) ) {
				$this->end_tag( 'p' );
			}

			// Cases where the content is a single line break.
			if ( preg_match( '/^\s*\n\s*$/', $content ) ) {
				$auto_br = $this->options['auto_br'] && $this->is_inside( 'p' );

				$content = self::normalize_paragraph( $content, $auto_br );

				$this->output .= $content;
			}
		} else {
			$auto_br = $this->options['auto_br'] &&
				$this->has_parent( self::br_parent_elements );

			$content = self::normalize_paragraph( $content, $auto_br );

			$this->output .= $content;
		}
	}


	/**
	 * Appends a start tag to the output property.
	 *
	 * @param string $tag A start tag.
	 */
	public function start_tag( $tag ) {
		list( $tag, $tag_name ) = self::normalize_start_tag( $tag );

		if ( in_array( $tag_name, self::p_child_elements ) ) {
			if (
				! $this->is_inside( 'p' ) and
				! $this->is_inside( self::p_child_elements ) and
				! $this->has_parent( self::p_nonparent_elements )
			) {
				// Open <p> if it does not exist.
				$this->start_tag( 'p' );
			}
		} elseif (
			'p' === $tag_name or
			in_array( $tag_name, self::p_parent_elements ) or
			in_array( $tag_name, self::p_nonparent_elements )
		) {
			// Close <p> if it exists.
			$this->end_tag( 'p' );
		}

		if ( 'dd' === $tag_name or 'dt' === $tag_name ) {
			// Close <dd> and <dt> if closing tag is omitted.
			$this->end_tag( 'dd' );
			$this->end_tag( 'dt' );
		}

		if ( 'li' === $tag_name ) {
			// Close <li> if closing tag is omitted.
			$this->end_tag( 'li' );
		}

		if ( 'optgroup' === $tag_name ) {
			// Close <option> and <optgroup> if closing tag is omitted.
			$this->end_tag( 'option' );
			$this->end_tag( 'optgroup' );
		}

		if ( 'option' === $tag_name ) {
			// Close <option> if closing tag is omitted.
			$this->end_tag( 'option' );
		}

		if ( 'rp' === $tag_name or 'rt' === $tag_name ) {
			// Close <rp> and <rt> if closing tag is omitted.
			$this->end_tag( 'rp' );
			$this->end_tag( 'rt' );
		}

		if ( 'td' === $tag_name or 'th' === $tag_name ) {
			// Close <td> and <th> if closing tag is omitted.
			$this->end_tag( 'td' );
			$this->end_tag( 'th' );
		}

		if ( 'tr' === $tag_name ) {
			// Close <tr> if closing tag is omitted.
			$this->end_tag( 'tr' );
		}

		if ( 'tbody' === $tag_name or 'tfoot' === $tag_name ) {
			// Close <thead> if closing tag is omitted.
			$this->end_tag( 'thead' );
		}

		if ( 'tfoot' === $tag_name ) {
			// Close <tbody> if closing tag is omitted.
			$this->end_tag( 'tbody' );
		}

		if ( ! in_array( $tag_name, self::void_elements ) ) {
			array_unshift( $this->stacked_elements, $tag_name );
		}

		if ( ! in_array( $tag_name, self::p_child_elements ) ) {
			if ( '' !== $this->output ) {
				$this->output = rtrim( $this->output ) . "\n";
			}

			if ( $this->options['auto_indent'] ) {
				$this->output .= self::indent( count( $this->stacked_elements ) - 1 );
			}
		}

		$this->output .= $tag;
	}


	/**
	 * Closes an element and its open descendants at a time.
	 *
	 * @param string $tag An end tag.
	 */
	public function end_tag( $tag ) {
		if ( preg_match( '/<\/(.+?)(?:\s|>)/', $tag, $matches ) ) {
			$tag_name = strtolower( $matches[1] );
		} else {
			$tag_name = strtolower( $tag );
		}

		$stacked_elements = array_values( $this->stacked_elements );

		$tag_position = array_search( $tag_name, $stacked_elements );

		if ( false === $tag_position ) {
			return;
		}

		// Element groups that make up an indirect nesting structure.
		// Descendant can contain ancestors.
		static $nesting_families = array(
			array(
				'ancestors' => array( 'dl', ),
				'descendants' => array( 'dd', 'dt', ),
			),
			array(
				'ancestors' => array( 'ol', 'ul', 'menu', ),
				'descendants' => array( 'li', ),
			),
			array(
				'ancestors' => array( 'table', ),
				'descendants' => array( 'td', 'th', 'tr', 'thead', 'tbody', 'tfoot', ),
			),
		);

		foreach ( $nesting_families as $family ) {
			$ancestors = (array) $family['ancestors'];
			$descendants = (array) $family['descendants'];

			if ( in_array( $tag_name, $descendants ) ) {
				$intersect = array_intersect(
					$ancestors,
					array_slice( $stacked_elements, 0, $tag_position )
				);

				if ( $intersect ) { // Ancestor appears after descendant.
					return;
				}
			}
		}

		while ( $element = array_shift( $this->stacked_elements ) ) {
			$this->append_end_tag( $element );

			if ( $element === $tag_name ) {
				break;
			}
		}
	}


	/**
	 * Closes all open tags.
	 */
	public function close_all_tags() {
		while ( $element = array_shift( $this->stacked_elements ) ) {
			$this->append_end_tag( $element );
		}
	}


	/**
	 * Appends an end tag to the output property.
	 *
	 * @param string $tag_name Tag name.
	 */
	public function append_end_tag( $tag_name ) {
		if ( ! in_array( $tag_name, self::p_child_elements ) ) {
			// Remove unnecessary <br />.
			$this->output = preg_replace( '/\s*<br \/>\s*$/', '', $this->output );

			$this->output = rtrim( $this->output ) . "\n";

			if ( $this->options['auto_indent'] ) {
				$this->output .= self::indent( count( $this->stacked_elements ) );
			}
		}

		$this->output .= sprintf( '</%s>', $tag_name );

		// Remove trailing <p></p>.
		$this->output = preg_replace( '/<p>\s*<\/p>$/', '', $this->output );
	}


	/**
	 * Appends an HTML comment to the output property.
	 *
	 * @param string $tag An HTML comment.
	 */
	public function append_comment( $tag ) {
		$this->output .= $tag;
	}


	/**
	 * Returns true if it is currently inside one of HTML elements specified
	 * by tag names.
	 *
	 * @param string|array $tag_names A tag name or an array of tag names.
	 */
	public function is_inside( $tag_names ) {
		$tag_names = (array) $tag_names;

		foreach ( $this->stacked_elements as $element ) {
			if ( in_array( $element, $tag_names ) ) {
				return true;
			}
		}

		return false;
	}


	/**
	 * Returns true if the parent node is one of HTML elements specified
	 * by tag names.
	 *
	 * @param string|array $tag_names A tag name or an array of tag names.
	 */
	public function has_parent( $tag_names ) {
		$tag_names = (array) $tag_names;

		$parent = reset( $this->stacked_elements );

		if ( false === $parent ) {
			return false;
		}

		return in_array( $parent, $tag_names );
	}


	/**
	 * Calculates the position of the next chunk based on the position and
	 * length of the current chunk.
	 *
	 * @param array $chunk An associative array of the current chunk.
	 * @return int The position of the next chunk.
	 */
	public static function calc_next_position( $chunk ) {
		return $chunk['position'] + strlen( $chunk['content'] );
	}


	/**
	 * Outputs a set of tabs to indent.
	 *
	 * @param int $level Indentation level.
	 * @return string A series of tabs.
	 */
	public static function indent( $level ) {
		$level = (int) $level;

		if ( 0 < $level ) {
			return str_repeat( "\t", $level );
		}

		return '';
	}


	/**
	 * Normalizes a start tag.
	 *
	 * @param string $tag A start tag or a tag name.
	 * @return array An array includes the normalized start tag and tag name.
	 */
	public static function normalize_start_tag( $tag ) {
		if ( preg_match( '/<(.+?)[\s\/>]/', $tag, $matches ) ) {
			$tag_name = strtolower( $matches[1] );
		} else {
			$tag_name = strtolower( $tag );
			$tag = sprintf( '<%s>', $tag_name );
		}

		if ( in_array( $tag_name, self::void_elements ) ) {
			// Normalize void element.
			$tag = preg_replace( '/\s*\/?>/', ' />', $tag );
		}

		return array( $tag, $tag_name );
	}


	/**
	 * Normalizes a paragraph of text.
	 *
	 * @param string $paragraph A paragraph of text.
	 * @param bool $auto_br Optional. If true, line breaks will be replaced
	 *             by a br element.
	 * @return string The normalized paragraph.
	 */
	public static function normalize_paragraph( $paragraph, $auto_br = false ) {
		if ( $auto_br ) {
			$paragraph = preg_replace( '/\s*\n\s*/', "<br />\n", $paragraph );
		}

		$paragraph = preg_replace( '/[ ]+/', " ", $paragraph );

		return $paragraph;
	}

}
includes/validation-functions.php000064400000015245147510545420013241 0ustar00<?php

/**
 * Checks whether a string is a valid NAME token.
 *
 * ID and NAME tokens must begin with a letter ([A-Za-z])
 * and may be followed by any number of letters, digits ([0-9]),
 * hyphens ("-"), underscores ("_"), colons (":"), and periods (".").
 *
 * @link http://www.w3.org/TR/html401/types.html#h-6.2
 *
 * @return bool True if it is a valid name, false if not.
 */
function wpcf7_is_name( $text ) {
	return preg_match( '/^[A-Za-z][-A-Za-z0-9_:.]*$/', $text );
}


/**
 * Checks whether the given text is a well-formed email address.
 */
function wpcf7_is_email( $text ) {
	$result = is_email( $text );
	return apply_filters( 'wpcf7_is_email', $result, $text );
}


/**
 * Checks whether the given text is a well-formed URL.
 */
function wpcf7_is_url( $text ) {
	$scheme = wp_parse_url( $text, PHP_URL_SCHEME );
	$result = $scheme && in_array( $scheme, wp_allowed_protocols(), true );
	return apply_filters( 'wpcf7_is_url', $result, $text );
}


/**
 * Checks whether the given text is a well-formed telephone number.
 */
function wpcf7_is_tel( $text ) {
	$text = preg_replace( '/[#*].*$/', '', $text ); // Remove extension
	$text = preg_replace( '%[()/.*#\s-]+%', '', $text );

	$is_international = false ||
		str_starts_with( $text, '+' ) ||
		str_starts_with( $text, '00' );

	if ( $is_international ) {
		$text = '+' . preg_replace( '/^[+0]+/', '', $text );
	}

	$result = true;

	if ( ! preg_match( '/^[+]?[0-9]+$/', $text ) ) {
		$result = false;
	}

	if ( ! ( 6 < strlen( $text ) and strlen( $text ) < 16 ) ) {
		$result = false;
	}

	return apply_filters( 'wpcf7_is_tel', $result, $text );
}


/**
 * Checks whether the given text is a well-formed number.
 *
 * @link https://html.spec.whatwg.org/multipage/input.html#number-state-(type=number)
 */
function wpcf7_is_number( $text ) {
	$result = false;

	$patterns = array(
		'/^[-]?[0-9]+(?:[eE][+-]?[0-9]+)?$/',
		'/^[-]?(?:[0-9]+)?[.][0-9]+(?:[eE][+-]?[0-9]+)?$/',
	);

	foreach ( $patterns as $pattern ) {
		if ( preg_match( $pattern, $text ) ) {
			$result = true;
			break;
		}
	}

	return apply_filters( 'wpcf7_is_number', $result, $text );
}


/**
 * Checks whether the given text is a valid date.
 *
 * @link https://html.spec.whatwg.org/multipage/input.html#date-state-(type=date)
 */
function wpcf7_is_date( $text ) {
	$result = preg_match(
		'/^([0-9]{4,})-([0-9]{2})-([0-9]{2})$/',
		$text,
		$matches
	);

	if ( $result ) {
		$result = checkdate( $matches[2], $matches[3], $matches[1] );
	}

	return apply_filters( 'wpcf7_is_date', $result, $text );
}


/**
 * Checks whether the given text is a valid time.
 *
 * @link https://html.spec.whatwg.org/multipage/input.html#time-state-(type=time)
 */
function wpcf7_is_time( $text ) {
	$result = preg_match(
		'/^([0-9]{2})\:([0-9]{2})(?:\:([0-9]{2}))?$/',
		$text,
		$matches
	);

	if ( $result ) {
		$hour = (int) $matches[1];
		$minute = (int) $matches[2];
		$second = empty( $matches[3] ) ? 0 : (int) $matches[3];

		$result = 0 <= $hour && $hour <= 23 &&
			0 <= $minute && $minute <= 59 &&
			0 <= $second && $second <= 59;
	}

	return apply_filters( 'wpcf7_is_time', $result, $text );
}


/**
 * Checks whether the given text is a well-formed mailbox list.
 *
 * @param string|array $mailbox_list The subject to be checked.
 *                     Comma-separated string or an array of mailboxes.
 * @return array|bool Array of email addresses if all items are well-formed
 *                    mailbox, false if not.
 */
function wpcf7_is_mailbox_list( $mailbox_list ) {
	if ( ! is_array( $mailbox_list ) ) {
		$mailbox_text = (string) $mailbox_list;

		$mailbox_text = preg_replace(
			'/\\\\(?:\"|\')/',
			'esc-quote',
			$mailbox_text
		);

		$mailbox_text = preg_replace(
			'/(?:\".*?\"|\'.*?\')/',
			'quoted-string',
			$mailbox_text
		);

		$mailbox_list = explode( ',', $mailbox_text );
	}

	$addresses = array();

	foreach ( $mailbox_list as $mailbox ) {
		if ( ! is_string( $mailbox ) ) {
			return false;
		}

		$mailbox = trim( $mailbox );

		if ( '' === $mailbox ) {
			continue;
		}

		if ( preg_match( '/<(.+)>$/', $mailbox, $matches ) ) {
			$addr_spec = $matches[1];
		} else {
			$addr_spec = $mailbox;
		}

		if ( ! wpcf7_is_email( $addr_spec ) ) {
			return false;
		}

		$addresses[] = $addr_spec;
	}

	return $addresses;
}


/**
 * Checks whether an email address belongs to a domain.
 *
 * @param string $email A mailbox or a comma-separated list of mailboxes.
 * @param string $domain Internet domain name.
 * @return bool True if all of the email addresses belong to the domain,
 *              false if not.
 */
function wpcf7_is_email_in_domain( $email, $domain ) {
	$email_list = wpcf7_is_mailbox_list( $email );

	if ( false === $email_list ) {
		return false;
	}

	$domain = strtolower( $domain );

	foreach ( $email_list as $email ) {
		$email_domain = substr( $email, strrpos( $email, '@' ) + 1 );
		$email_domain = strtolower( $email_domain );
		$domain_parts = explode( '.', $domain );

		do {
			$site_domain = implode( '.', $domain_parts );

			if ( $site_domain == $email_domain ) {
				continue 2;
			}

			array_shift( $domain_parts );
		} while ( $domain_parts );

		return false;
	}

	return true;
}


/**
 * Checks whether an email address belongs to the site domain.
 */
function wpcf7_is_email_in_site_domain( $email ) {
	if ( wpcf7_is_localhost() ) {
		return true;
	}

	$homes = array(
		home_url(),
		network_home_url(),
	);

	$homes = array_unique( $homes );

	foreach ( $homes as $home ) {
		$sitename = wp_parse_url( $home, PHP_URL_HOST );

		if ( WP_Http::is_ip_address( $sitename ) ) {
			return true;
		}

		if ( wpcf7_is_email_in_domain( $email, $sitename ) ) {
			return true;
		}
	}

	return false;
}


/**
 * Verifies that a given file path is under the directories that WordPress
 * manages for user contents.
 *
 * Returns false if the file at the given path does not exist yet.
 *
 * @param string $path A file path.
 * @return bool True if the path is under the content directories,
 *              false otherwise.
 */
function wpcf7_is_file_path_in_content_dir( $path ) {
	if ( ! is_string( $path ) or '' === $path ) {
		return false;
	}

	$callback = static function ( $path, $dir ) {
		if ( $real_path = realpath( $path ) ) {
			$path = $real_path;
		} else {
			return false;
		}

		if ( $real_dir = realpath( $dir ) ) {
			$dir = trailingslashit( $real_dir );
		} else {
			return false;
		}

		return str_starts_with(
			wp_normalize_path( $path ),
			wp_normalize_path( $dir )
		);
	};

	if (
		call_user_func( $callback, $path, WP_CONTENT_DIR )
	) {
		return true;
	}

	if (
		defined( 'UPLOADS' ) and
		call_user_func( $callback, $path, ABSPATH . UPLOADS )
	) {
		return true;
	}

	if (
		defined( 'WP_TEMP_DIR' ) and
		call_user_func( $callback, $path, WP_TEMP_DIR )
	) {
		return true;
	}

	return false;
}
readme.txt000064400000010622147510545420006552 0ustar00=== Contact Form 7 ===
Contributors: takayukister
Donate link: https://contactform7.com/donate/
Tags: contact form, schema-woven validation
Tested up to: 6.7
Requires at least: 6.6
Requires PHP: 7.4
Stable tag: 6.0.3
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Just another contact form plugin. Simple but flexible.

== Description ==

Contact Form 7 is a plugin designed to be a practical tool for all WordPress users who embrace the philosophy of free and open source software. It employs sophisticatedly modularized architecture and its original [Schema-Woven Validation](https://contactform7.com/schema-woven-validation/) technology.

= Docs and support =

You can find [docs](https://contactform7.com/docs/), [FAQ](https://contactform7.com/faq/) and more detailed information about Contact Form 7 on [contactform7.com](https://contactform7.com/). When you cannot find the answer to your question on the FAQ or in any of the documentation, check the [support forum](https://wordpress.org/support/plugin/contact-form-7/) on WordPress.org. If you cannot locate any topics that pertain to your particular issue, post a new topic for it.

= Contact Form 7 needs your support =

It is hard to continue to maintain this plugin without support from users like you. There are several ways for you to [contribute to the project](https://contactform7.com/contributing/): testing, coding, translating it into your local languages, helping other users, financial donations, etc, etc. We equally welcome you regardless of the way you contribute.

= Privacy notices =

With the default configuration, this plugin, in itself, does not:

* track users by stealth;
* write any user personal data to the database;
* send any data to external servers;
* use cookies.

If you activate certain features in this plugin, the contact form submitter's personal data, including their IP address, may be sent to the service provider. Thus, confirming the provider's privacy policy is recommended. These features include:

* reCAPTCHA ([Google](https://policies.google.com/?hl=en))
* Akismet ([Automattic](https://automattic.com/privacy/))
* [Constant Contact](https://www.constantcontact.com/legal/privacy-center)
* [Brevo](https://www.brevo.com/legal/privacypolicy/)
* [Stripe](https://stripe.com/privacy)

== Installation ==

1. Upload the entire `contact-form-7` folder to the `/wp-content/plugins/` directory.
1. Activate the plugin through the **Plugins** screen (**Plugins > Installed Plugins**).

You will find **Contact** menu in your WordPress admin screen.

For basic usage, have a look at the [plugin's website](https://contactform7.com/).

== Frequently Asked Questions ==

Do you have questions or issues with Contact Form 7? Use these support channels appropriately.

1. [Docs](https://contactform7.com/docs/)
1. [FAQ](https://contactform7.com/faq/)
1. [Support forum](https://wordpress.org/support/plugin/contact-form-7/)

[Support](https://contactform7.com/support/)

== Screenshots ==

1. screenshot-1.png

== Changelog ==

For more information, see [Releases](https://contactform7.com/category/releases/).

= 6.0.3 =

* Updates the copyright year to 2025.
* Updates the "Contact Form 7 needs your support" message content.
* Updates the Constant Contact deprecation warning.

= 6.0.2 =

* Removes unnecessary type declaration from nullable arguments to avoid deprecation warnings in PHP 8.4.

= 6.0.1 =

[https://contactform7.com/contact-form-7-601/](https://contactform7.com/contact-form-7-601/)

= 6.0 =

[https://contactform7.com/contact-form-7-60/](https://contactform7.com/contact-form-7-60/)

= 5.9.7 =

[https://contactform7.com/contact-form-7-597/](https://contactform7.com/contact-form-7-597/)

= 5.9.6 =

[https://contactform7.com/contact-form-7-596/](https://contactform7.com/contact-form-7-596/)

= 5.9.5 =

[https://contactform7.com/contact-form-7-595/](https://contactform7.com/contact-form-7-595/)

= 5.9.4 =

[https://contactform7.com/contact-form-7-594/](https://contactform7.com/contact-form-7-594/)

= 5.9.3 =

[https://contactform7.com/contact-form-7-593/](https://contactform7.com/contact-form-7-593/)

= 5.9.2 =

[https://contactform7.com/contact-form-7-592/](https://contactform7.com/contact-form-7-592/)

= 5.9 =

[https://contactform7.com/contact-form-7-59/](https://contactform7.com/contact-form-7-59/)

== Upgrade Notice ==
modules/really-simple-captcha.php000064400000033511147510545420013117 0ustar00<?php
/**
** A base module for [captchac] and [captchar]
**/

/* form_tag handler */

add_action( 'wpcf7_init', 'wpcf7_add_form_tag_captcha', 10, 0 );

function wpcf7_add_form_tag_captcha() {
	// CAPTCHA-Challenge (image)
	wpcf7_add_form_tag( 'captchac',
		'wpcf7_captchac_form_tag_handler',
		array(
			'name-attr' => true,
			'zero-controls-container' => true,
			'not-for-mail' => true,
		)
	);

	// CAPTCHA-Response (input)
	wpcf7_add_form_tag( 'captchar',
		'wpcf7_captchar_form_tag_handler',
		array(
			'name-attr' => true,
			'do-not-store' => true,
			'not-for-mail' => true,
		)
	);
}

function wpcf7_captchac_form_tag_handler( $tag ) {
	if ( ! class_exists( 'ReallySimpleCaptcha' ) ) {
		$error = sprintf(
			/* translators: %s: link labeled 'Really Simple CAPTCHA' */
			esc_html( __( "To use CAPTCHA, you need %s plugin installed.", 'contact-form-7' ) ),
			wpcf7_link( 'https://wordpress.org/plugins/really-simple-captcha/', 'Really Simple CAPTCHA' )
		);

		return sprintf( '<em>%s</em>', $error );
	}

	if ( empty( $tag->name ) ) {
		return '';
	}

	$class = wpcf7_form_controls_class( $tag->type );
	$class .= ' wpcf7-captcha-' . str_replace( ':', '', $tag->name );

	$atts = array();
	$atts['class'] = $tag->get_class_option( $class );
	$atts['id'] = $tag->get_id_option();

	$op = array( // Default
		'img_size' => array( 72, 24 ),
		'base' => array( 6, 18 ),
		'font_size' => 14,
		'font_char_width' => 15,
	);

	$op = array_merge( $op, wpcf7_captchac_options( $tag->options ) );

	if ( ! $filename = wpcf7_generate_captcha( $op ) ) {
		return '';
	}

	if ( ! empty( $op['img_size'] ) ) {
		if ( isset( $op['img_size'][0] ) ) {
			$atts['width'] = $op['img_size'][0];
		}

		if ( isset( $op['img_size'][1] ) ) {
			$atts['height'] = $op['img_size'][1];
		}
	}

	$atts['alt'] = 'captcha';
	$atts['src'] = wpcf7_captcha_url( $filename );

	$atts = wpcf7_format_atts( $atts );

	$prefix = substr( $filename, 0, strrpos( $filename, '.' ) );

	$html = sprintf(
		'<input type="hidden" name="%1$s" value="%2$s" /><img %3$s />',
		esc_attr( sprintf( '_wpcf7_captcha_challenge_%s', $tag->name ) ),
		esc_attr( $prefix ),
		$atts
	);

	return $html;
}

function wpcf7_captchar_form_tag_handler( $tag ) {
	if ( empty( $tag->name ) ) {
		return '';
	}

	$validation_error = wpcf7_get_validation_error( $tag->name );

	$class = wpcf7_form_controls_class( $tag->type );

	if ( $validation_error ) {
		$class .= ' wpcf7-not-valid';
	}

	$atts = array();

	$atts['size'] = $tag->get_size_option( '40' );
	$atts['maxlength'] = $tag->get_maxlength_option();
	$atts['minlength'] = $tag->get_minlength_option();

	if ( $atts['maxlength'] and $atts['minlength']
	and $atts['maxlength'] < $atts['minlength'] ) {
		unset( $atts['maxlength'], $atts['minlength'] );
	}

	$atts['class'] = $tag->get_class_option( $class );
	$atts['id'] = $tag->get_id_option();
	$atts['tabindex'] = $tag->get_option( 'tabindex', 'signed_int', true );
	$atts['autocomplete'] = 'off';

	if ( $validation_error ) {
		$atts['aria-invalid'] = 'true';
		$atts['aria-describedby'] = wpcf7_get_validation_error_reference(
			$tag->name
		);
	} else {
		$atts['aria-invalid'] = 'false';
	}

	$value = (string) reset( $tag->values );

	if ( wpcf7_is_posted() ) {
		$value = '';
	}

	if ( $tag->has_option( 'placeholder' )
	or $tag->has_option( 'watermark' ) ) {
		$atts['placeholder'] = $value;
		$value = '';
	}

	$atts['value'] = $value;
	$atts['type'] = 'text';
	$atts['name'] = $tag->name;

	$html = sprintf(
		'<span class="wpcf7-form-control-wrap" data-name="%1$s"><input %2$s />%3$s</span>',
		esc_attr( $tag->name ),
		wpcf7_format_atts( $atts ),
		$validation_error
	);

	return $html;
}


/* Validation filter */

add_filter( 'wpcf7_validate_captchar',
	'wpcf7_captcha_validation_filter', 10, 2 );

function wpcf7_captcha_validation_filter( $result, $tag ) {
	$type = $tag->type;
	$name = $tag->name;

	$captchac = '_wpcf7_captcha_challenge_' . $name;

	$prefix = (string) ( $_POST[$captchac] ?? '' );
	$response = (string) ( $_POST[$name] ?? '' );
	$response = wpcf7_canonicalize( $response );

	if ( 0 === strlen( $prefix )
	or ! wpcf7_check_captcha( $prefix, $response ) ) {
		$result->invalidate( $tag, wpcf7_get_message( 'captcha_not_match' ) );
	}

	if ( 0 !== strlen( $prefix ) ) {
		wpcf7_remove_captcha( $prefix );
	}

	return $result;
}


/* Ajax echo filter */

add_filter( 'wpcf7_refill_response', 'wpcf7_captcha_ajax_refill', 10, 1 );
add_filter( 'wpcf7_feedback_response', 'wpcf7_captcha_ajax_refill', 10, 1 );

function wpcf7_captcha_ajax_refill( $items ) {
	if ( ! is_array( $items ) ) {
		return $items;
	}

	$tags = wpcf7_scan_form_tags( array( 'type' => 'captchac' ) );

	if ( empty( $tags ) ) {
		return $items;
	}

	$refill = array();

	foreach ( $tags as $tag ) {
		$name = $tag->name;
		$options = $tag->options;

		if ( empty( $name ) ) {
			continue;
		}

		$op = wpcf7_captchac_options( $options );

		if ( $filename = wpcf7_generate_captcha( $op ) ) {
			$captcha_url = wpcf7_captcha_url( $filename );
			$refill[$name] = $captcha_url;
		}
	}

	if ( ! empty( $refill ) ) {
		$items['captcha'] = $refill;
	}

	return $items;
}


/* Messages */

add_filter( 'wpcf7_messages', 'wpcf7_captcha_messages', 10, 1 );

function wpcf7_captcha_messages( $messages ) {
	$messages = array_merge( $messages, array(
		'captcha_not_match' => array(
			'description' =>
				__( "The code that sender entered does not match the CAPTCHA", 'contact-form-7' ),
			'default' =>
				__( 'Your entered code is incorrect.', 'contact-form-7' ),
		),
	) );

	return $messages;
}


/* Warning message */

add_action( 'wpcf7_admin_warnings',
	'wpcf7_captcha_display_warning_message', 10, 3 );

function wpcf7_captcha_display_warning_message( $page, $action, $object ) {
	if ( $object instanceof WPCF7_ContactForm ) {
		$contact_form = $object;
	} else {
		return;
	}

	$has_tags = (bool) $contact_form->scan_form_tags(
		array( 'type' => array( 'captchac' ) ) );

	if ( ! $has_tags ) {
		return;
	}

	if ( ! class_exists( 'ReallySimpleCaptcha' ) ) {
		return;
	}

	$uploads_dir = wpcf7_captcha_tmp_dir();
	wpcf7_init_captcha();

	if ( ! is_dir( $uploads_dir ) or ! wp_is_writable( $uploads_dir ) ) {
		$message = sprintf( __( 'This contact form contains CAPTCHA fields, but the temporary folder for the files (%s) does not exist or is not writable. You can create the folder or change its permission manually.', 'contact-form-7' ), $uploads_dir );

		wp_admin_notice( esc_html( $message ), 'type=warning' );
	}

	if (
		! function_exists( 'imagecreatetruecolor' ) or
		! function_exists( 'imagettftext' )
	) {
		$message = __( "This contact form contains CAPTCHA fields, but the necessary libraries (GD and FreeType) are not available on your server.", 'contact-form-7' );

		wp_admin_notice( esc_html( $message ), 'type=warning' );
	}
}


/* CAPTCHA functions */

function wpcf7_init_captcha() {
	static $captcha = null;

	if ( $captcha ) {
		return $captcha;
	}

	if ( class_exists( 'ReallySimpleCaptcha' ) ) {
		$captcha = new ReallySimpleCaptcha();
	} else {
		return false;
	}

	$dir = trailingslashit( wpcf7_captcha_tmp_dir() );

	$captcha->tmp_dir = $dir;

	if ( is_callable( array( $captcha, 'make_tmp_dir' ) ) ) {
		$result = $captcha->make_tmp_dir();

		if ( ! $result ) {
			return false;
		}

		return $captcha;
	}

	$result = wp_mkdir_p( $dir );

	if ( ! $result ) {
		return false;
	}

	$htaccess_file = path_join( $dir, '.htaccess' );

	if ( file_exists( $htaccess_file ) ) {
		list( $first_line_comment ) = (array) file(
			$htaccess_file,
			FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES
		);

		if ( '# Apache 2.4+' === $first_line_comment ) {
			return $captcha;
		}
	}

	if ( $handle = @fopen( $htaccess_file, 'w' ) ) {
		fwrite( $handle, "# Apache 2.4+\n" );
		fwrite( $handle, "<IfModule authz_core_module>\n" );
		fwrite( $handle, "    Require all denied\n" );
		fwrite( $handle, '    <FilesMatch "^\w+\.(jpe?g|gif|png)$">' . "\n" );
		fwrite( $handle, "        Require all granted\n" );
		fwrite( $handle, "    </FilesMatch>\n" );
		fwrite( $handle, "</IfModule>\n" );
		fwrite( $handle, "\n" );
		fwrite( $handle, "# Apache 2.2\n" );
		fwrite( $handle, "<IfModule !authz_core_module>\n" );
		fwrite( $handle, "    Order deny,allow\n" );
		fwrite( $handle, "    Deny from all\n" );
		fwrite( $handle, '    <FilesMatch "^\w+\.(jpe?g|gif|png)$">' . "\n" );
		fwrite( $handle, "        Allow from all\n" );
		fwrite( $handle, "    </FilesMatch>\n" );
		fwrite( $handle, "</IfModule>\n" );

		fclose( $handle );
	}

	return $captcha;
}


/**
 * Returns the directory path for Really Simple CAPTCHA files.
 *
 * @return string Directory path.
 */
function wpcf7_captcha_tmp_dir() {
	if ( defined( 'WPCF7_CAPTCHA_TMP_DIR' ) ) {
		$dir = path_join( WP_CONTENT_DIR, WPCF7_CAPTCHA_TMP_DIR );
		wp_mkdir_p( $dir );

		if ( wpcf7_is_file_path_in_content_dir( $dir ) ) {
			return $dir;
		}
	}

	$dir = path_join( wpcf7_upload_dir( 'dir' ), 'wpcf7_captcha' );
	wp_mkdir_p( $dir );
	return $dir;
}


function wpcf7_captcha_tmp_url() {
	if ( defined( 'WPCF7_CAPTCHA_TMP_URL' ) ) {
		return WPCF7_CAPTCHA_TMP_URL;
	} else {
		return path_join( wpcf7_upload_dir( 'url' ), 'wpcf7_captcha' );
	}
}

function wpcf7_captcha_url( $filename ) {
	$url = path_join( wpcf7_captcha_tmp_url(), $filename );

	if ( is_ssl()
	and 'http:' == substr( $url, 0, 5 ) ) {
		$url = 'https:' . substr( $url, 5 );
	}

	return apply_filters( 'wpcf7_captcha_url', sanitize_url( $url ) );
}

function wpcf7_generate_captcha( $options = null ) {
	if ( ! $captcha = wpcf7_init_captcha() ) {
		return false;
	}

	if ( ! is_dir( $captcha->tmp_dir )
	or ! wp_is_writable( $captcha->tmp_dir ) ) {
		return false;
	}

	$img_type = imagetypes();

	if ( $img_type & IMG_PNG ) {
		$captcha->img_type = 'png';
	} elseif ( $img_type & IMG_GIF ) {
		$captcha->img_type = 'gif';
	} elseif ( $img_type & IMG_JPG ) {
		$captcha->img_type = 'jpeg';
	} else {
		return false;
	}

	if ( is_array( $options ) ) {
		if ( isset( $options['img_size'] ) ) {
			$captcha->img_size = $options['img_size'];
		}

		if ( isset( $options['base'] ) ) {
			$captcha->base = $options['base'];
		}

		if ( isset( $options['font_size'] ) ) {
			$captcha->font_size = $options['font_size'];
		}

		if ( isset( $options['font_char_width'] ) ) {
			$captcha->font_char_width = $options['font_char_width'];
		}

		if ( isset( $options['fg'] ) ) {
			$captcha->fg = $options['fg'];
		}

		if ( isset( $options['bg'] ) ) {
			$captcha->bg = $options['bg'];
		}
	}

	$prefix = wp_rand();
	$captcha_word = $captcha->generate_random_word();
	return $captcha->generate_image( $prefix, $captcha_word );
}

function wpcf7_check_captcha( $prefix, $response ) {
	if ( ! $captcha = wpcf7_init_captcha() ) {
		return false;
	}

	return $captcha->check( $prefix, $response );
}

function wpcf7_remove_captcha( $prefix ) {
	if ( ! $captcha = wpcf7_init_captcha() ) {
		return false;
	}

	// Contact Form 7 generates $prefix with wp_rand()
	if ( preg_match( '/[^0-9]/', $prefix ) ) {
		return false;
	}

	$captcha->remove( $prefix );
}

add_action( 'shutdown', 'wpcf7_cleanup_captcha_files', 20, 0 );

function wpcf7_cleanup_captcha_files() {
	if ( ! $captcha = wpcf7_init_captcha() ) {
		return false;
	}

	if ( is_callable( array( $captcha, 'cleanup' ) ) ) {
		return $captcha->cleanup();
	}

	$dir = trailingslashit( wpcf7_captcha_tmp_dir() );

	if ( ! is_dir( $dir )
	or ! is_readable( $dir )
	or ! wp_is_writable( $dir ) ) {
		return false;
	}

	if ( $handle = opendir( $dir ) ) {
		while ( false !== ( $file = readdir( $handle ) ) ) {
			if ( ! preg_match( '/^[0-9]+\.(php|txt|png|gif|jpeg)$/', $file ) ) {
				continue;
			}

			$stat = stat( path_join( $dir, $file ) );

			if ( $stat['mtime'] + HOUR_IN_SECONDS < time() ) {
				@unlink( path_join( $dir, $file ) );
			}
		}

		closedir( $handle );
	}
}

function wpcf7_captchac_options( $options ) {
	if ( ! is_array( $options ) ) {
		return array();
	}

	$op = array();
	$image_size_array = preg_grep( '%^size:[smlSML]$%', $options );

	if ( $image_size = array_shift( $image_size_array ) ) {
		preg_match( '%^size:([smlSML])$%', $image_size, $is_matches );

		switch ( strtolower( $is_matches[1] ) ) {
			case 's':
				$op['img_size'] = array( 60, 20 );
				$op['base'] = array( 6, 15 );
				$op['font_size'] = 11;
				$op['font_char_width'] = 13;
				break;
			case 'l':
				$op['img_size'] = array( 84, 28 );
				$op['base'] = array( 6, 20 );
				$op['font_size'] = 17;
				$op['font_char_width'] = 19;
				break;
			case 'm':
			default:
				$op['img_size'] = array( 72, 24 );
				$op['base'] = array( 6, 18 );
				$op['font_size'] = 14;
				$op['font_char_width'] = 15;
		}
	}

	$fg_color_array = preg_grep(
		'%^fg:#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$%', $options );

	if ( $fg_color = array_shift( $fg_color_array ) ) {
		preg_match( '%^fg:#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$%',
			$fg_color, $fc_matches );

		if ( 3 == strlen( $fc_matches[1] ) ) {
			$r = substr( $fc_matches[1], 0, 1 );
			$g = substr( $fc_matches[1], 1, 1 );
			$b = substr( $fc_matches[1], 2, 1 );

			$op['fg'] = array(
				hexdec( $r . $r ),
				hexdec( $g . $g ),
				hexdec( $b . $b ),
			);
		} elseif ( 6 == strlen( $fc_matches[1] ) ) {
			$r = substr( $fc_matches[1], 0, 2 );
			$g = substr( $fc_matches[1], 2, 2 );
			$b = substr( $fc_matches[1], 4, 2 );

			$op['fg'] = array(
				hexdec( $r ),
				hexdec( $g ),
				hexdec( $b ),
			);
		}
	}

	$bg_color_array = preg_grep(
		'%^bg:#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$%', $options );

	if ( $bg_color = array_shift( $bg_color_array ) ) {
		preg_match( '%^bg:#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$%',
			$bg_color, $bc_matches );

		if ( 3 == strlen( $bc_matches[1] ) ) {
			$r = substr( $bc_matches[1], 0, 1 );
			$g = substr( $bc_matches[1], 1, 1 );
			$b = substr( $bc_matches[1], 2, 1 );

			$op['bg'] = array(
				hexdec( $r . $r ),
				hexdec( $g . $g ),
				hexdec( $b . $b ),
			);
		} elseif ( 6 == strlen( $bc_matches[1] ) ) {
			$r = substr( $bc_matches[1], 0, 2 );
			$g = substr( $bc_matches[1], 2, 2 );
			$b = substr( $bc_matches[1], 4, 2 );

			$op['bg'] = array(
				hexdec( $r ),
				hexdec( $g ),
				hexdec( $b ),
			);
		}
	}

	return $op;
}
modules/submit.php000064400000004477147510545420010253 0ustar00<?php
/**
** A base module for [submit]
**/

/* form_tag handler */

add_action( 'wpcf7_init', 'wpcf7_add_form_tag_submit', 10, 0 );

function wpcf7_add_form_tag_submit() {
	wpcf7_add_form_tag( 'submit', 'wpcf7_submit_form_tag_handler' );
}

function wpcf7_submit_form_tag_handler( $tag ) {
	$class = wpcf7_form_controls_class( $tag->type, 'has-spinner' );

	$atts = array();

	$atts['class'] = $tag->get_class_option( $class );
	$atts['id'] = $tag->get_id_option();
	$atts['tabindex'] = $tag->get_option( 'tabindex', 'signed_int', true );

	$value = isset( $tag->values[0] ) ? $tag->values[0] : '';

	if ( empty( $value ) ) {
		$value = __( 'Send', 'contact-form-7' );
	}

	$atts['type'] = 'submit';
	$atts['value'] = $value;

	$atts = wpcf7_format_atts( $atts );

	$html = sprintf( '<input %1$s />', $atts );

	return $html;
}


/* Tag generator */

add_action( 'wpcf7_admin_init', 'wpcf7_add_tag_generator_submit', 55, 0 );

function wpcf7_add_tag_generator_submit() {
	$tag_generator = WPCF7_TagGenerator::get_instance();

	$tag_generator->add( 'submit', __( 'submit', 'contact-form-7' ),
		'wpcf7_tag_generator_submit',
		array( 'version' => '2' )
	);
}

function wpcf7_tag_generator_submit( $contact_form, $options ) {
	$field_types = array(
		'submit' => array(
			'display_name' => __( 'Submit button', 'contact-form-7' ),
			'heading' => __( 'Submit button form-tag generator', 'contact-form-7' ),
			'description' => __( 'Generates a form-tag for a <a href="https://contactform7.com/submit-button/">submit button</a>.', 'contact-form-7' ),
		),
	);

	$tgg = new WPCF7_TagGeneratorGenerator( $options['content'] );

?>
<header class="description-box">
	<h3><?php
		echo esc_html( $field_types['submit']['heading'] );
	?></h3>

	<p><?php
		$description = wp_kses(
			$field_types['submit']['description'],
			array(
				'a' => array( 'href' => true ),
				'strong' => array(),
			),
			array( 'http', 'https' )
		);

		echo $description;
	?></p>
</header>

<div class="control-box">
	<?php
		$tgg->print( 'field_type', array(
			'select_options' => array(
				'submit' => $field_types['submit']['display_name'],
			),
		) );

		$tgg->print( 'class_attr' );

		$tgg->print( 'default_value', array(
			'title' => __( 'Label', 'contact-form-7' ),
		) );
	?>
</div>

<footer class="insert-box">
	<?php
		$tgg->print( 'insert_box_content' );
	?>
</footer>
<?php
}
modules/date.php000064400000013337147510545420007660 0ustar00<?php
/**
** A base module for the following types of tags:
** 	[date] and [date*]		# Date
**/

/* form_tag handler */

add_action( 'wpcf7_init', 'wpcf7_add_form_tag_date', 10, 0 );

function wpcf7_add_form_tag_date() {
	wpcf7_add_form_tag( array( 'date', 'date*' ),
		'wpcf7_date_form_tag_handler',
		array(
			'name-attr' => true,
		)
	);
}

function wpcf7_date_form_tag_handler( $tag ) {
	if ( empty( $tag->name ) ) {
		return '';
	}

	$validation_error = wpcf7_get_validation_error( $tag->name );

	$class = wpcf7_form_controls_class( $tag->type );

	$class .= ' wpcf7-validates-as-date';

	if ( $validation_error ) {
		$class .= ' wpcf7-not-valid';
	}

	$atts = array();

	$atts['class'] = $tag->get_class_option( $class );
	$atts['id'] = $tag->get_id_option();
	$atts['tabindex'] = $tag->get_option( 'tabindex', 'signed_int', true );
	$atts['min'] = $tag->get_date_option( 'min' );
	$atts['max'] = $tag->get_date_option( 'max' );
	$atts['step'] = $tag->get_option( 'step', 'int', true );
	$atts['readonly'] = $tag->has_option( 'readonly' );

	$atts['autocomplete'] = $tag->get_option(
		'autocomplete', '[-0-9a-zA-Z]+', true
	);

	if ( $tag->is_required() ) {
		$atts['aria-required'] = 'true';
	}

	if ( $validation_error ) {
		$atts['aria-invalid'] = 'true';
		$atts['aria-describedby'] = wpcf7_get_validation_error_reference(
			$tag->name
		);
	} else {
		$atts['aria-invalid'] = 'false';
	}

	$value = (string) reset( $tag->values );

	if ( $tag->has_option( 'placeholder' )
	or $tag->has_option( 'watermark' ) ) {
		$atts['placeholder'] = $value;
		$value = '';
	}

	$value = $tag->get_default_option( $value );

	if ( $value ) {
		$datetime_obj = date_create_immutable(
			preg_replace( '/[_]+/', ' ', $value ),
			wp_timezone()
		);

		if ( $datetime_obj ) {
			$value = $datetime_obj->format( 'Y-m-d' );
		}
	}

	$value = wpcf7_get_hangover( $tag->name, $value );

	$atts['value'] = $value;
	$atts['type'] = $tag->basetype;
	$atts['name'] = $tag->name;

	$html = sprintf(
		'<span class="wpcf7-form-control-wrap" data-name="%1$s"><input %2$s />%3$s</span>',
		esc_attr( $tag->name ),
		wpcf7_format_atts( $atts ),
		$validation_error
	);

	return $html;
}


add_action(
	'wpcf7_swv_create_schema',
	'wpcf7_swv_add_date_rules',
	10, 2
);

function wpcf7_swv_add_date_rules( $schema, $contact_form ) {
	$tags = $contact_form->scan_form_tags( array(
		'basetype' => array( 'date' ),
	) );

	foreach ( $tags as $tag ) {
		if ( $tag->is_required() ) {
			$schema->add_rule(
				wpcf7_swv_create_rule( 'required', array(
					'field' => $tag->name,
					'error' => wpcf7_get_message( 'invalid_required' ),
				) )
			);
		}

		$schema->add_rule(
			wpcf7_swv_create_rule( 'date', array(
				'field' => $tag->name,
				'error' => wpcf7_get_message( 'invalid_date' ),
			) )
		);

		$min = $tag->get_date_option( 'min' );
		$max = $tag->get_date_option( 'max' );

		if ( false !== $min ) {
			$schema->add_rule(
				wpcf7_swv_create_rule( 'mindate', array(
					'field' => $tag->name,
					'threshold' => $min,
					'error' => wpcf7_get_message( 'date_too_early' ),
				) )
			);
		}

		if ( false !== $max ) {
			$schema->add_rule(
				wpcf7_swv_create_rule( 'maxdate', array(
					'field' => $tag->name,
					'threshold' => $max,
					'error' => wpcf7_get_message( 'date_too_late' ),
				) )
			);
		}
	}
}


/* Messages */

add_filter( 'wpcf7_messages', 'wpcf7_date_messages', 10, 1 );

function wpcf7_date_messages( $messages ) {
	return array_merge( $messages, array(
		'invalid_date' => array(
			'description' => __( "Date format that the sender entered is invalid", 'contact-form-7' ),
			'default' => __( "Please enter a date in YYYY-MM-DD format.", 'contact-form-7' ),
		),

		'date_too_early' => array(
			'description' => __( "Date is earlier than minimum limit", 'contact-form-7' ),
			'default' => __( "This field has a too early date.", 'contact-form-7' ),
		),

		'date_too_late' => array(
			'description' => __( "Date is later than maximum limit", 'contact-form-7' ),
			'default' => __( "This field has a too late date.", 'contact-form-7' ),
		),
	) );
}


/* Tag generator */

add_action( 'wpcf7_admin_init', 'wpcf7_add_tag_generator_date', 19, 0 );

function wpcf7_add_tag_generator_date() {
	$tag_generator = WPCF7_TagGenerator::get_instance();

	$tag_generator->add( 'date', __( 'date', 'contact-form-7' ),
		'wpcf7_tag_generator_date',
	 	array( 'version' => '2' )
	);
}

function wpcf7_tag_generator_date( $contact_form, $options ) {
	$field_types = array(
		'date' => array(
			'display_name' => __( 'Date field', 'contact-form-7' ),
			'heading' => __( 'Date field form-tag generator', 'contact-form-7' ),
			'description' => __( 'Generates a form-tag for a <a href="https://contactform7.com/date-field/">date input field</a>.', 'contact-form-7' ),
		),
	);

	$tgg = new WPCF7_TagGeneratorGenerator( $options['content'] );

?>
<header class="description-box">
	<h3><?php
		echo esc_html( $field_types['date']['heading'] );
	?></h3>

	<p><?php
		$description = wp_kses(
			$field_types['date']['description'],
			array(
				'a' => array( 'href' => true ),
				'strong' => array(),
			),
			array( 'http', 'https' )
		);

		echo $description;
	?></p>
</header>

<div class="control-box">
	<?php
		$tgg->print( 'field_type', array(
			'with_required' => true,
			'select_options' => array(
				'date' => $field_types['date']['display_name'],
			),
		) );

		$tgg->print( 'field_name' );

		$tgg->print( 'class_attr' );

		$tgg->print( 'min_max', array(
			'type' => 'date',
			'title' => __( 'Range', 'contact-form-7' ),
			'min_option' => 'min:',
			'max_option' => 'max:',
		) );

		$tgg->print( 'default_value', array(
			'type' => 'date',
			'with_placeholder' => false,
		) );
	?>
</div>

<footer class="insert-box">
	<?php
		$tgg->print( 'insert_box_content' );

		$tgg->print( 'mail_tag_tip' );
	?>
</footer>
<?php
}
modules/reflection.php000064400000004420147510545420011066 0ustar00<?php
/**
 * Reflection module
 *
 * @link https://contactform7.com/reflection/
 */


add_action( 'wpcf7_init', 'wpcf7_add_form_tag_reflection', 10, 0 );

/**
 * Registers reflection-related form-tag types.
 */
function wpcf7_add_form_tag_reflection() {
	wpcf7_add_form_tag( 'reflection',
		'wpcf7_reflection_form_tag_handler',
		array(
			'name-attr' => true,
			'display-block' => true,
			'not-for-mail' => true,
		)
	);

	wpcf7_add_form_tag( 'output',
		'wpcf7_output_form_tag_handler',
		array(
			'name-attr' => true,
			'not-for-mail' => true,
		)
	);
}


/**
 * The form-tag handler for the reflection type.
 */
function wpcf7_reflection_form_tag_handler( $tag ) {
	if ( empty( $tag->name ) ) {
		return '';
	}

	$values = $tag->values ? $tag->values : array( '' );

	if ( ! wpcf7_get_validation_error( $tag->name ) ) {
		$hangover = array_filter( (array) wpcf7_get_hangover( $tag->name ) );

		if ( $hangover ) {
			$values = $hangover;
		}
	}

	$content = array_reduce(
		$values,
		static function ( $carry, $item ) use ( $tag ) {
			$output_tag = sprintf(
				'<output %1$s>%2$s</output>',
				wpcf7_format_atts( array(
					'name' => $tag->name,
					'data-default' => $item,
				) ),
				( '' !== $item ) ? esc_html( $item ) : '&nbsp;'
			);

			return $carry . $output_tag;
		},
		''
	);

	$html = sprintf(
		'<fieldset %1$s>%2$s</fieldset>',
		wpcf7_format_atts( array(
			'data-reflection-of' => $tag->name,
			'class' => $tag->get_class_option(
				wpcf7_form_controls_class( $tag->type )
			),
			'id' => $tag->get_id_option(),
		) ),
		$content
	);

	return $html;
}


/**
 * The form-tag handler for the output type.
 */
function wpcf7_output_form_tag_handler( $tag ) {
	if ( empty( $tag->name ) ) {
		return '';
	}

	$value = (string) reset( $tag->values );

	if ( ! wpcf7_get_validation_error( $tag->name ) ) {
		$hangover = array_filter( (array) wpcf7_get_hangover( $tag->name ) );

		if ( $hangover ) {
			$value = (string) reset( $hangover );
		}
	}

	$html = sprintf(
		'<output %1$s>%2$s</output>',
		wpcf7_format_atts( array(
			'data-reflection-of' => $tag->name,
			'data-default' => $value,
			'name' => $tag->name,
			'class' => $tag->get_class_option(
				wpcf7_form_controls_class( $tag->type )
			),
			'id' => $tag->get_id_option(),
		) ),
		esc_html( $value )
	);

	return $html;
}
modules/stripe/stripe.php000064400000015517147510545420011561 0ustar00<?php
/**
 * Stripe module main file
 *
 * @link https://contactform7.com/stripe-integration/
 */

wpcf7_include_module_file( 'stripe/service.php' );
wpcf7_include_module_file( 'stripe/api.php' );


add_action(
	'wpcf7_init',
	'wpcf7_stripe_register_service',
	50, 0
);

/**
 * Registers the Stripe service.
 */
function wpcf7_stripe_register_service() {
	$integration = WPCF7_Integration::get_instance();

	$integration->add_service( 'stripe',
		WPCF7_Stripe::get_instance()
	);
}


add_action(
	'wpcf7_enqueue_scripts',
	'wpcf7_stripe_enqueue_scripts',
	10, 0
);

/**
 * Enqueues scripts and styles for the Stripe module.
 */
function wpcf7_stripe_enqueue_scripts() {
	$service = WPCF7_Stripe::get_instance();

	if ( ! $service->is_active() ) {
		return;
	}

	wp_enqueue_style( 'wpcf7-stripe',
		wpcf7_plugin_url( 'modules/stripe/style.css' ),
		array(), WPCF7_VERSION, 'all'
	);

	wp_register_script(
		'stripe',
		'https://js.stripe.com/v3/',
		array(),
		null
	);

	$assets = include(
		wpcf7_plugin_path( 'modules/stripe/index.asset.php' )
	);

	$assets = wp_parse_args( $assets, array(
		'dependencies' => array(),
		'version' => WPCF7_VERSION,
	) );

	wp_enqueue_script(
		'wpcf7-stripe',
		wpcf7_plugin_url( 'modules/stripe/index.js' ),
		array_merge(
			$assets['dependencies'],
			array(
				'wp-polyfill',
				'contact-form-7',
				'stripe',
			)
		),
		$assets['version'],
		array( 'in_footer' => true )
	);

	$api_keys = $service->get_api_keys();

	if ( $api_keys['publishable'] ) {
		wp_add_inline_script( 'wpcf7-stripe',
			sprintf(
				'var wpcf7_stripe = %s;',
				wp_json_encode( array(
					'publishable_key' => $api_keys['publishable'],
				), JSON_PRETTY_PRINT )
			),
			'before'
		);
	}
}


add_filter(
	'wpcf7_skip_spam_check',
	'wpcf7_stripe_skip_spam_check',
	10, 2
);

/**
 * Skips the spam check if it is not necessary.
 *
 * @return bool True if the spam check is not necessary.
 */
function wpcf7_stripe_skip_spam_check( $skip_spam_check, $submission ) {
	$service = WPCF7_Stripe::get_instance();

	if ( ! $service->is_active() ) {
		return $skip_spam_check;
	}

	if ( ! empty( $_POST['_wpcf7_stripe_payment_intent'] ) ) {
		$pi_id = trim( $_POST['_wpcf7_stripe_payment_intent'] );
		$payment_intent = $service->api()->retrieve_payment_intent( $pi_id );

		if ( isset( $payment_intent['status'] )
		and ( 'succeeded' === $payment_intent['status'] ) ) {
			$submission->push( 'payment_intent', $pi_id );
		}
	}

	if ( ! empty( $submission->pull( 'payment_intent' ) )
	and $submission->verify_posted_data_hash() ) {
		$skip_spam_check = true;
	}

	return $skip_spam_check;
}


add_action(
	'wpcf7_before_send_mail',
	'wpcf7_stripe_before_send_mail',
	10, 3
);

/**
 * Creates Stripe's Payment Intent.
 */
function wpcf7_stripe_before_send_mail( $contact_form, &$abort, $submission ) {
	$service = WPCF7_Stripe::get_instance();

	if ( ! $service->is_active() ) {
		return;
	}

	$tags = $contact_form->scan_form_tags( array( 'type' => 'stripe' ) );

	if ( ! $tags ) {
		return;
	}

	if ( ! empty( $submission->pull( 'payment_intent' ) ) ) {
		return;
	}

	$tag = $tags[0];
	$amount = $tag->get_option( 'amount', 'int', true );
	$currency = $tag->get_option( 'currency', '[a-zA-Z]{3}', true );

	$payment_intent_params = apply_filters(
		'wpcf7_stripe_payment_intent_parameters',
		array(
			'amount' => $amount ? absint( $amount ) : null,
			'currency' => $currency ? strtolower( $currency ) : null,
			'receipt_email' => $submission->get_posted_data( 'your-email' ),
		)
	);

	$payment_intent = $service->api()->create_payment_intent(
		$payment_intent_params
	);

	if ( $payment_intent ) {
		$submission->add_result_props( array(
			'stripe' => array(
				'payment_intent' => array(
					'id' => $payment_intent['id'],
					'client_secret' => $payment_intent['client_secret'],
				),
			),
		) );

		$submission->set_status( 'payment_required' );

		$submission->set_response(
			__( "Payment is required. Please pay by credit card.", 'contact-form-7' )
		);
	}

	$abort = true;
}


/**
 * Returns payment link URL.
 *
 * @param string $pi_id Payment Intent ID.
 * @return string The URL.
 */
function wpcf7_stripe_get_payment_link( $pi_id ) {
	return sprintf(
		'https://dashboard.stripe.com/payments/%s',
		urlencode( $pi_id )
	);
}


add_filter(
	'wpcf7_special_mail_tags',
	'wpcf7_stripe_smt',
	10, 4
);

/**
 * Registers the [_stripe_payment_link] special mail-tag.
 */
function wpcf7_stripe_smt( $output, $tag_name, $html, $mail_tag = null ) {
	if ( '_stripe_payment_link' === $tag_name ) {
		$submission = WPCF7_Submission::get_instance();

		$pi_id = $submission->pull( 'payment_intent' );

		if ( ! empty( $pi_id ) ) {
			$output = wpcf7_stripe_get_payment_link( $pi_id );
		}
	}

	return $output;
}


add_filter(
	'wpcf7_flamingo_inbound_message_parameters',
	'wpcf7_stripe_add_flamingo_inbound_message_params',
	10, 1
);

/**
 * Adds Stripe-related meta data to Flamingo Inbound Message parameters.
 */
function wpcf7_stripe_add_flamingo_inbound_message_params( $args ) {
	$submission = WPCF7_Submission::get_instance();

	$pi_id = $submission->pull( 'payment_intent' );

	if ( empty( $pi_id ) ) {
		return $args;
	}

	$pi_link = wpcf7_stripe_get_payment_link( $pi_id );

	$meta = (array) $args['meta'];

	$meta['stripe_payment_link'] = $pi_link;

	$args['meta'] = $meta;

	return $args;
}


add_action(
	'wpcf7_init',
	'wpcf7_add_form_tag_stripe',
	10, 0
);

/**
 * Registers the stripe form-tag handler.
 */
function wpcf7_add_form_tag_stripe() {
	wpcf7_add_form_tag(
		'stripe',
		'wpcf7_stripe_form_tag_handler',
		array(
			'display-block' => true,
			'singular' => true,
		)
	);
}


/**
 * Defines the stripe form-tag handler.
 *
 * @return string HTML content that replaces a stripe form-tag.
 */
function wpcf7_stripe_form_tag_handler( $tag ) {
	$card_element = sprintf(
		'<div %s></div>',
		wpcf7_format_atts( array(
			'class' => 'card-element wpcf7-form-control',
			'aria-invalid' => 'false',
		) )
	);

	$card_element = sprintf(
		'<div class="wpcf7-form-control-wrap hidden">%s</div>',
		$card_element
	);

	$button_1_label = __( 'Proceed to checkout', 'contact-form-7' );

	if ( isset( $tag->values[0] ) ) {
		$button_1_label = trim( $tag->values[0] );
	}

	$button_1 = sprintf(
		'<button %1$s>%2$s</button>',
		wpcf7_format_atts( array(
			'type' => 'submit',
			'class' => 'first',
		) ),
		esc_html( $button_1_label )
	);

	$button_2_label = __( 'Complete payment', 'contact-form-7' );

	if ( isset( $tag->values[1] ) ) {
		$button_2_label = trim( $tag->values[1] );
	}

	$button_2 = sprintf(
		'<button %1$s>%2$s</button>',
		wpcf7_format_atts( array(
			'type' => 'button',
			'class' => 'second hidden',
		) ),
		esc_html( $button_2_label )
	);

	$buttons = sprintf(
		'<span class="buttons has-spinner">%1$s %2$s</span>',
		$button_1, $button_2
	);

	return sprintf(
		'<div class="wpcf7-stripe">%1$s %2$s %3$s</div>',
		$card_element,
		$buttons,
		'<input type="hidden" name="_wpcf7_stripe_payment_intent" value="" />'
	);
}
modules/stripe/service.php000064400000013574147510545420011714 0ustar00<?php

if ( ! class_exists( 'WPCF7_Service' ) ) {
	return;
}

class WPCF7_Stripe extends WPCF7_Service {

	private static $instance;
	private $api_keys;


	public static function get_instance() {
		if ( empty( self::$instance ) ) {
			self::$instance = new self;
		}

		return self::$instance;
	}


	private function __construct() {
		$option = WPCF7::get_option( 'stripe' );

		if ( isset( $option['api_keys']['publishable'] )
		and isset( $option['api_keys']['secret'] ) ) {
			$this->api_keys = array(
				'publishable' => $option['api_keys']['publishable'],
				'secret' => $option['api_keys']['secret'],
			);
		}
	}


	public function get_title() {
		return __( 'Stripe', 'contact-form-7' );
	}


	public function is_active() {
		return (bool) $this->get_api_keys();
	}


	public function api() {
		if ( $this->is_active() ) {
			$api = new WPCF7_Stripe_API( $this->api_keys['secret'] );
			return $api;
		}
	}


	public function get_api_keys() {
		return $this->api_keys;
	}


	public function get_categories() {
		return array( 'payments' );
	}


	public function icon() {
	}


	public function link() {
		echo wpcf7_link(
			'https://stripe.com/',
			'stripe.com'
		);
	}


	protected function menu_page_url( $args = '' ) {
		$args = wp_parse_args( $args, array() );

		$url = menu_page_url( 'wpcf7-integration', false );
		$url = add_query_arg( array( 'service' => 'stripe' ), $url );

		if ( ! empty( $args ) ) {
			$url = add_query_arg( $args, $url );
		}

		return $url;
	}


	protected function save_data() {
		WPCF7::update_option( 'stripe', array(
			'api_keys' => $this->api_keys,
		) );
	}


	protected function reset_data() {
		$this->api_keys = null;
		$this->save_data();
	}


	public function load( $action = '' ) {
		if ( 'setup' == $action and 'POST' == $_SERVER['REQUEST_METHOD'] ) {
			check_admin_referer( 'wpcf7-stripe-setup' );

			if ( ! empty( $_POST['reset'] ) ) {
				$this->reset_data();
				$redirect_to = $this->menu_page_url( 'action=setup' );
			} else {
				$publishable = trim( $_POST['publishable'] ?? '' );
				$secret = trim( $_POST['secret'] ?? '' );

				if ( $publishable and $secret ) {
					$this->api_keys = array(
						'publishable' => $publishable,
						'secret' => $secret,
					);
					$this->save_data();

					$redirect_to = $this->menu_page_url( array(
						'message' => 'success',
					) );
				} else {
					$redirect_to = $this->menu_page_url( array(
						'action' => 'setup',
						'message' => 'invalid',
					) );
				}
			}

			wp_safe_redirect( $redirect_to );
			exit();
		}
	}


	public function admin_notice( $message = '' ) {
		if ( 'invalid' === $message ) {
			wp_admin_notice(
				sprintf(
					'<strong>%1$s</strong>: %2$s',
					esc_html( __( "Error", 'contact-form-7' ) ),
					esc_html( __( "Invalid key values.", 'contact-form-7' ) )
				),
				'type=error'
			);
		}

		if ( 'success' === $message ) {
			wp_admin_notice(
				esc_html( __( "Settings saved.", 'contact-form-7' ) ),
				'type=success'
			);
		}
	}


	public function display( $action = '' ) {
		echo sprintf(
			'<p>%s</p>',
			// https://stripe.com/docs/partners/support#intro
			esc_html( __( "Stripe is a simple and powerful way to accept payments online. Stripe has no setup fees, no monthly fees, and no hidden costs. Millions of businesses rely on Stripe’s software tools to accept payments securely and expand globally.", 'contact-form-7' ) )
		);

		echo sprintf(
			'<p><strong>%s</strong></p>',
			wpcf7_link(
				__( 'https://contactform7.com/stripe-integration/', 'contact-form-7' ),
				__( 'Stripe integration', 'contact-form-7' )
			)
		);

		if ( $this->is_active() ) {
			echo sprintf(
				'<p class="dashicons-before dashicons-yes">%s</p>',
				esc_html( __( "Stripe is active on this site.", 'contact-form-7' ) )
			);
		}

		if ( 'setup' == $action ) {
			$this->display_setup();
		} elseif ( is_ssl() or WP_DEBUG ) {
			echo sprintf(
				'<p><a href="%1$s" class="button">%2$s</a></p>',
				esc_url( $this->menu_page_url( 'action=setup' ) ),
				esc_html( __( 'Setup Integration', 'contact-form-7' ) )
			);
		} else {
			echo sprintf(
				'<p class="dashicons-before dashicons-warning">%s</p>',
				esc_html( __( "Stripe is not available on this site. It requires an HTTPS-enabled site.", 'contact-form-7' ) )
			);
		}
	}


	private function display_setup() {
		$api_keys = $this->get_api_keys();

		if ( $api_keys ) {
			$publishable = $api_keys['publishable'];
			$secret = $api_keys['secret'];
		} else {
			$publishable = '';
			$secret = '';
		}

?>
<form method="post" action="<?php echo esc_url( $this->menu_page_url( 'action=setup' ) ); ?>">
<?php wp_nonce_field( 'wpcf7-stripe-setup' ); ?>
<table class="form-table">
<tbody>
<tr>
	<th scope="row"><label for="publishable"><?php echo esc_html( __( 'Publishable Key', 'contact-form-7' ) ); ?></label></th>
	<td><?php
		if ( $this->is_active() ) {
			echo esc_html( $publishable );
			echo sprintf(
				'<input type="hidden" value="%s" id="publishable" name="publishable" />',
				esc_attr( $publishable )
			);
		} else {
			echo sprintf(
				'<input type="text" aria-required="true" value="%s" id="publishable" name="publishable" class="regular-text code" />',
				esc_attr( $publishable )
			);
		}
	?></td>
</tr>
<tr>
	<th scope="row"><label for="secret"><?php echo esc_html( __( 'Secret Key', 'contact-form-7' ) ); ?></label></th>
	<td><?php
		if ( $this->is_active() ) {
			echo esc_html( wpcf7_mask_password( $secret ) );
			echo sprintf(
				'<input type="hidden" value="%s" id="secret" name="secret" />',
				esc_attr( $secret )
			);
		} else {
			echo sprintf(
				'<input type="text" aria-required="true" value="%s" id="secret" name="secret" class="regular-text code" />',
				esc_attr( $secret )
			);
		}
	?></td>
</tr>
</tbody>
</table>
<?php
		if ( $this->is_active() ) {
			submit_button(
				_x( 'Remove Keys', 'API keys', 'contact-form-7' ),
				'small', 'reset'
			);
		} else {
			submit_button( __( 'Save Changes', 'contact-form-7' ) );
		}
?>
</form>
<?php
	}
}
modules/stripe/style.css000064400000000473147510545420011407 0ustar00.wpcf7 .wpcf7-stripe .wpcf7-form-control-wrap {
	margin: .6em 0;
}

.wpcf7 .wpcf7-stripe .wpcf7-form-control {
	display: block;
	background: #f6f7f7;
	padding: 12px 12px;
	border: 1px solid #787c82;
}

.wpcf7 .wpcf7-stripe button:disabled {
	cursor: not-allowed;
}

.wpcf7 .wpcf7-stripe .hidden {
	display: none;
}
modules/stripe/index.js000064400000007001147510545420011174 0ustar00document.addEventListener("DOMContentLoaded",(e=>{const t=()=>{const e=document.querySelectorAll("form.wpcf7-form .wpcf7-stripe");for(let t=0;t<e.length;t++){let r=e[t];r.querySelector("button").disabled=!0;let i=document.createElement("span");i.setAttribute("class","wpcf7-not-valid-tip"),i.insertAdjacentText("beforeend","This form includes a payment widget that requires a modern browser to work."),r.appendChild(i)}};if(void 0===window.wpcf7_stripe)return console.error("window.wpcf7_stripe is not defined."),void t();if("function"!=typeof window.Stripe)return console.error("window.Stripe is not defined."),void t();if("function"!=typeof wpcf7.submit)return console.error("wpcf7.submit is not defined."),void t();const r=Stripe(wpcf7_stripe.publishable_key),i=r.elements();document.addEventListener("wpcf7submit",(e=>{const t=e.detail.unitTag,s=`${t}-ve-stripe-card-element`,n=document.querySelector(`#${t} form`),o=n.closest(".wpcf7").querySelector(".screen-reader-response"),d=n.querySelector(".wpcf7-stripe .wpcf7-form-control-wrap"),c=n.querySelector(".wpcf7-stripe button.first"),a=n.querySelector(".wpcf7-stripe button.second"),l=n.querySelector('[name="_wpcf7_stripe_payment_intent"]');if(!l)return;l.setAttribute("value","");const u=e=>{const t=o.querySelector("ul"),r=t.querySelector(`li#${s}`);r&&r.remove();const i=document.createElement("li");i.setAttribute("id",s),i.insertAdjacentText("beforeend",e.message),t.appendChild(i)},p=e=>{const t=d.querySelector(".wpcf7-form-control");t.classList.add("wpcf7-not-valid"),t.setAttribute("aria-describedby",s);const r=document.createElement("span");r.setAttribute("class","wpcf7-not-valid-tip"),r.setAttribute("aria-hidden","true"),r.insertAdjacentText("beforeend",e.message),d.appendChild(r),d.querySelectorAll("[aria-invalid]").forEach((e=>{e.setAttribute("aria-invalid","true")})),t.closest(".use-floating-validation-tip")&&(t.addEventListener("focus",(e=>{r.setAttribute("style","display: none")})),r.addEventListener("mouseover",(e=>{r.setAttribute("style","display: none")})))},f=()=>{o.querySelectorAll(`ul li#${s}`).forEach((e=>{e.remove()})),d.querySelectorAll(".wpcf7-not-valid-tip").forEach((e=>{e.remove()})),d.querySelectorAll("[aria-invalid]").forEach((e=>{e.setAttribute("aria-invalid","false")})),d.querySelectorAll(".wpcf7-form-control").forEach((e=>{e.removeAttribute("aria-describedby"),e.classList.remove("wpcf7-not-valid")}))};if("payment_required"===e.detail.status){const s=e.detail.apiResponse.stripe.payment_intent;s.id&&l.setAttribute("value",s.id);const o=i.getElement("card")||i.create("card");o.mount(`#${t} .wpcf7-stripe .card-element`),o.clear(),d.classList.remove("hidden"),c.classList.add("hidden"),a.classList.remove("hidden"),a.disabled=!0,o.addEventListener("change",(e=>{if(f(),e.error){const t={message:e.error.message};u(t),p(t),a.disabled=!0}else a.disabled=!1})),a.addEventListener("click",(e=>{f(),a.disabled=!0,n.classList.add("submitting"),wpcf7.blocked||r.confirmCardPayment(s.client_secret,{payment_method:{card:o}}).then((e=>{if(e.error){e.error.decline_code&&["fraudulent","lost_card","merchant_blacklist","pickup_card","restricted_card","security_violation","service_not_allowed","stolen_card","transaction_not_allowed"].includes(e.error.decline_code)&&(wpcf7.blocked=!0),n.classList.remove("submitting");const t={message:e.error.message};u(t),p(t)}else"succeeded"===e.paymentIntent.status&&wpcf7.submit(n)}))}))}else d.classList.add("hidden"),c.classList.remove("hidden"),a.classList.add("hidden"),["mail_sent","mail_failed"].includes(e.detail.status)&&(c.disabled=!0)}))}));modules/stripe/api.php000064400000006667147510545420011032 0ustar00<?php

/**
 * Class for the Stripe API.
 *
 * @link https://stripe.com/docs/api
 */
class WPCF7_Stripe_API {

	const api_version = '2022-11-15';
	const partner_id = 'pp_partner_HHbvqLh1AaO7Am';
	const app_name = 'WordPress Contact Form 7';
	const app_url = 'https://contactform7.com/stripe-integration/';

	private $secret;


	/**
	 * Constructor.
	 *
	 * @param string $secret Secret key.
	 */
	public function __construct( $secret ) {
		$this->secret = $secret;
	}


	/**
	 * Sends a debug information for a remote request to the PHP error log.
	 *
	 * @param string $url URL to retrieve.
	 * @param array $request Request arguments.
	 * @param array|WP_Error $response The response or WP_Error on failure.
	 */
	private function log( $url, $request, $response ) {
		wpcf7_log_remote_request( $url, $request, $response );
	}


	/**
	 * Returns default set of HTTP request headers used for Stripe API.
	 *
	 * @link https://stripe.com/docs/building-plugins#setappinfo
	 *
	 * @return array An associative array of headers.
	 */
	private function default_headers() {
		$app_info = array(
			'name' => self::app_name,
			'partner_id' => self::partner_id,
			'url' => self::app_url,
			'version' => WPCF7_VERSION,
		);

		$ua = array(
			'lang' => 'php',
			'lang_version' => PHP_VERSION,
			'application' => $app_info,
		);

		$headers = array(
			'Authorization' => sprintf( 'Bearer %s', $this->secret ),
			'Stripe-Version' => self::api_version,
			'X-Stripe-Client-User-Agent' => wp_json_encode( $ua ),
			'User-Agent' => sprintf(
				'%1$s/%2$s (%3$s)',
				self::app_name,
				WPCF7_VERSION,
				self::app_url
			),
		);

		return $headers;
	}


	/**
	 * Creates a Payment Intent.
	 *
	 * @link https://stripe.com/docs/api/payment_intents/create
	 *
	 * @param string|array $args Optional. Arguments to control behavior.
	 * @return array|bool An associative array if 200 OK, false otherwise.
	 */
	public function create_payment_intent( $args = '' ) {
		$args = wp_parse_args( $args, array(
			'amount' => 0,
			'currency' => '',
			'receipt_email' => '',
		) );

		if ( ! is_email( $args['receipt_email'] ) ) {
			unset( $args['receipt_email'] );
		}

		$endpoint = 'https://api.stripe.com/v1/payment_intents';

		$request = array(
			'headers' => $this->default_headers(),
			'body' => $args,
		);

		$response = wp_remote_post( sanitize_url( $endpoint ), $request );

		if ( 200 != wp_remote_retrieve_response_code( $response ) ) {
			if ( WP_DEBUG ) {
				$this->log( $endpoint, $request, $response );
			}

			return false;
		}

		$response_body = wp_remote_retrieve_body( $response );
		$response_body = json_decode( $response_body, true );

		return $response_body;
	}


	/**
	 * Retrieve a Payment Intent.
	 *
	 * @link https://stripe.com/docs/api/payment_intents/retrieve
	 *
	 * @param string $id Payment Intent identifier.
	 * @return array|bool An associative array if 200 OK, false otherwise.
	 */
	public function retrieve_payment_intent( $id ) {
		$endpoint = sprintf(
			'https://api.stripe.com/v1/payment_intents/%s',
			urlencode( $id )
		);

		$request = array(
			'headers' => $this->default_headers(),
		);

		$response = wp_remote_get( sanitize_url( $endpoint ), $request );

		if ( 200 != wp_remote_retrieve_response_code( $response ) ) {
			if ( WP_DEBUG ) {
				$this->log( $endpoint, $request, $response );
			}

			return false;
		}

		$response_body = wp_remote_retrieve_body( $response );
		$response_body = json_decode( $response_body, true );

		return $response_body;
	}

}
modules/stripe/index.asset.php000064400000000121147510545420012461 0ustar00<?php

return array(
	'dependencies' => array(),
	'version' => WPCF7_VERSION,
);
modules/textarea.php000064400000011613147510545420010553 0ustar00<?php
/**
** A base module for [textarea] and [textarea*]
**/

/* form_tag handler */

add_action( 'wpcf7_init', 'wpcf7_add_form_tag_textarea', 10, 0 );

function wpcf7_add_form_tag_textarea() {
	wpcf7_add_form_tag( array( 'textarea', 'textarea*' ),
		'wpcf7_textarea_form_tag_handler', array( 'name-attr' => true )
	);
}

function wpcf7_textarea_form_tag_handler( $tag ) {
	if ( empty( $tag->name ) ) {
		return '';
	}

	$validation_error = wpcf7_get_validation_error( $tag->name );

	$class = wpcf7_form_controls_class( $tag->type );

	if ( $validation_error ) {
		$class .= ' wpcf7-not-valid';
	}

	$atts = array();

	$atts['cols'] = $tag->get_cols_option( '40' );
	$atts['rows'] = $tag->get_rows_option( '10' );
	$atts['maxlength'] = $tag->get_maxlength_option( '2000' );
	$atts['minlength'] = $tag->get_minlength_option();

	if ( $atts['maxlength'] and $atts['minlength']
	and $atts['maxlength'] < $atts['minlength'] ) {
		unset( $atts['maxlength'], $atts['minlength'] );
	}

	$atts['class'] = $tag->get_class_option( $class );
	$atts['id'] = $tag->get_id_option();
	$atts['tabindex'] = $tag->get_option( 'tabindex', 'signed_int', true );
	$atts['readonly'] = $tag->has_option( 'readonly' );

	$atts['autocomplete'] = $tag->get_option(
		'autocomplete', '[-0-9a-zA-Z]+', true
	);

	if ( $tag->is_required() ) {
		$atts['aria-required'] = 'true';
	}

	if ( $validation_error ) {
		$atts['aria-invalid'] = 'true';
		$atts['aria-describedby'] = wpcf7_get_validation_error_reference(
			$tag->name
		);
	} else {
		$atts['aria-invalid'] = 'false';
	}

	$value = empty( $tag->content )
		? (string) reset( $tag->values )
		: $tag->content;

	if ( $tag->has_option( 'placeholder' )
	or $tag->has_option( 'watermark' ) ) {
		$atts['placeholder'] = $value;
		$value = '';
	}

	$value = $tag->get_default_option( $value );

	$value = wpcf7_get_hangover( $tag->name, $value );

	$atts['name'] = $tag->name;

	$html = sprintf(
		'<span class="wpcf7-form-control-wrap" data-name="%1$s"><textarea %2$s>%3$s</textarea>%4$s</span>',
		esc_attr( $tag->name ),
		wpcf7_format_atts( $atts ),
		esc_textarea( $value ),
		$validation_error
	);

	return $html;
}


add_action(
	'wpcf7_swv_create_schema',
	'wpcf7_swv_add_textarea_rules',
	10, 2
);

function wpcf7_swv_add_textarea_rules( $schema, $contact_form ) {
	$tags = $contact_form->scan_form_tags( array(
		'basetype' => array( 'textarea' ),
	) );

	foreach ( $tags as $tag ) {
		if ( $tag->is_required() ) {
			$schema->add_rule(
				wpcf7_swv_create_rule( 'required', array(
					'field' => $tag->name,
					'error' => wpcf7_get_message( 'invalid_required' ),
				) )
			);
		}

		if ( $minlength = $tag->get_minlength_option() ) {
			$schema->add_rule(
				wpcf7_swv_create_rule( 'minlength', array(
					'field' => $tag->name,
					'threshold' => absint( $minlength ),
					'error' => wpcf7_get_message( 'invalid_too_short' ),
				) )
			);
		}

		if ( $maxlength = $tag->get_maxlength_option( '2000' ) ) {
			$schema->add_rule(
				wpcf7_swv_create_rule( 'maxlength', array(
					'field' => $tag->name,
					'threshold' => absint( $maxlength ),
					'error' => wpcf7_get_message( 'invalid_too_long' ),
				) )
			);
		}
	}
}


/* Tag generator */

add_action( 'wpcf7_admin_init', 'wpcf7_add_tag_generator_textarea', 20, 0 );

function wpcf7_add_tag_generator_textarea() {
	$tag_generator = WPCF7_TagGenerator::get_instance();

	$tag_generator->add( 'textarea',
		__( 'text area', 'contact-form-7' ),
		'wpcf7_tag_generator_textarea',
	 	array( 'version' => '2' )
	);
}

function wpcf7_tag_generator_textarea( $contact_form, $options ) {
	$field_types = array(
		'textarea' => array(
			'display_name' => __( 'Text area', 'contact-form-7' ),
			'heading' => __( 'Text area form-tag generator', 'contact-form-7' ),
			'description' => __( 'Generates a form-tag for a <a href="https://contactform7.com/text-fields/">multi-line plain text input area</a>.', 'contact-form-7' ),
		),
	);

	$tgg = new WPCF7_TagGeneratorGenerator( $options['content'] );

?>
<header class="description-box">
	<h3><?php
		echo esc_html( $field_types['textarea']['heading'] );
	?></h3>

	<p><?php
		$description = wp_kses(
			$field_types['textarea']['description'],
			array(
				'a' => array( 'href' => true ),
				'strong' => array(),
			),
			array( 'http', 'https' )
		);

		echo $description;
	?></p>
</header>

<div class="control-box">
	<?php
		$tgg->print( 'field_type', array(
			'with_required' => true,
			'select_options' => array(
				'textarea' => $field_types['textarea']['display_name'],
			),
		) );

		$tgg->print( 'field_name' );

		$tgg->print( 'class_attr' );

		$tgg->print( 'min_max', array(
			'title' => __( 'Length', 'contact-form-7' ),
			'min_option' => 'minlength:',
			'max_option' => 'maxlength:',
		) );

		$tgg->print( 'default_value', array(
			'with_placeholder' => true,
			'use_content' => true,
		) );
	?>
</div>

<footer class="insert-box">
	<?php
		$tgg->print( 'insert_box_content' );

		$tgg->print( 'mail_tag_tip' );
	?>
</footer>
<?php
}
modules/hidden.php000064400000001410147510545420010163 0ustar00<?php

add_action( 'wpcf7_init', 'wpcf7_add_form_tag_hidden', 10, 0 );

function wpcf7_add_form_tag_hidden() {
	wpcf7_add_form_tag( 'hidden',
		'wpcf7_hidden_form_tag_handler',
		array(
			'name-attr' => true,
			'display-hidden' => true,
		)
	);
}

function wpcf7_hidden_form_tag_handler( $tag ) {
	if ( empty( $tag->name ) ) {
		return '';
	}

	$atts = array();

	$class = wpcf7_form_controls_class( $tag->type );
	$atts['class'] = $tag->get_class_option( $class );
	$atts['id'] = $tag->get_id_option();

	$value = (string) reset( $tag->values );
	$value = $tag->get_default_option( $value );
	$atts['value'] = $value;

	$atts['type'] = 'hidden';
	$atts['name'] = $tag->name;
	$atts = wpcf7_format_atts( $atts );

	$html = sprintf( '<input %s />', $atts );
	return $html;
}
modules/response.php000064400000000714147510545420010574 0ustar00<?php
/**
** A base module for [response]
**/

/* form_tag handler */

add_action( 'wpcf7_init', 'wpcf7_add_form_tag_response', 10, 0 );

function wpcf7_add_form_tag_response() {
	wpcf7_add_form_tag( 'response',
		'wpcf7_response_form_tag_handler',
		array(
			'display-block' => true,
		)
	);
}

function wpcf7_response_form_tag_handler( $tag ) {
	if ( $contact_form = wpcf7_get_current_contact_form() ) {
		return $contact_form->form_response_output();
	}
}
modules/constant-contact/service.php000064400000030103147510545420013653 0ustar00<?php

if ( ! class_exists( 'WPCF7_Service_OAuth2' ) ) {
	return;
}

class WPCF7_ConstantContact extends WPCF7_Service_OAuth2 {

	const service_name = 'constant_contact';

	const authorization_endpoint
		= 'https://authz.constantcontact.com/oauth2/default/v1/authorize';

	const token_endpoint
		= 'https://authz.constantcontact.com/oauth2/default/v1/token';

	private static $instance;
	protected $contact_lists = array();

	public static function get_instance() {
		if ( empty( self::$instance ) ) {
			self::$instance = new self;
		}

		return self::$instance;
	}

	private function __construct() {
		$this->authorization_endpoint = self::authorization_endpoint;
		$this->token_endpoint = self::token_endpoint;

		$option = (array) WPCF7::get_option( self::service_name );

		if ( isset( $option['client_id'] ) ) {
			$this->client_id = $option['client_id'];
		}

		if ( isset( $option['client_secret'] ) ) {
			$this->client_secret = $option['client_secret'];
		}

		if ( isset( $option['access_token'] ) ) {
			$this->access_token = $option['access_token'];
		}

		if ( isset( $option['refresh_token'] ) ) {
			$this->refresh_token = $option['refresh_token'];
		}

		if ( $this->is_active() ) {
			if ( isset( $option['contact_lists'] ) ) {
				$this->contact_lists = $option['contact_lists'];
			}
		}

		add_action( 'wpcf7_admin_init', array( $this, 'auth_redirect' ) );
	}

	public function auth_redirect() {
		$auth = isset( $_GET['auth'] ) ? trim( $_GET['auth'] ) : '';

		if ( self::service_name === $auth
		and current_user_can( 'wpcf7_manage_integration' ) ) {
			$redirect_to = add_query_arg(
				array(
					'service' => self::service_name,
					'action' => 'auth_redirect',
					'code' => isset( $_GET['code'] ) ? trim( $_GET['code'] ) : '',
					'state' => isset( $_GET['state'] ) ? trim( $_GET['state'] ) : '',
				),
				menu_page_url( 'wpcf7-integration', false )
			);

			wp_safe_redirect( $redirect_to );
			exit();
		}
	}

	protected function save_data() {
		$option = array_merge(
			(array) WPCF7::get_option( self::service_name ),
			array(
				'client_id' => $this->client_id,
				'client_secret' => $this->client_secret,
				'access_token' => $this->access_token,
				'refresh_token' => $this->refresh_token,
				'contact_lists' => $this->contact_lists,
			)
		);

		WPCF7::update_option( self::service_name, $option );
	}

	protected function reset_data() {
		$this->client_id = '';
		$this->client_secret = '';
		$this->access_token = '';
		$this->refresh_token = '';
		$this->contact_lists = array();

		$this->save_data();
	}

	public function get_title() {
		return __( 'Constant Contact', 'contact-form-7' );
	}

	public function get_categories() {
		return array( 'email_marketing' );
	}

	public function icon() {
	}

	public function link() {
		echo 'constantcontact.com';
	}

	protected function get_redirect_uri() {
		return admin_url( '/?auth=' . self::service_name );
	}

	protected function menu_page_url( $args = '' ) {
		$args = wp_parse_args( $args, array() );

		$url = menu_page_url( 'wpcf7-integration', false );
		$url = add_query_arg( array( 'service' => self::service_name ), $url );

		if ( ! empty( $args ) ) {
			$url = add_query_arg( $args, $url );
		}

		return $url;
	}

	public function load( $action = '' ) {
		if ( 'auth_redirect' == $action ) {
			$code = isset( $_GET['code'] ) ? urldecode( $_GET['code'] ) : '';
			$state = isset( $_GET['state'] ) ? urldecode( $_GET['state'] ) : '';

			if ( $code and $state
			and wpcf7_verify_nonce( $state, 'wpcf7_constant_contact_authorize' ) ) {
				$response = $this->request_token( $code );
			}

			if ( ! empty( $this->access_token ) ) {
				$message = 'success';
			} else {
				$message = 'failed';
			}

			wp_safe_redirect( $this->menu_page_url(
				array(
					'action' => 'setup',
					'message' => $message,
				)
			) );

			exit();
		}

		if ( 'setup' == $action and 'POST' == $_SERVER['REQUEST_METHOD'] ) {
			check_admin_referer( 'wpcf7-constant-contact-setup' );

			if ( ! empty( $_POST['reset'] ) ) {
				$this->reset_data();
			} else {
				$this->client_id = isset( $_POST['client_id'] )
					? trim( $_POST['client_id'] ) : '';

				$this->client_secret = isset( $_POST['client_secret'] )
					? trim( $_POST['client_secret'] ) : '';

				$this->save_data();
				$this->authorize( 'contact_data offline_access' );
			}

			wp_safe_redirect( $this->menu_page_url( 'action=setup' ) );
			exit();
		}
	}

	protected function authorize( $scope = '' ) {
		$endpoint = add_query_arg(
			array_map( 'urlencode', array(
				'response_type' => 'code',
				'client_id' => $this->client_id,
				'redirect_uri' => $this->get_redirect_uri(),
				'scope' => $scope,
				'state' => wpcf7_create_nonce( 'wpcf7_constant_contact_authorize' ),
			) ),
			$this->authorization_endpoint
		);

		if ( wp_redirect( sanitize_url( $endpoint ) ) ) {
			exit();
		}
	}

	public function email_exists( $email ) {
		$endpoint = add_query_arg(
			array(
				'email' => $email,
				'status' => 'all',
			),
			'https://api.cc.email/v3/contacts'
		);

		$request = array(
			'method' => 'GET',
			'headers' => array(
				'Accept' => 'application/json',
				'Content-Type' => 'application/json; charset=utf-8',
			),
		);

		$response = $this->remote_request( $endpoint, $request );

		if ( 400 <= (int) wp_remote_retrieve_response_code( $response ) ) {
			if ( WP_DEBUG ) {
				$this->log( $endpoint, $request, $response );
			}

			return false;
		}

		$response_body = wp_remote_retrieve_body( $response );

		if ( empty( $response_body ) ) {
			return false;
		}

		$response_body = json_decode( $response_body, true );

		return ! empty( $response_body['contacts'] );
	}

	public function create_contact( $properties ) {
		$endpoint = 'https://api.cc.email/v3/contacts';

		$request = array(
			'method' => 'POST',
			'headers' => array(
				'Accept' => 'application/json',
				'Content-Type' => 'application/json; charset=utf-8',
			),
			'body' => wp_json_encode( $properties ),
		);

		$response = $this->remote_request( $endpoint, $request );

		if ( 400 <= (int) wp_remote_retrieve_response_code( $response ) ) {
			if ( WP_DEBUG ) {
				$this->log( $endpoint, $request, $response );
			}

			return false;
		}
	}

	public function get_contact_lists() {
		$endpoint = 'https://api.cc.email/v3/contact_lists';

		$request = array(
			'method' => 'GET',
			'headers' => array(
				'Accept' => 'application/json',
				'Content-Type' => 'application/json; charset=utf-8',
			),
		);

		$response = $this->remote_request( $endpoint, $request );

		if ( 400 <= (int) wp_remote_retrieve_response_code( $response ) ) {
			if ( WP_DEBUG ) {
				$this->log( $endpoint, $request, $response );
			}

			return false;
		}

		$response_body = wp_remote_retrieve_body( $response );

		if ( empty( $response_body ) ) {
			return false;
		}

		$response_body = json_decode( $response_body, true );

		if ( ! empty( $response_body['lists'] ) ) {
			return (array) $response_body['lists'];
		} else {
			return array();
		}
	}

	public function update_contact_lists( $selection = array() ) {
		$contact_lists = array();
		$contact_lists_on_api = $this->get_contact_lists();

		if ( false !== $contact_lists_on_api ) {
			foreach ( (array) $contact_lists_on_api as $list ) {
				if ( isset( $list['list_id'] ) ) {
					$list_id = trim( $list['list_id'] );
				} else {
					continue;
				}

				if ( isset( $this->contact_lists[$list_id]['selected'] ) ) {
					$list['selected'] = $this->contact_lists[$list_id]['selected'];
				} else {
					$list['selected'] = array();
				}

				$contact_lists[$list_id] = $list;
			}
		} else {
			$contact_lists = $this->contact_lists;
		}

		foreach ( (array) $selection as $key => $ids_or_names ) {
			foreach( $contact_lists as $list_id => $list ) {
				if ( in_array( $list['list_id'], (array) $ids_or_names, true )
				or in_array( $list['name'], (array) $ids_or_names, true ) ) {
					$contact_lists[$list_id]['selected'][$key] = true;
				} else {
					unset( $contact_lists[$list_id]['selected'][$key] );
				}
			}
		}

		$this->contact_lists = $contact_lists;

		if ( $selection ) {
			$this->save_data();
		}

		return $this->contact_lists;
	}

	public function admin_notice( $message = '' ) {
		switch ( $message ) {
			case 'success':
				wp_admin_notice(
					esc_html( __( "Connection established.", 'contact-form-7' ) ),
					'type=success'
				);

				break;
			case 'failed':
				wp_admin_notice(
					sprintf(
						'<strong>%1$s</strong>: %2$s',
						esc_html( __( "Error", 'contact-form-7' ) ),
						esc_html( __( "Failed to establish connection. Please double-check your configuration.", 'contact-form-7' ) )
					),
					'type=error'
				);

				break;
			case 'updated':
				wp_admin_notice(
					esc_html( __( "Configuration updated.", 'contact-form-7' ) ),
					'type=success'
				);

				break;
		}
	}

	public function display( $action = '' ) {
		echo sprintf(
			'<p><strong>%1$s</strong> %2$s</p>',
			esc_html( __( 'Warning:', 'contact-form-7' ) ),
			wpcf7_link(
				__( 'https://contactform7.com/2024/02/02/we-end-the-constant-contact-integration/', 'contact-form-7' ),
				__( "This feature is deprecated. You are not recommended to use it.", 'contact-form-7' )
			)
		);

		echo sprintf(
			'<p>%s</p>',
			esc_html( __( "The Constant Contact integration module allows you to send contact data collected through your contact forms to the Constant Contact API. You can create reliable email subscription services in a few easy steps.", 'contact-form-7' ) )
		);

		echo sprintf(
			'<p><strong>%s</strong></p>',
			wpcf7_link(
				__( 'https://contactform7.com/constant-contact-integration/', 'contact-form-7' ),
				__( 'Constant Contact integration', 'contact-form-7' )
			)
		);

		if ( $this->is_active() ) {
			echo sprintf(
				'<p class="dashicons-before dashicons-yes">%s</p>',
				esc_html( __( "This site is connected to the Constant Contact API.", 'contact-form-7' ) )
			);
		}

		if ( 'setup' == $action ) {
			$this->display_setup();
		} else {
			echo sprintf(
				'<p><a href="%1$s" class="button">%2$s</a></p>',
				esc_url( $this->menu_page_url( 'action=setup' ) ),
				esc_html( __( 'Setup Integration', 'contact-form-7' ) )
			);
		}
	}

	private function display_setup() {
?>
<form method="post" action="<?php echo esc_url( $this->menu_page_url( 'action=setup' ) ); ?>">
<?php wp_nonce_field( 'wpcf7-constant-contact-setup' ); ?>
<table class="form-table">
<tbody>
<tr>
	<th scope="row"><label for="client_id"><?php echo esc_html( __( 'API Key', 'contact-form-7' ) ); ?></label></th>
	<td><?php
		if ( $this->is_active() ) {
			echo esc_html( $this->client_id );
			echo sprintf(
				'<input type="hidden" value="%1$s" id="client_id" name="client_id" />',
				esc_attr( $this->client_id )
			);
		} else {
			echo sprintf(
				'<input type="text" aria-required="true" value="%1$s" id="client_id" name="client_id" class="regular-text code" />',
				esc_attr( $this->client_id )
			);
		}
	?></td>
</tr>
<tr>
	<th scope="row"><label for="client_secret"><?php echo esc_html( __( 'App Secret', 'contact-form-7' ) ); ?></label></th>
	<td><?php
		if ( $this->is_active() ) {
			echo esc_html( wpcf7_mask_password( $this->client_secret, 4, 4 ) );
			echo sprintf(
				'<input type="hidden" value="%1$s" id="client_secret" name="client_secret" />',
				esc_attr( $this->client_secret )
			);
		} else {
			echo sprintf(
				'<input type="text" aria-required="true" value="%1$s" id="client_secret" name="client_secret" class="regular-text code" />',
				esc_attr( $this->client_secret )
			);
		}
	?></td>
</tr>
<tr>
	<th scope="row"><label for="redirect_uri"><?php echo esc_html( __( 'Redirect URI', 'contact-form-7' ) ); ?></label></th>
	<td><?php
		echo sprintf(
			'<input type="text" value="%1$s" id="redirect_uri" name="redirect_uri" class="large-text code" readonly="readonly" onfocus="this.select();" style="font-size: 11px;" />',
			$this->get_redirect_uri()
		);
	?>
	<p class="description"><?php echo esc_html( __( "Set this URL as the redirect URI.", 'contact-form-7' ) ); ?></p>
	</td>
</tr>
</tbody>
</table>
<?php
		if ( $this->is_active() ) {
			submit_button(
				_x( 'Reset Keys', 'API keys', 'contact-form-7' ),
				'small', 'reset'
			);
		} else {
			submit_button(
				__( 'Connect to the Constant Contact API', 'contact-form-7' )
			);
		}
?>
</form>
<?php
	}

}
modules/constant-contact/constant-contact.php000064400000005212147510545420015500 0ustar00<?php
/**
 * Constant Contact module main file
 *
 * @link https://contactform7.com/constant-contact-integration/
 */

wpcf7_include_module_file( 'constant-contact/service.php' );
wpcf7_include_module_file( 'constant-contact/contact-post-request.php' );
wpcf7_include_module_file( 'constant-contact/contact-form-properties.php' );
wpcf7_include_module_file( 'constant-contact/doi.php' );


add_action(
	'wpcf7_init',
	'wpcf7_constant_contact_register_service',
	120, 0
);

/**
 * Registers the Constant Contact service.
 */
function wpcf7_constant_contact_register_service() {
	$integration = WPCF7_Integration::get_instance();

	$service = WPCF7_ConstantContact::get_instance();
	$integration->add_service( 'constant_contact', $service );
}


add_action( 'wpcf7_submit', 'wpcf7_constant_contact_submit', 10, 2 );

/**
 * Callback to the wpcf7_submit action hook. Creates a contact
 * based on the submission.
 */
function wpcf7_constant_contact_submit( $contact_form, $result ) {
	$service = WPCF7_ConstantContact::get_instance();

	if ( ! $service->is_active() ) {
		return;
	}

	if ( $contact_form->in_demo_mode() ) {
		return;
	}

	$do_submit = true;

	if ( empty( $result['status'] )
	or ! in_array( $result['status'], array( 'mail_sent' ) ) ) {
		$do_submit = false;
	}

	$prop = $contact_form->prop( 'constant_contact' );

	if ( empty( $prop['enable_contact_list'] ) ) {
		$do_submit = false;
	}

	$do_submit = apply_filters( 'wpcf7_constant_contact_submit',
		$do_submit, $contact_form, $result
	);

	if ( ! $do_submit ) {
		return;
	}

	$submission = WPCF7_Submission::get_instance();

	$consented = true;

	foreach ( $contact_form->scan_form_tags( 'feature=name-attr' ) as $tag ) {
		if ( $tag->has_option( 'consent_for:constant_contact' )
		and null == $submission->get_posted_data( $tag->name ) ) {
			$consented = false;
			break;
		}
	}

	if ( ! $consented ) {
		return;
	}

	$request_builder_class_name = apply_filters(
		'wpcf7_constant_contact_contact_post_request_builder',
		'WPCF7_ConstantContact_ContactPostRequest'
	);

	if ( ! class_exists( $request_builder_class_name ) ) {
		return;
	}

	$request_builder = new $request_builder_class_name;
	$request_builder->build( $submission );

	if ( ! $request_builder->is_valid() ) {
		return;
	}

	$email = $request_builder->get_email_address();

	if ( $email ) {
		if ( $service->email_exists( $email ) ) {
			return;
		}

		$token = null;

		do_action_ref_array( 'wpcf7_doi', array(
			'wpcf7_constant_contact',
			array(
				'email_to' => $email,
				'properties' => $request_builder->to_array(),
			),
			&$token,
		) );

		if ( isset( $token ) ) {
			return;
		}
	}

	$service->create_contact( $request_builder->to_array() );
}
modules/constant-contact/contact-post-request.php000064400000017453147510545420016334 0ustar00<?php

class WPCF7_ConstantContact_ContactPostRequest {

	private $email_address;
	private $first_name;
	private $last_name;
	private $job_title;
	private $company_name;
	private $create_source;
	private $birthday_month;
	private $birthday_day;
	private $anniversary;
	private $custom_fields = array();
	private $phone_numbers = array();
	private $street_addresses = array();
	private $list_memberships = array();

	public function __construct() {
	}

	public function build( WPCF7_Submission $submission ) {
		$this->set_create_source( 'Contact' );

		$this->set_first_name(
			$submission->get_posted_string( 'your-first-name' )
		);

		$this->set_last_name(
			$submission->get_posted_string( 'your-last-name' )
		);

		if ( ! ( $this->first_name || $this->last_name )
		and $your_name = $submission->get_posted_string( 'your-name' ) ) {
			$your_name = preg_split( '/[\s]+/', $your_name, 2 );
			$this->set_first_name( array_shift( $your_name ) );
			$this->set_last_name( array_shift( $your_name ) );
		}

		$this->set_email_address(
			$submission->get_posted_string( 'your-email' ),
			'implicit'
		);

		$this->set_job_title(
			$submission->get_posted_string( 'your-job-title' )
		);

		$this->set_company_name(
			$submission->get_posted_string( 'your-company-name' )
		);

		$this->set_birthday(
			$submission->get_posted_string( 'your-birthday-month' ),
			$submission->get_posted_string( 'your-birthday-day' )
		);

		if ( ! ( $this->birthday_month && $this->birthday_day ) ) {
			$date = $submission->get_posted_string( 'your-birthday' );

			if ( preg_match( '/^(\d{4})-(\d{2})-(\d{2})$/', $date, $matches ) ) {
				$this->set_birthday( $matches[2], $matches[3] );
			}
		}

		$this->set_anniversary(
			$submission->get_posted_string( 'your-anniversary' )
		);

		$this->add_phone_number(
			$submission->get_posted_string( 'your-phone-number' )
		);

		$this->add_street_address(
			$submission->get_posted_string( 'your-address-street' ),
			$submission->get_posted_string( 'your-address-city' ),
			$submission->get_posted_string( 'your-address-state' ),
			$submission->get_posted_string( 'your-address-postal-code' ),
			$submission->get_posted_string( 'your-address-country' )
		);

		$service_option = (array) WPCF7::get_option( 'constant_contact' );

		$contact_lists = isset( $service_option['contact_lists'] )
			? $service_option['contact_lists'] : array();

		$contact_form = $submission->get_contact_form();

		$prop = $contact_form->prop( 'constant_contact' );

		if ( ! empty( $prop['enable_contact_list'] )
		and ! empty( $prop['contact_lists'] ) ) {
			foreach ( (array) $prop['contact_lists'] as $list_id ) {
				$this->add_list_membership( $list_id );
			}
		}
	}

	public function is_valid() {
		return $this->create_source
			&& ( $this->email_address || $this->first_name || $this->last_name );
	}

	public function to_array() {
		$output = array(
			'email_address' => $this->email_address,
			'first_name' => $this->first_name,
			'last_name' => $this->last_name,
			'job_title' => $this->job_title,
			'company_name' => $this->company_name,
			'create_source' => $this->create_source,
			'birthday_month' => $this->birthday_month,
			'birthday_day' => $this->birthday_day,
			'anniversary' => $this->anniversary,
			'custom_fields' => $this->custom_fields,
			'phone_numbers' => $this->phone_numbers,
			'street_addresses' => $this->street_addresses,
			'list_memberships' => $this->list_memberships,
		);

		return array_filter( $output );
	}

	public function get_email_address() {
		if ( isset( $this->email_address['address'] ) ) {
			return $this->email_address['address'];
		}

		return '';
	}

	public function set_email_address( $address, $permission_to_send = '' ) {
		if ( ! wpcf7_is_email( $address )
		or 80 < $this->strlen( $address ) ) {
			return false;
		}

		$types_of_permission = array(
			'implicit', 'explicit', 'deprecate', 'pending',
			'unsubscribe', 'temp_hold', 'not_set',
		);

		if ( ! in_array( $permission_to_send, $types_of_permission ) ) {
			$permission_to_send = 'implicit';
		}

		return $this->email_address = array(
			'address' => $address,
			'permission_to_send' => $permission_to_send,
		);
	}

	public function set_first_name( $first_name ) {
		$first_name = trim( $first_name );

		if ( empty( $first_name )
		or 50 < $this->strlen( $first_name ) ) {
			return false;
		}

		return $this->first_name = $first_name;
	}

	public function set_last_name( $last_name ) {
		$last_name = trim( $last_name );

		if ( empty( $last_name )
		or 50 < $this->strlen( $last_name ) ) {
			return false;
		}

		return $this->last_name = $last_name;
	}

	public function set_job_title( $job_title ) {
		$job_title = trim( $job_title );

		if ( empty( $job_title )
		or 50 < $this->strlen( $job_title ) ) {
			return false;
		}

		return $this->job_title = $job_title;
	}

	public function set_company_name( $company_name ) {
		$company_name = trim( $company_name );

		if ( empty( $company_name )
		or 50 < $this->strlen( $company_name ) ) {
			return false;
		}

		return $this->company_name = $company_name;
	}

	public function set_create_source( $create_source ) {
		if ( ! in_array( $create_source, array( 'Contact', 'Account' ) ) ) {
			return false;
		}

		return $this->create_source = $create_source;
	}

	public function set_birthday( $month, $day ) {
		$month = (int) $month;
		$day = (int) $day;

		if ( $month < 1 || 12 < $month
		or $day < 1 || 31 < $day ) {
			return false;
		}

		$this->birthday_month = $month;
		$this->birthday_day = $day;

		return array( $this->birthday_month, $this->birthday_day );
	}

	public function set_anniversary( $anniversary ) {
		$pattern = sprintf(
			'#^(%s)$#',
			implode( '|', array(
				'\d{1,2}/\d{1,2}/\d{4}',
				'\d{4}/\d{1,2}/\d{1,2}',
				'\d{4}-\d{1,2}-\d{1,2}',
				'\d{1,2}-\d{1,2}-\d{4}',
			) )
		);

		if ( ! preg_match( $pattern, $anniversary ) ) {
			return false;
		}

		return $this->anniversary = $anniversary;
	}

	public function add_custom_field( $custom_field_id, $value ) {
		$uuid_pattern = '/^[0-9a-f-]+$/i';

		$value = trim( $value );

		if ( 25 <= count( $this->custom_fields )
		or ! preg_match( $uuid_pattern, $custom_field_id )
		or 255 < $this->strlen( $value ) ) {
			return false;
		}

		return $this->custom_fields[] = array(
			'custom_field_id' => $custom_field_id,
			'value' => $value,
		);
	}

	public function add_phone_number( $phone_number, $kind = 'home' ) {
		$phone_number = trim( $phone_number );

		if ( empty( $phone_number )
		or ! wpcf7_is_tel( $phone_number )
		or 25 < $this->strlen( $phone_number )
		or 2 <= count( $this->phone_numbers )
		or ! in_array( $kind, array( 'home', 'work', 'other' ) ) ) {
			return false;
		}

		return $this->phone_numbers[] = array(
			'phone_number' => $phone_number,
			'kind' => $kind,
		);
	}

	public function add_street_address( $street, $city, $state, $postal_code, $country, $kind = 'home' ) {
		$street = trim( $street );
		$city = trim( $city );
		$state = trim( $state );
		$postal_code = trim( $postal_code );
		$country = trim( $country );

		if ( ! ( $street || $city || $state || $postal_code || $country )
		or 1 <= count( $this->street_addresses )
		or ! in_array( $kind, array( 'home', 'work', 'other' ) )
		or 255 < $this->strlen( $street )
		or 50 < $this->strlen( $city )
		or 50 < $this->strlen( $state )
		or 50 < $this->strlen( $postal_code )
		or 50 < $this->strlen( $country ) ) {
			return false;
		}

		return $this->street_addresses[] = array(
			'kind' => $kind,
			'street' => $street,
			'city' => $city,
			'state' => $state,
			'postal_code' => $postal_code,
			'country' => $country,
		);
	}

	public function add_list_membership( $list_id ) {
		$uuid_pattern = '/^[0-9a-f-]+$/i';

		if ( 50 <= count( $this->list_memberships )
		or ! preg_match( $uuid_pattern, $list_id ) ) {
			return false;
		}

		return $this->list_memberships[] = $list_id;
	}

	protected function strlen( $text ) {
		return wpcf7_count_code_units( $text );
	}

}
modules/constant-contact/doi.php000064400000004226147510545420012775 0ustar00<?php
/**
 * Double Opt-In Helper-related functions
 *
 * @link https://contactform7.com/doi-helper/
 */


add_action(
	'doihelper_init',
	'wpcf7_constant_contact_doi_register_agent',
	10, 0
);

/**
 * Registers wpcf7_constant_contact as an agent.
 */
function wpcf7_constant_contact_doi_register_agent() {
	if ( ! function_exists( 'doihelper_register_agent' ) ) {
		return;
	}

	doihelper_register_agent( 'wpcf7_constant_contact', array(
		'optin_callback' => apply_filters(
			'wpcf7_constant_contact_doi_optin_callback',
			'wpcf7_constant_contact_doi_default_optin_callback'
		),
		'email_callback' => apply_filters(
			'wpcf7_constant_contact_doi_email_callback',
			'wpcf7_constant_contact_doi_default_email_callback'
		),
	) );
}


/**
 * Default optin_callback function.
 */
function wpcf7_constant_contact_doi_default_optin_callback( $properties ) {
	$service = WPCF7_ConstantContact::get_instance();

	if ( $service->is_active() ) {
		$service->create_contact( $properties );
	}
}


/**
 * Default email_callback function.
 */
function wpcf7_constant_contact_doi_default_email_callback( $args ) {
	if ( ! isset( $args['token'] ) or ! isset( $args['email_to'] ) ) {
		return;
	}

	$site_title = wp_specialchars_decode(
		get_bloginfo( 'name' ),
		ENT_QUOTES
	);

	$link = add_query_arg(
		array( 'doitoken' => $args['token'] ),
		home_url()
	);

	$to = $args['email_to'];

	$subject = sprintf(
		/* translators: %s: blog name */
		__( 'Opt-in confirmation from %s', 'contact-form-7' ),
		$site_title
	);

	$message = sprintf(
		/* translators: 1: blog name, 2: confirmation link */
		__( 'Hello,

This is a confirmation email sent from %1$s.

We have received your submission to our web form, according to which you have allowed us to add you to our contact list. But, the process has not yet been completed. To complete it, please click the following link.

%2$s

If it was not your intention, or if you have no idea why you received this message, please do not click on the link, and ignore this message. We will never collect or use your personal data without your clear consent.

Sincerely,
%1$s', 'contact-form-7' ),
		$site_title,
		$link
	);

	wp_mail( $to, $subject, $message );
}
modules/constant-contact/contact-form-properties.php000064400000013654147510545420017015 0ustar00<?php

add_filter(
	'wpcf7_pre_construct_contact_form_properties',
	'wpcf7_constant_contact_register_property',
	10, 2
);

/**
 * Registers the constant_contact contact form property.
 */
function wpcf7_constant_contact_register_property( $properties, $contact_form ) {
	$service = WPCF7_ConstantContact::get_instance();

	if ( $service->is_active() ) {
		$properties += array(
			'constant_contact' => array(),
		);
	}

	return $properties;
}


add_filter(
	'wpcf7_contact_form_property_constant_contact',
	'wpcf7_constant_contact_setup_property',
	10, 2
);

/**
 * Sets up the constant_contact property value. For back-compat, this attempts
 * to take over the value from old settings if the property is empty.
 */
function wpcf7_constant_contact_setup_property( $property, $contact_form ) {
	if ( ! empty( $property ) ) {
		$property = wp_parse_args(
			$property,
			array(
				'enable_contact_list' => false,
				'contact_lists' => array(),
			)
		);

		return $property;
	}

	$property = array(
		'enable_contact_list' => true,
		'contact_lists' => array(),
	);

	if ( $contact_form->initial() ) {
		return $property;
	}

	$service_option = (array) WPCF7::get_option( 'constant_contact' );

	$property['enable_contact_list'] = ! $contact_form->is_false(
		'constant_contact'
	);

	if ( isset( $service_option['contact_lists'] ) ) {
		$contact_lists = (array) $service_option['contact_lists'];
		$contact_lists_selected = array();

		foreach ( $contact_lists as $list ) {
			if ( empty( $list['selected'] ) ) {
				continue;
			}

			foreach ( (array) $list['selected'] as $key => $val ) {
				if ( ! isset( $contact_lists_selected[$key] ) ) {
					$contact_lists_selected[$key] = array();
				}

				$contact_lists_selected[$key][] = $list['list_id'];
			}
		}

		$related_keys = array(
			sprintf( 'wpcf7_contact_form:%d', $contact_form->id() ),
			'default',
		);

		foreach ( $related_keys as $key ) {
			if ( ! empty( $contact_lists_selected[$key] ) ) {
				$property['contact_lists'] = $contact_lists_selected[$key];
				break;
			}
		}
	}

	return $property;
}


add_action(
	'wpcf7_save_contact_form',
	'wpcf7_constant_contact_save_contact_form',
	10, 1
);

/**
 * Saves the constant_contact property value.
 */
function wpcf7_constant_contact_save_contact_form( $contact_form ) {
	$service = WPCF7_ConstantContact::get_instance();

	if ( ! $service->is_active() ) {
		return;
	}

	$prop = isset( $_POST['wpcf7-ctct'] )
		? (array) $_POST['wpcf7-ctct']
		: array();

	$prop = wp_parse_args(
		$prop,
		array(
			'enable_contact_list' => false,
			'contact_lists' => array(),
		)
	);

	$contact_form->set_properties( array(
		'constant_contact' => $prop,
	) );
}


add_filter(
	'wpcf7_editor_panels',
	'wpcf7_constant_contact_editor_panels',
	10, 1
);

/**
 * Builds the editor panel for the constant_contact property.
 */
function wpcf7_constant_contact_editor_panels( $panels ) {
	$service = WPCF7_ConstantContact::get_instance();

	if ( ! $service->is_active() ) {
		return $panels;
	}

	$contact_form = WPCF7_ContactForm::get_current();

	$prop = wp_parse_args(
		$contact_form->prop( 'constant_contact' ),
		array(
			'enable_contact_list' => false,
			'contact_lists' => array(),
		)
	);

	$editor_panel = static function () use ( $prop, $service ) {

		$description = sprintf(
			esc_html(
				__( "You can set up the Constant Contact integration here. For details, see %s.", 'contact-form-7' )
			),
			wpcf7_link(
				__( 'https://contactform7.com/constant-contact-integration/', 'contact-form-7' ),
				__( 'Constant Contact integration', 'contact-form-7' )
			)
		);

		$lists = $service->get_contact_lists();

?>
<h2><?php echo esc_html( __( 'Constant Contact', 'contact-form-7' ) ); ?></h2>

<fieldset>
	<legend><?php echo $description; ?></legend>

	<table class="form-table" role="presentation">
		<tbody>
			<tr class="<?php echo $prop['enable_contact_list'] ? '' : 'inactive'; ?>">
				<th scope="row">
		<?php

		echo esc_html( __( 'Contact lists', 'contact-form-7' ) );

		?>
				</th>
				<td>
					<fieldset>
						<legend class="screen-reader-text">
		<?php

		echo esc_html( __( 'Contact lists', 'contact-form-7' ) );

		?>
						</legend>
						<label for="wpcf7-ctct-enable-contact-list">
							<input type="checkbox" name="wpcf7-ctct[enable_contact_list]" id="wpcf7-ctct-enable-contact-list" value="1" <?php checked( $prop['enable_contact_list'] ); ?> />
		<?php

		echo esc_html(
			__( "Add form submitters to your contact lists", 'contact-form-7' )
		);

		?>
						</label>
					</fieldset>
				</td>
			</tr>
			<tr>
				<th scope="row"></th>
				<td>
					<fieldset>
		<?php

		if ( $lists ) {
			echo sprintf(
				'<legend>%1$s</legend>',
				esc_html( __( 'Select lists to which contacts are added:', 'contact-form-7' ) )
			);

			echo '<ul>';

			foreach ( $lists as $list ) {
				echo sprintf(
					'<li><label><input %1$s /> %2$s</label></li>',
					wpcf7_format_atts( array(
						'type' => 'checkbox',
						'name' => 'wpcf7-ctct[contact_lists][]',
						'value' => $list['list_id'],
						'checked' => in_array( $list['list_id'], $prop['contact_lists'] ),
					) ),
					esc_html( $list['name'] )
				);
			}

			echo '</ul>';
		} else {
			echo sprintf(
				'<legend>%1$s</legend>',
				esc_html( __( 'You have no contact list yet.', 'contact-form-7' ) )
			);
		}

		?>
					</fieldset>
		<?php

		echo sprintf(
			'<p><a %1$s>%2$s <span class="screen-reader-text">%3$s</span><span aria-hidden="true" class="dashicons dashicons-external"></span></a></p>',
			wpcf7_format_atts( array(
				'href' => 'https://app.constantcontact.com/pages/contacts/ui#lists',
				'target' => '_blank',
				'rel' => 'external noreferrer noopener',
			) ),
			esc_html( __( 'Manage your contact lists', 'contact-form-7' ) ),
			esc_html( __( '(opens in a new tab)', 'contact-form-7' ) )
		);

		?>
				</td>
			</tr>
		</tbody>
	</table>
</fieldset>
<?php
	};

	$panels += array(
		'ctct-panel' => array(
			'title' => __( 'Constant Contact', 'contact-form-7' ),
			'callback' => $editor_panel,
		),
	);

	return $panels;
}
modules/sendinblue/sendinblue.php000064400000012347147510545420013223 0ustar00<?php
/**
 * Brevo module main file
 *
 * @link https://contactform7.com/sendinblue-integration/
 */

wpcf7_include_module_file( 'sendinblue/service.php' );
wpcf7_include_module_file( 'sendinblue/contact-form-properties.php' );
wpcf7_include_module_file( 'sendinblue/doi.php' );


add_action( 'wpcf7_init', 'wpcf7_sendinblue_register_service', 10, 0 );

/**
 * Registers the Sendinblue service.
 */
function wpcf7_sendinblue_register_service() {
	$integration = WPCF7_Integration::get_instance();

	$integration->add_service( 'sendinblue',
		WPCF7_Sendinblue::get_instance()
	);
}


add_action( 'wpcf7_submit', 'wpcf7_sendinblue_submit', 10, 2 );

/**
 * Callback to the wpcf7_submit action hook. Creates a contact
 * based on the submission.
 */
function wpcf7_sendinblue_submit( $contact_form, $result ) {
	if ( $contact_form->in_demo_mode() ) {
		return;
	}

	$service = WPCF7_Sendinblue::get_instance();

	if ( ! $service->is_active() ) {
		return;
	}

	if ( empty( $result['posted_data_hash'] ) ) {
		return;
	}

	if ( empty( $result['status'] )
	or ! in_array( $result['status'], array( 'mail_sent', 'mail_failed' ) ) ) {
		return;
	}

	$submission = WPCF7_Submission::get_instance();

	$consented = true;

	foreach ( $contact_form->scan_form_tags( 'feature=name-attr' ) as $tag ) {
		if ( $tag->has_option( 'consent_for:sendinblue' )
		and null == $submission->get_posted_data( $tag->name ) ) {
			$consented = false;
			break;
		}
	}

	if ( ! $consented ) {
		return;
	}

	$prop = wp_parse_args(
		$contact_form->prop( 'sendinblue' ),
		array(
			'enable_contact_list' => false,
			'contact_lists' => array(),
			'enable_transactional_email' => false,
			'email_template' => 0,
		)
	);

	if ( ! $prop['enable_contact_list'] ) {
		return;
	}

	$attributes = wpcf7_sendinblue_collect_parameters();

	$params = array(
		'contact' => array(),
		'email' => array(),
	);

	if ( ! empty( $attributes['EMAIL'] ) or ! empty( $attributes['SMS'] ) ) {
		$params['contact'] = apply_filters(
			'wpcf7_sendinblue_contact_parameters',
			array(
				'email' => $attributes['EMAIL'],
				'attributes' => (object) $attributes,
				'listIds' => (array) $prop['contact_lists'],
				'updateEnabled' => false,
			)
		);
	}

	if ( $prop['enable_transactional_email'] and $prop['email_template'] ) {
		$first_name = isset( $attributes['FIRSTNAME'] )
			? trim( $attributes['FIRSTNAME'] )
			: '';

		$last_name = isset( $attributes['LASTNAME'] )
			? trim( $attributes['LASTNAME'] )
			: '';

		if ( $first_name or $last_name ) {
			$email_to_name = sprintf(
				/* translators: 1: first name, 2: last name */
				_x( '%1$s %2$s', 'personal name', 'contact-form-7' ),
				$first_name,
				$last_name
			);
		} else {
			$email_to_name = '';
		}

		$params['email'] = apply_filters(
			'wpcf7_sendinblue_email_parameters',
			array(
				'templateId' => absint( $prop['email_template'] ),
				'to' => array(
					array(
						'name' => $email_to_name,
						'email' => $attributes['EMAIL'],
					),
				),
				'params' => (object) $attributes,
				'tags' => array( 'Contact Form 7' ),
			)
		);
	}

	if ( is_email( $attributes['EMAIL'] ) ) {
		$token = null;

		do_action_ref_array( 'wpcf7_doi', array(
			'wpcf7_sendinblue',
			array(
				'email_to' => $attributes['EMAIL'],
				'properties' => $params,
			),
			&$token,
		) );

		if ( isset( $token ) ) {
			return;
		}
	}

	if ( ! empty( $params['contact'] ) ) {
		$contact_id = $service->create_contact( $params['contact'] );

		if ( $contact_id and ! empty( $params['email'] ) ) {
			$service->send_email( $params['email'] );
		}
	}
}


/**
 * Collects parameters for Sendinblue contact data based on submission.
 *
 * @return array Sendinblue contact parameters.
 */
function wpcf7_sendinblue_collect_parameters() {
	$params = array();

	$submission = WPCF7_Submission::get_instance();

	foreach ( (array) $submission->get_posted_data() as $name => $val ) {
		$name = strtoupper( $name );

		if ( 'YOUR-' == substr( $name, 0, 5 ) ) {
			$name = substr( $name, 5 );
		}

		if ( $val ) {
			$params += array(
				$name => $val,
			);
		}
	}

	if ( isset( $params['SMS'] ) ) {
		$sms = trim( implode( ' ', (array) $params['SMS'] ) );
		$sms = preg_replace( '/[#*].*$/', '', $sms ); // Remove extension

		$is_international = false ||
			str_starts_with( $sms, '+' ) ||
			str_starts_with( $sms, '00' );

		if ( $is_international ) {
			$sms = preg_replace( '/^[+0]+/', '', $sms );
		}

		$sms = preg_replace( '/[^0-9]/', '', $sms );

		if ( $is_international and 6 < strlen( $sms ) and strlen( $sms ) < 16 ) {
			$params['SMS'] = '+' . $sms;
		} else { // Invalid telephone number
			unset( $params['SMS'] );
		}
	}

	if ( isset( $params['NAME'] ) ) {
		$your_name = implode( ' ', (array) $params['NAME'] );
		$your_name = explode( ' ', $your_name );

		if ( ! isset( $params['LASTNAME'] ) ) {
			$params['LASTNAME'] = implode(
				' ',
				array_slice( $your_name, 1 )
			);
		}

		if ( ! isset( $params['FIRSTNAME'] ) ) {
			$params['FIRSTNAME'] = implode(
				' ',
				array_slice( $your_name, 0, 1 )
			);
		}
	}

	$params = array_map(
		function ( $param ) {
			if ( is_array( $param ) ) {
				$param = wpcf7_array_flatten( $param );
				$param = reset( $param );
			}

			return $param;
		},
		$params
	);

	$params = apply_filters(
		'wpcf7_sendinblue_collect_parameters',
		$params
	);

	return $params;
}
modules/sendinblue/doi.php000064400000004433147510545420011643 0ustar00<?php
/**
 * Double Opt-In Helper-related functions
 *
 * @link https://contactform7.com/doi-helper/
 */


add_action(
	'doihelper_init',
	'wpcf7_sendinblue_doi_register_agent',
	10, 0
);

/**
 * Registers wpcf7_sendinblue as an agent.
 */
function wpcf7_sendinblue_doi_register_agent() {
	if ( ! function_exists( 'doihelper_register_agent' ) ) {
		return;
	}

	doihelper_register_agent( 'wpcf7_sendinblue', array(
		'optin_callback' => apply_filters(
			'wpcf7_sendinblue_doi_optin_callback',
			'wpcf7_sendinblue_doi_default_optin_callback'
		),
		'email_callback' => apply_filters(
			'wpcf7_sendinblue_doi_email_callback',
			'wpcf7_sendinblue_doi_default_email_callback'
		),
	) );
}


/**
 * Default optin_callback function.
 */
function wpcf7_sendinblue_doi_default_optin_callback( $properties ) {
	$service = WPCF7_Sendinblue::get_instance();

	if ( ! $service->is_active() ) {
		return;
	}

	if ( ! empty( $properties['contact'] ) ) {
		$contact_id = $service->create_contact( $properties['contact'] );

		if ( $contact_id and ! empty( $properties['email'] ) ) {
			$service->send_email( $properties['email'] );
		}
	}
}


/**
 * Default email_callback function.
 */
function wpcf7_sendinblue_doi_default_email_callback( $args ) {
	if ( ! isset( $args['token'] ) or ! isset( $args['email_to'] ) ) {
		return;
	}

	$site_title = wp_specialchars_decode(
		get_bloginfo( 'name' ),
		ENT_QUOTES
	);

	$link = add_query_arg(
		array( 'doitoken' => $args['token'] ),
		home_url()
	);

	$to = $args['email_to'];

	$subject = sprintf(
		/* translators: %s: blog name */
		__( 'Opt-in confirmation from %s', 'contact-form-7' ),
		$site_title
	);

	$message = sprintf(
		/* translators: 1: blog name, 2: confirmation link */
		__( 'Hello,

This is a confirmation email sent from %1$s.

We have received your submission to our web form, according to which you have allowed us to add you to our contact list. But, the process has not yet been completed. To complete it, please click the following link.

%2$s

If it was not your intention, or if you have no idea why you received this message, please do not click on the link, and ignore this message. We will never collect or use your personal data without your clear consent.

Sincerely,
%1$s', 'contact-form-7' ),
		$site_title,
		$link
	);

	wp_mail( $to, $subject, $message );
}
modules/sendinblue/contact-form-properties.php000064400000016441147510545420015660 0ustar00<?php

add_filter(
	'wpcf7_pre_construct_contact_form_properties',
	'wpcf7_sendinblue_register_property',
	10, 2
);

/**
 * Registers the sendinblue contact form property.
 */
function wpcf7_sendinblue_register_property( $properties, $contact_form ) {
	$service = WPCF7_Sendinblue::get_instance();

	if ( $service->is_active() ) {
		$properties += array(
			'sendinblue' => array(),
		);
	}

	return $properties;
}


add_action(
	'wpcf7_save_contact_form',
	'wpcf7_sendinblue_save_contact_form',
	10, 3
);

/**
 * Saves the sendinblue property value.
 */
function wpcf7_sendinblue_save_contact_form( $contact_form, $args, $context ) {
	$service = WPCF7_Sendinblue::get_instance();

	if ( ! $service->is_active() ) {
		return;
	}

	$prop = (array) ( $_POST['wpcf7-sendinblue'] ?? array() );

	$prop = wp_parse_args(
		$prop,
		array(
			'enable_contact_list' => false,
			'contact_lists' => array(),
			'enable_transactional_email' => false,
			'email_template' => 0,
		)
	);

	$prop['contact_lists'] = array_map( 'absint', $prop['contact_lists'] );

	$prop['email_template'] = absint( $prop['email_template'] );

	$contact_form->set_properties( array(
		'sendinblue' => $prop,
	) );
}


add_filter(
	'wpcf7_editor_panels',
	'wpcf7_sendinblue_editor_panels',
	10, 1
);

/**
 * Builds the editor panel for the sendinblue property.
 */
function wpcf7_sendinblue_editor_panels( $panels ) {
	$service = WPCF7_Sendinblue::get_instance();

	if ( ! $service->is_active() ) {
		return $panels;
	}

	$contact_form = WPCF7_ContactForm::get_current();

	$prop = wp_parse_args(
		$contact_form->prop( 'sendinblue' ),
		array(
			'enable_contact_list' => false,
			'contact_lists' => array(),
			'enable_transactional_email' => false,
			'email_template' => 0,
		)
	);

	$editor_panel = static function () use ( $prop, $service ) {

		$description = sprintf(
			esc_html(
				__( "You can set up the Brevo integration here. For details, see %s.", 'contact-form-7' )
			),
			wpcf7_link(
				__( 'https://contactform7.com/sendinblue-integration/', 'contact-form-7' ),
				__( 'Brevo integration', 'contact-form-7' )
			)
		);

		$lists = wpcf7_sendinblue_get_lists();
		$templates = $service->get_templates();

?>
<h2><?php echo esc_html( __( 'Brevo', 'contact-form-7' ) ); ?></h2>

<fieldset>
	<legend><?php echo $description; ?></legend>

	<table class="form-table" role="presentation">
		<tbody>
			<tr class="<?php echo $prop['enable_contact_list'] ? '' : 'inactive'; ?>">
				<th scope="row">
		<?php

		echo esc_html( __( 'Contact lists', 'contact-form-7' ) );

		?>
				</th>
				<td>
					<fieldset>
						<legend class="screen-reader-text">
		<?php

		echo esc_html( __( 'Contact lists', 'contact-form-7' ) );

		?>
						</legend>
						<label for="wpcf7-sendinblue-enable-contact-list">
							<input type="checkbox" name="wpcf7-sendinblue[enable_contact_list]" id="wpcf7-sendinblue-enable-contact-list" value="1" <?php checked( $prop['enable_contact_list'] ); ?> />
		<?php

		echo esc_html(
			__( "Add form submitters to your contact lists", 'contact-form-7' )
		);

		?>
						</label>
					</fieldset>
				</td>
			</tr>
			<tr>
				<th scope="row"></th>
				<td>
					<fieldset>
		<?php

		if ( $lists ) {
			echo sprintf(
				'<legend>%1$s</legend>',
				esc_html( __( 'Select lists to which contacts are added:', 'contact-form-7' ) )
			);

			echo '<ul>';

			foreach ( $lists as $list ) {
				echo sprintf(
					'<li><label><input %1$s /> %2$s</label></li>',
					wpcf7_format_atts( array(
						'type' => 'checkbox',
						'name' => 'wpcf7-sendinblue[contact_lists][]',
						'value' => $list['id'],
						'checked' => in_array( $list['id'], $prop['contact_lists'] ),
					) ),
					esc_html( $list['name'] )
				);
			}

			echo '</ul>';
		} else {
			echo sprintf(
				'<legend>%1$s</legend>',
				esc_html( __( 'You have no contact list yet.', 'contact-form-7' ) )
			);
		}

		?>
					</fieldset>
		<?php

		echo sprintf(
			'<p><a %1$s>%2$s <span class="screen-reader-text">%3$s</span><span aria-hidden="true" class="dashicons dashicons-external"></span></a></p>',
			wpcf7_format_atts( array(
				'href' => 'https://my.sendinblue.com/lists',
				'target' => '_blank',
				'rel' => 'external noreferrer noopener',
			) ),
			esc_html( __( 'Manage your contact lists', 'contact-form-7' ) ),
			esc_html( __( '(opens in a new tab)', 'contact-form-7' ) )
		);

		?>
				</td>
			</tr>
			<tr class="<?php echo $prop['enable_transactional_email'] ? '' : 'inactive'; ?>">
				<th scope="row">
		<?php

		echo esc_html( __( 'Welcome email', 'contact-form-7' ) );

		?>
				</th>
				<td>
					<fieldset>
						<legend class="screen-reader-text">
		<?php

		echo esc_html( __( 'Welcome email', 'contact-form-7' ) );

		?>
						</legend>
						<label for="wpcf7-sendinblue-enable-transactional-email">
							<input type="checkbox" name="wpcf7-sendinblue[enable_transactional_email]" id="wpcf7-sendinblue-enable-transactional-email" value="1" <?php checked( $prop['enable_transactional_email'] ); ?> />
		<?php

		echo esc_html(
			__( "Send a welcome email to new contacts", 'contact-form-7' )
		);

		?>
						</label>
					</fieldset>
				</td>
			</tr>
			<tr>
				<th scope="row"></th>
				<td>
					<fieldset>
		<?php

		if ( $templates ) {
			echo sprintf(
				'<legend>%1$s</legend>',
				esc_html( __( 'Select an email template:', 'contact-form-7' ) )
			);

			echo '<select name="wpcf7-sendinblue[email_template]">';

			echo sprintf(
				'<option %1$s>%2$s</option>',
				wpcf7_format_atts( array(
					'value' => 0,
					'selected' => 0 === $prop['email_template'],
				) ),
				esc_html( __( '&mdash; Select &mdash;', 'contact-form-7' ) )
			);

			foreach ( $templates as $template ) {
				echo sprintf(
					'<option %1$s>%2$s</option>',
					wpcf7_format_atts( array(
						'value' => $template['id'],
						'selected' => $prop['email_template'] === $template['id'],
					) ),
					esc_html( $template['name'] )
				);
			}

			echo '</select>';
		} else {
			echo sprintf(
				'<legend>%1$s</legend>',
				esc_html( __( 'You have no active email template yet.', 'contact-form-7' ) )
			);
		}

		?>
					</fieldset>
		<?php

		echo sprintf(
			'<p><a %1$s>%2$s <span class="screen-reader-text">%3$s</span><span aria-hidden="true" class="dashicons dashicons-external"></span></a></p>',
			wpcf7_format_atts( array(
				'href' => 'https://my.sendinblue.com/camp/lists/template',
				'target' => '_blank',
				'rel' => 'external noreferrer noopener',
			) ),
			esc_html( __( 'Manage your email templates', 'contact-form-7' ) ),
			esc_html( __( '(opens in a new tab)', 'contact-form-7' ) )
		);

		?>
				</td>
			</tr>
		</tbody>
	</table>
</fieldset>
<?php
	};

	$panels += array(
		'sendinblue-panel' => array(
			'title' => __( 'Brevo', 'contact-form-7' ),
			'callback' => $editor_panel,
		),
	);

	return $panels;
}


/**
 * Retrieves contact lists from Brevo's database.
 */
function wpcf7_sendinblue_get_lists() {
	static $lists = array();

	$service = WPCF7_Sendinblue::get_instance();

	if ( ! empty( $lists ) or ! $service->is_active() ) {
		return $lists;
	}

	$limit = 50;
	$offset = 0;

	while ( count( $lists ) < $limit * 10 ) {
		$lists_next = (array) $service->get_lists( array(
			'limit' => $limit,
			'offset' => $offset,
		) );

		if ( ! empty( $lists_next ) ) {
			$lists = array_merge( $lists, $lists_next );
		}

		if ( count( $lists_next ) < $limit ) {
			break;
		}

		$offset += $limit;
	}

	return $lists;
}
modules/sendinblue/service.php000064400000022305147510545420012526 0ustar00<?php

if ( ! class_exists( 'WPCF7_Service' ) ) {
	return;
}

class WPCF7_Sendinblue extends WPCF7_Service {
	use WPCF7_Sendinblue_API;

	private static $instance;
	private $api_key;

	public static function get_instance() {
		if ( empty( self::$instance ) ) {
			self::$instance = new self;
		}

		return self::$instance;
	}

	private function __construct() {
		$option = WPCF7::get_option( 'sendinblue' );

		if ( isset( $option['api_key'] ) ) {
			$this->api_key = $option['api_key'];
		}
	}

	public function get_title() {
		return __( 'Brevo', 'contact-form-7' );
	}

	public function is_active() {
		return (bool) $this->get_api_key();
	}

	public function get_api_key() {
		return $this->api_key;
	}

	public function get_categories() {
		return array( 'email_marketing' );
	}

	public function icon() {
	}

	public function link() {
		echo wpcf7_link(
			'https://get.brevo.com/wpcf7-integration',
			'brevo.com'
		);
	}

	protected function log( $url, $request, $response ) {
		wpcf7_log_remote_request( $url, $request, $response );
	}

	protected function menu_page_url( $args = '' ) {
		$args = wp_parse_args( $args, array() );

		$url = menu_page_url( 'wpcf7-integration', false );
		$url = add_query_arg( array( 'service' => 'sendinblue' ), $url );

		if ( ! empty( $args ) ) {
			$url = add_query_arg( $args, $url );
		}

		return $url;
	}

	protected function save_data() {
		WPCF7::update_option( 'sendinblue', array(
			'api_key' => $this->api_key,
		) );
	}

	protected function reset_data() {
		$this->api_key = null;
		$this->save_data();
	}

	public function load( $action = '' ) {
		if ( 'setup' == $action and 'POST' == $_SERVER['REQUEST_METHOD'] ) {
			check_admin_referer( 'wpcf7-sendinblue-setup' );

			if ( ! empty( $_POST['reset'] ) ) {
				$this->reset_data();
				$redirect_to = $this->menu_page_url( 'action=setup' );
			} else {
				$this->api_key = trim( $_POST['api_key'] ?? '' );

				$confirmed = $this->confirm_key();

				if ( true === $confirmed ) {
					$redirect_to = $this->menu_page_url( array(
						'message' => 'success',
					) );

					$this->save_data();
				} elseif ( false === $confirmed ) {
					$redirect_to = $this->menu_page_url( array(
						'action' => 'setup',
						'message' => 'unauthorized',
					) );
				} else {
					$redirect_to = $this->menu_page_url( array(
						'action' => 'setup',
						'message' => 'invalid',
					) );
				}
			}

			wp_safe_redirect( $redirect_to );
			exit();
		}
	}

	public function admin_notice( $message = '' ) {
		if ( 'unauthorized' === $message ) {
			wp_admin_notice(
				sprintf(
					'<strong>%1$s</strong>: %2$s',
					esc_html( __( "Error", 'contact-form-7' ) ),
					esc_html( __( "You have not been authenticated. Make sure the provided API key is correct.", 'contact-form-7' ) )
				),
				'type=error'
			);
		}

		if ( 'invalid' === $message ) {
			wp_admin_notice(
				sprintf(
					'<strong>%1$s</strong>: %2$s',
					esc_html( __( "Error", 'contact-form-7' ) ),
					esc_html( __( "Invalid key values.", 'contact-form-7' ) )
				),
				'type=error'
			);
		}

		if ( 'success' === $message ) {
			wp_admin_notice(
				esc_html( __( "Settings saved.", 'contact-form-7' ) ),
				'type=success'
			);
		}
	}

	public function display( $action = '' ) {
		echo sprintf(
			'<p>%s</p>',
			esc_html( __( "Store and organize your contacts while protecting user privacy on Brevo, the leading CRM & email marketing platform in Europe. Brevo offers unlimited contacts and advanced marketing features.", 'contact-form-7' ) )
		);

		echo sprintf(
			'<p><strong>%s</strong></p>',
			wpcf7_link(
				__( 'https://contactform7.com/sendinblue-integration/', 'contact-form-7' ),
				__( 'Brevo integration', 'contact-form-7' )
			)
		);

		if ( $this->is_active() ) {
			echo sprintf(
				'<p class="dashicons-before dashicons-yes">%s</p>',
				esc_html( __( "Brevo is active on this site.", 'contact-form-7' ) )
			);
		}

		if ( 'setup' == $action ) {
			$this->display_setup();
		} else {
			echo sprintf(
				'<p><a href="%1$s" class="button">%2$s</a></p>',
				esc_url( $this->menu_page_url( 'action=setup' ) ),
				esc_html( __( 'Setup integration', 'contact-form-7' ) )
			);
		}
	}

	private function display_setup() {
		$api_key = $this->get_api_key();

?>
<form method="post" action="<?php echo esc_url( $this->menu_page_url( 'action=setup' ) ); ?>">
<?php wp_nonce_field( 'wpcf7-sendinblue-setup' ); ?>
<table class="form-table">
<tbody>
<tr>
	<th scope="row"><label for="publishable"><?php echo esc_html( __( 'API key', 'contact-form-7' ) ); ?></label></th>
	<td><?php
		if ( $this->is_active() ) {
			echo esc_html( wpcf7_mask_password( $api_key, 4, 8 ) );
			echo sprintf(
				'<input type="hidden" value="%s" id="api_key" name="api_key" />',
				esc_attr( $api_key )
			);
		} else {
			echo sprintf(
				'<input type="text" aria-required="true" value="%s" id="api_key" name="api_key" class="regular-text code" />',
				esc_attr( $api_key )
			);
		}
	?></td>
</tr>
</tbody>
</table>
<?php
		if ( $this->is_active() ) {
			submit_button(
				_x( 'Remove key', 'API keys', 'contact-form-7' ),
				'small', 'reset'
			);
		} else {
			submit_button( __( 'Save changes', 'contact-form-7' ) );
		}
?>
</form>
<?php
	}
}


/**
 * Trait for the Sendinblue API (v3).
 *
 * @link https://developers.sendinblue.com/reference
 */
trait WPCF7_Sendinblue_API {


	public function confirm_key() {
		$endpoint = 'https://api.sendinblue.com/v3/account';

		$request = array(
			'headers' => array(
				'Accept' => 'application/json',
				'Content-Type' => 'application/json; charset=utf-8',
				'API-Key' => $this->get_api_key(),
			),
		);

		$response = wp_remote_get( $endpoint, $request );
		$response_code = (int) wp_remote_retrieve_response_code( $response );

		if ( 200 === $response_code ) { // 200 OK
			return true;
		} elseif ( 401 === $response_code ) { // 401 Unauthorized
			return false;
		} elseif ( 400 <= $response_code ) {
			if ( WP_DEBUG ) {
				$this->log( $endpoint, $request, $response );
			}
		}
	}


	public function get_lists( $options = '' ) {
		$options = wp_parse_args( $options, array(
			'limit' => 50,
			'offset' => 0,
		) );

		$endpoint = add_query_arg(
			$options,
			'https://api.sendinblue.com/v3/contacts/lists'
		);

		$request = array(
			'headers' => array(
				'Accept' => 'application/json',
				'Content-Type' => 'application/json; charset=utf-8',
				'API-Key' => $this->get_api_key(),
			),
		);

		$response = wp_remote_get( $endpoint, $request );
		$response_code = (int) wp_remote_retrieve_response_code( $response );

		if ( 200 === $response_code ) { // 200 OK
			$response_body = wp_remote_retrieve_body( $response );
			$response_body = json_decode( $response_body, true );

			if ( empty( $response_body['lists'] ) ) {
				return array();
			} else {
				return (array) $response_body['lists'];
			}
		} elseif ( 400 <= $response_code ) {
			if ( WP_DEBUG ) {
				$this->log( $endpoint, $request, $response );
			}
		}
	}


	public function get_templates() {
		$endpoint = add_query_arg(
			array(
				'templateStatus' => 'true',
				'limit' => 100,
				'offset' => 0,
			),
			'https://api.sendinblue.com/v3/smtp/templates'
		);

		$request = array(
			'headers' => array(
				'Accept' => 'application/json',
				'Content-Type' => 'application/json; charset=utf-8',
				'API-Key' => $this->get_api_key(),
			),
		);

		$response = wp_remote_get( $endpoint, $request );
		$response_code = (int) wp_remote_retrieve_response_code( $response );

		if ( 200 === $response_code ) { // 200 OK
			$response_body = wp_remote_retrieve_body( $response );
			$response_body = json_decode( $response_body, true );

			if ( empty( $response_body['templates'] ) ) {
				return array();
			} else {
				return (array) $response_body['templates'];
			}
		} elseif ( 400 <= $response_code ) {
			if ( WP_DEBUG ) {
				$this->log( $endpoint, $request, $response );
			}
		}
	}


	public function create_contact( $properties ) {
		$endpoint = 'https://api.sendinblue.com/v3/contacts';

		$request = array(
			'headers' => array(
				'Accept' => 'application/json',
				'Content-Type' => 'application/json; charset=utf-8',
				'API-Key' => $this->get_api_key(),
			),
			'body' => wp_json_encode( $properties ),
		);

		$response = wp_remote_post( $endpoint, $request );
		$response_code = (int) wp_remote_retrieve_response_code( $response );

		if ( in_array( $response_code, array( 201, 204 ), true ) ) {
			$contact_id = wp_remote_retrieve_body( $response );
			return $contact_id;
		} elseif ( 400 <= $response_code ) {
			if ( WP_DEBUG ) {
				$this->log( $endpoint, $request, $response );
			}
		}

		return false;
	}


	public function send_email( $properties ) {
		$endpoint = 'https://api.sendinblue.com/v3/smtp/email';

		$request = array(
			'headers' => array(
				'Accept' => 'application/json',
				'Content-Type' => 'application/json; charset=utf-8',
				'API-Key' => $this->get_api_key(),
			),
			'body' => wp_json_encode( $properties ),
		);

		$response = wp_remote_post( $endpoint, $request );
		$response_code = (int) wp_remote_retrieve_response_code( $response );

		if ( 201 === $response_code ) { // 201 Transactional email sent
			$message_id = wp_remote_retrieve_body( $response );
			return $message_id;
		} elseif ( 400 <= $response_code ) {
			if ( WP_DEBUG ) {
				$this->log( $endpoint, $request, $response );
			}
		}

		return false;
	}


}
modules/disallowed-list.php000064400000003423147510545420012036 0ustar00<?php

add_filter( 'wpcf7_spam', 'wpcf7_disallowed_list', 10, 2 );

function wpcf7_disallowed_list( $spam, $submission ) {
	if ( $spam ) {
		return $spam;
	}

	$target = wpcf7_array_flatten( $submission->get_posted_data() );
	$target[] = $submission->get_meta( 'remote_ip' );
	$target[] = $submission->get_meta( 'user_agent' );
	$target = implode( "\n", $target );

	$word = wpcf7_check_disallowed_list( $target );

	$word = wpcf7_apply_filters_deprecated(
		'wpcf7_submission_is_blacklisted',
		array( $word, $submission ),
		'5.3',
		'wpcf7_submission_has_disallowed_words'
	);

	$word = apply_filters(
		'wpcf7_submission_has_disallowed_words',
		$word,
		$submission
	);

	if ( $word ) {
		if ( is_bool( $word ) ) {
			$reason = __( "Disallowed words are used.", 'contact-form-7' );
		} else {
			$reason = sprintf(
				__( "Disallowed words (%s) are used.", 'contact-form-7' ),
				implode( ', ', (array) $word )
			);
		}

		$submission->add_spam_log( array(
			'agent' => 'disallowed_list',
			'reason' => $reason,
		) );
	}

	$spam = (bool) $word;

	return $spam;
}

function wpcf7_check_disallowed_list( $target ) {
	$mod_keys = get_option( 'disallowed_keys' );

	if ( is_scalar( $mod_keys ) ) {
		$mod_keys = trim( $mod_keys );
	} else {
		$mod_keys = '';
	}

	if ( '' === $mod_keys ) {
		return false;
	}

	foreach ( explode( "\n", $mod_keys ) as $word ) {
		$word = trim( $word );
		$length = strlen( $word );

		if ( $length < 2 or 256 < $length ) {
			continue;
		}

		$pattern = sprintf( '#%s#i', preg_quote( $word, '#' ) );

		if ( preg_match( $pattern, $target ) ) {
			return $word;
		}
	}

	return false;
}

function wpcf7_blacklist_check( $target ) {
	wpcf7_deprecated_function(
		__FUNCTION__,
		'5.3',
		'wpcf7_check_disallowed_list'
	);

	return wpcf7_check_disallowed_list( $target );
}
modules/listo.php000064400000001363147510545420010071 0ustar00<?php
/**
** Retrieve list data from the Listo plugin.
** Listo http://wordpress.org/plugins/listo/
**/

add_filter( 'wpcf7_form_tag_data_option', 'wpcf7_listo', 10, 3 );

function wpcf7_listo( $data, $options, $args ) {
	if ( ! function_exists( 'listo' ) ) {
		return $data;
	}

	$args = wp_parse_args( $args, array() );

	if ( $contact_form = wpcf7_get_current_contact_form() ) {
		$args['locale'] = $contact_form->locale();
	}

	foreach ( (array) $options as $option ) {
		$option = explode( '.', $option );
		$type = $option[0];

		if ( isset( $option[1] ) ) {
			$args['group'] = $option[1];
		} else {
			unset( $args['group'] );
		}

		if ( $list = listo( $type, $args ) ) {
			$data = array_merge( (array) $data, $list );
		}
	}

	return $data;
}
modules/flamingo.php000064400000020531147510545420010531 0ustar00<?php
/**
** Module for Flamingo plugin.
** http://wordpress.org/extend/plugins/flamingo/
**/

add_action( 'wpcf7_submit', 'wpcf7_flamingo_submit', 10, 2 );

function wpcf7_flamingo_submit( $contact_form, $result ) {
	if ( ! class_exists( 'Flamingo_Contact' )
	or ! class_exists( 'Flamingo_Inbound_Message' ) ) {
		return;
	}

	if ( $contact_form->in_demo_mode() ) {
		return;
	}

	$cases = (array) apply_filters( 'wpcf7_flamingo_submit_if',
		array( 'spam', 'mail_sent', 'mail_failed' )
	);

	if ( empty( $result['status'] )
	or ! in_array( $result['status'], $cases ) ) {
		return;
	}

	$submission = WPCF7_Submission::get_instance();

	if ( ! $submission
	or ! $posted_data = $submission->get_posted_data() ) {
		return;
	}

	if ( $submission->get_meta( 'do_not_store' ) ) {
		return;
	}

	// Exclude do-not-store form-tag values.
	$posted_data = array_filter(
		$posted_data,
		static function ( $name ) use ( $contact_form ) {
			return ! $contact_form->scan_form_tags( array(
				'name' => $name,
				'feature' => 'do-not-store',
			) );
		},
		ARRAY_FILTER_USE_KEY
	);

	$email = wpcf7_flamingo_get_value( 'email', $contact_form );
	$name = wpcf7_flamingo_get_value( 'name', $contact_form );
	$subject = wpcf7_flamingo_get_value( 'subject', $contact_form );

	$meta = array();

	$special_mail_tags = array( 'serial_number', 'remote_ip',
		'user_agent', 'url', 'date', 'time', 'post_id', 'post_name',
		'post_title', 'post_url', 'post_author', 'post_author_email',
		'site_title', 'site_description', 'site_url', 'site_admin_email',
		'user_login', 'user_email', 'user_display_name',
	);

	foreach ( $special_mail_tags as $smt ) {
		$tagname = sprintf( '_%s', $smt );

		$mail_tag = new WPCF7_MailTag(
			sprintf( '[%s]', $tagname ),
			$tagname,
			''
		);

		$meta[$smt] = apply_filters( 'wpcf7_special_mail_tags', null,
			$tagname, false, $mail_tag
		);
	}

	$timestamp = $submission->get_meta( 'timestamp' );

	if ( $timestamp and $datetime = date_create( '@' . $timestamp ) ) {
		$datetime->setTimezone( wp_timezone() );
		$last_contacted = $datetime->format( 'Y-m-d H:i:s' );
	} else {
		$last_contacted = '0000-00-00 00:00:00';
	}

	if ( 'mail_sent' == $result['status'] ) {
		$flamingo_contact = Flamingo_Contact::add( array(
			'email' => $email,
			'name' => $name,
			'last_contacted' => $last_contacted,
		) );
	}

	$post_meta = get_post_meta( $contact_form->id(), '_flamingo', true );

	$channel_id = isset( $post_meta['channel'] )
		? (int) $post_meta['channel']
		: wpcf7_flamingo_add_channel(
				$contact_form->name(),
				$contact_form->title()
			);

	if ( $channel_id ) {
		if ( ! isset( $post_meta['channel'] )
		or $post_meta['channel'] !== $channel_id ) {
			$post_meta = empty( $post_meta ) ? array() : (array) $post_meta;
			$post_meta = array_merge( $post_meta, array(
				'channel' => $channel_id,
			) );

			update_post_meta( $contact_form->id(), '_flamingo', $post_meta );
		}

		$channel = get_term( $channel_id,
			Flamingo_Inbound_Message::channel_taxonomy
		);

		if ( ! $channel or is_wp_error( $channel ) ) {
			$channel = 'contact-form-7';
		} else {
			$channel = $channel->slug;
		}
	} else {
		$channel = 'contact-form-7';
	}

	$args = array(
		'channel' => $channel,
		'status' => $submission->get_status(),
		'subject' => $subject,
		'from' => trim( sprintf( '%s <%s>', $name, $email ) ),
		'from_name' => $name,
		'from_email' => $email,
		'fields' => $posted_data,
		'meta' => $meta,
		'akismet' => $submission->pull( 'akismet' ),
		'spam' => ( 'spam' == $result['status'] ),
		'consent' => $submission->collect_consent(),
		'timestamp' => $timestamp,
		'posted_data_hash' => $submission->get_posted_data_hash(),
	);

	if ( $args['spam'] ) {
		$args['spam_log'] = $submission->get_spam_log();
	}

	$args['recaptcha'] = $submission->pull( 'recaptcha' );

	$args = apply_filters( 'wpcf7_flamingo_inbound_message_parameters', $args );

	$flamingo_inbound = Flamingo_Inbound_Message::add( $args );

	if ( empty( $flamingo_contact ) ) {
		$flamingo_contact_id = 0;
	} elseif ( method_exists( $flamingo_contact, 'id' ) ) {
		$flamingo_contact_id = $flamingo_contact->id();
	} else {
		$flamingo_contact_id = $flamingo_contact->id;
	}

	if ( empty( $flamingo_inbound ) ) {
		$flamingo_inbound_id = 0;
	} elseif ( method_exists( $flamingo_inbound, 'id' ) ) {
		$flamingo_inbound_id = $flamingo_inbound->id();
	} else {
		$flamingo_inbound_id = $flamingo_inbound->id;
	}

	$result += array(
		'flamingo_contact_id' => absint( $flamingo_contact_id ),
		'flamingo_inbound_id' => absint( $flamingo_inbound_id ),
	);

	do_action( 'wpcf7_after_flamingo', $result );
}

function wpcf7_flamingo_get_value( $field, $contact_form ) {
	if ( empty( $field )
	or empty( $contact_form ) ) {
		return false;
	}

	$value = '';

	if ( in_array( $field, array( 'email', 'name', 'subject' ) ) ) {
		$template = $contact_form->pref( 'flamingo_' . $field );

		if ( null === $template ) {
			$template = sprintf( '[your-%s]', $field );
		} else {
			$template = trim( wpcf7_strip_quote( $template ) );
		}

		$value = wpcf7_mail_replace_tags( $template );
	}

	$value = apply_filters( 'wpcf7_flamingo_get_value', $value,
		$field, $contact_form
	);

	return $value;
}

function wpcf7_flamingo_add_channel( $slug, $name = '' ) {
	if ( ! class_exists( 'Flamingo_Inbound_Message' ) ) {
		return false;
	}

	$parent = term_exists( 'contact-form-7',
		Flamingo_Inbound_Message::channel_taxonomy
	);

	if ( ! $parent ) {
		$parent = wp_insert_term( __( 'Contact Form 7', 'contact-form-7' ),
			Flamingo_Inbound_Message::channel_taxonomy,
			array( 'slug' => 'contact-form-7' )
		);

		if ( is_wp_error( $parent ) ) {
			return false;
		}
	}

	$parent = (int) $parent['term_id'];

	if ( ! is_taxonomy_hierarchical( Flamingo_Inbound_Message::channel_taxonomy ) ) {
		// backward compat for Flamingo 1.0.4 and lower
		return $parent;
	}

	if ( empty( $name ) ) {
		$name = $slug;
	}

	$channel = term_exists( $slug,
		Flamingo_Inbound_Message::channel_taxonomy,
		$parent
	);

	if ( ! $channel ) {
		$channel = wp_insert_term( $name,
			Flamingo_Inbound_Message::channel_taxonomy,
			array( 'slug' => $slug, 'parent' => $parent )
		);

		if ( is_wp_error( $channel ) ) {
			return false;
		}
	}

	return (int) $channel['term_id'];
}

add_action( 'wpcf7_after_update', 'wpcf7_flamingo_update_channel', 10, 1 );

function wpcf7_flamingo_update_channel( $contact_form ) {
	if ( ! class_exists( 'Flamingo_Inbound_Message' ) ) {
		return false;
	}

	$post_meta = get_post_meta( $contact_form->id(), '_flamingo', true );

	$channel = isset( $post_meta['channel'] )
		? get_term( $post_meta['channel'],
				Flamingo_Inbound_Message::channel_taxonomy
			)
		: get_term_by( 'slug', $contact_form->name(),
				Flamingo_Inbound_Message::channel_taxonomy
			);

	if ( ! $channel or is_wp_error( $channel ) ) {
		return;
	}

	if ( $channel->name !== wp_unslash( $contact_form->title() ) ) {
		wp_update_term( $channel->term_id,
			Flamingo_Inbound_Message::channel_taxonomy,
			array(
				'name' => $contact_form->title(),
				'slug' => $contact_form->name(),
				'parent' => $channel->parent,
			)
		);
	}
}


add_filter( 'wpcf7_special_mail_tags', 'wpcf7_flamingo_serial_number', 10, 4 );

/**
 * Returns output string of a special mail-tag.
 *
 * @param string $output The string to be output.
 * @param string $name The tag name of the special mail-tag.
 * @param bool $html Whether the mail-tag is used in an HTML content.
 * @param WPCF7_MailTag $mail_tag An object representation of the mail-tag.
 * @return string Output of the given special mail-tag.
 */
function wpcf7_flamingo_serial_number( $output, $name, $html, $mail_tag = null ) {
	if ( ! $mail_tag instanceof WPCF7_MailTag ) {
		wpcf7_doing_it_wrong(
			sprintf( '%s()', __FUNCTION__ ),
			__( 'The fourth parameter ($mail_tag) must be an instance of the WPCF7_MailTag class.', 'contact-form-7' ),
			'5.2.2'
		);
	}

	if ( '_serial_number' != $name ) {
		return $output;
	}

	if ( ! class_exists( 'Flamingo_Inbound_Message' )
	or ! method_exists( 'Flamingo_Inbound_Message', 'count' ) ) {
		return $output;
	}

	if ( ! $contact_form = WPCF7_ContactForm::get_current() ) {
		return $output;
	}

	$post_meta = get_post_meta( $contact_form->id(), '_flamingo', true );

	$channel_id = isset( $post_meta['channel'] )
		? (int) $post_meta['channel']
		: wpcf7_flamingo_add_channel(
				$contact_form->name(), $contact_form->title()
			);

	if ( $channel_id ) {
		return 1 + (int) Flamingo_Inbound_Message::count(
			array( 'channel_id' => $channel_id )
		);
	}

	return 0;
}
modules/recaptcha/index.js000064400000001646147510545420011631 0ustar00document.addEventListener("DOMContentLoaded",(e=>{var t;wpcf7_recaptcha={...null!==(t=wpcf7_recaptcha)&&void 0!==t?t:{}};const c=wpcf7_recaptcha.sitekey,{homepage:n,contactform:a}=wpcf7_recaptcha.actions,o=e=>{const{action:t,func:n,params:a}=e;grecaptcha.execute(c,{action:t}).then((e=>{const c=new CustomEvent("wpcf7grecaptchaexecuted",{detail:{action:t,token:e}});document.dispatchEvent(c)})).then((()=>{"function"==typeof n&&n(...a)})).catch((e=>console.error(e)))};if(grecaptcha.ready((()=>{o({action:n})})),document.addEventListener("change",(e=>{o({action:a})})),"undefined"!=typeof wpcf7&&"function"==typeof wpcf7.submit){const e=wpcf7.submit;wpcf7.submit=(t,c={})=>{o({action:a,func:e,params:[t,c]})}}document.addEventListener("wpcf7grecaptchaexecuted",(e=>{const t=document.querySelectorAll('form.wpcf7-form input[name="_wpcf7_recaptcha_response"]');for(let c=0;c<t.length;c++)t[c].setAttribute("value",e.detail.token)}))}));modules/recaptcha/service.php000064400000020142147510545420012325 0ustar00<?php

if ( ! class_exists( 'WPCF7_Service' ) ) {
	return;
}

class WPCF7_RECAPTCHA extends WPCF7_Service {

	private static $instance;
	private $sitekeys;
	private $last_score;


	public static function get_instance() {
		if ( empty( self::$instance ) ) {
			self::$instance = new self;
		}

		return self::$instance;
	}


	private function __construct() {
		$this->sitekeys = WPCF7::get_option( 'recaptcha' );
	}


	public function get_title() {
		return __( 'reCAPTCHA', 'contact-form-7' );
	}


	public function is_active() {
		$sitekey = $this->get_sitekey();
		$secret = $this->get_secret( $sitekey );
		return $sitekey && $secret;
	}


	public function get_categories() {
		return array( 'spam_protection' );
	}


	public function icon() {
	}


	public function link() {
		echo wpcf7_link(
			'https://www.google.com/recaptcha/intro/index.html',
			'google.com/recaptcha'
		);
	}


	public function get_global_sitekey() {
		static $sitekey = '';

		if ( $sitekey ) {
			return $sitekey;
		}

		if ( defined( 'WPCF7_RECAPTCHA_SITEKEY' ) ) {
			$sitekey = WPCF7_RECAPTCHA_SITEKEY;
		}

		$sitekey = apply_filters( 'wpcf7_recaptcha_sitekey', $sitekey );

		return $sitekey;
	}


	public function get_global_secret() {
		static $secret = '';

		if ( $secret ) {
			return $secret;
		}

		if ( defined( 'WPCF7_RECAPTCHA_SECRET' ) ) {
			$secret = WPCF7_RECAPTCHA_SECRET;
		}

		$secret = apply_filters( 'wpcf7_recaptcha_secret', $secret );

		return $secret;
	}


	public function get_sitekey() {
		if ( $this->get_global_sitekey() and $this->get_global_secret() ) {
			return $this->get_global_sitekey();
		}

		if ( empty( $this->sitekeys )
		or ! is_array( $this->sitekeys ) ) {
			return false;
		}

		$sitekeys = array_keys( $this->sitekeys );

		return $sitekeys[0];
	}


	public function get_secret( $sitekey ) {
		if ( $this->get_global_sitekey() and $this->get_global_secret() ) {
			return $this->get_global_secret();
		}

		$sitekeys = (array) $this->sitekeys;

		if ( isset( $sitekeys[$sitekey] ) ) {
			return $sitekeys[$sitekey];
		} else {
			return false;
		}
	}


	protected function log( $url, $request, $response ) {
		wpcf7_log_remote_request( $url, $request, $response );
	}


	public function verify( $token ) {
		$is_human = false;

		if ( empty( $token ) or ! $this->is_active() ) {
			return $is_human;
		}

		$endpoint = 'https://www.google.com/recaptcha/api/siteverify';

		if ( apply_filters( 'wpcf7_use_recaptcha_net', false ) ) {
			$endpoint = 'https://www.recaptcha.net/recaptcha/api/siteverify';
		}

		$sitekey = $this->get_sitekey();
		$secret = $this->get_secret( $sitekey );

		$request = array(
			'body' => array(
				'secret' => $secret,
				'response' => $token,
			),
		);

		$response = wp_remote_post( sanitize_url( $endpoint ), $request );

		if ( 200 != wp_remote_retrieve_response_code( $response ) ) {
			if ( WP_DEBUG ) {
				$this->log( $endpoint, $request, $response );
			}

			return $is_human;
		}

		$response_body = wp_remote_retrieve_body( $response );
		$response_body = json_decode( $response_body, true );

		$this->last_score = $score = isset( $response_body['score'] )
			? $response_body['score']
			: 0;

		$threshold = $this->get_threshold();
		$is_human = $threshold < $score;

		$is_human = apply_filters( 'wpcf7_recaptcha_verify_response',
			$is_human, $response_body );

		if ( $submission = WPCF7_Submission::get_instance() ) {
			$submission->push( 'recaptcha', array(
				'version' => '3.0',
				'threshold' => $threshold,
				'response' => $response_body,
			) );
		}

		return $is_human;
	}


	public function get_threshold() {
		return apply_filters( 'wpcf7_recaptcha_threshold', 0.50 );
	}


	public function get_last_score() {
		return $this->last_score;
	}


	protected function menu_page_url( $args = '' ) {
		$args = wp_parse_args( $args, array() );

		$url = menu_page_url( 'wpcf7-integration', false );
		$url = add_query_arg( array( 'service' => 'recaptcha' ), $url );

		if ( ! empty( $args ) ) {
			$url = add_query_arg( $args, $url );
		}

		return $url;
	}


	protected function save_data() {
		WPCF7::update_option( 'recaptcha', $this->sitekeys );
	}


	protected function reset_data() {
		$this->sitekeys = null;
		$this->save_data();
	}


	public function load( $action = '' ) {
		if ( 'setup' == $action and 'POST' == $_SERVER['REQUEST_METHOD'] ) {
			check_admin_referer( 'wpcf7-recaptcha-setup' );

			if ( ! empty( $_POST['reset'] ) ) {
				$this->reset_data();
				$redirect_to = $this->menu_page_url( 'action=setup' );
			} else {
				$sitekey = trim( $_POST['sitekey'] ?? '' );
				$secret = trim( $_POST['secret'] ?? '' );

				if ( $sitekey and $secret ) {
					$this->sitekeys = array( $sitekey => $secret );
					$this->save_data();

					$redirect_to = $this->menu_page_url( array(
						'message' => 'success',
					) );
				} else {
					$redirect_to = $this->menu_page_url( array(
						'action' => 'setup',
						'message' => 'invalid',
					) );
				}
			}

			if ( WPCF7::get_option( 'recaptcha_v2_v3_warning' ) ) {
				WPCF7::update_option( 'recaptcha_v2_v3_warning', false );
			}

			wp_safe_redirect( $redirect_to );
			exit();
		}
	}


	public function admin_notice( $message = '' ) {
		if ( 'invalid' === $message ) {
			wp_admin_notice(
				sprintf(
					'<strong>%1$s</strong>: %2$s',
					esc_html( __( "Error", 'contact-form-7' ) ),
					esc_html( __( "Invalid key values.", 'contact-form-7' ) )
				),
				'type=error'
			);
		}

		if ( 'success' === $message ) {
			wp_admin_notice(
				esc_html( __( "Settings saved.", 'contact-form-7' ) ),
				'type=success'
			);
		}
	}


	public function display( $action = '' ) {
		echo sprintf(
			'<p>%s</p>',
			esc_html( __( "reCAPTCHA protects you against spam and other types of automated abuse. With Contact Form 7&#8217;s reCAPTCHA integration module, you can block abusive form submissions by spam bots.", 'contact-form-7' ) )
		);

		echo sprintf(
			'<p><strong>%s</strong></p>',
			wpcf7_link(
				__( 'https://contactform7.com/recaptcha/', 'contact-form-7' ),
				__( 'reCAPTCHA (v3)', 'contact-form-7' )
			)
		);

		if ( $this->is_active() ) {
			echo sprintf(
				'<p class="dashicons-before dashicons-yes">%s</p>',
				esc_html( __( "reCAPTCHA is active on this site.", 'contact-form-7' ) )
			);
		}

		if ( 'setup' == $action ) {
			$this->display_setup();
		} else {
			echo sprintf(
				'<p><a href="%1$s" class="button">%2$s</a></p>',
				esc_url( $this->menu_page_url( 'action=setup' ) ),
				esc_html( __( 'Setup Integration', 'contact-form-7' ) )
			);
		}
	}


	private function display_setup() {
		$sitekey = $this->is_active() ? $this->get_sitekey() : '';
		$secret = $this->is_active() ? $this->get_secret( $sitekey ) : '';

?>
<form method="post" action="<?php echo esc_url( $this->menu_page_url( 'action=setup' ) ); ?>">
<?php wp_nonce_field( 'wpcf7-recaptcha-setup' ); ?>
<table class="form-table">
<tbody>
<tr>
	<th scope="row"><label for="sitekey"><?php echo esc_html( __( 'Site Key', 'contact-form-7' ) ); ?></label></th>
	<td><?php
		if ( $this->is_active() ) {
			echo esc_html( $sitekey );
			echo sprintf(
				'<input type="hidden" value="%1$s" id="sitekey" name="sitekey" />',
				esc_attr( $sitekey )
			);
		} else {
			echo sprintf(
				'<input type="text" aria-required="true" value="%1$s" id="sitekey" name="sitekey" class="regular-text code" />',
				esc_attr( $sitekey )
			);
		}
	?></td>
</tr>
<tr>
	<th scope="row"><label for="secret"><?php echo esc_html( __( 'Secret Key', 'contact-form-7' ) ); ?></label></th>
	<td><?php
		if ( $this->is_active() ) {
			echo esc_html( wpcf7_mask_password( $secret, 4, 4 ) );
			echo sprintf(
				'<input type="hidden" value="%1$s" id="secret" name="secret" />',
				esc_attr( $secret )
			);
		} else {
			echo sprintf(
				'<input type="text" aria-required="true" value="%1$s" id="secret" name="secret" class="regular-text code" />',
				esc_attr( $secret )
			);
		}
	?></td>
</tr>
</tbody>
</table>
<?php
		if ( $this->is_active() ) {
			if ( $this->get_global_sitekey() and $this->get_global_secret() ) {
				// nothing
			} else {
				submit_button(
					_x( 'Remove Keys', 'API keys', 'contact-form-7' ),
					'small', 'reset'
				);
			}
		} else {
			submit_button( __( 'Save Changes', 'contact-form-7' ) );
		}
?>
</form>
<?php
	}
}
modules/recaptcha/recaptcha.php000064400000012644147510545420012627 0ustar00<?php
/**
 * reCAPTCHA module main file
 *
 * @link https://contactform7.com/recaptcha/
 */

wpcf7_include_module_file( 'recaptcha/service.php' );


add_action( 'wpcf7_init', 'wpcf7_recaptcha_register_service', 40, 0 );

/**
 * Registers the reCAPTCHA service.
 */
function wpcf7_recaptcha_register_service() {
	$integration = WPCF7_Integration::get_instance();

	$integration->add_service( 'recaptcha',
		WPCF7_RECAPTCHA::get_instance()
	);
}


add_action(
	'wp_enqueue_scripts',
	'wpcf7_recaptcha_enqueue_scripts',
	20, 0
);

/**
 * Enqueues frontend scripts for reCAPTCHA.
 */
function wpcf7_recaptcha_enqueue_scripts() {
	$service = WPCF7_RECAPTCHA::get_instance();

	if ( ! $service->is_active() ) {
		return;
	}

	$url = 'https://www.google.com/recaptcha/api.js';

	if ( apply_filters( 'wpcf7_use_recaptcha_net', false ) ) {
		$url = 'https://www.recaptcha.net/recaptcha/api.js';
	}

	wp_register_script( 'google-recaptcha',
		add_query_arg(
			array(
				'render' => $service->get_sitekey(),
			),
			$url
		),
		array(),
		'3.0',
		array( 'in_footer' => true )
	);

	$assets = include(
		wpcf7_plugin_path( 'modules/recaptcha/index.asset.php' )
	);

	$assets = wp_parse_args( $assets, array(
		'dependencies' => array(),
		'version' => WPCF7_VERSION,
	) );

	wp_register_script(
		'wpcf7-recaptcha',
		wpcf7_plugin_url( 'modules/recaptcha/index.js' ),
		array_merge(
			$assets['dependencies'],
			array(
				'google-recaptcha',
				'wp-polyfill',
			)
		),
		$assets['version'],
		array( 'in_footer' => true )
	);

	wp_enqueue_script( 'wpcf7-recaptcha' );

	$wpcf7_recaptcha_obj = array(
		'sitekey' => $service->get_sitekey(),
		'actions' => apply_filters( 'wpcf7_recaptcha_actions', array(
			'homepage' => 'homepage',
			'contactform' => 'contactform',
		) ),
	);

	wp_add_inline_script( 'wpcf7-recaptcha',
		sprintf(
			'var wpcf7_recaptcha = %s;',
			wp_json_encode( $wpcf7_recaptcha_obj, JSON_PRETTY_PRINT )
		),
		'before'
	);
}


add_filter(
	'wpcf7_form_hidden_fields',
	'wpcf7_recaptcha_add_hidden_fields',
	100, 1
);

/**
 * Adds hidden form field for reCAPTCHA.
 */
function wpcf7_recaptcha_add_hidden_fields( $fields ) {
	$service = WPCF7_RECAPTCHA::get_instance();

	if ( ! $service->is_active() ) {
		return $fields;
	}

	return array_merge( $fields, array(
		'_wpcf7_recaptcha_response' => '',
	) );
}


add_filter( 'wpcf7_spam', 'wpcf7_recaptcha_verify_response', 9, 2 );

/**
 * Verifies reCAPTCHA token on the server side.
 */
function wpcf7_recaptcha_verify_response( $spam, $submission ) {
	if ( $spam ) {
		return $spam;
	}

	$service = WPCF7_RECAPTCHA::get_instance();

	if ( ! $service->is_active() ) {
		return $spam;
	}

	$token = trim( $_POST['_wpcf7_recaptcha_response'] ?? '' );

	if ( $service->verify( $token ) ) { // Human
		$spam = false;
	} else { // Bot
		$spam = true;

		if ( '' === $token ) {
			$submission->add_spam_log( array(
				'agent' => 'recaptcha',
				'reason' => __(
					'reCAPTCHA response token is empty.',
					'contact-form-7'
				),
			) );
		} else {
			$submission->add_spam_log( array(
				'agent' => 'recaptcha',
				'reason' => sprintf(
					__(
						'reCAPTCHA score (%1$.2f) is lower than the threshold (%2$.2f).',
						'contact-form-7'
					),
					$service->get_last_score(),
					$service->get_threshold()
				),
			) );
		}
	}

	return $spam;
}


add_action( 'wpcf7_init', 'wpcf7_recaptcha_add_form_tag_recaptcha', 10, 0 );

/**
 * Registers form-tag types for reCAPTCHA.
 */
function wpcf7_recaptcha_add_form_tag_recaptcha() {
	$service = WPCF7_RECAPTCHA::get_instance();

	if ( ! $service->is_active() ) {
		return;
	}

	wpcf7_add_form_tag( 'recaptcha',
		'__return_empty_string', // no output
		array( 'display-block' => true )
	);
}


add_action( 'wpcf7_upgrade', 'wpcf7_upgrade_recaptcha_v2_v3', 10, 2 );

/**
 * Adds warnings for users upgrading from reCAPTCHA v2 to v3.
 */
function wpcf7_upgrade_recaptcha_v2_v3( $new_ver, $old_ver ) {
	if ( version_compare( '5.1-dev', $old_ver, '<=' ) ) {
		return;
	}

	$service = WPCF7_RECAPTCHA::get_instance();

	if ( ! $service->is_active() or $service->get_global_sitekey() ) {
		return;
	}

	// Maybe v2 keys are used now. Warning necessary.
	WPCF7::update_option( 'recaptcha_v2_v3_warning', true );
	WPCF7::update_option( 'recaptcha', null );
}


add_action( 'wpcf7_admin_menu', 'wpcf7_admin_init_recaptcha_v2_v3', 10, 0 );

/**
 * Adds filters and actions for warnings.
 */
function wpcf7_admin_init_recaptcha_v2_v3() {
	if ( ! WPCF7::get_option( 'recaptcha_v2_v3_warning' ) ) {
		return;
	}

	add_filter(
		'wpcf7_admin_menu_change_notice',
		'wpcf7_admin_menu_change_notice_recaptcha_v2_v3',
		10, 1
	);

	add_action(
		'wpcf7_admin_warnings',
		'wpcf7_admin_warnings_recaptcha_v2_v3',
		5, 3
	);
}


/**
 * Increments the admin menu counter for the Integration page.
 */
function wpcf7_admin_menu_change_notice_recaptcha_v2_v3( $counts ) {
	$counts['wpcf7-integration'] += 1;
	return $counts;
}


/**
 * Prints warnings on the admin screen.
 */
function wpcf7_admin_warnings_recaptcha_v2_v3( $page, $action, $object ) {
	if ( 'wpcf7-integration' !== $page ) {
		return;
	}

	$message = sprintf(
		esc_html( __(
			"API keys for reCAPTCHA v3 are different from those for v2; keys for v2 do not work with the v3 API. You need to register your sites again to get new keys for v3. For details, see %s.",
			'contact-form-7'
		) ),
		wpcf7_link(
			__( 'https://contactform7.com/recaptcha/', 'contact-form-7' ),
			__( 'reCAPTCHA (v3)', 'contact-form-7' )
		)
	);

	wp_admin_notice( $message, 'type=warning' );
}
modules/recaptcha/index.asset.php000064400000000121147510545420013105 0ustar00<?php

return array(
	'dependencies' => array(),
	'version' => WPCF7_VERSION,
);
modules/select.php000064400000014412147510545420010215 0ustar00<?php
/**
** A base module for [select] and [select*]
**/

/* form_tag handler */

add_action( 'wpcf7_init', 'wpcf7_add_form_tag_select', 10, 0 );

function wpcf7_add_form_tag_select() {
	wpcf7_add_form_tag( array( 'select', 'select*' ),
		'wpcf7_select_form_tag_handler',
		array(
			'name-attr' => true,
			'selectable-values' => true,
		)
	);
}

function wpcf7_select_form_tag_handler( $tag ) {
	if ( empty( $tag->name ) ) {
		return '';
	}

	$validation_error = wpcf7_get_validation_error( $tag->name );

	$class = wpcf7_form_controls_class( $tag->type );

	if ( $validation_error ) {
		$class .= ' wpcf7-not-valid';
	}

	$atts = array();

	$atts['class'] = $tag->get_class_option( $class );
	$atts['id'] = $tag->get_id_option();
	$atts['tabindex'] = $tag->get_option( 'tabindex', 'signed_int', true );

	$atts['autocomplete'] = $tag->get_option(
		'autocomplete', '[-0-9a-zA-Z]+', true
	);

	if ( $tag->is_required() ) {
		$atts['aria-required'] = 'true';
	}

	if ( $validation_error ) {
		$atts['aria-invalid'] = 'true';
		$atts['aria-describedby'] = wpcf7_get_validation_error_reference(
			$tag->name
		);
	} else {
		$atts['aria-invalid'] = 'false';
	}

	$multiple = $tag->has_option( 'multiple' );
	$include_blank = $tag->has_option( 'include_blank' );
	$first_as_label = $tag->has_option( 'first_as_label' );

	if ( $tag->has_option( 'size' ) ) {
		$size = $tag->get_option( 'size', 'int', true );

		if ( $size ) {
			$atts['size'] = $size;
		} elseif ( $multiple ) {
			$atts['size'] = 4;
		} else {
			$atts['size'] = 1;
		}
	}

	if ( $data = (array) $tag->get_data_option() ) {
		$tag->values = array_merge( $tag->values, array_values( $data ) );
		$tag->labels = array_merge( $tag->labels, array_values( $data ) );
	}

	$values = $tag->values;
	$labels = $tag->labels;

	$default_choice = $tag->get_default_option( null, array(
		'multiple' => $multiple,
	) );

	if ( $include_blank
	or empty( $values ) ) {
		array_unshift(
			$labels,
			__( '&#8212;Please choose an option&#8212;', 'contact-form-7' )
		);
		array_unshift( $values, '' );
	} elseif ( $first_as_label ) {
		$values[0] = '';
	}

	$html = '';
	$hangover = wpcf7_get_hangover( $tag->name );

	foreach ( $values as $key => $value ) {
		if ( $hangover ) {
			$selected = in_array( $value, (array) $hangover, true );
		} else {
			$selected = in_array( $value, (array) $default_choice, true );
		}

		$item_atts = array(
			'value' => $value,
			'selected' => $selected,
		);

		$label = isset( $labels[$key] ) ? $labels[$key] : $value;

		$html .= sprintf(
			'<option %1$s>%2$s</option>',
			wpcf7_format_atts( $item_atts ),
			esc_html( $label )
		);
	}

	$atts['multiple'] = (bool) $multiple;
	$atts['name'] = $tag->name . ( $multiple ? '[]' : '' );

	$html = sprintf(
		'<span class="wpcf7-form-control-wrap" data-name="%1$s"><select %2$s>%3$s</select>%4$s</span>',
		esc_attr( $tag->name ),
		wpcf7_format_atts( $atts ),
		$html,
		$validation_error
	);

	return $html;
}


add_action(
	'wpcf7_swv_create_schema',
	'wpcf7_swv_add_select_rules',
	10, 2
);

function wpcf7_swv_add_select_rules( $schema, $contact_form ) {
	$tags = $contact_form->scan_form_tags( array(
		'type' => array( 'select*' ),
	) );

	foreach ( $tags as $tag ) {
		$schema->add_rule(
			wpcf7_swv_create_rule( 'required', array(
				'field' => $tag->name,
				'error' => wpcf7_get_message( 'invalid_required' ),
			) )
		);
	}
}


add_action(
	'wpcf7_swv_create_schema',
	'wpcf7_swv_add_select_enum_rules',
	20, 2
);

function wpcf7_swv_add_select_enum_rules( $schema, $contact_form ) {
	$tags = $contact_form->scan_form_tags( array(
		'basetype' => array( 'select' ),
	) );

	$values = array_reduce(
		$tags,
		function ( $values, $tag ) {
			if ( ! isset( $values[$tag->name] ) ) {
				$values[$tag->name] = array();
			}

			$tag_values = array_merge(
				(array) $tag->values,
				(array) $tag->get_data_option()
			);

			if ( $tag->has_option( 'first_as_label' ) ) {
				$tag_values = array_slice( $tag_values, 1 );
			}

			$values[$tag->name] = array_merge(
				$values[$tag->name],
				$tag_values
			);

			return $values;
		},
		array()
	);

	foreach ( $values as $field => $field_values ) {
		$field_values = array_map(
			static function ( $value ) {
				return html_entity_decode(
					(string) $value,
					ENT_QUOTES | ENT_HTML5,
					'UTF-8'
				);
			},
			$field_values
		);

		$field_values = array_filter(
			array_unique( $field_values ),
			static function ( $value ) {
				return '' !== $value;
			}
		);

		$schema->add_rule(
			wpcf7_swv_create_rule( 'enum', array(
				'field' => $field,
				'accept' => array_values( $field_values ),
				'error' => $contact_form->filter_message(
					__( "Undefined value was submitted through this field.", 'contact-form-7' )
				),
			) )
		);
	}
}


/* Tag generator */

add_action( 'wpcf7_admin_init', 'wpcf7_add_tag_generator_menu', 25, 0 );

function wpcf7_add_tag_generator_menu() {
	$tag_generator = WPCF7_TagGenerator::get_instance();

	$tag_generator->add( 'menu', __( 'drop-down menu', 'contact-form-7' ),
		'wpcf7_tag_generator_menu',
	 	array( 'version' => '2' )
	);
}

function wpcf7_tag_generator_menu( $contact_form, $options ) {
	$field_types = array(
		'select' => array(
			'display_name' => __( 'Drop-down menu', 'contact-form-7' ),
			'heading' => __( 'Drop-down menu form-tag generator', 'contact-form-7' ),
			'description' => __( 'Generates a form-tag for a <a href="https://contactform7.com/checkboxes-radio-buttons-and-menus/">drop-down menu</a>.', 'contact-form-7' ),
		),
	);

	$tgg = new WPCF7_TagGeneratorGenerator( $options['content'] );

?>
<header class="description-box">
	<h3><?php
		echo esc_html( $field_types['select']['heading'] );
	?></h3>

	<p><?php
		$description = wp_kses(
			$field_types['select']['description'],
			array(
				'a' => array( 'href' => true ),
				'strong' => array(),
			),
			array( 'http', 'https' )
		);

		echo $description;
	?></p>
</header>

<div class="control-box">
	<?php
		$tgg->print( 'field_type', array(
			'with_required' => true,
			'select_options' => array(
				'select' => $field_types['select']['display_name'],
			),
		) );

		$tgg->print( 'field_name' );

		$tgg->print( 'class_attr' );

		$tgg->print( 'selectable_values', array(
			'first_as_label' => true,
		) );
	?>
</div>

<footer class="insert-box">
	<?php
		$tgg->print( 'insert_box_content' );

		$tgg->print( 'mail_tag_tip' );
	?>
</footer>
<?php
}
modules/doi-helper.php000064400000001332147510545420010763 0ustar00<?php
/**
 * Double Opt-In Helper module
 *
 * @link https://contactform7.com/doi-helper/
 */


add_action( 'wpcf7_doi', 'wpcf7_doihelper_start_session', 10, 3 );

/**
 * Starts a double opt-in session.
 */
function wpcf7_doihelper_start_session( $agent_name, $args, &$token ) {
	if ( isset( $token ) ) {
		return;
	}

	if ( ! function_exists( 'doihelper_start_session' ) ) {
		return;
	}

	$submission = WPCF7_Submission::get_instance();

	if ( ! $submission ) {
		return;
	}

	$contact_form = $submission->get_contact_form();

	$do_doi = apply_filters( 'wpcf7_do_doi',
		! $contact_form->is_false( 'doi' ),
		$agent_name,
		$args
	);

	if ( ! $do_doi ) {
		return;
	}

	$token = doihelper_start_session( $agent_name, $args );
}
modules/checkbox.php000064400000023026147510545420010525 0ustar00<?php
/**
** A base module for [checkbox], [checkbox*], and [radio]
**/

/* form_tag handler */

add_action( 'wpcf7_init', 'wpcf7_add_form_tag_checkbox', 10, 0 );

function wpcf7_add_form_tag_checkbox() {
	wpcf7_add_form_tag( array( 'checkbox', 'checkbox*', 'radio' ),
		'wpcf7_checkbox_form_tag_handler',
		array(
			'name-attr' => true,
			'selectable-values' => true,
			'multiple-controls-container' => true,
		)
	);
}

function wpcf7_checkbox_form_tag_handler( $tag ) {
	if ( empty( $tag->name ) ) {
		return '';
	}

	$validation_error = wpcf7_get_validation_error( $tag->name );

	$class = wpcf7_form_controls_class( $tag->type );

	if ( $validation_error ) {
		$class .= ' wpcf7-not-valid';
	}

	$label_first = $tag->has_option( 'label_first' );
	$use_label_element = $tag->has_option( 'use_label_element' );
	$exclusive = $tag->has_option( 'exclusive' );
	$free_text = $tag->has_option( 'free_text' );
	$multiple = false;

	if ( 'checkbox' == $tag->basetype ) {
		$multiple = ! $exclusive;
	} else { // radio
		$exclusive = false;
	}

	if ( $exclusive ) {
		$class .= ' wpcf7-exclusive-checkbox';
	}

	$atts = array();

	$atts['class'] = $tag->get_class_option( $class );
	$atts['id'] = $tag->get_id_option();

	if ( $validation_error ) {
		$atts['aria-describedby'] = wpcf7_get_validation_error_reference(
			$tag->name
		);
	}

	$tabindex = $tag->get_option( 'tabindex', 'signed_int', true );

	if ( false !== $tabindex ) {
		$tabindex = (int) $tabindex;
	}

	$html = '';
	$count = 0;

	if ( $data = (array) $tag->get_data_option() ) {
		if ( $free_text ) {
			$tag->values = array_merge(
				array_slice( $tag->values, 0, -1 ),
				array_values( $data ),
				array_slice( $tag->values, -1 )
			);

			$tag->labels = array_merge(
				array_slice( $tag->labels, 0, -1 ),
				array_values( $data ),
				array_slice( $tag->labels, -1 )
			);
		} else {
			$tag->values = array_merge( $tag->values, array_values( $data ) );
			$tag->labels = array_merge( $tag->labels, array_values( $data ) );
		}
	}

	$values = $tag->values;
	$labels = $tag->labels;

	$default_choice = $tag->get_default_option( null, array(
		'multiple' => $multiple,
	) );

	$hangover = wpcf7_get_hangover( $tag->name, $multiple ? array() : '' );

	foreach ( $values as $key => $value ) {
		if ( $hangover ) {
			$checked = in_array( $value, (array) $hangover, true );
		} else {
			$checked = in_array( $value, (array) $default_choice, true );
		}

		if ( isset( $labels[$key] ) ) {
			$label = $labels[$key];
		} else {
			$label = $value;
		}

		$item_atts = array(
			'type' => $tag->basetype,
			'name' => $tag->name . ( $multiple ? '[]' : '' ),
			'value' => $value,
			'checked' => $checked,
			'tabindex' => $tabindex,
		);

		$item_atts = wpcf7_format_atts( $item_atts );

		if ( $label_first ) { // put label first, input last
			$item = sprintf(
				'<span class="wpcf7-list-item-label">%1$s</span><input %2$s />',
				esc_html( $label ),
				$item_atts
			);
		} else {
			$item = sprintf(
				'<input %2$s /><span class="wpcf7-list-item-label">%1$s</span>',
				esc_html( $label ),
				$item_atts
			);
		}

		if ( $use_label_element ) {
			$item = '<label>' . $item . '</label>';
		}

		if ( false !== $tabindex and 0 < $tabindex ) {
			$tabindex += 1;
		}

		$class = 'wpcf7-list-item';
		$count += 1;

		if ( 1 == $count ) {
			$class .= ' first';
		}

		if ( count( $values ) == $count ) { // last round
			$class .= ' last';

			if ( $free_text ) {
				$free_text_name = sprintf( '_wpcf7_free_text_%s', $tag->name );

				$free_text_atts = array(
					'name' => $free_text_name,
					'class' => 'wpcf7-free-text',
					'tabindex' => $tabindex,
				);

				if ( wpcf7_is_posted()
				and isset( $_POST[$free_text_name] ) ) {
					$free_text_atts['value'] = wp_unslash( $_POST[$free_text_name] );
				}

				$free_text_atts = wpcf7_format_atts( $free_text_atts );

				$item .= sprintf( ' <input type="text" %s />', $free_text_atts );

				$class .= ' has-free-text';
			}
		}

		$item = '<span class="' . esc_attr( $class ) . '">' . $item . '</span>';
		$html .= $item;
	}

	$html = sprintf(
		'<span class="wpcf7-form-control-wrap" data-name="%1$s"><span %2$s>%3$s</span>%4$s</span>',
		esc_attr( $tag->name ),
		wpcf7_format_atts( $atts ),
		$html,
		$validation_error
	);

	return $html;
}


add_action(
	'wpcf7_swv_create_schema',
	'wpcf7_swv_add_checkbox_rules',
	10, 2
);

function wpcf7_swv_add_checkbox_rules( $schema, $contact_form ) {
	$tags = $contact_form->scan_form_tags( array(
		'basetype' => array( 'checkbox', 'radio' ),
	) );

	foreach ( $tags as $tag ) {
		if ( $tag->is_required() or 'radio' === $tag->type ) {
			$schema->add_rule(
				wpcf7_swv_create_rule( 'required', array(
					'field' => $tag->name,
					'error' => wpcf7_get_message( 'invalid_required' ),
				) )
			);
		}

		if ( 'radio' === $tag->type or $tag->has_option( 'exclusive' ) ) {
			$schema->add_rule(
				wpcf7_swv_create_rule( 'maxitems', array(
					'field' => $tag->name,
					'threshold' => 1,
					'error' => $contact_form->filter_message(
						__( "Too many items are selected.", 'contact-form-7' )
					),
				) )
			);
		}
	}
}


add_action(
	'wpcf7_swv_create_schema',
	'wpcf7_swv_add_checkbox_enum_rules',
	20, 2
);

function wpcf7_swv_add_checkbox_enum_rules( $schema, $contact_form ) {
	$tags = $contact_form->scan_form_tags( array(
		'basetype' => array( 'checkbox', 'radio' ),
	) );

	$values = array_reduce(
		$tags,
		function ( $values, $tag ) {
			if ( $tag->has_option( 'free_text' ) ) {
				$values[$tag->name] = 'free_text';
			}

			if (
				isset( $values[$tag->name] ) and
				! is_array( $values[$tag->name] ) // Maybe 'free_text'
			) {
				return $values;
			}

			if ( ! isset( $values[$tag->name] ) ) {
				$values[$tag->name] = array();
			}

			$tag_values = array_merge(
				(array) $tag->values,
				(array) $tag->get_data_option()
			);

			$values[$tag->name] = array_merge(
				$values[$tag->name],
				$tag_values
			);

			return $values;
		},
		array()
	);

	foreach ( $values as $field => $field_values ) {
		if ( ! is_array( $field_values ) ) { // Maybe 'free_text'
			continue;
		}

		$field_values = array_map(
			static function ( $value ) {
				return html_entity_decode(
					(string) $value,
					ENT_QUOTES | ENT_HTML5,
					'UTF-8'
				);
			},
			$field_values
		);

		$field_values = array_filter(
			array_unique( $field_values ),
			static function ( $value ) {
				return '' !== $value;
			}
		);

		$schema->add_rule(
			wpcf7_swv_create_rule( 'enum', array(
				'field' => $field,
				'accept' => array_values( $field_values ),
				'error' => $contact_form->filter_message(
					__( "Undefined value was submitted through this field.", 'contact-form-7' )
				),
			) )
		);
	}
}


add_filter( 'wpcf7_posted_data_checkbox',
	'wpcf7_posted_data_checkbox',
	10, 3
);

add_filter( 'wpcf7_posted_data_checkbox*',
	'wpcf7_posted_data_checkbox',
	10, 3
);

add_filter( 'wpcf7_posted_data_radio',
	'wpcf7_posted_data_checkbox',
	10, 3
);

function wpcf7_posted_data_checkbox( $value, $value_orig, $form_tag ) {
	if ( $form_tag->has_option( 'free_text' ) ) {
		$value = (array) $value;

		$free_text_name = sprintf( '_wpcf7_free_text_%s', $form_tag->name );
		$free_text = wp_unslash( $_POST[$free_text_name] ?? '' );

		$last_val = array_pop( $value );

		if ( isset( $last_val ) ) {
			$last_val = sprintf( '%s %s', $last_val, $free_text );
			$value[] = trim( $last_val );
		}
	}

	return $value;
}


/* Tag generator */

add_action( 'wpcf7_admin_init',
	'wpcf7_add_tag_generator_checkbox_and_radio', 30, 0 );

function wpcf7_add_tag_generator_checkbox_and_radio() {
	$tag_generator = WPCF7_TagGenerator::get_instance();

	$basetypes = array(
		'checkbox' => __( 'checkboxes', 'contact-form-7' ),
		'radio' => __( 'radio buttons', 'contact-form-7' ),
	);

	foreach ( $basetypes as $id => $title ) {
		$tag_generator->add( $id, $title,
			'wpcf7_tag_generator_checkbox',
			array( 'version' => '2' )
		);
	}
}

function wpcf7_tag_generator_checkbox( $contact_form, $options ) {
	$field_types = array(
		'checkbox' => array(
			'display_name' => __( 'Checkboxes', 'contact-form-7' ),
			'heading' => __( 'Checkboxes form-tag generator', 'contact-form-7' ),
			'description' => __( 'Generates a form-tag for a group of <a href="https://contactform7.com/checkboxes-radio-buttons-and-menus/">checkboxes</a>.', 'contact-form-7' ),
		),
		'radio' => array(
			'display_name' => __( 'Radio buttons', 'contact-form-7' ),
			'heading' => __( 'Radio buttons form-tag generator', 'contact-form-7' ),
			'description' => __( 'Generates a form-tag for a group of <a href="https://contactform7.com/checkboxes-radio-buttons-and-menus/">radio buttons</a>.', 'contact-form-7' ),
		),
	);

	$basetype = $options['id'];

	if ( ! in_array( $basetype, array_keys( $field_types ) ) ) {
		$basetype = 'checkbox';
	}

	$tgg = new WPCF7_TagGeneratorGenerator( $options['content'] );

?>
<header class="description-box">
	<h3><?php
		echo esc_html( $field_types[$basetype]['heading'] );
	?></h3>

	<p><?php
		$description = wp_kses(
			$field_types[$basetype]['description'],
			array(
				'a' => array( 'href' => true ),
				'strong' => array(),
			),
			array( 'http', 'https' )
		);

		echo $description;
	?></p>
</header>

<div class="control-box">
	<?php
		$tgg->print( 'field_type', array(
			'with_required' => 'checkbox' === $basetype,
			'select_options' => array(
				$basetype => $field_types[$basetype]['display_name'],
			),
		) );

		$tgg->print( 'field_name' );

		$tgg->print( 'class_attr' );

		$tgg->print( 'selectable_values', array(
			'use_label_element' => 'checked',
		) );
	?>
</div>

<footer class="insert-box">
	<?php
		$tgg->print( 'insert_box_content' );

		$tgg->print( 'mail_tag_tip' );
	?>
</footer>
<?php
}
modules/acceptance.php000064400000016615147510545420011033 0ustar00<?php
/**
** A base module for [acceptance]
**/

/* form_tag handler */

add_action( 'wpcf7_init', 'wpcf7_add_form_tag_acceptance', 10, 0 );

function wpcf7_add_form_tag_acceptance() {
	wpcf7_add_form_tag( 'acceptance',
		'wpcf7_acceptance_form_tag_handler',
		array(
			'name-attr' => true,
			'selectable-values' => true,
		)
	);
}

function wpcf7_acceptance_form_tag_handler( $tag ) {
	if ( empty( $tag->name ) ) {
		return '';
	}

	$validation_error = wpcf7_get_validation_error( $tag->name );

	$class = wpcf7_form_controls_class( $tag->type );

	if ( $validation_error ) {
		$class .= ' wpcf7-not-valid';
	}

	if ( $tag->has_option( 'invert' ) ) {
		$class .= ' invert';
	}

	if ( $tag->has_option( 'optional' ) ) {
		$class .= ' optional';
	}

	$atts = array(
		'class' => trim( $class ),
	);

	$item_atts = array(
		'type' => 'checkbox',
		'name' => $tag->name,
		'value' => '1',
		'tabindex' => $tag->get_option( 'tabindex', 'signed_int', true ),
		'checked' => $tag->has_option( 'default:on' ),
		'class' => $tag->get_class_option() ? $tag->get_class_option() : null,
		'id' => $tag->get_id_option(),
	);

	if ( $validation_error ) {
		$item_atts['aria-invalid'] = 'true';
		$item_atts['aria-describedby'] = wpcf7_get_validation_error_reference(
			$tag->name
		);
	} else {
		$item_atts['aria-invalid'] = 'false';
	}

	$item_atts = wpcf7_format_atts( $item_atts );

	$content = empty( $tag->content )
		? (string) reset( $tag->values )
		: $tag->content;

	$content = trim( $content );

	if ( $content ) {
		if ( $tag->has_option( 'label_first' ) ) {
			$html = sprintf(
				'<span class="wpcf7-list-item-label">%2$s</span><input %1$s />',
				$item_atts,
				$content
			);
		} else {
			$html = sprintf(
				'<input %1$s /><span class="wpcf7-list-item-label">%2$s</span>',
				$item_atts,
				$content
			);
		}

		$html = sprintf(
			'<span class="wpcf7-list-item"><label>%s</label></span>',
			$html
		);

	} else {
		$html = sprintf(
			'<span class="wpcf7-list-item"><input %1$s /></span>',
			$item_atts
		);
	}

	$html = sprintf(
		'<span class="wpcf7-form-control-wrap" data-name="%1$s"><span %2$s>%3$s</span>%4$s</span>',
		esc_attr( $tag->name ),
		wpcf7_format_atts( $atts ),
		$html,
		$validation_error
	);

	return $html;
}


/* Validation filter */

add_filter( 'wpcf7_validate_acceptance',
	'wpcf7_acceptance_validation_filter', 10, 2 );

function wpcf7_acceptance_validation_filter( $result, $tag ) {
	if ( ! wpcf7_acceptance_as_validation() ) {
		return $result;
	}

	if ( $tag->has_option( 'optional' ) ) {
		return $result;
	}

	$name = $tag->name;
	$value = ( ! empty( $_POST[$name] ) ? 1 : 0 );

	$invert = $tag->has_option( 'invert' );

	if ( $invert and $value
	or ! $invert and ! $value ) {
		$result->invalidate( $tag, wpcf7_get_message( 'accept_terms' ) );
	}

	return $result;
}


/* Acceptance filter */

add_filter( 'wpcf7_acceptance', 'wpcf7_acceptance_filter', 10, 2 );

function wpcf7_acceptance_filter( $accepted, $submission ) {
	$tags = wpcf7_scan_form_tags( array( 'type' => 'acceptance' ) );

	foreach ( $tags as $tag ) {
		$name = $tag->name;

		if ( empty( $name ) ) {
			continue;
		}

		$value = ( ! empty( $_POST[$name] ) ? 1 : 0 );

		$content = empty( $tag->content )
			? (string) reset( $tag->values )
			: $tag->content;

		$content = trim( $content );

		if ( $value and $content ) {
			$submission->add_consent( $name, $content );
		}

		if ( $tag->has_option( 'optional' ) ) {
			continue;
		}

		$invert = $tag->has_option( 'invert' );

		if ( $invert and $value
		or ! $invert and ! $value ) {
			$accepted = false;
		}
	}

	return $accepted;
}

add_filter( 'wpcf7_form_class_attr',
	'wpcf7_acceptance_form_class_attr', 10, 1 );

function wpcf7_acceptance_form_class_attr( $class_attr ) {
	if ( wpcf7_acceptance_as_validation() ) {
		return $class_attr . ' wpcf7-acceptance-as-validation';
	}

	return $class_attr;
}

function wpcf7_acceptance_as_validation() {
	if ( ! $contact_form = wpcf7_get_current_contact_form() ) {
		return false;
	}

	return $contact_form->is_true( 'acceptance_as_validation' );
}

add_filter( 'wpcf7_mail_tag_replaced_acceptance',
	'wpcf7_acceptance_mail_tag', 10, 4 );

function wpcf7_acceptance_mail_tag( $replaced, $submitted, $html, $mail_tag ) {
	$form_tag = $mail_tag->corresponding_form_tag();

	if ( ! $form_tag ) {
		return $replaced;
	}

	if ( ! empty( $submitted ) ) {
		$replaced = __( 'Consented', 'contact-form-7' );
	} else {
		$replaced = __( 'Not consented', 'contact-form-7' );
	}

	$content = empty( $form_tag->content )
		? (string) reset( $form_tag->values )
		: $form_tag->content;

	if ( ! $html ) {
		$content = wp_strip_all_tags( $content );
	}

	$content = trim( $content );

	if ( $content ) {
		$replaced = sprintf(
			/* translators: 1: 'Consented' or 'Not consented', 2: conditions */
			_x( '%1$s: %2$s', 'mail output for acceptance checkboxes',
				'contact-form-7' ),
			$replaced,
			$content
		);
	}

	return $replaced;
}


/* Tag generator */

add_action( 'wpcf7_admin_init', 'wpcf7_add_tag_generator_acceptance', 35, 0 );

function wpcf7_add_tag_generator_acceptance() {
	$tag_generator = WPCF7_TagGenerator::get_instance();

	$tag_generator->add( 'acceptance', __( 'acceptance', 'contact-form-7' ),
		'wpcf7_tag_generator_acceptance',
	 	array( 'version' => '2' )
	);
}

function wpcf7_tag_generator_acceptance( $contact_form, $options ) {
	$field_types = array(
		'acceptance' => array(
			'display_name' => __( 'Acceptance checkbox', 'contact-form-7' ),
			'heading' => __( 'Acceptance checkbox form-tag generator', 'contact-form-7' ),
			'description' => __( 'Generates a form-tag for an <a href="https://contactform7.com/acceptance-checkbox/">acceptance checkbox</a>.', 'contact-form-7' ),
		),
	);

	$tgg = new WPCF7_TagGeneratorGenerator( $options['content'] );

?>
<header class="description-box">
	<h3><?php
		echo esc_html( $field_types['acceptance']['heading'] );
	?></h3>

	<p><?php
		$description = wp_kses(
			$field_types['acceptance']['description'],
			array(
				'a' => array( 'href' => true ),
				'strong' => array(),
			),
			array( 'http', 'https' )
		);

		echo $description;
	?></p>
</header>

<div class="control-box">
	<fieldset>
		<legend id="<?php echo esc_attr( $tgg->ref( 'type-legend' ) ); ?>"><?php
			echo esc_html( __( 'Field type', 'contact-form-7' ) );
		?></legend>

		<select data-tag-part="basetype" aria-labelledby="<?php echo esc_attr( $tgg->ref( 'type-legend' ) ); ?>"><?php
			echo sprintf(
				'<option %1$s>%2$s</option>',
				wpcf7_format_atts( array(
					'value' => 'acceptance',
				) ),
				esc_html( $field_types['acceptance']['display_name'] )
			);
		?></select>
		<br />
		<label>
			<input type="checkbox" data-tag-part="option" data-tag-option="optional" checked="checked" />
			<?php echo esc_html( __( "This checkbox is optional.", 'contact-form-7' ) ); ?>
		</label>
	</fieldset>

	<?php
		$tgg->print( 'field_name' );

		$tgg->print( 'class_attr' );
	?>

	<fieldset>
		<legend id="<?php echo esc_attr( $tgg->ref( 'value-legend' ) ); ?>"><?php
			echo esc_html( __( 'Condition', 'contact-form-7' ) );
		?></legend>
		<?php
			echo sprintf(
				'<input %s />',
				wpcf7_format_atts( array(
					'type' => 'text',
					'required' => true,
					'value' => __( 'Put the condition for consent here.', 'contact-form-7' ),
					'data-tag-part' => 'content',
					'aria-labelledby' => $tgg->ref( 'value-legend' ),
				) )
			);
		?>
	</fieldset>
</div>

<footer class="insert-box">
	<?php
		$tgg->print( 'insert_box_content' );

		$tgg->print( 'mail_tag_tip' );
	?>
</footer>
<?php
}
modules/quiz.php000064400000014450147510545420007730 0ustar00<?php
/**
** A base module for [quiz]
**/

/* form_tag handler */

add_action( 'wpcf7_init', 'wpcf7_add_form_tag_quiz', 10, 0 );

function wpcf7_add_form_tag_quiz() {
	wpcf7_add_form_tag( 'quiz',
		'wpcf7_quiz_form_tag_handler',
		array(
			'name-attr' => true,
			'do-not-store' => true,
			'not-for-mail' => true,
		)
	);
}

function wpcf7_quiz_form_tag_handler( $tag ) {
	if ( empty( $tag->name ) ) {
		return '';
	}

	$validation_error = wpcf7_get_validation_error( $tag->name );

	$class = wpcf7_form_controls_class( $tag->type );

	if ( $validation_error ) {
		$class .= ' wpcf7-not-valid';
	}

	$atts = array();

	$atts['size'] = $tag->get_size_option( '40' );
	$atts['maxlength'] = $tag->get_maxlength_option();
	$atts['minlength'] = $tag->get_minlength_option();

	if ( $atts['maxlength'] and $atts['minlength']
	and $atts['maxlength'] < $atts['minlength'] ) {
		unset( $atts['maxlength'], $atts['minlength'] );
	}

	$atts['class'] = $tag->get_class_option( $class );
	$atts['id'] = $tag->get_id_option();
	$atts['tabindex'] = $tag->get_option( 'tabindex', 'signed_int', true );
	$atts['autocomplete'] = 'off';
	$atts['aria-required'] = 'true';

	if ( $validation_error ) {
		$atts['aria-invalid'] = 'true';
		$atts['aria-describedby'] = wpcf7_get_validation_error_reference(
			$tag->name
		);
	} else {
		$atts['aria-invalid'] = 'false';
	}

	$pipes = $tag->pipes;

	if ( $pipes instanceof WPCF7_Pipes
	and ! $pipes->zero() ) {
		$pipe = $pipes->random_pipe();
		$question = $pipe->before;
		$answer = $pipe->after;
	} else {
		// default quiz
		$question = '1+1=?';
		$answer = '2';
	}

	$answer = wpcf7_canonicalize( $answer, array(
		'strip_separators' => true,
	) );

	$atts['type'] = 'text';
	$atts['name'] = $tag->name;

	$html = sprintf(
		'<span class="wpcf7-form-control-wrap" data-name="%1$s"><label><span class="wpcf7-quiz-label">%2$s</span> <input %3$s /></label><input type="hidden" name="_wpcf7_quiz_answer_%4$s" value="%5$s" />%6$s</span>',
		esc_attr( $tag->name ),
		esc_html( $question ),
		wpcf7_format_atts( $atts ),
		$tag->name,
		wp_hash( $answer, 'wpcf7_quiz' ),
		$validation_error
	);

	return $html;
}


/* Validation filter */

add_filter( 'wpcf7_validate_quiz', 'wpcf7_quiz_validation_filter', 10, 2 );

function wpcf7_quiz_validation_filter( $result, $tag ) {
	$name = $tag->name;

	$answer = wp_unslash( $_POST[$name] ?? '' );

	$answer = wpcf7_canonicalize( $answer, array(
		'strip_separators' => true,
	) );

	$answer_hash = wp_hash( $answer, 'wpcf7_quiz' );

	$expected_hash = (string) ( $_POST['_wpcf7_quiz_answer_' . $name] ?? '' );

	if ( ! hash_equals( $expected_hash, $answer_hash ) ) {
		$result->invalidate( $tag, wpcf7_get_message( 'quiz_answer_not_correct' ) );
	}

	return $result;
}


/* Ajax echo filter */

add_filter( 'wpcf7_refill_response', 'wpcf7_quiz_ajax_refill', 10, 1 );
add_filter( 'wpcf7_feedback_response', 'wpcf7_quiz_ajax_refill', 10, 1 );

function wpcf7_quiz_ajax_refill( $items ) {
	if ( ! is_array( $items ) ) {
		return $items;
	}

	$fes = wpcf7_scan_form_tags( array( 'type' => 'quiz' ) );

	if ( empty( $fes ) ) {
		return $items;
	}

	$refill = array();

	foreach ( $fes as $fe ) {
		$name = $fe['name'];
		$pipes = $fe['pipes'];

		if ( empty( $name ) ) {
			continue;
		}

		if ( $pipes instanceof WPCF7_Pipes
		and ! $pipes->zero() ) {
			$pipe = $pipes->random_pipe();
			$question = $pipe->before;
			$answer = $pipe->after;
		} else {
			// default quiz
			$question = '1+1=?';
			$answer = '2';
		}

		$answer = wpcf7_canonicalize( $answer, array(
			'strip_separators' => true,
		) );

		$refill[$name] = array( $question, wp_hash( $answer, 'wpcf7_quiz' ) );
	}

	if ( ! empty( $refill ) ) {
		$items['quiz'] = $refill;
	}

	return $items;
}


/* Messages */

add_filter( 'wpcf7_messages', 'wpcf7_quiz_messages', 10, 1 );

function wpcf7_quiz_messages( $messages ) {
	$messages = array_merge( $messages, array(
		'quiz_answer_not_correct' => array(
			'description' =>
				__( "Sender does not enter the correct answer to the quiz", 'contact-form-7' ),
			'default' =>
				__( "The answer to the quiz is incorrect.", 'contact-form-7' ),
		),
	) );

	return $messages;
}


/* Tag generator */

add_action( 'wpcf7_admin_init', 'wpcf7_add_tag_generator_quiz', 40, 0 );

function wpcf7_add_tag_generator_quiz() {
	$tag_generator = WPCF7_TagGenerator::get_instance();

	$tag_generator->add( 'quiz', __( 'quiz', 'contact-form-7' ),
		'wpcf7_tag_generator_quiz',
	 	array( 'version' => '2' )
	);
}

function wpcf7_tag_generator_quiz( $contact_form, $options ) {
	$field_types = array(
		'quiz' => array(
			'display_name' => __( 'Quiz', 'contact-form-7' ),
			'heading' => __( 'Quiz form-tag generator', 'contact-form-7' ),
			'description' => __( 'Generates a form-tag for a <a href="https://contactform7.com/quiz/">quiz</a>.', 'contact-form-7' ),
		),
	);

	$tgg = new WPCF7_TagGeneratorGenerator( $options['content'] );

?>
<header class="description-box">
	<h3><?php
		echo esc_html( $field_types['quiz']['heading'] );
	?></h3>

	<p><?php
		$description = wp_kses(
			$field_types['quiz']['description'],
			array(
				'a' => array( 'href' => true ),
				'strong' => array(),
			),
			array( 'http', 'https' )
		);

		echo $description;
	?></p>
</header>

<div class="control-box">
	<?php
		$tgg->print( 'field_type', array(
			'select_options' => array(
				'quiz' => $field_types['quiz']['display_name'],
			),
		) );

		$tgg->print( 'field_name' );

		$tgg->print( 'class_attr' );
	?>

	<fieldset>
		<legend id="<?php echo esc_attr( $tgg->ref( 'selectable-values-legend' ) ); ?>"><?php
			echo esc_html( __( 'Questions and answers', 'contact-form-7' ) );
		?></legend>
		<?php
			echo sprintf(
				'<span %1$s>%2$s</span>',
				wpcf7_format_atts( array(
					'id' => $tgg->ref( 'selectable-values-description' ),
				) ),
				esc_html( __( "One pipe-separated question-answer pair (question|answer) per line.", 'contact-form-7' ) )
			);
		?>
		<br />
		<?php
			echo sprintf(
				'<textarea %1$s>%2$s</textarea>',
				wpcf7_format_atts( array(
					'required' => true,
					'data-tag-part' => 'value',
					'aria-labelledby' => $tgg->ref( 'selectable-values-legend' ),
					'aria-describedby' => $tgg->ref( 'selectable-values-description' ),
				) ),
				esc_html( __( "The capital of Brazil? | Rio", 'contact-form-7' ) )
			);
		?>
	</fieldset>

</div>

<footer class="insert-box">
	<?php
		$tgg->print( 'insert_box_content' );
	?>
</footer>
<?php
}
modules/file.php000064400000014326147510545420007661 0ustar00<?php
/**
** A base module for [file] and [file*]
**/

/* form_tag handler */

add_action( 'wpcf7_init', 'wpcf7_add_form_tag_file', 10, 0 );

function wpcf7_add_form_tag_file() {
	wpcf7_add_form_tag( array( 'file', 'file*' ),
		'wpcf7_file_form_tag_handler',
		array(
			'name-attr' => true,
			'file-uploading' => true,
		)
	);
}

function wpcf7_file_form_tag_handler( $tag ) {
	if ( empty( $tag->name ) ) {
		return '';
	}

	$validation_error = wpcf7_get_validation_error( $tag->name );

	$class = wpcf7_form_controls_class( $tag->type );

	if ( $validation_error ) {
		$class .= ' wpcf7-not-valid';
	}

	$atts = array();

	$atts['size'] = $tag->get_size_option( '40' );
	$atts['class'] = $tag->get_class_option( $class );
	$atts['id'] = $tag->get_id_option();
	$atts['capture'] = $tag->get_option( 'capture', '(user|environment)', true );
	$atts['tabindex'] = $tag->get_option( 'tabindex', 'signed_int', true );

	$atts['accept'] = wpcf7_acceptable_filetypes(
		$tag->get_option( 'filetypes' ), 'attr'
	);

	if ( $tag->is_required() ) {
		$atts['aria-required'] = 'true';
	}

	if ( $validation_error ) {
		$atts['aria-invalid'] = 'true';
		$atts['aria-describedby'] = wpcf7_get_validation_error_reference(
			$tag->name
		);
	} else {
		$atts['aria-invalid'] = 'false';
	}

	$atts['type'] = 'file';
	$atts['name'] = $tag->name;

	$html = sprintf(
		'<span class="wpcf7-form-control-wrap" data-name="%1$s"><input %2$s />%3$s</span>',
		esc_attr( $tag->name ),
		wpcf7_format_atts( $atts ),
		$validation_error
	);

	return $html;
}


add_action(
	'wpcf7_swv_create_schema',
	'wpcf7_swv_add_file_rules',
	10, 2
);

function wpcf7_swv_add_file_rules( $schema, $contact_form ) {
	$tags = $contact_form->scan_form_tags( array(
		'basetype' => array( 'file' ),
	) );

	foreach ( $tags as $tag ) {
		if ( $tag->is_required() ) {
			$schema->add_rule(
				wpcf7_swv_create_rule( 'requiredfile', array(
					'field' => $tag->name,
					'error' => wpcf7_get_message( 'invalid_required' ),
				) )
			);
		}

		$schema->add_rule(
			wpcf7_swv_create_rule( 'file', array(
				'field' => $tag->name,
				'accept' => explode( ',', wpcf7_acceptable_filetypes(
					$tag->get_option( 'filetypes' ), 'attr'
				) ),
				'error' => wpcf7_get_message( 'upload_file_type_invalid' ),
			) )
		);

		$schema->add_rule(
			wpcf7_swv_create_rule( 'maxfilesize', array(
				'field' => $tag->name,
				'threshold' => $tag->get_limit_option(),
				'error' => wpcf7_get_message( 'upload_file_too_large' ),
			) )
		);
	}
}


add_filter( 'wpcf7_mail_tag_replaced_file', 'wpcf7_file_mail_tag', 10, 4 );
add_filter( 'wpcf7_mail_tag_replaced_file*', 'wpcf7_file_mail_tag', 10, 4 );

function wpcf7_file_mail_tag( $replaced, $submitted, $html, $mail_tag ) {
	$submission = WPCF7_Submission::get_instance();
	$uploaded_files = $submission->uploaded_files();
	$name = $mail_tag->field_name();

	if ( ! empty( $uploaded_files[$name] ) ) {
		$paths = (array) $uploaded_files[$name];
		$paths = array_map( 'wp_basename', $paths );

		$replaced = wpcf7_flat_join( $paths, array(
			'separator' => wp_get_list_item_separator(),
		) );
	}

	return $replaced;
}


/* Tag generator */

add_action( 'wpcf7_admin_init', 'wpcf7_add_tag_generator_file', 50, 0 );

function wpcf7_add_tag_generator_file() {
	$tag_generator = WPCF7_TagGenerator::get_instance();

	$tag_generator->add( 'file', __( 'file', 'contact-form-7' ),
		'wpcf7_tag_generator_file',
	 	array( 'version' => '2' )
	);
}

function wpcf7_tag_generator_file( $contact_form, $options ) {
	$field_types = array(
		'file' => array(
			'display_name' => __( 'File uploading field', 'contact-form-7' ),
			'heading' => __( 'File uploading field form-tag generator', 'contact-form-7' ),
			'description' => __( 'Generates a form-tag for a <a href="https://contactform7.com/file-uploading-and-attachment/">file uploading field</a>.', 'contact-form-7' ),
		),
	);

	$tgg = new WPCF7_TagGeneratorGenerator( $options['content'] );

?>
<header class="description-box">
	<h3><?php
		echo esc_html( $field_types['file']['heading'] );
	?></h3>

	<p><?php
		$description = wp_kses(
			$field_types['file']['description'],
			array(
				'a' => array( 'href' => true ),
				'strong' => array(),
			),
			array( 'http', 'https' )
		);

		echo $description;
	?></p>
</header>

<div class="control-box">
	<?php
		$tgg->print( 'field_type', array(
			'with_required' => true,
			'select_options' => array(
				'file' => $field_types['file']['display_name'],
			),
		) );

		$tgg->print( 'field_name' );

		$tgg->print( 'class_attr' );
	?>

	<fieldset>
		<legend id="<?php echo esc_attr( $tgg->ref( 'filetypes-option-legend' ) ); ?>"><?php
			echo esc_html( __( 'Acceptable file types', 'contact-form-7' ) );
		?></legend>
		<label><?php
		echo sprintf(
			'<span %1$s>%2$s</span><br />',
			wpcf7_format_atts( array(
				'id' => $tgg->ref( 'filetypes-option-description' ),
			) ),
			esc_html( __( "Pipe-separated file types list. You can use file extensions and MIME types.", 'contact-form-7' ) )
		);

		echo sprintf(
			'<input %s />',
			wpcf7_format_atts( array(
				'type' => 'text',
				'pattern' => '[0-9a-z*\/\|]*',
				'value' => 'audio/*|video/*|image/*',
				'aria-labelledby' => $tgg->ref( 'filetypes-option-legend' ),
				'aria-describedby' => $tgg->ref( 'filetypes-option-description' ),
				'data-tag-part' => 'option',
				'data-tag-option' => 'filetypes:',
			) )
		);
		?></label>
	</fieldset>

	<fieldset>
		<legend id="<?php echo esc_attr( $tgg->ref( 'limit-option-legend' ) ); ?>"><?php
			echo esc_html( __( 'File size limit', 'contact-form-7' ) );
		?></legend>
		<label><?php
		echo sprintf(
			'<span %1$s>%2$s</span><br />',
			wpcf7_format_atts( array(
				'id' => $tgg->ref( 'limit-option-description' ),
			) ),
			esc_html( __( "In bytes. You can use kb and mb suffixes.", 'contact-form-7' ) )
		);

		echo sprintf(
			'<input %s />',
			wpcf7_format_atts( array(
				'type' => 'text',
				'pattern' => '[1-9][0-9]*([kKmM]?[bB])?',
				'value' => '1mb',
				'aria-labelledby' => $tgg->ref( 'limit-option-legend' ),
				'aria-describedby' => $tgg->ref( 'limit-option-description' ),
				'data-tag-part' => 'option',
				'data-tag-option' => 'limit:',
			) )
		);
		?></label>
	</fieldset>
</div>

<footer class="insert-box">
	<?php
		$tgg->print( 'insert_box_content' );

		$tgg->print( 'mail_tag_tip' );
	?>
</footer>
<?php
}
modules/number.php000064400000014441147510545420010230 0ustar00<?php
/**
** A base module for the following types of tags:
** 	[number] and [number*]		# Number
** 	[range] and [range*]		# Range
**/

/* form_tag handler */

add_action( 'wpcf7_init', 'wpcf7_add_form_tag_number', 10, 0 );

function wpcf7_add_form_tag_number() {
	wpcf7_add_form_tag( array( 'number', 'number*', 'range', 'range*' ),
		'wpcf7_number_form_tag_handler',
		array(
			'name-attr' => true,
		)
	);
}

function wpcf7_number_form_tag_handler( $tag ) {
	if ( empty( $tag->name ) ) {
		return '';
	}

	$validation_error = wpcf7_get_validation_error( $tag->name );

	$class = wpcf7_form_controls_class( $tag->type );

	$class .= ' wpcf7-validates-as-number';

	if ( $validation_error ) {
		$class .= ' wpcf7-not-valid';
	}

	$atts = array();

	$atts['class'] = $tag->get_class_option( $class );
	$atts['id'] = $tag->get_id_option();
	$atts['tabindex'] = $tag->get_option( 'tabindex', 'signed_int', true );
	$atts['min'] = $tag->get_option( 'min', 'signed_num', true );
	$atts['max'] = $tag->get_option( 'max', 'signed_num', true );
	$atts['step'] = $tag->get_option( 'step', 'num', true );
	$atts['readonly'] = $tag->has_option( 'readonly' );

	$atts['autocomplete'] = $tag->get_option(
		'autocomplete', '[-0-9a-zA-Z]+', true
	);

	if ( $tag->is_required() ) {
		$atts['aria-required'] = 'true';
	}

	if ( $validation_error ) {
		$atts['aria-invalid'] = 'true';
		$atts['aria-describedby'] = wpcf7_get_validation_error_reference(
			$tag->name
		);
	} else {
		$atts['aria-invalid'] = 'false';
	}

	$value = (string) reset( $tag->values );

	if ( $tag->has_option( 'placeholder' )
	or $tag->has_option( 'watermark' ) ) {
		$atts['placeholder'] = $value;
		$value = '';
	}

	$value = $tag->get_default_option( $value );

	$value = wpcf7_get_hangover( $tag->name, $value );

	$atts['value'] = $value;

	if ( 'range' === $tag->basetype ) {
		if ( ! wpcf7_is_number( $atts['min'] ) ) {
			$atts['min'] = '0';
		}

		if ( ! wpcf7_is_number( $atts['max'] ) ) {
			$atts['max'] = '100';
		}

		if ( '' === $atts['value'] ) {
			if ( $atts['min'] < $atts['max'] ) {
				$atts['value'] = ( $atts['min'] + $atts['max'] ) / 2;
			} else {
				$atts['value'] = $atts['min'];
			}
		}
	}

	$atts['type'] = $tag->basetype;
	$atts['name'] = $tag->name;

	$html = sprintf(
		'<span class="wpcf7-form-control-wrap" data-name="%1$s"><input %2$s />%3$s</span>',
		esc_attr( $tag->name ),
		wpcf7_format_atts( $atts ),
		$validation_error
	);

	return $html;
}


add_action(
	'wpcf7_swv_create_schema',
	'wpcf7_swv_add_number_rules',
	10, 2
);

function wpcf7_swv_add_number_rules( $schema, $contact_form ) {
	$tags = $contact_form->scan_form_tags( array(
		'basetype' => array( 'number', 'range' ),
	) );

	foreach ( $tags as $tag ) {
		if ( $tag->is_required() ) {
			$schema->add_rule(
				wpcf7_swv_create_rule( 'required', array(
					'field' => $tag->name,
					'error' => wpcf7_get_message( 'invalid_required' ),
				) )
			);
		}

		$schema->add_rule(
			wpcf7_swv_create_rule( 'number', array(
				'field' => $tag->name,
				'error' => wpcf7_get_message( 'invalid_number' ),
			) )
		);

		$min = $tag->get_option( 'min', 'signed_num', true );
		$max = $tag->get_option( 'max', 'signed_num', true );

		if ( 'range' === $tag->basetype ) {
			if ( ! wpcf7_is_number( $min ) ) {
				$min = '0';
			}

			if ( ! wpcf7_is_number( $max ) ) {
				$max = '100';
			}
		}

		if ( wpcf7_is_number( $min ) ) {
			$schema->add_rule(
				wpcf7_swv_create_rule( 'minnumber', array(
					'field' => $tag->name,
					'threshold' => $min,
					'error' => wpcf7_get_message( 'number_too_small' ),
				) )
			);
		}

		if ( wpcf7_is_number( $max ) ) {
			$schema->add_rule(
				wpcf7_swv_create_rule( 'maxnumber', array(
					'field' => $tag->name,
					'threshold' => $max,
					'error' => wpcf7_get_message( 'number_too_large' ),
				) )
			);
		}
	}
}


/* Messages */

add_filter( 'wpcf7_messages', 'wpcf7_number_messages', 10, 1 );

function wpcf7_number_messages( $messages ) {
	return array_merge( $messages, array(
		'invalid_number' => array(
			'description' => __( "Number format that the sender entered is invalid", 'contact-form-7' ),
			'default' => __( "Please enter a number.", 'contact-form-7' ),
		),

		'number_too_small' => array(
			'description' => __( "Number is smaller than minimum limit", 'contact-form-7' ),
			'default' => __( "This field has a too small number.", 'contact-form-7' ),
		),

		'number_too_large' => array(
			'description' => __( "Number is larger than maximum limit", 'contact-form-7' ),
			'default' => __( "This field has a too large number.", 'contact-form-7' ),
		),
	) );
}


/* Tag generator */

add_action( 'wpcf7_admin_init', 'wpcf7_add_tag_generator_number', 18, 0 );

function wpcf7_add_tag_generator_number() {
	$tag_generator = WPCF7_TagGenerator::get_instance();

	$tag_generator->add( 'number', __( 'number', 'contact-form-7' ),
		'wpcf7_tag_generator_number',
	 	array( 'version' => '2' )
	);
}

function wpcf7_tag_generator_number( $contact_form, $options ) {
	$field_types = array(
		'number' => array(
			'display_name' => __( 'Number field', 'contact-form-7' ),
			'heading' => __( 'Number field form-tag generator', 'contact-form-7' ),
			'description' => __( 'Generates a form-tag for a <a href="https://contactform7.com/number-fields/">number input field</a>.', 'contact-form-7' ),
		),
	);

	$tgg = new WPCF7_TagGeneratorGenerator( $options['content'] );

?>
<header class="description-box">
	<h3><?php
		echo esc_html( $field_types['number']['heading'] );
	?></h3>

	<p><?php
		$description = wp_kses(
			$field_types['number']['description'],
			array(
				'a' => array( 'href' => true ),
				'strong' => array(),
			),
			array( 'http', 'https' )
		);

		echo $description;
	?></p>
</header>

<div class="control-box">
	<?php
		$tgg->print( 'field_type', array(
			'with_required' => true,
			'select_options' => array(
				'number' => __( 'Spinbox', 'contact-form-7' ),
				'range' => __( 'Slider', 'contact-form-7' ),
			),
		) );

		$tgg->print( 'field_name' );

		$tgg->print( 'class_attr' );

		$tgg->print( 'min_max', array(
			'title' => __( 'Range', 'contact-form-7' ),
			'min_option' => 'min:',
			'max_option' => 'max:',
		) );

		$tgg->print( 'default_value', array(
			'type' => 'number',
			'with_placeholder' => false,
		) );
	?>
</div>

<footer class="insert-box">
	<?php
		$tgg->print( 'insert_box_content' );

		$tgg->print( 'mail_tag_tip' );
	?>
</footer>
<?php
}
modules/text.php000064400000020001147510545420007711 0ustar00<?php
/**
** A base module for the following types of tags:
** 	[text] and [text*]		# Single-line text
** 	[email] and [email*]	# Email address
** 	[url] and [url*]		# URL
** 	[tel] and [tel*]		# Telephone number
**/

/* form_tag handler */

add_action( 'wpcf7_init', 'wpcf7_add_form_tag_text', 10, 0 );

function wpcf7_add_form_tag_text() {
	wpcf7_add_form_tag(
		array( 'text', 'text*', 'email', 'email*', 'url', 'url*', 'tel', 'tel*' ),
		'wpcf7_text_form_tag_handler',
		array(
			'name-attr' => true,
		)
	);
}

function wpcf7_text_form_tag_handler( $tag ) {
	if ( empty( $tag->name ) ) {
		return '';
	}

	$validation_error = wpcf7_get_validation_error( $tag->name );

	$class = wpcf7_form_controls_class( $tag->type, 'wpcf7-text' );

	if ( in_array( $tag->basetype, array( 'email', 'url', 'tel' ) ) ) {
		$class .= ' wpcf7-validates-as-' . $tag->basetype;
	}

	if ( $validation_error ) {
		$class .= ' wpcf7-not-valid';
	}

	$atts = array();

	$atts['size'] = $tag->get_size_option( '40' );
	$atts['maxlength'] = $tag->get_maxlength_option( '400' );
	$atts['minlength'] = $tag->get_minlength_option();

	if ( $atts['maxlength'] and $atts['minlength']
	and $atts['maxlength'] < $atts['minlength'] ) {
		unset( $atts['maxlength'], $atts['minlength'] );
	}

	$atts['class'] = $tag->get_class_option( $class );
	$atts['id'] = $tag->get_id_option();
	$atts['list'] = $tag->get_option( 'list', 'id', true );
	$atts['tabindex'] = $tag->get_option( 'tabindex', 'signed_int', true );
	$atts['readonly'] = $tag->has_option( 'readonly' );

	$atts['autocomplete'] = $tag->get_option(
		'autocomplete', '[-0-9a-zA-Z]+', true
	);

	if ( $tag->is_required() ) {
		$atts['aria-required'] = 'true';
	}

	if ( $validation_error ) {
		$atts['aria-invalid'] = 'true';
		$atts['aria-describedby'] = wpcf7_get_validation_error_reference(
			$tag->name
		);
	} else {
		$atts['aria-invalid'] = 'false';
	}

	$value = (string) reset( $tag->values );

	if ( $tag->has_option( 'placeholder' )
	or $tag->has_option( 'watermark' ) ) {
		$atts['placeholder'] = $value;
		$value = '';
	}

	$value = $tag->get_default_option( $value );

	$value = wpcf7_get_hangover( $tag->name, $value );

	$atts['value'] = $value;
	$atts['type'] = $tag->basetype;
	$atts['name'] = $tag->name;

	$html = sprintf(
		'<span class="wpcf7-form-control-wrap" data-name="%1$s"><input %2$s />%3$s</span>',
		esc_attr( $tag->name ),
		wpcf7_format_atts( $atts ),
		$validation_error
	);

	return $html;
}


add_action(
	'wpcf7_swv_create_schema',
	'wpcf7_swv_add_text_rules',
	10, 2
);

function wpcf7_swv_add_text_rules( $schema, $contact_form ) {
	$tags = $contact_form->scan_form_tags( array(
		'basetype' => array( 'text', 'email', 'url', 'tel' ),
	) );

	foreach ( $tags as $tag ) {
		if ( $tag->is_required() ) {
			$schema->add_rule(
				wpcf7_swv_create_rule( 'required', array(
					'field' => $tag->name,
					'error' => wpcf7_get_message( 'invalid_required' ),
				) )
			);
		}

		if ( 'email' === $tag->basetype ) {
			$schema->add_rule(
				wpcf7_swv_create_rule( 'email', array(
					'field' => $tag->name,
					'error' => wpcf7_get_message( 'invalid_email' ),
				) )
			);
		}

		if ( 'url' === $tag->basetype ) {
			$schema->add_rule(
				wpcf7_swv_create_rule( 'url', array(
					'field' => $tag->name,
					'error' => wpcf7_get_message( 'invalid_url' ),
				) )
			);
		}

		if ( 'tel' === $tag->basetype ) {
			$schema->add_rule(
				wpcf7_swv_create_rule( 'tel', array(
					'field' => $tag->name,
					'error' => wpcf7_get_message( 'invalid_tel' ),
				) )
			);
		}

		if ( $minlength = $tag->get_minlength_option() ) {
			$schema->add_rule(
				wpcf7_swv_create_rule( 'minlength', array(
					'field' => $tag->name,
					'threshold' => absint( $minlength ),
					'error' => wpcf7_get_message( 'invalid_too_short' ),
				) )
			);
		}

		if ( $maxlength = $tag->get_maxlength_option( '400' ) ) {
			$schema->add_rule(
				wpcf7_swv_create_rule( 'maxlength', array(
					'field' => $tag->name,
					'threshold' => absint( $maxlength ),
					'error' => wpcf7_get_message( 'invalid_too_long' ),
				) )
			);
		}
	}
}


/* Messages */

add_filter( 'wpcf7_messages', 'wpcf7_text_messages', 10, 1 );

function wpcf7_text_messages( $messages ) {
	$messages = array_merge( $messages, array(
		'invalid_email' => array(
			'description' =>
				__( "Email address that the sender entered is invalid", 'contact-form-7' ),
			'default' =>
				__( "Please enter an email address.", 'contact-form-7' ),
		),

		'invalid_url' => array(
			'description' =>
				__( "URL that the sender entered is invalid", 'contact-form-7' ),
			'default' =>
				__( "Please enter a URL.", 'contact-form-7' ),
		),

		'invalid_tel' => array(
			'description' =>
				__( "Telephone number that the sender entered is invalid", 'contact-form-7' ),
			'default' =>
				__( "Please enter a telephone number.", 'contact-form-7' ),
		),
	) );

	return $messages;
}


/* Tag generator */

add_action( 'wpcf7_admin_init', 'wpcf7_add_tag_generator_text', 15, 0 );

function wpcf7_add_tag_generator_text() {
	$tag_generator = WPCF7_TagGenerator::get_instance();

	$basetypes = array(
		'text' => __( 'text', 'contact-form-7' ),
		'email' => __( 'email', 'contact-form-7' ),
		'url' => __( 'URL', 'contact-form-7' ),
		'tel' => __( 'tel', 'contact-form-7' ),
	);

	foreach ( $basetypes as $id => $title ) {
		$tag_generator->add( $id, $title,
			'wpcf7_tag_generator_text',
			array( 'version' => '2' )
		);
	}
}

function wpcf7_tag_generator_text( $contact_form, $options ) {
	$field_types = array(
		'text' => array(
			'display_name' => __( 'Text field', 'contact-form-7' ),
			'heading' => __( 'Text field form-tag generator', 'contact-form-7' ),
			'description' => __( 'Generates a form-tag for a <a href="https://contactform7.com/text-fields/">single-line plain text input field</a>.', 'contact-form-7' ),
			'maybe_purpose' => 'author_name',
		),
		'email' => array(
			'display_name' => __( 'Email address field', 'contact-form-7' ),
			'heading' => __( 'Email address field form-tag generator', 'contact-form-7' ),
			'description' => __( 'Generates a form-tag for an <a href="https://contactform7.com/text-fields/">email address input field</a>.', 'contact-form-7' ),
			'maybe_purpose' => 'author_email',
		),
		'url' => array(
			'display_name' => __( 'URL field', 'contact-form-7' ),
			'heading' => __( 'URL field form-tag generator', 'contact-form-7' ),
			'description' => __( 'Generates a form-tag for a <a href="https://contactform7.com/text-fields/">URL input field</a>.', 'contact-form-7' ),
			'maybe_purpose' => 'author_url',
		),
		'tel' => array(
			'display_name' => __( 'Telephone number field', 'contact-form-7' ),
			'heading' => __( 'Telephone number field form-tag generator', 'contact-form-7' ),
			'description' => __( 'Generates a form-tag for a <a href="https://contactform7.com/text-fields/">telephone number input field</a>.', 'contact-form-7' ),
			'maybe_purpose' => 'author_tel',
		),
	);

	$basetype = $options['id'];

	if ( ! in_array( $basetype, array_keys( $field_types ) ) ) {
		$basetype = 'text';
	}

	$tgg = new WPCF7_TagGeneratorGenerator( $options['content'] );

?>
<header class="description-box">
	<h3><?php
		echo esc_html( $field_types[$basetype]['heading'] );
	?></h3>

	<p><?php
		$description = wp_kses(
			$field_types[$basetype]['description'],
			array(
				'a' => array( 'href' => true ),
				'strong' => array(),
			),
			array( 'http', 'https' )
		);

		echo $description;
	?></p>
</header>

<div class="control-box">
	<?php
		$tgg->print( 'field_type', array(
			'with_required' => true,
			'select_options' => array(
				$basetype => $field_types[$basetype]['display_name'],
			),
		) );

		$tgg->print( 'field_name', array(
			'ask_if' => $field_types[$basetype]['maybe_purpose']
		) );

		$tgg->print( 'class_attr' );

		$tgg->print( 'min_max', array(
			'title' => __( 'Length', 'contact-form-7' ),
			'min_option' => 'minlength:',
			'max_option' => 'maxlength:',
		) );

		$tgg->print( 'default_value', array(
			'with_placeholder' => true,
		) );
	?>
</div>

<footer class="insert-box">
	<?php
		$tgg->print( 'insert_box_content' );

		$tgg->print( 'mail_tag_tip' );
	?>
</footer>
<?php
}
modules/akismet/akismet.php000064400000014567147510545420012043 0ustar00<?php
/**
 * The Akismet integration module
 *
 * @link https://akismet.com/development/api/
 */

wpcf7_include_module_file( 'akismet/service.php' );


add_action(
	'wpcf7_init',
	'wpcf7_akismet_register_service',
	30, 0
);

/**
 * Registers the Akismet service.
 */
function wpcf7_akismet_register_service() {
	$integration = WPCF7_Integration::get_instance();

	$integration->add_service( 'akismet',
		WPCF7_Akismet::get_instance()
	);
}


add_filter( 'wpcf7_spam', 'wpcf7_akismet', 10, 2 );

function wpcf7_akismet( $spam, $submission ) {
	if ( $spam ) {
		return $spam;
	}

	if ( ! wpcf7_akismet_is_available() ) {
		return false;
	}

	if ( ! $params = wpcf7_akismet_submitted_params() ) {
		return false;
	}

	$comment = array(
		'comment_type' => 'contact-form',
		'comment_author' => $params['author'],
		'comment_author_email' => $params['author_email'],
		'comment_author_url' => $params['author_url'],
		'comment_content' => $params['content'],
		'blog' => home_url(),
		'blog_lang' => get_locale(),
		'blog_charset' => get_option( 'blog_charset' ),
		'user_ip' => $submission->get_meta( 'remote_ip' ),
		'user_agent' => $submission->get_meta( 'user_agent' ),
		'referrer' => $_SERVER['HTTP_REFERER'] ?? '',
	);

	$datetime = date_create_immutable(
		'@' . $submission->get_meta( 'timestamp' )
	);

	if ( $datetime ) {
		$comment['comment_date_gmt'] = $datetime->format( DATE_ATOM );
	}

	if ( $permalink = get_permalink() ) {
		$comment['permalink'] = $permalink;
	}

	$server_vars = array_diff_key(
		$_SERVER,
		array_flip( array( 'HTTP_COOKIE', 'HTTP_COOKIE2', 'PHP_AUTH_PW' ) )
	);

	$comment = array_merge( $comment, $server_vars );

	$comment = apply_filters( 'wpcf7_akismet_parameters', $comment );

	if ( wpcf7_akismet_comment_check( $comment ) ) {
		$spam = true;

		$submission->add_spam_log( array(
			'agent' => 'akismet',
			'reason' => __( "Akismet returns a spam response.", 'contact-form-7' ),
		) );
	} else {
		$spam = false;
	}

	return $spam;
}


/**
 * Returns true if Akismet is active and has a valid API key.
 */
function wpcf7_akismet_is_available() {
	if ( is_callable( array( 'Akismet', 'get_api_key' ) ) ) {
		return (bool) Akismet::get_api_key();
	}

	return false;
}


/**
 * Returns an array of parameters based on the current form submission.
 * Returns false if Akismet is not active on the contact form.
 */
function wpcf7_akismet_submitted_params() {
	$akismet_tags = array_filter(
		wpcf7_scan_form_tags(),
		static function ( $tag ) {
			$akismet_option = $tag->get_option( 'akismet',
				'(author|author_email|author_url)',
				true
			);

			return (bool) $akismet_option;
		}
	);

	if ( ! $akismet_tags ) { // Akismet is not active on this contact form.
		return false;
	}

	$params = array(
		'author' => '',
		'author_email' => '',
		'author_url' => '',
		'content' => '',
	);

	foreach ( (array) $_POST as $key => $val ) {
		if ( '_wpcf7' == substr( $key, 0, 6 )
		or '_wpnonce' == $key ) {
			continue;
		}

		$vals = array_filter(
			wpcf7_array_flatten( $val ),
			static function ( $val ) {
				return '' !== trim( $val );
			}
		);

		if ( empty( $vals ) ) {
			continue;
		}

		if ( $tags = wpcf7_scan_form_tags( array( 'name' => $key ) ) ) {
			$tag = $tags[0];

			$akismet_option = $tag->get_option( 'akismet',
				'(author|author_email|author_url)',
				true
			);

			if ( 'author' === $akismet_option ) {
				$params['author'] = sprintf(
					'%s %s',
					$params['author'],
					implode( ' ', $vals )
				);

				continue;
			}

			if ( 'author_email' === $akismet_option
			and '' === $params['author_email'] ) {
				$params['author_email'] = $vals[0];
				continue;
			}

			if ( 'author_url' === $akismet_option
			and '' === $params['author_url'] ) {
				$params['author_url'] = $vals[0];
				continue;
			}

			$vals = array_filter(
				$vals,
				static function ( $val ) use ( $tag ) {
					if ( wpcf7_form_tag_supports( $tag->type, 'selectable-values' )
					and in_array( $val, $tag->labels ) ) {
						return false;
					} else {
						return true;
					}
				}
			);
		}

		if ( $vals ) {
			$params['content'] .= "\n\n" . implode( ', ', $vals );
		}
	}

	$params = array_map( 'trim', $params );

	return $params;
}


/**
 * Sends data to Akismet.
 *
 * @param array $comment Submission and environment data.
 * @return bool True if Akismet called it spam, or false otherwise.
 */
function wpcf7_akismet_comment_check( $comment ) {
	$spam = false;
	$query_string = wpcf7_build_query( $comment );

	if ( is_callable( array( 'Akismet', 'http_post' ) ) ) {
		$response = Akismet::http_post( $query_string, 'comment-check' );
	} else {
		return $spam;
	}

	if ( 'true' == $response[1] ) {
		$spam = true;
	}

	if ( $submission = WPCF7_Submission::get_instance() ) {
		$submission->push( 'akismet', array(
			'comment' => $comment,
			'spam' => $spam,
		) );
	}

	return apply_filters( 'wpcf7_akismet_comment_check', $spam, $comment );
}


add_filter( 'wpcf7_posted_data', 'wpcf7_akismet_posted_data', 10, 1 );

/**
 * Removes Akismet-related properties from the posted data.
 *
 * This does not affect the $_POST variable itself.
 *
 * @link https://plugins.trac.wordpress.org/browser/akismet/tags/5.0/_inc/akismet-frontend.js
 */
function wpcf7_akismet_posted_data( $posted_data ) {
	if ( wpcf7_akismet_is_available() ) {
		$posted_data = array_diff_key(
			$posted_data,
			array(
				'ak_bib' => '',
				'ak_bfs' => '',
				'ak_bkpc' => '',
				'ak_bkp' => '',
				'ak_bmc' => '',
				'ak_bmcc' => '',
				'ak_bmk' => '',
				'ak_bck' => '',
				'ak_bmmc' => '',
				'ak_btmc' => '',
				'ak_bsc' => '',
				'ak_bte' => '',
				'ak_btec' => '',
				'ak_bmm' => '',
			)
		);
	}

	return $posted_data;
}


add_filter(
	'wpcf7_default_template',
	'wpcf7_akismet_default_template',
	10, 2
);

function wpcf7_akismet_default_template( $template, $prop ) {
	if ( ! wpcf7_akismet_is_available() ) {
		return $template;
	}

	if ( 'form' === $prop ) {
		$template = str_replace(
			array(
				'[text* your-name ',
				'[email* your-email ',
			),
			array(
				'[text* your-name akismet:author ',
				'[email* your-email akismet:author_email ',
			),
			$template
		);

		$privacy_notice = sprintf( '%s %s',
			__( "This form uses Akismet to reduce spam.", 'contact-form-7' ),
			wpcf7_link(
				'https://akismet.com/privacy/',
				__( "Learn how your data is processed.", 'contact-form-7' ),
				array(
					'target' => '_blank',
					'rel' => 'nofollow noopener',
				)
			)
		);

		$template .= "\n\n" . $privacy_notice;
	}

	return $template;
}
modules/akismet/service.php000064400000002770147510545420012037 0ustar00<?php

if ( ! class_exists( 'WPCF7_Service' ) ) {
	return;
}

class WPCF7_Akismet extends WPCF7_Service {

	private static $instance;


	public static function get_instance() {
		if ( empty( self::$instance ) ) {
			self::$instance = new self;
		}

		return self::$instance;
	}


	public function get_title() {
		return __( 'Akismet', 'contact-form-7' );
	}


	public function is_active() {
		return wpcf7_akismet_is_available();
	}


	public function get_categories() {
		return array( 'spam_protection' );
	}


	public function icon() {
	}


	public function link() {
		echo wpcf7_link(
			'https://akismet.com/',
			'akismet.com'
		);
	}


	public function display( $action = '' ) {
		echo sprintf(
			'<p>%s</p>',
			esc_html( __( "CAPTCHAs are designed to distinguish spambots from humans, and are therefore helpless against human spammers. In contrast to CAPTCHAs, Akismet checks form submissions against the global database of spam; this means Akismet is a comprehensive solution against spam. This is why we consider Akismet to be the centerpiece of the spam prevention strategy.", 'contact-form-7' ) )
		);

		echo sprintf(
			'<p><strong>%s</strong></p>',
			wpcf7_link(
				__( 'https://contactform7.com/spam-filtering-with-akismet/', 'contact-form-7' ),
				__( 'Spam filtering with Akismet', 'contact-form-7' )
			)
		);

		if ( $this->is_active() ) {
			echo sprintf(
				'<p class="dashicons-before dashicons-yes">%s</p>',
				esc_html( __( "Akismet is active on this site.", 'contact-form-7' ) )
			);
		}
	}

}
modules/count.php000064400000002713147510545420010067 0ustar00<?php
/**
** A base module for [count], Twitter-like character count
**/

/* form_tag handler */

add_action( 'wpcf7_init', 'wpcf7_add_form_tag_count', 10, 0 );

function wpcf7_add_form_tag_count() {
	wpcf7_add_form_tag( 'count',
		'wpcf7_count_form_tag_handler',
		array(
			'name-attr' => true,
			'zero-controls-container' => true,
			'not-for-mail' => true,
		)
	);
}

function wpcf7_count_form_tag_handler( $tag ) {
	if ( empty( $tag->name ) ) {
		return '';
	}

	$targets = wpcf7_scan_form_tags( array( 'name' => $tag->name ) );
	$maxlength = $minlength = null;

	while ( $targets ) {
		$target = array_shift( $targets );

		if ( 'count' != $target->type ) {
			$maxlength = $target->get_maxlength_option();
			$minlength = $target->get_minlength_option();
			break;
		}
	}

	if ( $maxlength and $minlength
	and $maxlength < $minlength ) {
		$maxlength = $minlength = null;
	}

	if ( $tag->has_option( 'down' ) ) {
		$value = (int) $maxlength;
		$class = 'wpcf7-character-count down';
	} else {
		$value = '0';
		$class = 'wpcf7-character-count up';
	}

	$atts = array();

	$atts['id'] = $tag->get_id_option();
	$atts['class'] = $tag->get_class_option( $class );
	$atts['data-target-name'] = $tag->name;
	$atts['data-starting-value'] = $value;
	$atts['data-current-value'] = $value;
	$atts['data-maximum-value'] = $maxlength;
	$atts['data-minimum-value'] = $minlength;

	$html = sprintf(
		'<span %1$s>%2$s</span>',
		wpcf7_format_atts( $atts ),
		$value
	);

	return $html;
}
load.php000064400000013344147510545420006210 0ustar00<?php

require_once WPCF7_PLUGIN_DIR . '/includes/l10n.php';
require_once WPCF7_PLUGIN_DIR . '/includes/capabilities.php';
require_once WPCF7_PLUGIN_DIR . '/includes/functions.php';
require_once WPCF7_PLUGIN_DIR . '/includes/formatting.php';
require_once WPCF7_PLUGIN_DIR . '/includes/pipe.php';
require_once WPCF7_PLUGIN_DIR . '/includes/pocket-holder.php';
require_once WPCF7_PLUGIN_DIR . '/includes/form-tag.php';
require_once WPCF7_PLUGIN_DIR . '/includes/form-tags-manager.php';
require_once WPCF7_PLUGIN_DIR . '/includes/shortcodes.php';
require_once WPCF7_PLUGIN_DIR . '/includes/swv/swv.php';
require_once WPCF7_PLUGIN_DIR . '/includes/contact-form-functions.php';
require_once WPCF7_PLUGIN_DIR . '/includes/contact-form-template.php';
require_once WPCF7_PLUGIN_DIR . '/includes/contact-form.php';
require_once WPCF7_PLUGIN_DIR . '/includes/mail.php';
require_once WPCF7_PLUGIN_DIR . '/includes/mail-tag.php';
require_once WPCF7_PLUGIN_DIR . '/includes/special-mail-tags.php';
require_once WPCF7_PLUGIN_DIR . '/includes/file.php';
require_once WPCF7_PLUGIN_DIR . '/includes/validation-functions.php';
require_once WPCF7_PLUGIN_DIR . '/includes/validation.php';
require_once WPCF7_PLUGIN_DIR . '/includes/submission.php';
require_once WPCF7_PLUGIN_DIR . '/includes/upgrade.php';
require_once WPCF7_PLUGIN_DIR . '/includes/integration.php';
require_once WPCF7_PLUGIN_DIR . '/includes/config-validator/validator.php';
require_once WPCF7_PLUGIN_DIR . '/includes/rest-api.php';
require_once WPCF7_PLUGIN_DIR . '/includes/block-editor/block-editor.php';
require_once WPCF7_PLUGIN_DIR . '/includes/html-formatter.php';

if ( is_admin() ) {
	require_once WPCF7_PLUGIN_DIR . '/admin/admin.php';
} else {
	require_once WPCF7_PLUGIN_DIR . '/includes/controller.php';
}


class WPCF7 {

	/**
	 * Loads modules from the modules directory.
	 */
	public static function load_modules() {
		self::load_module( 'acceptance' );
		self::load_module( 'akismet' );
		self::load_module( 'checkbox' );
		self::load_module( 'constant-contact' );
		self::load_module( 'count' );
		self::load_module( 'date' );
		self::load_module( 'disallowed-list' );
		self::load_module( 'doi-helper' );
		self::load_module( 'file' );
		self::load_module( 'flamingo' );
		self::load_module( 'hidden' );
		self::load_module( 'listo' );
		self::load_module( 'number' );
		self::load_module( 'quiz' );
		self::load_module( 'really-simple-captcha' );
		self::load_module( 'recaptcha' );
		self::load_module( 'reflection' );
		self::load_module( 'response' );
		self::load_module( 'select' );
		self::load_module( 'sendinblue' );
		self::load_module( 'stripe' );
		self::load_module( 'submit' );
		self::load_module( 'text' );
		self::load_module( 'textarea' );
	}


	/**
	 * Loads the specified module.
	 *
	 * @param string $mod Name of module.
	 * @return bool True on success, false on failure.
	 */
	protected static function load_module( $mod ) {
		return false
			|| wpcf7_include_module_file( $mod . '/' . $mod . '.php' )
			|| wpcf7_include_module_file( $mod . '.php' );
	}


	/**
	 * Retrieves a named entry from the option array of Contact Form 7.
	 *
	 * @param string $name Array item key.
	 * @param mixed $default_value Optional. Default value to return if the entry
	 *                             does not exist. Default false.
	 * @return mixed Array value tied to the $name key. If nothing found,
	 *               the $default_value value will be returned.
	 */
	public static function get_option( $name, $default_value = false ) {
		$option = get_option( 'wpcf7' );

		if ( false === $option ) {
			return $default_value;
		}

		if ( isset( $option[$name] ) ) {
			return $option[$name];
		} else {
			return $default_value;
		}
	}


	/**
	 * Update an entry value on the option array of Contact Form 7.
	 *
	 * @param string $name Array item key.
	 * @param mixed $value Option value.
	 */
	public static function update_option( $name, $value ) {
		$old_option = get_option( 'wpcf7' );
		$old_option = ( false === $old_option ) ? array() : (array) $old_option;

		update_option( 'wpcf7',
			array_merge( $old_option, array( $name => $value ) )
		);

		do_action( 'wpcf7_update_option', $name, $value, $old_option );
	}
}


add_action( 'plugins_loaded', 'wpcf7', 10, 0 );

/**
 * Loads modules and registers WordPress shortcodes.
 */
function wpcf7() {
	WPCF7::load_modules();

	add_shortcode( 'contact-form-7', 'wpcf7_contact_form_tag_func' );
	add_shortcode( 'contact-form', 'wpcf7_contact_form_tag_func' );
}


add_action( 'init', 'wpcf7_init', 10, 0 );

/**
 * Registers post types for contact forms.
 */
function wpcf7_init() {
	wpcf7_get_request_uri();
	wpcf7_register_post_types();

	do_action( 'wpcf7_init' );
}


add_action( 'admin_init', 'wpcf7_upgrade', 10, 0 );

/**
 * Upgrades option data when necessary.
 */
function wpcf7_upgrade() {
	$old_ver = WPCF7::get_option( 'version', '0' );
	$new_ver = WPCF7_VERSION;

	if ( $old_ver == $new_ver ) {
		return;
	}

	do_action( 'wpcf7_upgrade', $new_ver, $old_ver );

	WPCF7::update_option( 'version', $new_ver );
}


add_action( 'activate_' . WPCF7_PLUGIN_BASENAME, 'wpcf7_install', 10, 0 );

/**
 * Callback tied to plugin activation action hook. Attempts to create
 * initial user dataset.
 */
function wpcf7_install() {
	if ( $opt = get_option( 'wpcf7' ) ) {
		return;
	}

	wpcf7_register_post_types();
	wpcf7_upgrade();

	if ( get_posts( array( 'post_type' => 'wpcf7_contact_form' ) ) ) {
		return;
	}

	$contact_form = WPCF7_ContactForm::get_template(
		array(
			'title' =>
				/* translators: title of your first contact form. %d: number fixed to '1' */
				sprintf( __( 'Contact form %d', 'contact-form-7' ), 1 ),
		)
	);

	$contact_form->save();

	WPCF7::update_option( 'bulk_validate',
		array(
			'timestamp' => time(),
			'version' => WPCF7_VERSION,
			'count_valid' => 1,
			'count_invalid' => 0,
		)
	);
}
admin/edit-contact-form.php000064400000020402147510545420011671 0ustar00<?php

// don't load directly
if ( ! defined( 'ABSPATH' ) ) {
	die( '-1' );
}

$save_button = sprintf(
	'<input %s />',
	wpcf7_format_atts( array(
		'type' => 'submit',
		'class' => 'button-primary',
		'name' => 'wpcf7-save',
		'value' => __( 'Save', 'contact-form-7' ),
	) )
);

?>

<div class="wrap" id="wpcf7-contact-form-editor">

<?php

echo sprintf(
	'<h1 class="wp-heading-inline">%1$s</h1> %2$s',
	esc_html(
		$post->initial()
		? __( 'Add New Contact Form', 'contact-form-7' )
		: __( 'Edit Contact Form', 'contact-form-7' )
	),
	( $post->initial() || ! current_user_can( 'wpcf7_edit_contact_forms' ) )
	? ''
	: wpcf7_link(
		menu_page_url( 'wpcf7-new', false ),
		__( 'Add New', 'contact-form-7' ),
		array( 'class' => 'page-title-action' )
	)
);

?>

<hr class="wp-header-end">

<?php

do_action( 'wpcf7_admin_warnings',
	$post->initial() ? 'wpcf7-new' : 'wpcf7',
	wpcf7_current_action(),
	$post
);

do_action( 'wpcf7_admin_notices',
	$post->initial() ? 'wpcf7-new' : 'wpcf7',
	wpcf7_current_action(),
	$post
);

if ( $post ) :

	echo sprintf(
		'<form %s>',
		wpcf7_format_atts( array(
			'method' => 'post',
			'action' => esc_url( add_query_arg(
				array( 'post' => $post_id ),
				menu_page_url( 'wpcf7', false )
			) ),
			'id' => 'wpcf7-admin-form-element',
			'disabled' => ! current_user_can( 'wpcf7_edit_contact_form', $post_id ),
		) )
	);

	if ( current_user_can( 'wpcf7_edit_contact_form', $post_id ) ) {
		wp_nonce_field( 'wpcf7-save-contact-form_' . $post_id );
	}

?>
<input type="hidden" id="post_ID" name="post_ID" value="<?php echo (int) $post_id; ?>" />
<input type="hidden" id="wpcf7-locale" name="wpcf7-locale" value="<?php echo esc_attr( $post->locale() ); ?>" />
<input type="hidden" id="hiddenaction" name="action" value="save" />
<input type="hidden" id="active-tab" name="active-tab" value="<?php echo esc_attr( $_GET['active-tab'] ?? '' ); ?>" />

<div id="poststuff">
<div id="post-body" class="metabox-holder columns-2 wp-clearfix">
<div id="post-body-content">
<div id="titlediv">
<div id="titlewrap">
<?php

	echo sprintf(
		'<input %s />',
		wpcf7_format_atts( array(
			'type' => 'text',
			'name' => 'post_title',
			'value' => $post->initial() ? '' : $post->title(),
			'id' => 'title',
			'spellcheck' => 'true',
			'autocomplete' => 'off',
			'disabled' => ! current_user_can( 'wpcf7_edit_contact_form', $post_id ),
			'placeholder' => __( 'Enter title here', 'contact-form-7' ),
			'aria-label' => __( 'Enter title here', 'contact-form-7' ),
		) )
	);

?>
</div><!-- #titlewrap -->

<div class="inside">
<?php

	if ( ! $post->initial() ) {

		if ( $shortcode = $post->shortcode() ) {
			echo sprintf(
				'<p class="description"><label for="wpcf7-shortcode">%1$s</label> <span class="shortcode wp-ui-highlight"><input %2$s /></span></p>',
				esc_html( __( "Copy this shortcode and paste it into your post, page, or text widget content:", 'contact-form-7' ) ),
				wpcf7_format_atts( array(
					'type' => 'text',
					'id' => 'wpcf7-shortcode',
					'onfocus' => 'this.select();',
					'readonly' => true,
					'class' => 'large-text code',
					'value' => $shortcode,
				) )
			);
		}

		if ( $shortcode = $post->shortcode( array( 'use_old_format' => true ) ) ) {
			echo sprintf(
				'<p class="description"><label for="wpcf7-shortcode-old">%1$s</label> <span class="shortcode old"><input %2$s /></span></p>',
				esc_html( __( "You can also use this old-style shortcode:", 'contact-form-7' ) ),
				wpcf7_format_atts( array(
					'type' => 'text',
					'id' => 'wpcf7-shortcode-old',
					'onfocus' => 'this.select();',
					'readonly' => true,
					'class' => 'large-text code',
					'value' => $shortcode,
				) )
			);
		}

	}

?>
</div>

</div><!-- #titlediv -->
</div><!-- #post-body-content -->

<div id="postbox-container-1" class="postbox-container">

<?php

	if ( current_user_can( 'wpcf7_edit_contact_form', $post_id ) ) :

?>

<section id="submitdiv" class="postbox">
<h2><?php echo esc_html( __( 'Status', 'contact-form-7' ) ); ?></h2>
<div class="inside">
<div class="submitbox" id="submitpost">

<div id="minor-publishing-actions">

<div class="hidden">
	<input type="submit" class="button-primary" name="wpcf7-save" value="<?php echo esc_attr( __( 'Save', 'contact-form-7' ) ); ?>" />
</div>

<?php

		if ( ! $post->initial() ) {
			echo sprintf(
				'<input %s />',
				wpcf7_format_atts( array(
					'type' => 'submit',
					'name' => 'wpcf7-copy',
					'class' => 'copy button',
					'value' => __( 'Duplicate', 'contact-form-7' ),
				) )
			);
		}

?>

</div><!-- #minor-publishing-actions -->

<div id="misc-publishing-actions">

<?php

		do_action( 'wpcf7_admin_misc_pub_section', $post_id );

?>
</div><!-- #misc-publishing-actions -->

<div id="major-publishing-actions">

<?php

		if ( ! $post->initial() ) {
			echo sprintf(
				'<div id="delete-action"><input %s /></div>',
				wpcf7_format_atts( array(
					'type' => 'submit',
					'name' => 'wpcf7-delete',
					'class' => 'delete submitdelete',
					'value' => __( 'Delete', 'contact-form-7' ),
				) )
			);
		}

?>

<div id="publishing-action">
	<span class="spinner"></span>
	<?php echo $save_button; ?>
</div>
<div class="clear"></div>
</div><!-- #major-publishing-actions -->
</div><!-- #submitpost -->
</div>
</section><!-- #submitdiv -->

<?php

	endif;

?>

<section id="informationdiv" class="postbox">
<h2><?php echo esc_html( __( "Do you need help?", 'contact-form-7' ) ); ?></h2>
<div class="inside">
	<p><?php echo esc_html( __( "Here are some available options to help solve your problems.", 'contact-form-7' ) ); ?></p>
	<ol>
		<li><?php echo sprintf(
			/* translators: 1: FAQ, 2: Docs ("FAQ & Docs") */
			__( '%1$s and %2$s', 'contact-form-7' ),
			wpcf7_link(
				__( 'https://contactform7.com/faq/', 'contact-form-7' ),
				__( 'FAQ', 'contact-form-7' )
			),
			wpcf7_link(
				__( 'https://contactform7.com/docs/', 'contact-form-7' ),
				__( 'docs', 'contact-form-7' )
			)
		); ?></li>
		<li><?php echo wpcf7_link(
			__( 'https://wordpress.org/support/plugin/contact-form-7/', 'contact-form-7' ),
			__( 'Support forums', 'contact-form-7' )
		); ?></li>
		<li><?php echo wpcf7_link(
			__( 'https://contactform7.com/custom-development/', 'contact-form-7' ),
			__( 'Professional services', 'contact-form-7' )
		); ?></li>
	</ol>
</div>
</section><!-- #informationdiv -->

</div><!-- #postbox-container-1 -->

<div id="postbox-container-2" class="postbox-container">
<div id="contact-form-editor" data-active-tab="">

<?php

	$editor = new WPCF7_Editor( $post );
	$panels = array();

	if ( current_user_can( 'wpcf7_edit_contact_form', $post_id ) ) {
		$panels = array(
			'form-panel' => array(
				'title' => __( 'Form', 'contact-form-7' ),
				'callback' => 'wpcf7_editor_panel_form',
			),
			'mail-panel' => array(
				'title' => __( 'Mail', 'contact-form-7' ),
				'callback' => 'wpcf7_editor_panel_mail',
			),
			'messages-panel' => array(
				'title' => __( 'Messages', 'contact-form-7' ),
				'callback' => 'wpcf7_editor_panel_messages',
			),
		);

		$additional_settings = $post->prop( 'additional_settings' );

		if ( ! is_scalar( $additional_settings ) ) {
			$additional_settings = '';
		}

		$additional_settings = trim( $additional_settings );
		$additional_settings = explode( "\n", $additional_settings );
		$additional_settings = array_filter( $additional_settings );
		$additional_settings = count( $additional_settings );

		$panels['additional-settings-panel'] = array(
			'title' => $additional_settings
				? sprintf(
					/* translators: %d: number of additional settings */
					__( 'Additional Settings (%d)', 'contact-form-7' ),
					$additional_settings )
				: __( 'Additional Settings', 'contact-form-7' ),
			'callback' => 'wpcf7_editor_panel_additional_settings',
		);
	}

	$panels = apply_filters( 'wpcf7_editor_panels', $panels );

	foreach ( $panels as $id => $panel ) {
		$editor->add_panel( $id, $panel['title'], $panel['callback'] );
	}

	$editor->display();

?>
</div><!-- #contact-form-editor -->

<?php

	if ( current_user_can( 'wpcf7_edit_contact_form', $post_id ) ) {
		echo sprintf(
			'<p class="submit">%s</p>',
			$save_button
		);
	}

?>

</div><!-- #postbox-container-2 -->

</div><!-- #post-body -->
<br class="clear" />
</div><!-- #poststuff -->
</form>

<?php

endif;

?>

</div><!-- .wrap -->

<?php

$tag_generator = WPCF7_TagGenerator::get_instance();
$tag_generator->print_panels( $post );

do_action( 'wpcf7_admin_footer', $post );
admin/admin.php000064400000042250147510545420007447 0ustar00<?php

require_once WPCF7_PLUGIN_DIR . '/admin/includes/admin-functions.php';
require_once WPCF7_PLUGIN_DIR . '/admin/includes/help-tabs.php';
require_once WPCF7_PLUGIN_DIR . '/admin/includes/tag-generator.php';
require_once WPCF7_PLUGIN_DIR . '/admin/includes/welcome-panel.php';
require_once WPCF7_PLUGIN_DIR . '/admin/includes/config-validator.php';


add_action(
	'admin_init',
	static function () {
		do_action( 'wpcf7_admin_init' );
	},
	10, 0
);


add_action(
	'admin_menu',
	'wpcf7_admin_menu',
	9, 0
);

function wpcf7_admin_menu() {
	do_action( 'wpcf7_admin_menu' );

	add_menu_page(
		__( 'Contact Form 7', 'contact-form-7' ),
		__( 'Contact', 'contact-form-7' )
			. wpcf7_admin_menu_change_notice(),
		'wpcf7_read_contact_forms',
		'wpcf7',
		'wpcf7_admin_management_page',
		'dashicons-email',
		30
	);

	$edit = add_submenu_page( 'wpcf7',
		__( 'Edit Contact Form', 'contact-form-7' ),
		__( 'Contact Forms', 'contact-form-7' )
			. wpcf7_admin_menu_change_notice( 'wpcf7' ),
		'wpcf7_read_contact_forms',
		'wpcf7',
		'wpcf7_admin_management_page'
	);

	add_action( 'load-' . $edit, 'wpcf7_load_contact_form_admin', 10, 0 );

	$addnew = add_submenu_page( 'wpcf7',
		__( 'Add New Contact Form', 'contact-form-7' ),
		__( 'Add New', 'contact-form-7' )
			. wpcf7_admin_menu_change_notice( 'wpcf7-new' ),
		'wpcf7_edit_contact_forms',
		'wpcf7-new',
		'wpcf7_admin_add_new_page'
	);

	add_action( 'load-' . $addnew, 'wpcf7_load_contact_form_admin', 10, 0 );

	$integration = WPCF7_Integration::get_instance();

	if ( $integration->service_exists() ) {
		$integration = add_submenu_page( 'wpcf7',
			__( 'Integration with External API', 'contact-form-7' ),
			__( 'Integration', 'contact-form-7' )
				. wpcf7_admin_menu_change_notice( 'wpcf7-integration' ),
			'wpcf7_manage_integration',
			'wpcf7-integration',
			'wpcf7_admin_integration_page'
		);

		add_action( 'load-' . $integration, 'wpcf7_load_integration_page', 10, 0 );
	}
}


function wpcf7_admin_menu_change_notice( $menu_slug = '' ) {
	$counts = apply_filters( 'wpcf7_admin_menu_change_notice',
		array(
			'wpcf7' => 0,
			'wpcf7-new' => 0,
			'wpcf7-integration' => 0,
		)
	);

	if ( empty( $menu_slug ) ) {
		$count = absint( array_sum( $counts ) );
	} elseif ( isset( $counts[$menu_slug] ) ) {
		$count = absint( $counts[$menu_slug] );
	} else {
		$count = 0;
	}

	if ( $count ) {
		return sprintf(
			' <span class="update-plugins %1$d"><span class="plugin-count">%2$s</span></span>',
			$count,
			esc_html( number_format_i18n( $count ) )
		);
	}

	return '';
}


add_action(
	'admin_enqueue_scripts',
	'wpcf7_admin_enqueue_scripts',
	10, 1
);

function wpcf7_admin_enqueue_scripts( $hook_suffix ) {
	if ( false === strpos( $hook_suffix, 'wpcf7' ) ) {
		return;
	}

	wp_enqueue_style( 'contact-form-7-admin',
		wpcf7_plugin_url( 'admin/includes/css/styles.css' ),
		array(), WPCF7_VERSION, 'all'
	);

	if ( wpcf7_is_rtl() ) {
		wp_enqueue_style( 'contact-form-7-admin-rtl',
			wpcf7_plugin_url( 'admin/includes/css/styles-rtl.css' ),
			array(), WPCF7_VERSION, 'all'
		);
	}

	$assets = include(
		wpcf7_plugin_path( 'admin/includes/js/index.asset.php' )
	);

	$assets = wp_parse_args( $assets, array(
		'dependencies' => array(),
		'version' => WPCF7_VERSION,
	) );

	wp_enqueue_script( 'wpcf7-admin',
		wpcf7_plugin_url( 'admin/includes/js/index.js' ),
		$assets['dependencies'],
		$assets['version'],
		array( 'in_footer' => true )
	);

	wp_set_script_translations( 'wpcf7-admin', 'contact-form-7' );

	$wpcf7_obj = array(
		'apiSettings' => array(
			'root' => sanitize_url( rest_url( 'contact-form-7/v1' ) ),
			'namespace' => 'contact-form-7/v1',
		),
	);

	$post = wpcf7_get_current_contact_form();

	if ( $post ) {
		$wpcf7_obj = array_merge( $wpcf7_obj, array(
			'nonce' => array(
				'save' => wp_create_nonce(
					sprintf(
						'wpcf7-save-contact-form_%s',
						$post->initial() ? -1 : $post->id()
					)
				),
				'copy' => wp_create_nonce(
					sprintf(
						'wpcf7-copy-contact-form_%s',
						$post->initial() ? -1 : $post->id()
					)
				),
				'delete' => wp_create_nonce(
					sprintf(
						'wpcf7-delete-contact-form_%s',
						$post->initial() ? -1 : $post->id()
					)
				),
			),
			'configValidator' => array(
				'errors' => array(),
				'docUrl' => WPCF7_ConfigValidator::get_doc_link(),
			),
		) );

		if (
			current_user_can( 'wpcf7_edit_contact_form', $post->id() ) and
			wpcf7_validate_configuration()
		) {
			$config_validator = new WPCF7_ConfigValidator( $post );
			$config_validator->restore();

			$wpcf7_obj['configValidator'] = array_merge(
				$wpcf7_obj['configValidator'],
				array(
					'errors' => $config_validator->collect_error_messages(),
				)
			);
		}
	}

	wp_add_inline_script( 'wpcf7-admin',
		sprintf(
			'var wpcf7 = %s;',
			wp_json_encode( $wpcf7_obj, JSON_PRETTY_PRINT )
		),
		'before'
	);
}


add_filter(
	'set_screen_option_wpcf7_contact_forms_per_page',
	static function ( $result, $option, $value ) {
		$wpcf7_screens = array(
			'wpcf7_contact_forms_per_page',
		);

		if ( in_array( $option, $wpcf7_screens ) ) {
			$result = $value;
		}

		return $result;
	},
	10, 3
);


function wpcf7_load_contact_form_admin() {
	global $plugin_page;

	$action = wpcf7_current_action();

	do_action( 'wpcf7_admin_load',
		trim( $_GET['page'] ?? '' ),
		$action
	);

	if ( 'save' === $action ) {
		$id = $_POST['post_ID'] ?? '-1';

		check_admin_referer( 'wpcf7-save-contact-form_' . $id );

		if ( ! current_user_can( 'wpcf7_edit_contact_form', $id ) ) {
			wp_die(
				__( "You are not allowed to edit this item.", 'contact-form-7' )
			);
		}

		$contact_form = wpcf7_save_contact_form(
			array_merge(
				$_REQUEST,
				array(
					'id' => $id,
					'title' => $_POST['post_title'] ?? null,
					'locale' => $_POST['wpcf7-locale'] ?? null,
					'form' => $_POST['wpcf7-form'] ?? '',
					'mail' => $_POST['wpcf7-mail'] ?? array(),
					'mail_2' => $_POST['wpcf7-mail-2'] ?? array(),
					'messages' => $_POST['wpcf7-messages'] ?? array(),
					'additional_settings' => $_POST['wpcf7-additional-settings'] ?? '',
				)
			)
		);

		if ( $contact_form and wpcf7_validate_configuration() ) {
			$config_validator = new WPCF7_ConfigValidator( $contact_form );
			$config_validator->validate();
			$config_validator->save();
		}

		$query = array(
			'post' => $contact_form ? $contact_form->id() : 0,
			'active-tab' => wpcf7_canonicalize_name( $_POST['active-tab'] ?? '' ),
		);

		if ( ! $contact_form ) {
			$query['message'] = 'failed';
		} elseif ( -1 == $id ) {
			$query['message'] = 'created';
		} else {
			$query['message'] = 'saved';
		}

		$redirect_to = add_query_arg( $query, menu_page_url( 'wpcf7', false ) );
		wp_safe_redirect( $redirect_to );
		exit();
	}

	if ( 'copy' === $action ) {
		$id = absint( $_POST['post_ID'] ?? $_REQUEST['post'] ?? '' );

		check_admin_referer( 'wpcf7-copy-contact-form_' . $id );

		if ( ! current_user_can( 'wpcf7_edit_contact_form', $id ) ) {
			wp_die(
				__( "You are not allowed to edit this item.", 'contact-form-7' )
			);
		}

		$query = array();

		if ( $contact_form = wpcf7_contact_form( $id ) ) {
			$new_contact_form = $contact_form->copy();
			$new_contact_form->save();

			$query['post'] = $new_contact_form->id();
			$query['message'] = 'created';
		}

		$redirect_to = add_query_arg( $query, menu_page_url( 'wpcf7', false ) );

		wp_safe_redirect( $redirect_to );
		exit();
	}

	if ( 'delete' === $action ) {
		if ( ! empty( $_POST['post_ID'] ) ) {
			check_admin_referer( 'wpcf7-delete-contact-form_' . $_POST['post_ID'] );
		} elseif ( ! is_array( $_REQUEST['post'] ) ) {
			check_admin_referer( 'wpcf7-delete-contact-form_' . $_REQUEST['post'] );
		} else {
			check_admin_referer( 'bulk-posts' );
		}

		$posts = (array) ( $_POST['post_ID'] ?? $_REQUEST['post'] ?? array() );

		$deleted = 0;

		foreach ( $posts as $post ) {
			$post = WPCF7_ContactForm::get_instance( $post );

			if ( empty( $post ) ) {
				continue;
			}

			if ( ! current_user_can( 'wpcf7_delete_contact_form', $post->id() ) ) {
				wp_die(
					__( "You are not allowed to delete this item.", 'contact-form-7' )
				);
			}

			if ( ! $post->delete() ) {
				wp_die( __( "Error in deleting.", 'contact-form-7' ) );
			}

			$deleted += 1;
		}

		$query = array();

		if ( ! empty( $deleted ) ) {
			$query['message'] = 'deleted';
		}

		$redirect_to = add_query_arg( $query, menu_page_url( 'wpcf7', false ) );

		wp_safe_redirect( $redirect_to );
		exit();
	}

	$post = null;

	if ( 'wpcf7-new' === $plugin_page ) {
		$post = WPCF7_ContactForm::get_template( array(
			'locale' => $_GET['locale'] ?? null,
		) );
	} elseif ( ! empty( $_GET['post'] ) ) {
		$post = WPCF7_ContactForm::get_instance( $_GET['post'] );
	}

	$current_screen = get_current_screen();

	$help_tabs = new WPCF7_Help_Tabs( $current_screen );

	if ( $post
	and current_user_can( 'wpcf7_edit_contact_form', $post->id() ) ) {
		$help_tabs->set_help_tabs( 'edit' );
	} else {
		$help_tabs->set_help_tabs( 'list' );

		if ( ! class_exists( 'WPCF7_Contact_Form_List_Table' ) ) {
			require_once WPCF7_PLUGIN_DIR . '/admin/includes/class-contact-forms-list-table.php';
		}

		add_filter(
			'manage_' . $current_screen->id . '_columns',
			array( 'WPCF7_Contact_Form_List_Table', 'define_columns' ),
			10, 0
		);

		add_screen_option( 'per_page', array(
			'default' => 20,
			'option' => 'wpcf7_contact_forms_per_page',
		) );
	}
}


function wpcf7_admin_management_page() {
	if ( $post = wpcf7_get_current_contact_form() ) {
		$post_id = $post->initial() ? -1 : $post->id();

		require_once WPCF7_PLUGIN_DIR . '/admin/includes/editor.php';
		require_once WPCF7_PLUGIN_DIR . '/admin/edit-contact-form.php';
		return;
	}

	if ( 'validate' == wpcf7_current_action()
	and wpcf7_validate_configuration()
	and current_user_can( 'wpcf7_edit_contact_forms' ) ) {
		wpcf7_admin_bulk_validate_page();
		return;
	}

	$list_table = new WPCF7_Contact_Form_List_Table();
	$list_table->prepare_items();

?>
<div class="wrap" id="wpcf7-contact-form-list-table">

<h1 class="wp-heading-inline"><?php
	echo esc_html( __( 'Contact Forms', 'contact-form-7' ) );
?></h1>

<?php
	if ( current_user_can( 'wpcf7_edit_contact_forms' ) ) {
		echo wpcf7_link(
			menu_page_url( 'wpcf7-new', false ),
			__( 'Add New', 'contact-form-7' ),
			array( 'class' => 'page-title-action' )
		);
	}

	if ( ! empty( $_REQUEST['s'] ) ) {
		echo sprintf(
			'<span class="subtitle">'
			/* translators: %s: search keywords */
			. __( 'Search results for &#8220;%s&#8221;', 'contact-form-7' )
			. '</span>',
			esc_html( $_REQUEST['s'] )
		);
	}
?>

<hr class="wp-header-end">

<?php
	do_action( 'wpcf7_admin_warnings',
		'wpcf7', wpcf7_current_action(), null
	);

	wpcf7_welcome_panel();

	do_action( 'wpcf7_admin_notices',
		'wpcf7', wpcf7_current_action(), null
	);
?>

<form method="get" action="">
	<input type="hidden" name="page" value="<?php echo esc_attr( $_REQUEST['page'] ); ?>" />
	<?php $list_table->search_box( __( 'Search Contact Forms', 'contact-form-7' ), 'wpcf7-contact' ); ?>
	<?php $list_table->display(); ?>
</form>

</div>
<?php
}


function wpcf7_admin_add_new_page() {
	$post = wpcf7_get_current_contact_form();

	if ( ! $post ) {
		$post = WPCF7_ContactForm::get_template();
	}

	$post_id = -1;

	require_once WPCF7_PLUGIN_DIR . '/admin/includes/editor.php';
	require_once WPCF7_PLUGIN_DIR . '/admin/edit-contact-form.php';
}


function wpcf7_load_integration_page() {
	do_action( 'wpcf7_admin_load',
		trim( $_GET['page'] ?? '' ),
		wpcf7_current_action()
	);

	$integration = WPCF7_Integration::get_instance();

	if ( isset( $_REQUEST['service'] )
	and $integration->service_exists( $_REQUEST['service'] ) ) {
		$service = $integration->get_service( $_REQUEST['service'] );
		$service->load( wpcf7_current_action() );
	}

	$help_tabs = new WPCF7_Help_Tabs( get_current_screen() );
	$help_tabs->set_help_tabs( 'integration' );
}


function wpcf7_admin_integration_page() {
	$integration = WPCF7_Integration::get_instance();

	$service = isset( $_REQUEST['service'] )
		? $integration->get_service( $_REQUEST['service'] )
		: null;

?>
<div class="wrap" id="wpcf7-integration">

<h1><?php echo esc_html( __( 'Integration with External API', 'contact-form-7' ) ); ?></h1>

<p><?php
	echo sprintf(
		/* translators: %s: link labeled 'Integration with external APIs' */
		esc_html( __( "You can expand the possibilities of your contact forms by integrating them with external services. For details, see %s.", 'contact-form-7' ) ),
		wpcf7_link(
			__( 'https://contactform7.com/integration-with-external-apis/', 'contact-form-7' ),
			__( 'Integration with external APIs', 'contact-form-7' )
		)
	);
?></p>

<?php
	do_action( 'wpcf7_admin_warnings',
		'wpcf7-integration', wpcf7_current_action(), $service
	);

	do_action( 'wpcf7_admin_notices',
		'wpcf7-integration', wpcf7_current_action(), $service
	);

	if ( $service ) {
		$message = $_REQUEST['message'] ?? '';
		$service->admin_notice( $message );

		$integration->list_services( array(
			'include' => $_REQUEST['service'],
		) );
	} else {
		$integration->list_services();
	}
?>

</div>
<?php
}


add_action( 'wpcf7_admin_notices', 'wpcf7_admin_updated_message', 10, 3 );

function wpcf7_admin_updated_message( $page, $action, $object ) {
	if ( ! in_array( $page, array( 'wpcf7', 'wpcf7-new' ) ) ) {
		return;
	}

	if ( empty( $_REQUEST['message'] ) ) {
		return;
	}

	if ( 'created' === $_REQUEST['message'] ) {
		$message = __( "Contact form created.", 'contact-form-7' );
	} elseif ( 'saved' === $_REQUEST['message'] ) {
		$message = __( "Contact form saved.", 'contact-form-7' );
	} elseif ( 'deleted' === $_REQUEST['message'] ) {
		$message = __( "Contact form deleted.", 'contact-form-7' );
	}

	if ( ! empty( $message ) ) {
		wp_admin_notice( esc_html( $message ), 'type=success' );
	}

	if ( 'failed' === $_REQUEST['message'] ) {
		$message =
			__( "There was an error saving the contact form.", 'contact-form-7' );

		wp_admin_notice( esc_html( $message ), 'type=error' );
	}

	if ( 'validated' === $_REQUEST['message'] ) {
		$bulk_validate = WPCF7::get_option( 'bulk_validate', array() );
		$count_invalid = absint( $bulk_validate['count_invalid'] ?? 0 );

		if ( $count_invalid ) {
			$message = sprintf(
				_n(
					/* translators: %s: number of contact forms */
					"Configuration validation completed. %s invalid contact form was found.",
					"Configuration validation completed. %s invalid contact forms were found.",
					$count_invalid, 'contact-form-7'
				),
				number_format_i18n( $count_invalid )
			);

			wp_admin_notice( esc_html( $message ), 'type=warning' );
		} else {
			$message = __( "Configuration validation completed. No invalid contact form was found.", 'contact-form-7' );

			wp_admin_notice( esc_html( $message ), 'type=success' );
		}
	}
}


add_filter( 'plugin_action_links', 'wpcf7_plugin_action_links', 10, 2 );

function wpcf7_plugin_action_links( $links, $file ) {
	if ( $file != WPCF7_PLUGIN_BASENAME ) {
		return $links;
	}

	if ( ! current_user_can( 'wpcf7_read_contact_forms' ) ) {
		return $links;
	}

	$settings_link = wpcf7_link(
		menu_page_url( 'wpcf7', false ),
		__( 'Settings', 'contact-form-7' )
	);

	array_unshift( $links, $settings_link );

	return $links;
}


add_action( 'wpcf7_admin_warnings', 'wpcf7_old_wp_version_error', 10, 3 );

function wpcf7_old_wp_version_error( $page, $action, $object ) {
	$wp_version = get_bloginfo( 'version' );

	if ( version_compare( $wp_version, WPCF7_REQUIRED_WP_VERSION, '<' ) ) {
		$message = sprintf(
			/* translators: 1: version of Contact Form 7, 2: version of WordPress, 3: URL */
			__( '<strong>Contact Form 7 %1$s requires WordPress %2$s or higher.</strong> Please <a href="%3$s">update WordPress</a> first.', 'contact-form-7' ),
			WPCF7_VERSION,
			WPCF7_REQUIRED_WP_VERSION,
			admin_url( 'update-core.php' )
		);

		wp_admin_notice( $message, 'type=warning' );
	}
}


add_action( 'wpcf7_admin_warnings', 'wpcf7_not_allowed_to_edit', 10, 3 );

function wpcf7_not_allowed_to_edit( $page, $action, $object ) {
	if ( $object instanceof WPCF7_ContactForm ) {
		$contact_form = $object;
	} else {
		return;
	}

	if ( ! current_user_can( 'wpcf7_edit_contact_form', $contact_form->id() ) ) {
		$message = __( "You are not allowed to edit this contact form.", 'contact-form-7' );

		wp_admin_notice( esc_html( $message ), 'type=warning' );
	}
}


add_action( 'wpcf7_admin_warnings', 'wpcf7_outdated_php_warning', 10, 3 );

function wpcf7_outdated_php_warning( $page, $action, $object ) {
	if ( version_compare( PHP_VERSION, '7.4', '<' ) ) {
		$message = __( "The next major release of Contact Form 7 will discontinue support for outdated PHP versions. If you don't upgrade PHP, you will not be able to upgrade the plugin.", 'contact-form-7' );

		wp_admin_notice( esc_html( $message ), 'type=warning' );
	}
}


add_action( 'wpcf7_admin_warnings', 'wpcf7_ctct_deprecated_warning', 10, 3 );

function wpcf7_ctct_deprecated_warning( $page, $action, $object ) {
	$service = WPCF7_ConstantContact::get_instance();

	if ( $service->is_active() ) {
		$message = wp_kses(
			__( 'The Constant Contact integration is deprecated and planned to be <a href="https://contactform7.com/2025/01/08/complete-removal-of-constant-contact-integration/">completely removed</a> anytime soon. Contact Form 7 recommends <a href="https://contactform7.com/sendinblue-integration/">Brevo</a> as an alternative.', 'contact-form-7' ),
			array(
				'a' => array( 'href' => true ),
				'strong' => array(),
			),
			array( 'http', 'https' )
		);

		wp_admin_notice( $message, 'type=warning' );
	}
}
admin/includes/tag-generator.php000064400000030447147510545420012731 0ustar00<?php

/**
 * The base class for form-tag generators management.
 */
class WPCF7_TagGenerator {

	private static $instance;

	private $panels = array();

	private function __construct() {}


	/**
	 * Returns the singleton instance of this class.
	 */
	public static function get_instance() {
		if ( empty( self::$instance ) ) {
			self::$instance = new self;
		}

		return self::$instance;
	}


	/**
	 * Adds a form-tag generator instance.
	 */
	public function add( $id, $title, $callback, $options = '' ) {
		$id = trim( $id );

		if (
			'' === $id or
			! wpcf7_is_name( $id ) or
			! is_callable( $callback )
		) {
			return false;
		}

		$options = wp_parse_args( $options, array(
			'version' => '1',
		) );

		$this->panels[$id] = array(
			'title' => $title,
			'content' => 'tag-generator-panel-' . $id,
			'options' => $options,
			'callback' => $callback,
		);

		if ( version_compare( $options['version'], '2', '<' ) ) {
			$message = sprintf(
				/* translators: 1: version, 2: tag generator title */
				__( 'Use of tag generator instances older than version 2 is deprecated. Version %1$s instance (%2$s) detected.', 'contact-form-7' ),
				$options['version'],
				$title
			);

			wp_trigger_error( __METHOD__, $message, E_USER_DEPRECATED );
		}

		return true;
	}


	/**
	 * Renders form-tag generator calling buttons.
	 */
	public function print_buttons() {
		echo '<span id="tag-generator-list" class="hide-if-no-js">';

		foreach ( (array) $this->panels as $panel ) {
			echo sprintf(
				'<button %1$s>%2$s</button>',
				wpcf7_format_atts( array(
					'type' => 'button',
					'data-taggen' => 'open-dialog',
					'data-target' => $panel['content'],
					'title' => sprintf(
						/* translators: %s: title of form-tag */
						__( 'Form-tag Generator: %s', 'contact-form-7' ),
						$panel['title']
					),
				) ),
				esc_html( $panel['title'] )
			);
		}

		echo '</span>';
	}


	/**
	 * Renders form-tag generator dialog panels (hidden until called).
	 */
	public function print_panels( WPCF7_ContactForm $contact_form ) {
		foreach ( (array) $this->panels as $id => $panel ) {
			$callback = $panel['callback'];

			$options = array_merge( $panel['options'], array(
				'id' => $id,
				'title' => $panel['title'],
				'content' => $panel['content'],
			) );

			if ( is_callable( $callback ) ) {
				echo "\n";
				echo sprintf(
					'<dialog id="%s" class="tag-generator-dialog">',
					esc_attr( $options['content'] )
				);
				echo "\n";
				echo sprintf(
					'<button %1$s>%2$s</button>',
					wpcf7_format_atts( array(
						'class' => 'close-button',
						'title' => __( 'Close this dialog box', 'contact-form-7' ),
						'data-taggen' => 'close-dialog',
					) ),
					esc_html( __( 'Close', 'contact-form-7' ) )
				);
				echo "\n";
				echo sprintf(
					'<form %s>',
					wpcf7_format_atts( array(
						'method' => 'dialog',
						'class' => 'tag-generator-panel',
						'data-id' => $options['id'],
						'data-version' => $options['version'],
					) )
				);
				echo "\n";
				call_user_func( $callback, $contact_form, $options );
				echo "\n";
				echo '</form>';
				echo "\n";
				echo '</dialog>';
				echo "\n\n";
			}
		}
	}

}


/**
 * Class helps to implement a form-tag generator content.
 */
class WPCF7_TagGeneratorGenerator {

	private $key = '';


	/**
	 * The constructor.
	 */
	public function __construct( $key ) {
		$this->key = $key;
	}


	/**
	 * Returns a unique reference ID.
	 */
	public function ref( $suffix = '' ) {
		$ref = sprintf( '%s-%s', $this->key, $suffix );
		$ref = strtolower( $ref );
		$ref = preg_replace( '/[^0-9a-z-]/', '', $ref );
		$ref = preg_replace( '/[-]+/', '-', $ref );
		$ref = trim( $ref, '-' );
		return $ref;
	}


	/**
	 * Calls one of the template methods.
	 */
	public function print( $part, $options = '' ) {
		if ( is_callable( array( $this, $part ) ) ) {
			call_user_func( array( $this, $part ), $options );
		}
	}


	/**
	 * Template method for field type field.
	 */
	private function field_type( $options = '' ) {
		$options = wp_parse_args( $options, array(
			'with_required' => false,
			'select_options' => array(),
		) );

?>
<fieldset>
	<legend id="<?php echo esc_attr( $this->ref( 'type-legend' ) ); ?>"><?php
		echo esc_html( __( 'Field type', 'contact-form-7' ) );
	?></legend>

	<select data-tag-part="basetype" aria-labelledby="<?php echo esc_attr( $this->ref( 'type-legend' ) ); ?>"><?php
		foreach ( (array) $options['select_options'] as $basetype => $title ) {
			echo sprintf(
				'<option %1$s>%2$s</option>',
				wpcf7_format_atts( array(
					'value' => $basetype,
				) ),
				esc_html( $title )
			);
		}
	?></select>

	<?php if ( $options['with_required'] ) { ?>
	<br />
	<label>
		<input type="checkbox" data-tag-part="type-suffix" value="*" />
		<?php echo esc_html( __( "This is a required field.", 'contact-form-7' ) ); ?>
	</label>
	<?php } ?>
</fieldset>
<?php
	}


	/**
	 * Template method for field name field.
	 */
	private function field_name( $options = '' ) {
		$options = wp_parse_args( $options, array(
			'ask_if' => '',
		) );

?>
<fieldset>
	<legend id="<?php echo esc_attr( $this->ref( 'name-legend' ) ); ?>"><?php
		echo esc_html( __( 'Field name', 'contact-form-7' ) );
	?></legend>
	<input type="text" data-tag-part="name" pattern="[A-Za-z][A-Za-z0-9_\-]*" aria-labelledby="<?php echo esc_attr( $this->ref( 'name-legend' ) ); ?>" />

<?php
		$tag_option = $label = '';

		if ( 'author_name' === $options['ask_if'] ) {
			$tag_option = 'autocomplete:name';

			if ( wpcf7_akismet_is_available() ) {
				$tag_option .= ' akismet:author';
			}

			$label = __( "This field expects the submitter name.", 'contact-form-7' );
		} elseif ( 'author_email' === $options['ask_if'] ) {
			$tag_option = 'autocomplete:email';

			if ( wpcf7_akismet_is_available() ) {
				$tag_option .= ' akismet:author_email';
			}

			$label = __( "This field expects the submitter email.", 'contact-form-7' );
		} elseif ( 'author_url' === $options['ask_if'] ) {
			$tag_option = 'autocomplete:url';

			if ( wpcf7_akismet_is_available() ) {
				$tag_option .= ' akismet:author_url';
			}

			$label = __( "This field expects the submitter URL.", 'contact-form-7' );
		} elseif ( 'author_tel' === $options['ask_if'] ) {
			$tag_option = 'autocomplete:tel';
			$label = __( "This field expects the submitter telephone number.", 'contact-form-7' );
		}

		if ( $tag_option ) {
?>
	<br />
	<label>
		<input type="checkbox" data-tag-part="option" data-tag-option="<?php echo esc_attr( $tag_option ); ?>" />
		<?php echo esc_html( $label ); ?>
	</label>
<?php
		}
?>
</fieldset>
<?php
	}


	/**
	 * Template method for ID attribute option field.
	 */
	private function id_attr( $options = '' ) {
?>
<fieldset>
	<legend id="<?php echo esc_attr( $this->ref( 'id-legend' ) ); ?>"><?php
		echo esc_html( __( 'ID attribute', 'contact-form-7' ) );
	?></legend>
	<input type="text" data-tag-part="option" data-tag-option="id:" pattern="[A-Za-z][A-Za-z0-9_\-]*" aria-labelledby="<?php echo esc_attr( $this->ref( 'id-legend' ) ); ?>" />
</fieldset>
<?php
	}


	/**
	 * Template method for class attribute option field.
	 */
	private function class_attr( $options = '' ) {
?>
<fieldset>
	<legend id="<?php echo esc_attr( $this->ref( 'class-legend' ) ); ?>"><?php
		echo esc_html( __( 'Class attribute', 'contact-form-7' ) );
	?></legend>
	<input type="text" data-tag-part="option" data-tag-option="class:" pattern="[A-Za-z0-9_\-\s]*" aria-labelledby="<?php echo esc_attr( $this->ref( 'class-legend' ) ); ?>" />
</fieldset>
<?php
	}


	/**
	 * Template method for min/max options.
	 */
	private function min_max( $options = '' ) {
		$options = wp_parse_args( $options, array(
			'type' => 'number',
			'title' => __( 'Length', 'contact-form-7' ),
			'min_option' => 'minlength:',
			'max_option' => 'maxlength:',
			'accept_minus' => false,
		) );

?>
<fieldset>
	<legend><?php
		echo esc_html( $options['title'] );
	?></legend>
	<label><?php
		echo esc_html( __( 'Min', 'contact-form-7' ) ) . "\n";

		echo sprintf(
			'<input %s />',
			wpcf7_format_atts( array(
				'type' => $options['type'],
				'data-tag-part' => 'option',
				'data-tag-option' => $options['min_option'],
				'min' => $options['accept_minus'] ? null : 0,
			) )
		);
	?></label>
	&#8660;
	<label><?php
		echo esc_html( __( 'Max', 'contact-form-7' ) ) . "\n";

		echo sprintf(
			'<input %s />',
			wpcf7_format_atts( array(
				'type' => $options['type'],
				'data-tag-part' => 'option',
				'data-tag-option' => $options['max_option'],
				'min' => $options['accept_minus'] ? null : 0,
			) )
		);
	?></label>
</fieldset>
<?php
	}


	/**
	 * Template method for default value field.
	 */
	private function default_value( $options = '' ) {
		$options = wp_parse_args( $options, array(
			'type' => 'text',
			'title' => __( 'Default value', 'contact-form-7' ),
			'with_placeholder' => false,
			'use_content' => false,
		) );

?>
<fieldset>
	<legend id="<?php echo esc_attr( $this->ref( 'value-legend' ) ); ?>"><?php
		echo esc_html( $options['title'] );
	?></legend>
	<?php
		echo sprintf(
			'<input %s />',
			wpcf7_format_atts( array(
				'type' => $options['type'],
				'data-tag-part' => $options['use_content'] ? 'content' : 'value',
				'aria-labelledby' => $this->ref( 'value-legend' ),
			) )
		);
	?>

	<?php if ( $options['with_placeholder'] ) { ?>
	<br />
	<label>
		<input type="checkbox" data-tag-part="option" data-tag-option="placeholder" /> <?php echo esc_html( __( "Use this text as the placeholder.", 'contact-form-7' ) ); ?>
	</label>
	<?php } ?>

</fieldset>
<?php
	}


	/**
	 * Template method for selectable values useful for checkboxes or a menu.
	 */
	private function selectable_values( $options = '' ) {
		$options = wp_parse_args( $options, array(
			'first_as_label' => false,
			'use_label_element' => false,
		) );

?>
<fieldset>
	<legend id="<?php echo esc_attr( $this->ref( 'selectable-values-legend' ) ); ?>"><?php
		echo esc_html( __( 'Selectable values', 'contact-form-7' ) );
	?></legend>
	<?php
		echo sprintf(
			'<span %1$s>%2$s</span>',
			wpcf7_format_atts( array(
				'id' => $this->ref( 'selectable-values-description' ),
			) ),
			esc_html( __( "One item per line.", 'contact-form-7' ) )
		);
	?>
	<br />
	<?php
		echo sprintf(
			'<textarea %1$s>%2$s</textarea>',
			wpcf7_format_atts( array(
				'required' => true,
				'data-tag-part' => 'value',
				'aria-labelledby' => $this->ref( 'selectable-values-legend' ),
				'aria-describedby' => $this->ref( 'selectable-values-description' ),
			) ),
			esc_html( __( "Option 1\nOption 2\nOption 3", 'contact-form-7' ) )
		);
	?>

	<?php if ( $options['first_as_label'] ) { ?>
	<br />
	<?php
		echo sprintf(
			'<label><input %1$s /> %2$s</label>',
			wpcf7_format_atts( array(
				'type' => 'checkbox',
				'checked' => 'checked' === $options['first_as_label'],
				'data-tag-part' => 'option',
				'data-tag-option' => 'first_as_label',
			) ),
			esc_html( __( "Use the first item as a label.", 'contact-form-7' ) )
		);
	?>
	<?php } ?>

	<?php if ( $options['use_label_element'] ) { ?>
	<br />
	<?php
		echo sprintf(
			'<label><input %1$s /> %2$s</label>',
			wpcf7_format_atts( array(
				'type' => 'checkbox',
				'checked' => 'checked' === $options['use_label_element'],
				'data-tag-part' => 'option',
				'data-tag-option' => 'use_label_element',
			) ),
			esc_html( __( "Wrap each item with a label element.", 'contact-form-7' ) )
		);
	?>
	<?php } ?>

</fieldset>
<?php
	}


	/**
	 * Template method for insert-box content including the result form-tag.
	 */
	private function insert_box_content( $options = '' ) {
?>
<div class="flex-container">
	<?php
		echo sprintf(
			'<input %s />',
			wpcf7_format_atts( array(
				'type' => 'text',
				'class' => 'code',
				'readonly' => true,
				'onfocus' => 'this.select();',
				'data-tag-part' => 'tag',
				'aria-label' => __( "The form-tag to be inserted into the form template", 'contact-form-7' ),
			) )
		);
	?>
	<button type="button" class="button button-primary" data-taggen="insert-tag"><?php echo esc_html( __( 'Insert Tag', 'contact-form-7' ) ); ?></button>
</div>
<?php
	}


	/**
	 * Template method for a tip message about mail-tag.
	 */
	private function mail_tag_tip( $options = '' ) {
		$tip = sprintf(
			/* translators: %s: mail-tag corresponding to the form-tag */
			esc_html( __( 'To use the user input in the email, insert the corresponding mail-tag %s into the email template.', 'contact-form-7' ) ),
			'<strong data-tag-part="mail-tag"></strong>'
		);

?>
<p class="mail-tag-tip"><?php echo $tip; ?></p>
<?php
	}

}
admin/includes/class-contact-forms-list-table.php000064400000013323147510545420016104 0ustar00<?php

if ( ! class_exists( 'WP_List_Table' ) ) {
	require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
}

class WPCF7_Contact_Form_List_Table extends WP_List_Table {

	public static function define_columns() {
		$columns = array(
			'cb' => '<input type="checkbox" />',
			'title' => __( 'Title', 'contact-form-7' ),
			'shortcode' => __( 'Shortcode', 'contact-form-7' ),
			'author' => __( 'Author', 'contact-form-7' ),
			'date' => __( 'Date', 'contact-form-7' ),
		);

		return $columns;
	}

	public function __construct() {
		parent::__construct( array(
			'singular' => 'post',
			'plural' => 'posts',
			'ajax' => false,
		) );
	}

	public function prepare_items() {
		$current_screen = get_current_screen();
		$per_page = $this->get_items_per_page( 'wpcf7_contact_forms_per_page' );

		$args = array(
			'posts_per_page' => $per_page,
			'orderby' => 'title',
			'order' => 'ASC',
			'offset' => ( $this->get_pagenum() - 1 ) * $per_page,
		);

		if ( ! empty( $_REQUEST['s'] ) ) {
			$args['s'] = $_REQUEST['s'];
		}

		if ( ! empty( $_REQUEST['orderby'] ) ) {
			if ( 'title' == $_REQUEST['orderby'] ) {
				$args['orderby'] = 'title';
			} elseif ( 'author' == $_REQUEST['orderby'] ) {
				$args['orderby'] = 'author';
			} elseif ( 'date' == $_REQUEST['orderby'] ) {
				$args['orderby'] = 'date';
			}
		}

		if ( ! empty( $_REQUEST['order'] ) ) {
			if ( 'asc' == strtolower( $_REQUEST['order'] ) ) {
				$args['order'] = 'ASC';
			} elseif ( 'desc' == strtolower( $_REQUEST['order'] ) ) {
				$args['order'] = 'DESC';
			}
		}

		$this->items = WPCF7_ContactForm::find( $args );

		$total_items = WPCF7_ContactForm::count();
		$total_pages = ceil( $total_items / $per_page );

		$this->set_pagination_args( array(
			'total_items' => $total_items,
			'total_pages' => $total_pages,
			'per_page' => $per_page,
		) );
	}

	public function get_columns() {
		return get_column_headers( get_current_screen() );
	}

	protected function get_sortable_columns() {
		$columns = array(
			'title' => array( 'title', true ),
			'author' => array( 'author', false ),
			'date' => array( 'date', false ),
		);

		return $columns;
	}

	protected function get_bulk_actions() {
		$actions = array(
			'delete' => __( 'Delete', 'contact-form-7' ),
		);

		return $actions;
	}

	protected function column_default( $item, $column_name ) {
		return '';
	}

	public function column_cb( $item ) {
		return sprintf(
			'<input type="checkbox" name="%1$s[]" value="%2$s" />',
			$this->_args['singular'],
			$item->id()
		);
	}

	public function column_title( $item ) {
		$edit_link = add_query_arg(
			array(
				'post' => absint( $item->id() ),
				'action' => 'edit',
			),
			menu_page_url( 'wpcf7', false )
		);

		$output = sprintf(
			'<a class="row-title" href="%1$s" aria-label="%2$s">%3$s</a>',
			esc_url( $edit_link ),
			esc_attr( sprintf(
				/* translators: %s: title of contact form */
				__( 'Edit &#8220;%s&#8221;', 'contact-form-7' ),
				$item->title()
			) ),
			esc_html( $item->title() )
		);

		$output = sprintf( '<strong>%s</strong>', $output );

		if ( wpcf7_validate_configuration()
		and current_user_can( 'wpcf7_edit_contact_form', $item->id() ) ) {
			$config_validator = new WPCF7_ConfigValidator( $item );
			$config_validator->restore();

			if ( $count_errors = $config_validator->count_errors() ) {
				$error_notice = sprintf(
					_n(
						/* translators: %s: number of errors detected */
						'%s configuration error detected',
						'%s configuration errors detected',
						$count_errors, 'contact-form-7' ),
					number_format_i18n( $count_errors )
				);

				$output .= sprintf(
					'<div class="config-error"><span class="icon-in-circle" aria-hidden="true">!</span> %s</div>',
					$error_notice
				);
			}
		}

		return $output;
	}

	protected function handle_row_actions( $item, $column_name, $primary ) {
		if ( $column_name !== $primary ) {
			return '';
		}

		$edit_link = add_query_arg(
			array(
				'post' => absint( $item->id() ),
				'action' => 'edit',
			),
			menu_page_url( 'wpcf7', false )
		);

		$actions = array(
			'edit' => wpcf7_link( $edit_link, __( 'Edit', 'contact-form-7' ) ),
		);

		if ( current_user_can( 'wpcf7_edit_contact_form', $item->id() ) ) {
			$copy_link = add_query_arg(
				array(
					'post' => absint( $item->id() ),
					'action' => 'copy',
				),
				menu_page_url( 'wpcf7', false )
			);

			$copy_link = wp_nonce_url(
				$copy_link,
				'wpcf7-copy-contact-form_' . absint( $item->id() )
			);

			$actions = array_merge( $actions, array(
				'copy' => wpcf7_link( $copy_link, __( 'Duplicate', 'contact-form-7' ) ),
			) );
		}

		return $this->row_actions( $actions );
	}

	public function column_author( $item ) {
		$post = get_post( $item->id() );

		if ( ! $post ) {
			return;
		}

		$author = get_userdata( $post->post_author );

		if ( false === $author ) {
			return;
		}

		return esc_html( $author->display_name );
	}

	public function column_shortcode( $item ) {
		$shortcodes = array( $item->shortcode() );

		$output = '';

		foreach ( $shortcodes as $shortcode ) {
			$output .= "\n" . '<span class="shortcode"><input type="text"'
				. ' onfocus="this.select();" readonly="readonly"'
				. ' value="' . esc_attr( $shortcode ) . '"'
				. ' class="large-text code" /></span>';
		}

		return trim( $output );
	}

	public function column_date( $item ) {
		$datetime = get_post_datetime( $item->id() );

		if ( false === $datetime ) {
			return '';
		}

		$t_time = sprintf(
			/* translators: 1: date, 2: time */
			__( '%1$s at %2$s', 'contact-form-7' ),
			/* translators: date format, see https://www.php.net/date */
			$datetime->format( __( 'Y/m/d', 'contact-form-7' ) ),
			/* translators: time format, see https://www.php.net/date */
			$datetime->format( __( 'g:i a', 'contact-form-7' ) )
		);

		return $t_time;
	}
}
admin/includes/welcome-panel.php000064400000020673147510545420012722 0ustar00<?php

abstract class WPCF7_WelcomePanelColumn {

	abstract protected function icon();
	abstract protected function title();
	abstract protected function content();

	public function print_content() {
		$icon = sprintf(
			'<span class="dashicons dashicons-%s" aria-hidden="true"></span>',
			esc_attr( $this->icon() )
		);

		$title = sprintf(
			'<h3>%1$s %2$s</h3>',
			$icon,
			$this->title()
		);

		$content = $this->content();

		if ( is_array( $content ) ) {
			$content = implode( "\n\n", $content );
		}

		$content = wp_kses_post( $content );
		$content = wptexturize( $content );
		$content = convert_chars( $content );
		$content = wpautop( $content );

		echo "\n";
		echo '<div class="welcome-panel-column">';
		echo $title;
		echo $content;
		echo '</div>';
	}
}


class WPCF7_WelcomePanelColumn_AntiSpam extends WPCF7_WelcomePanelColumn {

	protected function icon() {
		return 'shield';
	}

	protected function title() {
		return esc_html(
			__( "Getting spammed? You have protection.", 'contact-form-7' )
		);
	}

	protected function content() {
		return array(
			esc_html( __( "Spammers target everything; your contact forms are not an exception. Before you get spammed, protect your contact forms with the powerful anti-spam features Contact Form 7 provides.", 'contact-form-7' ) ),
			sprintf(
				/* translators: links labeled 1: 'Akismet', 2: 'reCAPTCHA', 3: 'disallowed list' */
				esc_html( __( 'Contact Form 7 supports spam-filtering with %1$s. Intelligent %2$s blocks annoying spambots. Plus, using %3$s, you can block messages containing specified keywords or those sent from specified IP addresses.', 'contact-form-7' ) ),
				wpcf7_link(
					__( 'https://contactform7.com/spam-filtering-with-akismet/', 'contact-form-7' ),
					__( 'Akismet', 'contact-form-7' )
				),
				wpcf7_link(
					__( 'https://contactform7.com/recaptcha/', 'contact-form-7' ),
					__( 'reCAPTCHA', 'contact-form-7' )
				),
				wpcf7_link(
					__( 'https://contactform7.com/comment-blacklist/', 'contact-form-7' ),
					__( 'disallowed list', 'contact-form-7' )
				)
			),
		);
	}
}


class WPCF7_WelcomePanelColumn_Donation extends WPCF7_WelcomePanelColumn {

	protected function icon() {
		return 'megaphone';
	}

	protected function title() {
		return esc_html(
			__( "Contact Form 7 needs your support.", 'contact-form-7' )
		);
	}

	protected function content() {
		return array(
			esc_html( __( "It is hard to continue to maintain this plugin without support from users like you.", 'contact-form-7' ) ),
			sprintf(
				/* translators: %s: link labeled 'contribute to the project' */
				esc_html( __( 'There are several ways for you to %s: testing, coding, translating it into your local languages, helping other users, financial donations, etc, etc. We equally welcome you regardless of the way you contribute.', 'contact-form-7' ) ),
				wpcf7_link(
					__( 'https://contactform7.com/contributing/', 'contact-form-7' ),
					__( 'contribute to the project', 'contact-form-7' )
				)
			),
		);
	}
}


class WPCF7_WelcomePanelColumn_Flamingo extends WPCF7_WelcomePanelColumn {

	protected function icon() {
		return 'editor-help';
	}

	protected function title() {
		return esc_html(
			__( "Before you cry over spilt mail&#8230;", 'contact-form-7' )
		);
	}

	protected function content() {
		return array(
			esc_html( __( "Contact Form 7 does not store submitted messages anywhere. Therefore, you may lose important messages forever if your mail server has issues or you make a mistake in mail configuration.", 'contact-form-7' ) ),
			sprintf(
				/* translators: %s: link labeled 'Flamingo' */
				esc_html( __( 'Install a message storage plugin before this happens to you. %s saves all messages through contact forms into the database. Flamingo is a free WordPress plugin created by the same author as Contact Form 7.', 'contact-form-7' ) ),
				wpcf7_link(
					__( 'https://contactform7.com/save-submitted-messages-with-flamingo/', 'contact-form-7' ),
					__( 'Flamingo', 'contact-form-7' )
				)
			),
		);
	}
}


class WPCF7_WelcomePanelColumn_Integration extends WPCF7_WelcomePanelColumn {

	protected function icon() {
		return 'superhero-alt';
	}

	protected function title() {
		return esc_html(
			__( "You have strong allies to back you up.", 'contact-form-7' )
		);
	}

	protected function content() {
		return array(
			sprintf(
				/* translators: 1: link labeled 'Brevo' */
				esc_html( __( 'Your contact forms will become more powerful and versatile by integrating them with external APIs. With CRM and email marketing services, you can build your own contact lists (%1$s).', 'contact-form-7' ) ),
				wpcf7_link(
					__( 'https://contactform7.com/sendinblue-integration/', 'contact-form-7' ),
					__( 'Brevo', 'contact-form-7' )
				)
			),
			sprintf(
				/* translators: 1: link labeled 'reCAPTCHA', 2: link labeled 'Stripe' */
				esc_html( __( 'With help from cloud-based machine learning, anti-spam services will protect your forms (%1$s). Even payment services are natively supported (%2$s).', 'contact-form-7' ) ),
				wpcf7_link(
					__( 'https://contactform7.com/recaptcha/', 'contact-form-7' ),
					__( 'reCAPTCHA', 'contact-form-7' )
				),
				wpcf7_link(
					__( 'https://contactform7.com/stripe-integration/', 'contact-form-7' ),
					__( 'Stripe', 'contact-form-7' )
				)
			),
		);
	}
}


function wpcf7_welcome_panel() {
	$columns = array();

	$flamingo_is_active = defined( 'FLAMINGO_VERSION' );

	$sendinblue_is_active = false;

	if ( class_exists( 'WPCF7_Sendinblue' )
	and $sendinblue = WPCF7_Sendinblue::get_instance() ) {
		$sendinblue_is_active = $sendinblue->is_active();
	}

	if ( $flamingo_is_active and $sendinblue_is_active ) {
		$columns[] = new WPCF7_WelcomePanelColumn_AntiSpam();
		$columns[] = new WPCF7_WelcomePanelColumn_Donation();
	} elseif ( $flamingo_is_active ) {
		$columns[] = new WPCF7_WelcomePanelColumn_Integration();
		$columns[] = new WPCF7_WelcomePanelColumn_AntiSpam();
	} elseif ( $sendinblue_is_active ) {
		$columns[] = new WPCF7_WelcomePanelColumn_Flamingo();
		$columns[] = new WPCF7_WelcomePanelColumn_AntiSpam();
	} else {
		$columns[] = new WPCF7_WelcomePanelColumn_Flamingo();
		$columns[] = new WPCF7_WelcomePanelColumn_Integration();
	}

	$classes = 'wpcf7-welcome-panel';

	$vers = (array) get_user_meta( get_current_user_id(),
		'wpcf7_hide_welcome_panel_on', true
	);

	if ( wpcf7_version_grep( wpcf7_version( 'only_major=1' ), $vers ) ) {
		$classes .= ' hidden';
	}

?>
<div id="wpcf7-welcome-panel" class="<?php echo esc_attr( $classes ); ?>">
	<?php wp_nonce_field( 'wpcf7-welcome-panel-nonce', 'welcomepanelnonce', false ); ?>
	<a class="welcome-panel-close" href="<?php echo esc_url( menu_page_url( 'wpcf7', false ) ); ?>"><?php echo esc_html( __( 'Dismiss', 'contact-form-7' ) ); ?></a>

	<div class="welcome-panel-content">
		<div class="welcome-panel-column-container">
<?php

	foreach ( $columns as $column ) {
		$column->print_content();
	}

?>
		</div>
	</div>
</div>
<?php
}


add_action(
	'wp_ajax_wpcf7-update-welcome-panel',
	'wpcf7_admin_ajax_welcome_panel',
	10, 0
);

function wpcf7_admin_ajax_welcome_panel() {
	check_ajax_referer( 'wpcf7-welcome-panel-nonce', 'welcomepanelnonce' );

	$vers = get_user_meta( get_current_user_id(),
		'wpcf7_hide_welcome_panel_on', true
	);

	if ( empty( $vers ) or ! is_array( $vers ) ) {
		$vers = array();
	}

	if ( empty( $_POST['visible'] ) ) {
		$vers[] = wpcf7_version( 'only_major=1' );
	} else {
		$vers = array_diff( $vers, array( wpcf7_version( 'only_major=1' ) ) );
	}

	$vers = array_unique( $vers );

	update_user_meta( get_current_user_id(),
		'wpcf7_hide_welcome_panel_on', $vers
	);

	wp_die( 1 );
}


add_filter(
	'screen_settings',
	'wpcf7_welcome_panel_screen_settings',
	10, 2
);

function wpcf7_welcome_panel_screen_settings( $screen_settings, $screen ) {

	if ( 'toplevel_page_wpcf7' !== $screen->id ) {
		return $screen_settings;
	}

	$vers = (array) get_user_meta( get_current_user_id(),
		'wpcf7_hide_welcome_panel_on', true
	);

	$checkbox_id = 'wpcf7-welcome-panel-show';
	$checked = ! in_array( wpcf7_version( 'only_major=1' ), $vers );

	$checkbox = sprintf(
		'<input %s />',
		wpcf7_format_atts( array(
			'id' => $checkbox_id,
			'type' => 'checkbox',
			'checked' => $checked,
		) )
	);

	$screen_settings .= sprintf( '
<fieldset class="wpcf7-welcome-panel-options">
<legend>%1$s</legend>
<label for="%2$s">%3$s %4$s</label>
</fieldset>',
 		esc_html( __( 'Welcome panel', 'contact-form-7' ) ),
		esc_attr( $checkbox_id ),
		$checkbox,
		esc_html( __( 'Show welcome panel', 'contact-form-7' ) )
	);

	return $screen_settings;
}
admin/includes/js/index.js000064400000031114147510545420011532 0ustar00(()=>{"use strict";var e={n:t=>{var a=t&&t.__esModule?()=>t.default:()=>t;return e.d(a,{a}),a},d:(t,a)=>{for(var r in a)e.o(a,r)&&!e.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:a[r]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)};const t=window.wp.i18n,a=e=>{e&&document.querySelector(`.contact-form-editor-panel#${e}`)&&(document.querySelector("#contact-form-editor")?.setAttribute("data-active-tab",e),document.querySelectorAll('input[name="active-tab"]').forEach((t=>{t.value=e})),document.querySelectorAll("#contact-form-editor-tabs li").forEach((t=>{t.dataset?.panel===e?(t.classList.add("active"),t.setAttribute("tabindex","0"),t.focus()):(t.classList.remove("active"),t.setAttribute("tabindex","-1"))})),document.querySelectorAll(".contact-form-editor-panel").forEach((t=>{t.id===e?(t.classList.add("active"),t.style.setProperty("display","block")):(t.classList.remove("active"),t.style.setProperty("display","none"))})))},r=window.wp.apiFetch;var c=e.n(r);const o=e=>{const t=document.createElement("span");return t.classList.add("icon-in-circle"),t.setAttribute("aria-hidden","true"),t.append(e),t},n=e=>e.replace(/[^0-9a-z]+/gi,"-"),l=e=>{const t=document.querySelector(`#${e.dataset?.toggle}`);t&&(e.checked?t.classList.remove("hidden"):t.classList.add("hidden"))},i=()=>{document.querySelectorAll("#contact-form-editor .config-error, #misc-publishing-actions .config-error").forEach((e=>{e.remove()})),document.querySelectorAll("#contact-form-editor [data-config-field]").forEach((e=>{const t=e.dataset.configField;d(t).length?(e.setAttribute("aria-invalid","true"),e.setAttribute("aria-describedby",n(`wpcf7-config-error-for-${t}`)),e.after(u(t))):e.removeAttribute("aria-invalid")})),document.querySelectorAll("#contact-form-editor-tabs [data-panel]").forEach((e=>{e.querySelectorAll(".icon-in-circle").forEach((e=>{e.remove()})),s(e.dataset.panel)&&e.querySelector("a")?.append(o("!"))}));let e=0;if(document.querySelectorAll("#contact-form-editor .contact-form-editor-panel").forEach((a=>{const r=s(a.id);if(r){e+=r;const c=document.createElement("div");c.classList.add("config-error"),c.append(o("!"),(0,t.sprintf)((0,t._n)("%d configuration error detected in this tab panel.","%d configuration errors detected in this tab panel.",r,"contact-form-7"),r)),a.prepend(c)}})),e){const a=document.createElement("div");a.classList.add("misc-pub-section","config-error");const r=document.createElement("a");r.setAttribute("href",wpcf7.configValidator.docUrl),r.append((0,t.__)("How to resolve?","contact-form-7")),a.append(o("!"),(0,t.sprintf)((0,t._n)("%d configuration error detected.","%d configuration errors detected.",e,"contact-form-7"),e),document.createElement("br"),r),document.querySelector("#misc-publishing-actions")?.append(a)}},s=e=>document.querySelectorAll(`#${e} ul.config-error li`)?.length,d=e=>{const t=[];for(const a in wpcf7.configValidator.errors)a===e&&t.push(...wpcf7.configValidator.errors[a]);return t},u=e=>{if(!e)return"";const t=document.createElement("ul");return t.setAttribute("id",n(`wpcf7-config-error-for-${e}`)),t.classList.add("config-error"),d(e).forEach((e=>{if(!e.message)return;const a=document.createElement("li");if(a.append(o("!")),e.link){const t=document.createElement("a");t.setAttribute("href",e.link),t.append(e.message),a.append(" ",t)}else a.append(" ",e.message);t.append(a)})),t},m=document.querySelector("#wpcf7-welcome-panel"),p=e=>{const t=m.querySelector("#welcomepanelnonce")?.value;if(!t)return;const a=new FormData;a.append("action","wpcf7-update-welcome-panel"),a.append("visible",e),a.append("welcomepanelnonce",t),fetch(new Request(ajaxurl,{method:"POST",body:a})),e?m.classList.remove("hidden"):m.classList.add("hidden")},f=e=>{var t;const a=e.dataset.id,r=e.querySelector('[name="name"]');let c=null!==(t=r?.value.trim())&&void 0!==t?t:"";r&&(c||(c=`${a}-${Math.floor(1e3*Math.random())}`),r.value=c),e.querySelectorAll(".tag").forEach((t=>{const a=e.querySelector('[name="tagtype"]')?.value||t.name;a&&(t.value=v(a,e))})),e.querySelectorAll("span.mail-tag").forEach((e=>{e.innerText=`[${c}]`})),e.querySelectorAll("input.mail-tag").forEach((e=>{e.value=`[${c}]`}))},v=(e,t)=>{var a,r,c;const o=null!==(a=t.querySelector(`.scope.${e}`))&&void 0!==a?a:t,n=e+(t.querySelector('[name="required"]:checked')?"*":""),l=null!==(r=t.querySelector('[name="name"]')?.value)&&void 0!==r?r:"",i=[];o.querySelectorAll(".option").forEach((e=>{"checkbox"===e.type?e.checked&&i.push(e.name):"radio"===e.type?e.checked&&!e.classList.contains("default")&&i.push(`${e.name}:${e.value}`):""!==e.value&&(e.classList.contains("filetype")?i.push(`${e.name}:${e.value.split(/[,|\s]+/).join("|")}`):e.classList.contains("color")?i.push(`${e.name}:#${e.value}`):"class"===e.name?e.value.split(" ").forEach((e=>{i.push(`class:${e}`)})):i.push(`${e.name}:${e.value}`))})),"radio"===e&&i.push("default:1");const s=null!==(c=o.querySelector('[name="values"]')?.value.split("\n").map((e=>e.trim())).filter((e=>""!==e)).map((e=>`"${e.replace(/["]/g,"&quot;")}"`)))&&void 0!==c?c:[],d=[n,l,i.join(" "),s.join(" ")].map((e=>e.trim())).filter((e=>""!==e)),u=o.querySelector('[name="content"]')?.value.trim();return u?`[${d.join(" ")}] ${u} [/${n}]`:`[${d.join(" ")}]`},g=e=>{const t=h(e);t?(e.querySelectorAll('[data-tag-part="tag"]').forEach((e=>{e.value=t})),e.querySelectorAll('[data-taggen="insert-tag"]').forEach((e=>{e.disabled=!1})),e.querySelectorAll('[data-tag-part="mail-tag"]').forEach((t=>{const a=e.querySelector('[data-tag-part="name"]');a&&(t.innerText=`[${a.value.trim()}]`)}))):(e.querySelectorAll('[data-tag-part="tag"]').forEach((e=>{e.value=""})),e.querySelectorAll('[data-taggen="insert-tag"]').forEach((e=>{e.disabled=!0})))},h=e=>{var t,a;const r=e.querySelector('[data-tag-part="basetype"]')?.value.trim();if(!r)return;if(e.querySelector(":invalid"))return;let c=r;const o=e.querySelector('[data-tag-part="type-suffix"]');o&&(["checkbox","radio"].includes(o?.type)?c+=o.checked?o.value.trim():"":c+=o.value.trim());const n=e.querySelector('[data-tag-part="name"]');let l=null!==(t=n?.value.trim())&&void 0!==t?t:"";n&&(l||(l=`${r}-${Math.floor(1e3*Math.random())}`),n.value=l);const i=[];e.querySelectorAll('[data-tag-part="option"]').forEach((e=>{const t=e.dataset.tagOption?.trim();t&&(["checkbox","radio"].includes(e?.type)&&!e.checked||t.split(" ").forEach((t=>{t.endsWith(":")?e.value?.split(" ").forEach((e=>{(e=e.trim())&&i.push(t+e)})):i.push(t)})))}));const s=null!==(a=e.querySelector('[data-tag-part="value"]')?.value.split("\n").map((e=>e.trim())).filter((e=>""!==e)).map((e=>`"${e.replace(/["]/g,"&quot;")}"`)))&&void 0!==a?a:[],d=[c,l,i.join(" "),s.join(" ")].map((e=>e.trim())).filter((e=>""!==e)),u=e.querySelector('[data-tag-part="content"]')?.value.trim();return u?`[${d.join(" ")}] ${u} [/${c}]`:`[${d.join(" ")}]`},y=e=>{const t=document.querySelector("#wpcf7-admin-form-element");if(!t)return;let a=!1;t.querySelectorAll("input, textarea, select").forEach((e=>{if(!a)switch(e.type){case"button":case"hidden":case"image":case"reset":case"search":case"submit":break;case"checkbox":case"radio":a=e.defaultChecked!==e.checked;break;case"select-multiple":case"select-one":e.querySelectorAll("option").forEach((e=>{a||e.defaultSelected===e.selected||(a=!0)}));break;default:a=e.defaultValue!==e.value}})),a&&e.preventDefault()};document.addEventListener("DOMContentLoaded",(e=>{document.querySelectorAll("#contact-form-editor-tabs li").forEach((e=>{e.addEventListener("click",(t=>{a(e.dataset?.panel),t.preventDefault()})),e.addEventListener("keyup",(t=>{if(["ArrowDown","ArrowRight"].includes(t.key)){const t=e.nextElementSibling;t&&a(t.dataset?.panel)}if(["ArrowUp","ArrowLeft"].includes(t.key)){const t=e.previousElementSibling;t&&a(t.dataset?.panel)}}))})),document.querySelectorAll(".contact-form-editor-panel").forEach((e=>{e.classList.contains("active")?document.querySelector("#contact-form-editor")?.setAttribute("data-active-tab",e.id):e.style.setProperty("display","none")})),document.querySelectorAll("#contact-form-editor [data-config-field]").forEach((e=>{e.addEventListener("change",(e=>{const t=document.querySelector('[name="post_ID"]')?.value;t&&0<t&&(e=>{const{namespace:t}=wpcf7.apiSettings,a=`/${t}/contact-forms/${e}`,r=new FormData;document.querySelectorAll("#contact-form-editor [data-config-field]").forEach((e=>{const t=e.name?.replace(/^wpcf7-/,"").replace(/-/g,"_");if(!t)return;let a;["checkbox","radio"].includes(e.type)?e.checked&&(a=e.value):a=e.value,void 0!==a&&(t.endsWith("[]")?r.append(t,a):r.set(t,a))})),r.set("context","dry-run"),c()({path:a,method:"POST",body:r}).then((e=>{wpcf7.configValidator.errors=e.config_errors,i()}))})(t)}))})),i(),(()=>{if(!m)return;const e=document.querySelector("#wpcf7-welcome-panel-show");m.querySelectorAll(".welcome-panel-close").forEach((t=>{t.addEventListener("click",(t=>{p(0),e?.removeAttribute("checked"),t.preventDefault()}))})),e?.addEventListener("click",(t=>{p(e?.checked?1:0)}))})(),document.querySelectorAll('[data-taggen="open-dialog"]').forEach((e=>{e.addEventListener("click",(t=>{const a=document.querySelector(`#${e.dataset.target}`);if(a){const e=a.querySelector("form.tag-generator-panel");e&&("1"===e.dataset.version?(e=>{f(e),e.querySelectorAll(".control-box").forEach((t=>{t.addEventListener("change",(t=>{var a;"name"===(a=t.target).name&&(a.value=a.value.replace(/[^0-9a-zA-Z:._-]/g,"").replace(/^[^a-zA-Z]+/,"")),a.classList.contains("numeric")&&(a.value=a.value.replace(/[^0-9.-]/g,"")),a.classList.contains("idvalue")&&(a.value=a.value.replace(/[^-0-9a-zA-Z_]/g,"")),a.classList.contains("classvalue")&&(a.value=a.value.split(" ").map((e=>e.replace(/[^-0-9a-zA-Z_]/g,""))).join(" ").replace(/\s+/g," ").trim()),a.classList.contains("color")&&(a.value=a.value.replace(/[^0-9a-fA-F]/g,"")),a.classList.contains("filesize")&&(a.value=a.value.replace(/[^0-9kKmMbB]/g,"")),a.classList.contains("filetype")&&(a.value=a.value.replace(/[^0-9a-zA-Z.,|\s]/g,"")),a.classList.contains("date")&&(a.value.match(/^\d{4}-\d{2}-\d{2}$/)||(a.value="")),"values"===a.name&&(a.value=a.value.trim()),f(e)}))}))})(e):"2"===e.dataset.version&&(e=>{var t;null!==(t=e.reset())&&void 0!==t||g(e),e.querySelectorAll(".control-box").forEach((t=>{t.addEventListener("change",(t=>{g(e)})),t.addEventListener("keyup",(t=>{var a;"text"!==(null!==(a=t.target.type)&&void 0!==a?a:"")&&"textarea"!==t.target.tagName?.toLowerCase()||g(e)}))}))})(e)),a.showModal()}}))})),document.querySelectorAll("dialog.tag-generator-dialog").forEach((e=>{e.querySelectorAll('[data-taggen="close-dialog"]').forEach((t=>{t.addEventListener("click",(t=>e.close("")))})),e.querySelectorAll('[data-taggen="insert-tag"], .insert-tag').forEach((t=>{t.addEventListener("click",(t=>{const a=e.querySelector('[data-tag-part="tag"], .tag');e.close(a?.value)}))})),e.addEventListener("close",(t=>{var a;const r=document.querySelector("textarea#wpcf7-form");if(null===r)return;if(""===e.returnValue)return;const c=null!==(a=r.selectionEnd)&&void 0!==a?a:0;0===c&&(e.returnValue+="\n\n"),r.value=r.value.substring(0,c)+e.returnValue+r.value.substring(c),r.selectionStart=c,r.selectionEnd=c+e.returnValue.length,r.focus()}))})),(()=>{const e=document.querySelector("#wpcf7-admin-form-element");e&&(window.addEventListener("beforeunload",y),e.addEventListener("submit",(e=>{e.submitter?.name&&"wpcf7-copy"===e.submitter.name||window.removeEventListener("beforeunload",y)})))})();const r=document.querySelector("input#title");r&&""===r.value&&r.focus(),document.querySelector("#wpcf7-admin-form-element")?.addEventListener("submit",(e=>{const a=document.querySelector('#wpcf7-admin-form-element [name="action"]'),r=document.querySelector('#wpcf7-admin-form-element [name="_wpnonce"]');"wpcf7-save"===e.submitter?.name&&(a&&(a.value="save"),r&&(r.value=wpcf7.nonce.save),document.querySelectorAll("#wpcf7-admin-form-element #publishing-action .spinner").forEach((e=>{e.classList.add("is-active")}))),"wpcf7-copy"===e.submitter?.name&&(a&&(a.value="copy"),r&&(r.value=wpcf7.nonce.copy)),"wpcf7-delete"===e.submitter?.name&&(window.confirm((0,t.__)("You are about to delete this contact form.\n  'Cancel' to stop, 'OK' to delete.","contact-form-7"))?(a&&(a.value="delete"),r&&(r.value=wpcf7.nonce.delete)):e.preventDefault())})),document.querySelectorAll(".contact-form-editor-box-mail span.mailtag").forEach((e=>{e.addEventListener("click",(t=>{const a=document.createRange();a.selectNodeContents(e),window.getSelection().addRange(a)}))})),document.querySelectorAll("[data-toggle]").forEach((e=>{l(e),e.addEventListener("change",(t=>{l(e)}))})),document.querySelectorAll("#wpcf7-ctct-enable-contact-list, #wpcf7-sendinblue-enable-contact-list, #wpcf7-sendinblue-enable-transactional-email").forEach((e=>{e.addEventListener("change",(t=>{e.checked?e.closest("tr").classList.remove("inactive"):e.closest("tr").classList.add("inactive")}))}))}))})();admin/includes/js/index.asset.php000064400000000162147510545420013022 0ustar00<?php

return array(
	'dependencies' => array(
		'wp-api-fetch',
		'wp-i18n',
	),
	'version' => WPCF7_VERSION,
);
admin/includes/config-validator.php000064400000006505147510545420013420 0ustar00<?php

add_action( 'wpcf7_admin_menu', 'wpcf7_admin_init_bulk_cv', 10, 0 );

function wpcf7_admin_init_bulk_cv() {
	if ( ! wpcf7_validate_configuration()
	or ! current_user_can( 'wpcf7_edit_contact_forms' ) ) {
		return;
	}

	$result = WPCF7::get_option( 'bulk_validate' );
	$last_important_update = WPCF7_ConfigValidator::last_important_update;

	if ( ! empty( $result['version'] )
	and version_compare( $last_important_update, $result['version'], '<=' ) ) {
		return;
	}

	add_filter( 'wpcf7_admin_menu_change_notice',
		'wpcf7_admin_menu_change_notice_bulk_cv',
		10, 1
	);

	add_action( 'wpcf7_admin_warnings',
		'wpcf7_admin_warnings_bulk_cv',
		5, 3
	);
}

function wpcf7_admin_menu_change_notice_bulk_cv( $counts ) {
	$counts['wpcf7'] += 1;
	return $counts;
}

function wpcf7_admin_warnings_bulk_cv( $page, $action, $object ) {
	if ( 'wpcf7' === $page and 'validate' === $action ) {
		return;
	}

	$link = wpcf7_link(
		add_query_arg(
			array( 'action' => 'validate' ),
			menu_page_url( 'wpcf7', false )
		),
		__( 'Validate Contact Form 7 Configuration', 'contact-form-7' )
	);

	$message = __( "Misconfiguration leads to mail delivery failure or other troubles. Validate your contact forms now.", 'contact-form-7' );

	wp_admin_notice(
		sprintf(
			'%1$s &raquo; %2$s',
			esc_html( $message ),
			$link
		),
		'type=warning'
	);
}

add_action( 'wpcf7_admin_load', 'wpcf7_load_bulk_validate_page', 10, 2 );

function wpcf7_load_bulk_validate_page( $page, $action ) {
	if ( 'wpcf7' != $page
	or 'validate' != $action
	or ! wpcf7_validate_configuration()
	or 'POST' != $_SERVER['REQUEST_METHOD'] ) {
		return;
	}

	check_admin_referer( 'wpcf7-bulk-validate' );

	if ( ! current_user_can( 'wpcf7_edit_contact_forms' ) ) {
		wp_die( __( "You are not allowed to validate configuration.", 'contact-form-7' ) );
	}

	$contact_forms = WPCF7_ContactForm::find();

	$result = array(
		'timestamp' => time(),
		'version' => WPCF7_VERSION,
		'count_valid' => 0,
		'count_invalid' => 0,
	);

	foreach ( $contact_forms as $contact_form ) {
		$config_validator = new WPCF7_ConfigValidator( $contact_form );
		$config_validator->validate();
		$config_validator->save();

		if ( $config_validator->is_valid() ) {
			$result['count_valid'] += 1;
		} else {
			$result['count_invalid'] += 1;
		}
	}

	WPCF7::update_option( 'bulk_validate', $result );

	$redirect_to = add_query_arg(
		array(
			'message' => 'validated',
		),
		menu_page_url( 'wpcf7', false )
	);

	wp_safe_redirect( $redirect_to );
	exit();
}

function wpcf7_admin_bulk_validate_page() {
	$contact_forms = WPCF7_ContactForm::find();
	$count = WPCF7_ContactForm::count();

	$submit_text = sprintf(
		_n(
			/* translators: %s: number of contact forms */
			"Validate %s contact form now",
			"Validate %s contact forms now",
			$count, 'contact-form-7'
		),
		number_format_i18n( $count )
	);

?>
<div class="wrap">

<h1><?php echo esc_html( __( 'Validate Configuration', 'contact-form-7' ) ); ?></h1>

<form method="post" action="">
	<input type="hidden" name="action" value="validate" />
	<?php wp_nonce_field( 'wpcf7-bulk-validate' ); ?>
	<p><input type="submit" class="button" value="<?php echo esc_attr( $submit_text ); ?>" /></p>
</form>

<?php
	echo wpcf7_link(
		__( 'https://contactform7.com/configuration-validator-faq/', 'contact-form-7' ),
		__( 'FAQ about Configuration Validator', 'contact-form-7' )
	);
?>

</div>
<?php
}
admin/includes/css/styles-rtl.css000064400000002174147510545420013101 0ustar00/*
 * Tabs
 */
#contact-form-editor-tabs {
	padding: 9px 10px 0 15px;
}

/*
 * Form Tab
 */
.tag-generator-panel {
	text-align: right;
}

.tag-generator-dialog > .close-button {
	right: auto;
	left: 8px;
}

form.tag-generator-panel[data-version="1"] {
	.control-box > fieldset > legend {
		border: 1px solid #dfdfdf;
		border-right: 4px solid #00a0d2;
	}

	.insert-box input.tag {
		float: right;
	}

	.insert-box .submitbox input[type="button"] {
		float: left;
	}
}

/*
 * Mail Tab
 */
.contact-form-editor-box-mail span.mailtag {
	margin: 0 4px 0 0;
}

/*
 * Welcome Panel
 */
.wpcf7-welcome-panel .welcome-panel-close {
	left: 10px;
	right: auto;
	padding: 10px 21px 10px 15px;
}

.wpcf7-welcome-panel .welcome-panel-close::before {
	right: 0;
	left: auto;
}

.wpcf7-welcome-panel .welcome-panel-content {
	margin-right: 13px;
}

.wpcf7-welcome-panel .welcome-panel-column {
	float: right;
 	padding: 0 0 0 2%;
}

/*
 * Integration
 */
.card {
	border-left: 1px solid #e5e5e5;
	border-right: 4px solid #e5e5e5;
}

.card img.icon {
	float: right;
	margin: 8px -8px 8px 8px;
}

.card h2.title {
	float: right;
}

.card .infobox {
	float: left;
}
admin/includes/css/styles.css000064400000024012147510545420012275 0ustar00#titlediv .inside p.description {
	margin: 8px 2px 0;
}

#titlediv .inside p.description label {
	cursor: pointer;
}

span.shortcode {
	display: block;
	margin: 2px 0;
}

span.shortcode.old {
	background: #777;
	color: #fff;
}

span.shortcode input {
	font-size: 12px;
	border: none;
	box-shadow: none;
	padding: 4px 8px;
	margin: 0;
}

#wpcf7-contact-form-list-table span.shortcode input,
#wpcf7-contact-form-editor span.shortcode input {
	background: transparent;
}

#wpcf7-contact-form-list-table span.shortcode input {
	color: #444;
}

#wpcf7-contact-form-editor span.shortcode input {
	color: #fff;
}

#submitpost input.copy {
	margin-bottom: 10px;
}

#submitpost input.delete {
	padding: 0;
	margin: 0;
	border: none;
	cursor: pointer;
	background: inherit;
	color: #a00;
}

#submitpost input.delete:hover {
	color: #dc3232; /* Red */
}

#submitpost input.delete:focus {
	outline: thin dotted;
}

.postbox-container .postbox h3 {
	border-bottom: 1px solid transparent;
}

div.config-error, span.config-error, ul.config-error {
	color: #444;
	font-style: normal;
	font-size: 13px;
}

ul.config-error {
	margin: 2px 0;
}

ul.config-error li {
	list-style: none;
	padding: 2px 2px;
	margin: 0;
}

#misc-publishing-actions .config-error {
	line-height: 2;
}

[data-config-field][aria-invalid="true"] {
	border-color: #dc3232;
}

#contact-form-editor-tabs li a .icon-in-circle,
#contact-form-editor .config-error .icon-in-circle,
.wp-list-table .config-error .icon-in-circle,
.icon-in-circle {
	display: inline-block;
	vertical-align: baseline;
	margin: 1px 6px 0;
	padding: 0 5px;
	min-width: 7px;
	height: 17px;
	border-radius: 11px;
	background-color: #ca4a1f;
	color: #fff;
	font-size: 12px;
	font-weight: bold;
	line-height: 17px;
	text-align: center;
	z-index: 26;
}

/*
 * Tabs
 */
#contact-form-editor-tabs {
	border-bottom: 1px solid #aaa;
	padding: 9px 15px 0 10px;
	margin: 0;
}

#contact-form-editor-tabs li {
	display: inline-block;
	list-style: none;
	border: 1px solid #ccc;
	border-bottom: 1px solid #aaa;
	padding: 0;
	margin: 0 4px -1px;
	background-color: #e4e4e4;
}

#contact-form-editor-tabs li.active {
	border-top: 1px solid #aaa;
	border-right: 1px solid #aaa;
	border-left: 1px solid #aaa;
	border-bottom: 1px solid #f5f5f5;
	background-color: #f5f5f5;
}

#contact-form-editor-tabs li a {
	padding: 6px 10px;
	font-size: 14px;
	font-weight: normal;
	line-height: 30px;
	color: #333;
	text-decoration: none;
}

#contact-form-editor-tabs li.active a {
	color: #000;
	font-size: 14px;
	font-weight: bold;
}

#contact-form-editor-tabs li a:hover {
	color: #000;
}

#contact-form-editor .contact-form-editor-panel > div.config-error {
	margin-bottom: 1.4em;
}

#contact-form-editor-tabs li.active a .icon-in-circle {
	display: none;
}

#contact-form-editor .contact-form-editor-panel h2 {
	font-size: 18px;
	font-weight: 400;
	line-height: 24px;
	margin: 8px 0;
	padding: 0;
}

#contact-form-editor .contact-form-editor-panel {
	background-color: #f5f5f5;
	border: 1px solid #aaa;
	border-top: none;
	padding: 16px;
}

#contact-form-editor .form-table th {
	width: 100px;
}

#contact-form-editor .contact-form-editor-panel fieldset legend {
	line-height: 1.5;
	margin: .6em 0 .4em;
}

/*
 * Form Tab
 */
#tag-generator-list button {
	font-size: 12px;
	height: 26px;
	line-height: 24px;
	margin: 2px;
	padding: 0 8px 1px;
}

.tag-generator-dialog {
	padding: 12px;
	border: 1px solid #c3c4c7;
	box-shadow: 0 1px 1px rgba( 0, 0, 0, 0.04 );
	height: 720px;
	width: 720px;
	overflow: auto;
}

.tag-generator-dialog::backdrop {
	background: rgb( 0 0 0 / 50% );
}

.tag-generator-dialog > .close-button {
	position: absolute;
	top: 8px;
	right: 8px;
}

form.tag-generator-panel {
	display: flex;
	flex-direction: column;
	height: 720px;
	width: 720px;
	max-height: 100%;
	max-width: 100%;
	margin-block-end: 0;
}

form.tag-generator-panel[data-version="2"] {
	&:invalid .mail-tag-tip {
		display: none;
	}

	.description-box {
		box-sizing: border-box;
		flex: none;
		margin-inline: -12px;
		padding-inline: 12px;
		border-bottom: 1px solid #dfdfdf;
	}

	.control-box {
		box-sizing: border-box;
		flex: auto;
		display: flex;
		flex-direction: column;
		gap: 12px 0;
		min-height: 120px;
		overflow: auto;
	}

	.control-box > fieldset {
		margin-block: 8px;
		margin-inline-start: 10em;
		line-height: 2.25;
	}

	.control-box > fieldset > legend {
		font-weight: bolder;
		margin-block: 8px;
		margin-inline-start: -10em;
		line-height: 1.25;
	}

	.control-box input[type="text"] {
		width: 20rem;
		max-width: 88%;
	}

	.control-box input[type="number"] {
		width: 8rem;
		max-width: 44%;
	}

	.control-box textarea {
		height: 12ex;
		width: 20rem;
		max-width: 88%;
	}

	.control-box select {
		width: 20rem;
		max-width: 88%;
	}

	.control-box input:invalid,
	.control-box textarea:invalid {
		background-color: #ffe9de;
	}

	.insert-box {
		box-sizing: border-box;
		flex: none;
		margin-block-end: -12px;
		margin-inline: -12px;
		padding-block: 24px 12px;
		padding-inline: 12px;
		background-color: #fcfcfc;
		border-top: 1px solid #dfdfdf;
	}

	.insert-box .flex-container {
		display: flex;
	}

	.insert-box .flex-container > [data-tag-part="tag"] {
		flex: auto;
		margin-inline-end: 8px;
	}

	.insert-box .mail-tag-tip::before {
		font: 1.2rem dashicons;
		content: "\f348";
		color: #646970;
		padding-inline-end: 4px;
		vertical-align: top;
	}
}

form.tag-generator-panel[data-version="1"] {
	.control-box {
		padding: 0;
		margin: 0;
		overflow: auto;
		flex-grow: 1;
	}

	.control-box > fieldset > legend {
		border: 1px solid #dfdfdf;
		border-left: 4px solid #00a0d2;
		background: #f7fcfe;
		padding: 4px 12px;
		margin: 4px 0;
		line-height: 1.4em;
		width: 100%;
		box-sizing: border-box;
	}

	table {
		width: 100%;
	}

	table.form-table th {
		width: 120px;
		padding: 4px 10px 4px 0;
		font-size: 13px;
	}

	table.form-table td {
		padding: 4px 10px;
		font-size: 13px;
	}

	.control-box input.oneline {
		width: 200px;
	}

	.control-box input.large-text {
		width: 400px;
	}

	.control-box textarea.values {
		width: 200px;
		height: 6em;
	}

	.control-box input[type="number"],
	.control-box input[type="date"] {
		width: 88px;
	}

	.control-box table caption {
		text-align: left;
		font-size: 110%;
		font-weight: bold;
		color: #777;
		margin: 10px 0 5px;
	}

	.control-box table.form-table td label {
		line-height: 1.1em;
	}

	.control-box table.form-table td label .description {
		line-height: 1.4em;
	}

	.insert-box {
		margin: 0 -15px -15px;
		padding: 8px 16px;
		background-color: #fcfcfc;
		border-top: 1px solid #dfdfdf;
		overflow: auto;
	}

	.insert-box input.tag {
		width: 510px;
		float: left;
		background-color: transparent;
		box-shadow: none;
	}

	.insert-box .submitbox {
		padding: 0;
	}

	.insert-box .submitbox input[type="button"] {
		float: right;
	}

	.insert-box .description label {
		cursor: text;
	}
}

/*
 * Mail Tab
 */
.contact-form-editor-box-mail span.mailtag {
	display: inline-block;
	margin: 0 0 0 4px;
	padding: 1px 2px;
	cursor: pointer;
	color: #000;
}

.contact-form-editor-box-mail span.mailtag.used {
	color: #666;
}

.contact-form-editor-box-mail span.mailtag.unused {
	font-weight: bold;
}

/*
 * Messages Tab
 */
#messages-panel p.description {
	margin: 5px 0 10px;
}

/*
 * Tabs for integration modules
 */
#ctct-panel table tr.inactive ~ tr,
#sendinblue-panel table tr.inactive ~ tr {
	display: none;
}

#ctct-panel .dashicons,
#sendinblue-panel .dashicons {
 	text-decoration: none;
}

#ctct-panel td p,
#sendinblue-panel td p {
 	margin-top: 12px;
}

/*
 * List Table
 */
.fixed .column-title {
	width: 38%;
}

.fixed .column-shortcode {
	width: 38%;
}

/*
 * Welcome Panel
 */
.wpcf7-welcome-panel {
	position: relative;
	overflow: auto;
	margin: 16px 0;
	padding: 23px 10px 0;
	border: 1px solid #c3c4c7;
	box-shadow: 0 1px 1px rgba(0, 0, 0, 0.04);
	background: #fff;
	font-size: 13px;
	line-height: 1.7;
}

.wpcf7-welcome-panel h3 {
	font-size: 16px;
	font-weight: 600;
	line-height: 2.1em;
	margin: 1em 0 1.2em;
}

.wpcf7-welcome-panel h3 .dashicons {
	position: relative;
	top: -2px;
	display: inline-block;
	width: 60px;
	color: #575757;
	font-size: 40px;
}

.wpcf7-welcome-panel p {
	color: #646970;
}

.wpcf7-welcome-panel p a {
	font-weight: bold;
}

.wpcf7-welcome-panel .welcome-panel-close {
	position: absolute;
	z-index: 2;
	top: 10px;
	right: 10px;
	padding: 10px 15px 10px 21px;
	font-size: 13px;
	line-height: 1.23076923; /* Chrome rounding, needs to be 16px equivalent */
	text-decoration: none;
}

.wpcf7-welcome-panel .welcome-panel-close::before {
	background: 0 0;
	color: #787c82;
	content: "\f153";
	display: block;
	font: normal 16px/20px dashicons;
	speak: never;
	height: 20px;
	text-align: center;
	width: 20px;
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
	position: absolute;
	top: 8px;
	left: 0;
	transition: all .1s ease-in-out;
}

.wpcf7-welcome-panel .welcome-panel-content {
	display: block;
	margin-left: 13px;
	max-width: 1500px;
	min-height: auto;
}

.wpcf7-welcome-panel .welcome-panel-column-container {
	clear: both;
	position: relative;
}

.wpcf7-welcome-panel .welcome-panel-column {
	display: block;
	width: 48%;
	min-width: 200px;
	float: left;
	padding: 0 2% 0 0;
	margin: 0 0 1em 0;
}

@media screen and (max-width: 870px) {
	.wpcf7-welcome-panel .welcome-panel-column {
		display: block;
		float: none;
		width: 100%;
	}
}

.wpcf7-welcome-panel .welcome-panel-column p {
	margin-top: 7px;
	color: #3c434a;
}

/*
 * Integration
 */
.card {
	background: #fff none repeat scroll 0 0;
	border: 1px solid #e5e5e5;
	border-left: 4px solid #e5e5e5;
	box-shadow: 0 1px 1px rgba(0, 0, 0, 0.04);
	margin-top: 20px;
	max-width: 520px;
	min-width: 255px;
	padding: 0.7em 2em 1em;
	position: relative;
}

.card.active {
	border-color: #00a0d2;
}

.card img.icon {
	float: left;
	margin: 8px 8px 8px -8px;
}

.card h2.title {
	float: left;
	max-width: 240px;
	font-size: 1.3em;
	font-weight: 600;
}

.card .infobox {
	float: right;
	font-size: 13px;
	color: #666;
	margin: 1em;
	line-height: 1.5;
	max-width: 240px;
}

.card .inside .form-table th {
	padding: 15px 10px 15px 0;
	width: 160px;
}

.card .inside .form-table td {
	padding: 10px 10px;
}

.card .checkboxes li {
	margin: 0;
}
admin/includes/admin-functions.php000064400000001104147510545420013254 0ustar00<?php

function wpcf7_current_action() {
	if ( isset( $_REQUEST['action'] ) and -1 != $_REQUEST['action'] ) {
		return $_REQUEST['action'];
	}

	if ( isset( $_REQUEST['action2'] ) and -1 != $_REQUEST['action2'] ) {
		return $_REQUEST['action2'];
	}

	return false;
}

function wpcf7_admin_has_edit_cap() {
	return current_user_can( 'wpcf7_edit_contact_forms' );
}

function wpcf7_add_tag_generator( $name, $title, $elm_id, $callback, $options = array() ) {
	$tag_generator = WPCF7_TagGenerator::get_instance();
	return $tag_generator->add( $name, $title, $callback, $options );
}
admin/includes/editor.php000064400000023713147510545420011456 0ustar00<?php

class WPCF7_Editor {

	private $contact_form;
	private $panels = array();

	public function __construct( WPCF7_ContactForm $contact_form ) {
		$this->contact_form = $contact_form;
	}

	public function add_panel( $panel_id, $title, $callback ) {
		if ( wpcf7_is_name( $panel_id ) ) {
			$this->panels[$panel_id] = array(
				'title' => $title,
				'callback' => $callback,
			);
		}
	}

	public function display() {
		if ( empty( $this->panels ) ) {
			return;
		}

		$active_panel_id = trim( $_GET['active-tab'] ?? '' );

		if ( ! array_key_exists( $active_panel_id, $this->panels ) ) {
			$active_panel_id = array_key_first( $this->panels );
		}

		echo '<nav>';
		echo '<ul id="contact-form-editor-tabs">';

		foreach ( $this->panels as $panel_id => $panel ) {
			$active = $panel_id === $active_panel_id;

			echo sprintf(
				'<li %1$s><a %2$s>%3$s</a></li>',
				wpcf7_format_atts( array(
					'id' => sprintf( '%s-tab', $panel_id ),
					'class' => $active ? 'active' : null,
					'tabindex' => $active ? '0' : '-1',
					'data-panel' => $panel_id,
				) ),
				wpcf7_format_atts( array(
					'href' => sprintf( '#%s', $panel_id ),
				) ),
				esc_html( $panel['title'] )
			);
		}

		echo '</ul>';
		echo '</nav>';

		foreach ( $this->panels as $panel_id => $panel ) {
			$active = $panel_id === $active_panel_id;

			echo sprintf(
				'<section %s>',
				wpcf7_format_atts( array(
					'id' => $panel_id,
					'class' => 'contact-form-editor-panel' . ( $active ? ' active' : '' ),
				) )
			);

			if ( is_callable( $panel['callback'] ) ) {
				call_user_func( $panel['callback'], $this->contact_form );
			}

			echo '</section>';
		}
	}
}

function wpcf7_editor_panel_form( $post ) {
	$desc_link = wpcf7_link(
		__( 'https://contactform7.com/editing-form-template/', 'contact-form-7' ),
		__( 'Editing form template', 'contact-form-7' ) );
	$description = __( "You can edit the form template here. For details, see %s.", 'contact-form-7' );
	$description = sprintf( esc_html( $description ), $desc_link );
?>

<h2><?php echo esc_html( __( 'Form', 'contact-form-7' ) ); ?></h2>

<fieldset>
<legend><?php echo $description; ?></legend>

<?php
	$tag_generator = WPCF7_TagGenerator::get_instance();
	$tag_generator->print_buttons();
?>

<textarea id="wpcf7-form" name="wpcf7-form" cols="100" rows="24" class="large-text code" data-config-field="form.body"><?php echo esc_textarea( $post->prop( 'form' ) ); ?></textarea>
</fieldset>
<?php
}

function wpcf7_editor_panel_mail( $post ) {
	wpcf7_editor_box_mail( $post );

	echo '<br class="clear" />';

	wpcf7_editor_box_mail( $post, array(
		'id' => 'wpcf7-mail-2',
		'name' => 'mail_2',
		'title' => __( 'Mail (2)', 'contact-form-7' ),
		'use' => __( 'Use Mail (2)', 'contact-form-7' ),
	) );
}

function wpcf7_editor_box_mail( $post, $options = '' ) {
	$options = wp_parse_args( $options, array(
		'id' => 'wpcf7-mail',
		'name' => 'mail',
		'title' => __( 'Mail', 'contact-form-7' ),
		'use' => null,
	) );

	$id = esc_attr( $options['id'] );

	$mail = wp_parse_args( $post->prop( $options['name'] ), array(
		'active' => false,
		'recipient' => '',
		'sender' => '',
		'subject' => '',
		'body' => '',
		'additional_headers' => '',
		'attachments' => '',
		'use_html' => false,
		'exclude_blank' => false,
	) );

?>
<div class="contact-form-editor-box-mail" id="<?php echo esc_attr( $id ); ?>">
<h2><?php echo esc_html( $options['title'] ); ?></h2>

<?php
	if ( ! empty( $options['use'] ) ) {
		echo sprintf(
			'<label %1$s><input %2$s /> %3$s</label>',
			wpcf7_format_atts( array(
				'for' => sprintf( '%s-active', $id ),
			) ),
			wpcf7_format_atts( array(
				'type' => 'checkbox',
				'id' => sprintf( '%s-active', $id ),
				'name' => sprintf( '%s[active]', $id ),
				'data-config-field' => '',
				'data-toggle' => sprintf( '%s-fieldset', $id ),
				'value' => '1',
				'checked' => $mail['active'],
			) ),
			esc_html( $options['use'] )
		);

		echo sprintf(
			'<p class="description">%s</p>',
			esc_html( __( "Mail (2) is an additional mail template often used as an autoresponder.", 'contact-form-7' ) )
		);
	}
?>

<fieldset id="<?php echo esc_attr( sprintf( '%s-fieldset', $id ) ); ?>">
<legend>
<?php
	$desc_link = wpcf7_link(
		__( 'https://contactform7.com/setting-up-mail/', 'contact-form-7' ),
		__( 'Setting up mail', 'contact-form-7' ) );
	$description = __( "You can edit the mail template here. For details, see %s.", 'contact-form-7' );
	$description = sprintf( esc_html( $description ), $desc_link );
	echo $description;
	echo '<br />';

	echo esc_html( __( "In the following fields, you can use these mail-tags:",
		'contact-form-7' ) );
	echo '<br />';
	$post->suggest_mail_tags( $options['name'] );
?>
</legend>
<table class="form-table">
<tbody>
	<tr>
	<th scope="row">
		<label for="<?php echo $id; ?>-recipient"><?php echo esc_html( __( 'To', 'contact-form-7' ) ); ?></label>
	</th>
	<td>
		<input type="text" id="<?php echo $id; ?>-recipient" name="<?php echo $id; ?>[recipient]" class="large-text code" size="70" value="<?php echo esc_attr( $mail['recipient'] ); ?>" data-config-field="<?php echo sprintf( '%s.recipient', esc_attr( $options['name'] ) ); ?>" />
	</td>
	</tr>

	<tr>
	<th scope="row">
		<label for="<?php echo $id; ?>-sender"><?php echo esc_html( __( 'From', 'contact-form-7' ) ); ?></label>
	</th>
	<td>
		<input type="text" id="<?php echo $id; ?>-sender" name="<?php echo $id; ?>[sender]" class="large-text code" size="70" value="<?php echo esc_attr( $mail['sender'] ); ?>" data-config-field="<?php echo sprintf( '%s.sender', esc_attr( $options['name'] ) ); ?>" />
	</td>
	</tr>

	<tr>
	<th scope="row">
		<label for="<?php echo $id; ?>-subject"><?php echo esc_html( __( 'Subject', 'contact-form-7' ) ); ?></label>
	</th>
	<td>
		<input type="text" id="<?php echo $id; ?>-subject" name="<?php echo $id; ?>[subject]" class="large-text code" size="70" value="<?php echo esc_attr( $mail['subject'] ); ?>" data-config-field="<?php echo sprintf( '%s.subject', esc_attr( $options['name'] ) ); ?>" />
	</td>
	</tr>

	<tr>
	<th scope="row">
		<label for="<?php echo $id; ?>-additional-headers"><?php echo esc_html( __( 'Additional headers', 'contact-form-7' ) ); ?></label>
	</th>
	<td>
		<textarea id="<?php echo $id; ?>-additional-headers" name="<?php echo $id; ?>[additional_headers]" cols="100" rows="4" class="large-text code" data-config-field="<?php echo sprintf( '%s.additional_headers', esc_attr( $options['name'] ) ); ?>"><?php echo esc_textarea( $mail['additional_headers'] ); ?></textarea>
	</td>
	</tr>

	<tr>
	<th scope="row">
		<label for="<?php echo $id; ?>-body"><?php echo esc_html( __( 'Message body', 'contact-form-7' ) ); ?></label>
	</th>
	<td>
		<textarea id="<?php echo $id; ?>-body" name="<?php echo $id; ?>[body]" cols="100" rows="18" class="large-text code" data-config-field="<?php echo sprintf( '%s.body', esc_attr( $options['name'] ) ); ?>"><?php echo esc_textarea( $mail['body'] ); ?></textarea>

		<p><label for="<?php echo $id; ?>-exclude-blank"><input type="checkbox" id="<?php echo $id; ?>-exclude-blank" name="<?php echo $id; ?>[exclude_blank]" value="1"<?php echo ( ! empty( $mail['exclude_blank'] ) ) ? ' checked="checked"' : ''; ?> /> <?php echo esc_html( __( 'Exclude lines with blank mail-tags from output', 'contact-form-7' ) ); ?></label></p>

		<p><label for="<?php echo $id; ?>-use-html"><input type="checkbox" id="<?php echo $id; ?>-use-html" name="<?php echo $id; ?>[use_html]" value="1"<?php echo ( $mail['use_html'] ) ? ' checked="checked"' : ''; ?> /> <?php echo esc_html( __( 'Use HTML content type', 'contact-form-7' ) ); ?></label></p>
	</td>
	</tr>

	<tr>
	<th scope="row">
		<label for="<?php echo $id; ?>-attachments"><?php echo esc_html( __( 'File attachments', 'contact-form-7' ) ); ?></label>
	</th>
	<td>
		<textarea id="<?php echo $id; ?>-attachments" name="<?php echo $id; ?>[attachments]" cols="100" rows="4" class="large-text code" data-config-field="<?php echo sprintf( '%s.attachments', esc_attr( $options['name'] ) ); ?>"><?php echo esc_textarea( $mail['attachments'] ); ?></textarea>
	</td>
	</tr>
</tbody>
</table>
</fieldset>
</div>
<?php
}

function wpcf7_editor_panel_messages( $post ) {
	$desc_link = wpcf7_link(
		__( 'https://contactform7.com/editing-messages/', 'contact-form-7' ),
		__( 'Editing messages', 'contact-form-7' ) );
	$description = __( "You can edit messages used in various situations here. For details, see %s.", 'contact-form-7' );
	$description = sprintf( esc_html( $description ), $desc_link );

	$messages = wpcf7_messages();

	if ( isset( $messages['captcha_not_match'] )
	and ! wpcf7_use_really_simple_captcha() ) {
		unset( $messages['captcha_not_match'] );
	}

?>
<h2><?php echo esc_html( __( 'Messages', 'contact-form-7' ) ); ?></h2>
<fieldset>
<legend><?php echo $description; ?></legend>
<?php

	foreach ( $messages as $key => $arr ) {
		$field_id = sprintf( 'wpcf7-message-%s', strtr( $key, '_', '-' ) );
		$field_name = sprintf( 'wpcf7-messages[%s]', $key );

?>
<p class="description">
<label for="<?php echo $field_id; ?>"><?php echo esc_html( $arr['description'] ); ?><br />
<input type="text" id="<?php echo $field_id; ?>" name="<?php echo $field_name; ?>" class="large-text" size="70" value="<?php echo esc_attr( $post->message( $key, false ) ); ?>" data-config-field="<?php echo sprintf( 'messages.%s', esc_attr( $key ) ); ?>" />
</label>
</p>
<?php
	}
?>
</fieldset>
<?php
}

function wpcf7_editor_panel_additional_settings( $post ) {
	$desc_link = wpcf7_link(
		__( 'https://contactform7.com/additional-settings/', 'contact-form-7' ),
		__( 'Additional settings', 'contact-form-7' ) );
	$description = __( "You can add customization code snippets here. For details, see %s.", 'contact-form-7' );
	$description = sprintf( esc_html( $description ), $desc_link );

?>
<h2><?php echo esc_html( __( 'Additional Settings', 'contact-form-7' ) ); ?></h2>
<fieldset>
<legend><?php echo $description; ?></legend>
<textarea id="wpcf7-additional-settings" name="wpcf7-additional-settings" cols="100" rows="8" class="large-text" data-config-field="additional_settings.body"><?php echo esc_textarea( $post->prop( 'additional_settings' ) ); ?></textarea>
</fieldset>
<?php
}
admin/includes/help-tabs.php000064400000015534147510545420012051 0ustar00<?php

class WPCF7_Help_Tabs {

	private $screen;

	public function __construct( WP_Screen $screen ) {
		$this->screen = $screen;
	}

	public function set_help_tabs( $screen_type ) {
		switch ( $screen_type ) {
			case 'list':
				$this->screen->add_help_tab( array(
					'id' => 'list_overview',
					'title' => __( 'Overview', 'contact-form-7' ),
					'content' => $this->content( 'list_overview' ),
				) );

				$this->screen->add_help_tab( array(
					'id' => 'list_available_actions',
					'title' => __( 'Available Actions', 'contact-form-7' ),
					'content' => $this->content( 'list_available_actions' ),
				) );

				$this->sidebar();

				return;
			case 'edit':
				$this->screen->add_help_tab( array(
					'id' => 'edit_overview',
					'title' => __( 'Overview', 'contact-form-7' ),
					'content' => $this->content( 'edit_overview' ),
				) );

				$this->screen->add_help_tab( array(
					'id' => 'edit_form_tags',
					'title' => __( 'Form-tags', 'contact-form-7' ),
					'content' => $this->content( 'edit_form_tags' ),
				) );

				$this->screen->add_help_tab( array(
					'id' => 'edit_mail_tags',
					'title' => __( 'Mail-tags', 'contact-form-7' ),
					'content' => $this->content( 'edit_mail_tags' ),
				) );

				$this->sidebar();

				return;
			case 'integration':
				$this->screen->add_help_tab( array(
					'id' => 'integration_overview',
					'title' => __( 'Overview', 'contact-form-7' ),
					'content' => $this->content( 'integration_overview' ),
				) );

				$this->sidebar();

				return;
		}
	}

	private function content( $name ) {
		$content = array();

		$content['list_overview'] = '<p>' . __( "On this screen, you can manage contact forms provided by Contact Form 7. You can manage an unlimited number of contact forms. Each contact form has a unique ID and Contact Form 7 shortcode ([contact-form-7 ...]). To insert a contact form into a post or a text widget, insert the shortcode into the target.", 'contact-form-7' ) . '</p>';

		$content['list_available_actions'] = '<p>' . __( "Hovering over a row in the contact forms list will display action links that allow you to manage your contact form. You can perform the following actions:", 'contact-form-7' ) . '</p>';
		$content['list_available_actions'] .= '<p>' . __( "<strong>Edit</strong> - Navigates to the editing screen for that contact form. You can also reach that screen by clicking on the contact form title.", 'contact-form-7' ) . '</p>';
		$content['list_available_actions'] .= '<p>' . __( "<strong>Duplicate</strong> - Clones that contact form. A cloned contact form inherits all content from the original, but has a different ID.", 'contact-form-7' ) . '</p>';

		$content['edit_overview'] = '<p>' . __( "On this screen, you can edit a contact form. A contact form is comprised of the following components:", 'contact-form-7' ) . '</p>';
		$content['edit_overview'] .= '<p>' . __( "<strong>Title</strong> is the title of a contact form. This title is only used for labeling a contact form, and can be edited.", 'contact-form-7' ) . '</p>';
		$content['edit_overview'] .= '<p>' . __( "<strong>Form</strong> is a content of HTML form. You can use arbitrary HTML, which is allowed inside a form element. You can also use Contact Form 7&#8217;s form-tags here.", 'contact-form-7' ) . '</p>';
		$content['edit_overview'] .= '<p>' . __( "<strong>Mail</strong> manages a mail template (headers and message body) that this contact form will send when users submit it. You can use Contact Form 7&#8217;s mail-tags here.", 'contact-form-7' ) . '</p>';
		$content['edit_overview'] .= '<p>' . __( "<strong>Mail (2)</strong> is an additional mail template that works similar to Mail. Mail (2) is different in that it is sent only when Mail has been sent successfully.", 'contact-form-7' ) . '</p>';
		$content['edit_overview'] .= '<p>' . __( "In <strong>Messages</strong>, you can edit various types of messages used for this contact form. These messages are relatively short messages, like a validation error message you see when you leave a required field blank.", 'contact-form-7' ) . '</p>';
		$content['edit_overview'] .= '<p>' . __( "<strong>Additional Settings</strong> provides a place where you can customize the behavior of this contact form by adding code snippets.", 'contact-form-7' ) . '</p>';

		$content['edit_form_tags'] = '<p>' . __( "A form-tag is a short code enclosed in square brackets used in a form content. A form-tag generally represents an input field, and its components can be separated into four parts: type, name, options, and values. Contact Form 7 supports several types of form-tags including text fields, number fields, date fields, checkboxes, radio buttons, menus, file-uploading fields, CAPTCHAs, and quiz fields.", 'contact-form-7' ) . '</p>';
		$content['edit_form_tags'] .= '<p>' . __( "While form-tags have a comparatively complex syntax, you do not need to know the syntax to add form-tags because you can use the straightforward tag generator (<strong>Generate Tag</strong> button on this screen).", 'contact-form-7' ) . '</p>';

		$content['edit_mail_tags'] = '<p>' . __( "A mail-tag is also a short code enclosed in square brackets that you can use in every Mail and Mail (2) field. A mail-tag represents a user input value through an input field of a corresponding form-tag.", 'contact-form-7' ) . '</p>';
		$content['edit_mail_tags'] .= '<p>' . __( "There are also special mail-tags that have specific names, but do not have corresponding form-tags. They are used to represent meta information of form submissions like the submitter&#8217;s IP address or the URL of the page.", 'contact-form-7' ) . '</p>';

		$content['integration_overview'] = '<p>' . __( "On this screen, you can manage services that are available through Contact Form 7. Using API will allow you to collaborate with any services that are available.", 'contact-form-7' ) . '</p>';
		$content['integration_overview'] .= '<p>' . __( "You may need to first sign up for an account with the service that you plan to use. When you do so, you would need to authorize Contact Form 7 to access the service with your account.", 'contact-form-7' ) . '</p>';
		$content['integration_overview'] .= '<p>' . __( "Any information you provide will not be shared with service providers without your authorization.", 'contact-form-7' ) . '</p>';

		if ( ! empty( $content[$name] ) ) {
			return $content[$name];
		}
	}

	public function sidebar() {
		$content = '<p><strong>' . __( 'For more information:', 'contact-form-7' ) . '</strong></p>';
		$content .= '<p>' . wpcf7_link( __( 'https://contactform7.com/docs/', 'contact-form-7' ), __( 'Docs', 'contact-form-7' ) ) . '</p>';
		$content .= '<p>' . wpcf7_link( __( 'https://contactform7.com/faq/', 'contact-form-7' ), __( 'FAQ', 'contact-form-7' ) ) . '</p>';
		$content .= '<p>' . wpcf7_link( __( 'https://contactform7.com/support/', 'contact-form-7' ), __( 'Support', 'contact-form-7' ) ) . '</p>';

		$this->screen->set_help_sidebar( $content );
	}
}
license.txt000064400000046070147510545420006745 0ustar00Contact Form 7 WordPress Plugin, 2007-2025 Takayuki Miyoshi
Contact Form 7 is distributed under the terms of the GNU GPL

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA


Contact Form 7 WordPress Plugin bundles the following third-party resources:

The official icon designed by Cheung Vong
https://contactform7.com/2020/04/08/new-official-logo/


=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

                    GNU GENERAL PUBLIC LICENSE
                       Version 2, June 1991

 Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

                            Preamble

  The licenses for most software are designed to take away your
freedom to share and change it.  By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users.  This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it.  (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.)  You can apply it to
your programs, too.

  When we speak of free software, we are referring to freedom, not
price.  Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.

  To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.

  For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have.  You must make sure that they, too, receive or can get the
source code.  And you must show them these terms so they know their
rights.

  We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.

  Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software.  If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.

  Finally, any free program is threatened constantly by software
patents.  We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary.  To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.

  The precise terms and conditions for copying, distribution and
modification follow.

                    GNU GENERAL PUBLIC LICENSE
   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

  0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License.  The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language.  (Hereinafter, translation is included without limitation in
the term "modification".)  Each licensee is addressed as "you".

Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope.  The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.

  1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.

You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.

  2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:

    a) You must cause the modified files to carry prominent notices
    stating that you changed the files and the date of any change.

    b) You must cause any work that you distribute or publish, that in
    whole or in part contains or is derived from the Program or any
    part thereof, to be licensed as a whole at no charge to all third
    parties under the terms of this License.

    c) If the modified program normally reads commands interactively
    when run, you must cause it, when started running for such
    interactive use in the most ordinary way, to print or display an
    announcement including an appropriate copyright notice and a
    notice that there is no warranty (or else, saying that you provide
    a warranty) and that users may redistribute the program under
    these conditions, and telling the user how to view a copy of this
    License.  (Exception: if the Program itself is interactive but
    does not normally print such an announcement, your work based on
    the Program is not required to print an announcement.)

These requirements apply to the modified work as a whole.  If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works.  But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.

Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.

In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.

  3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:

    a) Accompany it with the complete corresponding machine-readable
    source code, which must be distributed under the terms of Sections
    1 and 2 above on a medium customarily used for software interchange; or,

    b) Accompany it with a written offer, valid for at least three
    years, to give any third party, for a charge no more than your
    cost of physically performing source distribution, a complete
    machine-readable copy of the corresponding source code, to be
    distributed under the terms of Sections 1 and 2 above on a medium
    customarily used for software interchange; or,

    c) Accompany it with the information you received as to the offer
    to distribute corresponding source code.  (This alternative is
    allowed only for noncommercial distribution and only if you
    received the program in object code or executable form with such
    an offer, in accord with Subsection b above.)

The source code for a work means the preferred form of the work for
making modifications to it.  For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable.  However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.

If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.

  4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License.  Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.

  5. You are not required to accept this License, since you have not
signed it.  However, nothing else grants you permission to modify or
distribute the Program or its derivative works.  These actions are
prohibited by law if you do not accept this License.  Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.

  6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions.  You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.

  7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all.  For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.

If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.

It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices.  Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.

This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.

  8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded.  In such case, this License incorporates
the limitation as if written in the body of this License.

  9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time.  Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.

Each version is given a distinguishing version number.  If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation.  If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.

  10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission.  For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this.  Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.

                            NO WARRANTY

  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.

  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.

                     END OF TERMS AND CONDITIONS

            How to Apply These Terms to Your New Programs

  If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.

  To do so, attach the following notices to the program.  It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.

    <one line to give the program's name and a brief idea of what it does.>
    Copyright (C) <year>  <name of author>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License along
    with this program; if not, write to the Free Software Foundation, Inc.,
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

Also add information on how to contact you by electronic and paper mail.

If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:

    Gnomovision version 69, Copyright (C) year name of author
    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
    This is free software, and you are welcome to redistribute it
    under certain conditions; type `show c' for details.

The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License.  Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.

You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary.  Here is a sample; alter the names:

  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
  `Gnomovision' (which makes passes at compilers) written by James Hacker.

  <signature of Ty Coon>, 1 April 1989
  Ty Coon, President of Vice

This General Public License does not permit incorporating your program into
proprietary programs.  If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library.  If this is what you want to do, use the GNU Lesser General
Public License instead of this License.
© 2025 GrazzMean