/home/fresvfqn/waterdamagerestorationandrepairsmithtown.com/Compressed/add-ons.tar
snmp_monitoring/litespeed_cacti_template.xml000064400000246546150545647700015562 0ustar00<cacti>	
	<hash_020016cc93c4e8ed28d5a5e98f795a6abf0626>
		<name>LiteSpeed</name>
		<graph_templates>hash_00001616ed2d0aa716489be372dd598afe0b9e|hash_000016022aa61c315e6588a6acd2c013fcf5c5|hash_000016974ad3f65464268b1e61142e1d377048|hash_000016bac5833ec4bd88e46603947c40f163dd|hash_0000164740ee10c62708a97452e64c39918381|hash_0000160ec40ca42977e0f88770a13629862650|hash_000016a85d4e176d782c3bef5da7ed00cce513</graph_templates>
		<data_queries>hash_040016e423847310ebee7dc22eaf3938d709f9|hash_04001676d81d4e3c52dab62afa5205a9c517a2|hash_040016c6bc8ced2a4d8fac0fde1c0cead29779</data_queries>
	</hash_020016cc93c4e8ed28d5a5e98f795a6abf0626>
	<hash_00001616ed2d0aa716489be372dd598afe0b9e>
		<name>LiteSpeed: Vhost</name>
		<graph>
			<t_title>on</t_title>
			<title></title>
			<t_image_format_id></t_image_format_id>
			<image_format_id>1</image_format_id>
			<t_height></t_height>
			<height>120</height>
			<t_width></t_width>
			<width>500</width>
			<t_slope_mode>0</t_slope_mode>
			<slope_mode>on</slope_mode>
			<t_auto_scale></t_auto_scale>
			<auto_scale>on</auto_scale>
			<t_auto_scale_opts></t_auto_scale_opts>
			<auto_scale_opts>2</auto_scale_opts>
			<t_auto_scale_log></t_auto_scale_log>
			<auto_scale_log></auto_scale_log>
			<t_scale_log_units>0</t_scale_log_units>
			<scale_log_units></scale_log_units>
			<t_auto_scale_rigid></t_auto_scale_rigid>
			<auto_scale_rigid>on</auto_scale_rigid>
			<t_auto_padding></t_auto_padding>
			<auto_padding>on</auto_padding>
			<t_export></t_export>
			<export>on</export>
			<t_upper_limit></t_upper_limit>
			<upper_limit>100</upper_limit>
			<t_lower_limit></t_lower_limit>
			<lower_limit>0</lower_limit>
			<t_base_value></t_base_value>
			<base_value>1000</base_value>
			<t_unit_value></t_unit_value>
			<unit_value></unit_value>
			<t_unit_exponent_value></t_unit_exponent_value>
			<unit_exponent_value></unit_exponent_value>
			<t_vertical_label></t_vertical_label>
			<vertical_label>requests</vertical_label>
		</graph>
		<items>
			<hash_1000168bfdc71ae071c75aae9c3149d293f31c>
				<task_item_id>hash_08001676fbeb01ef35493c81578394cdc9f453</task_item_id>
				<color_id>96E78A</color_id>
				<alpha>FF</alpha>
				<graph_type_id>7</graph_type_id>
				<consolidation_function_id>1</consolidation_function_id>
				<cdef_id>0</cdef_id>
				<value></value>
				<gprint_id>hash_060016e9c43831e54eca8069317a2ce8c6f751</gprint_id>
				<text_format>ReqInProcess</text_format>
				<hard_return></hard_return>
				<sequence>1</sequence>
			</hash_1000168bfdc71ae071c75aae9c3149d293f31c>
			<hash_10001660a88c66c7825785f62cbf9862ea1a79>
				<task_item_id>hash_08001676fbeb01ef35493c81578394cdc9f453</task_item_id>
				<color_id>0</color_id>
				<alpha>FF</alpha>
				<graph_type_id>9</graph_type_id>
				<consolidation_function_id>4</consolidation_function_id>
				<cdef_id>0</cdef_id>
				<value></value>
				<gprint_id>hash_060016e9c43831e54eca8069317a2ce8c6f751</gprint_id>
				<text_format>Now:</text_format>
				<hard_return></hard_return>
				<sequence>2</sequence>
			</hash_10001660a88c66c7825785f62cbf9862ea1a79>
			<hash_10001640f32c86f322d1449574cbf972a360c3>
				<task_item_id>hash_08001676fbeb01ef35493c81578394cdc9f453</task_item_id>
				<color_id>0</color_id>
				<alpha>FF</alpha>
				<graph_type_id>9</graph_type_id>
				<consolidation_function_id>1</consolidation_function_id>
				<cdef_id>0</cdef_id>
				<value></value>
				<gprint_id>hash_060016e9c43831e54eca8069317a2ce8c6f751</gprint_id>
				<text_format>Avg:</text_format>
				<hard_return></hard_return>
				<sequence>3</sequence>
			</hash_10001640f32c86f322d1449574cbf972a360c3>
			<hash_100016385c598ee928ce0a6438d491777d8cfa>
				<task_item_id>hash_08001676fbeb01ef35493c81578394cdc9f453</task_item_id>
				<color_id>0</color_id>
				<alpha>FF</alpha>
				<graph_type_id>9</graph_type_id>
				<consolidation_function_id>3</consolidation_function_id>
				<cdef_id>0</cdef_id>
				<value></value>
				<gprint_id>hash_060016e9c43831e54eca8069317a2ce8c6f751</gprint_id>
				<text_format>Max:</text_format>
				<hard_return>on</hard_return>
				<sequence>4</sequence>
			</hash_100016385c598ee928ce0a6438d491777d8cfa>
			<hash_100016ca50796bc2609bcc2aa3617ab23196ae>
				<task_item_id>hash_080016e5084b9e07fdcc5535637f75b8af3222</task_item_id>
				<color_id>0D006A</color_id>
				<alpha>FF</alpha>
				<graph_type_id>4</graph_type_id>
				<consolidation_function_id>1</consolidation_function_id>
				<cdef_id>0</cdef_id>
				<value></value>
				<gprint_id>hash_060016e9c43831e54eca8069317a2ce8c6f751</gprint_id>
				<text_format>ReqPerSecond</text_format>
				<hard_return></hard_return>
				<sequence>5</sequence>
			</hash_100016ca50796bc2609bcc2aa3617ab23196ae>
			<hash_10001649e23d20228afc3ce8f4687a6e5498ce>
				<task_item_id>hash_080016e5084b9e07fdcc5535637f75b8af3222</task_item_id>
				<color_id>0</color_id>
				<alpha>FF</alpha>
				<graph_type_id>9</graph_type_id>
				<consolidation_function_id>4</consolidation_function_id>
				<cdef_id>0</cdef_id>
				<value></value>
				<gprint_id>hash_060016e9c43831e54eca8069317a2ce8c6f751</gprint_id>
				<text_format>Now:</text_format>
				<hard_return></hard_return>
				<sequence>6</sequence>
			</hash_10001649e23d20228afc3ce8f4687a6e5498ce>
			<hash_100016eb44c7ac124e6b165c878cbbc0f7d073>
				<task_item_id>hash_080016e5084b9e07fdcc5535637f75b8af3222</task_item_id>
				<color_id>0</color_id>
				<alpha>FF</alpha>
				<graph_type_id>9</graph_type_id>
				<consolidation_function_id>1</consolidation_function_id>
				<cdef_id>0</cdef_id>
				<value></value>
				<gprint_id>hash_060016e9c43831e54eca8069317a2ce8c6f751</gprint_id>
				<text_format>Avg:</text_format>
				<hard_return></hard_return>
				<sequence>7</sequence>
			</hash_100016eb44c7ac124e6b165c878cbbc0f7d073>
			<hash_100016c44b1ad8a111114b67eb73349e680b24>
				<task_item_id>hash_080016e5084b9e07fdcc5535637f75b8af3222</task_item_id>
				<color_id>0</color_id>
				<alpha>FF</alpha>
				<graph_type_id>9</graph_type_id>
				<consolidation_function_id>3</consolidation_function_id>
				<cdef_id>0</cdef_id>
				<value></value>
				<gprint_id>hash_060016e9c43831e54eca8069317a2ce8c6f751</gprint_id>
				<text_format>Max:</text_format>
				<hard_return>on</hard_return>
				<sequence>8</sequence>
			</hash_100016c44b1ad8a111114b67eb73349e680b24>
		</items>
		<inputs>
			<hash_090016302d9068165758c4f42aba130d289b98>
				<name>Data Source [Req_Second]</name>
				<description></description>
				<column_name>task_item_id</column_name>
				<items>hash_000016ca50796bc2609bcc2aa3617ab23196ae|hash_00001649e23d20228afc3ce8f4687a6e5498ce|hash_000016eb44c7ac124e6b165c878cbbc0f7d073|hash_000016c44b1ad8a111114b67eb73349e680b24</items>
			</hash_090016302d9068165758c4f42aba130d289b98>
			<hash_09001670dd359a25dfb9c3e6d2faef544d61dd>
				<name>Data Source [Req_InProcess]</name>
				<description></description>
				<column_name>task_item_id</column_name>
				<items>hash_0000168bfdc71ae071c75aae9c3149d293f31c|hash_00001660a88c66c7825785f62cbf9862ea1a79|hash_00001640f32c86f322d1449574cbf972a360c3|hash_000016385c598ee928ce0a6438d491777d8cfa</items>
			</hash_09001670dd359a25dfb9c3e6d2faef544d61dd>
		</inputs>
	</hash_00001616ed2d0aa716489be372dd598afe0b9e>
	<hash_000016022aa61c315e6588a6acd2c013fcf5c5>
		<name>LiteSpeed: ExtApp: Connections</name>
		<graph>
			<t_title>on</t_title>
			<title></title>
			<t_image_format_id></t_image_format_id>
			<image_format_id>1</image_format_id>
			<t_height></t_height>
			<height>120</height>
			<t_width></t_width>
			<width>500</width>
			<t_slope_mode>0</t_slope_mode>
			<slope_mode>on</slope_mode>
			<t_auto_scale></t_auto_scale>
			<auto_scale>on</auto_scale>
			<t_auto_scale_opts></t_auto_scale_opts>
			<auto_scale_opts>2</auto_scale_opts>
			<t_auto_scale_log></t_auto_scale_log>
			<auto_scale_log></auto_scale_log>
			<t_scale_log_units>0</t_scale_log_units>
			<scale_log_units></scale_log_units>
			<t_auto_scale_rigid></t_auto_scale_rigid>
			<auto_scale_rigid></auto_scale_rigid>
			<t_auto_padding></t_auto_padding>
			<auto_padding>on</auto_padding>
			<t_export></t_export>
			<export>on</export>
			<t_upper_limit></t_upper_limit>
			<upper_limit>100</upper_limit>
			<t_lower_limit></t_lower_limit>
			<lower_limit>0</lower_limit>
			<t_base_value></t_base_value>
			<base_value>1000</base_value>
			<t_unit_value></t_unit_value>
			<unit_value></unit_value>
			<t_unit_exponent_value></t_unit_exponent_value>
			<unit_exponent_value></unit_exponent_value>
			<t_vertical_label></t_vertical_label>
			<vertical_label>connections</vertical_label>
		</graph>
		<items>
			<hash_1000162847edc56a65520b49fb4502906b87fc>
				<task_item_id>hash_08001624140062cfa9de88c593a71be9a40e0f</task_item_id>
				<color_id>96E78A</color_id>
				<alpha>FF</alpha>
				<graph_type_id>7</graph_type_id>
				<consolidation_function_id>1</consolidation_function_id>
				<cdef_id>0</cdef_id>
				<value></value>
				<gprint_id>hash_060016e9c43831e54eca8069317a2ce8c6f751</gprint_id>
				<text_format>PoolSize</text_format>
				<hard_return></hard_return>
				<sequence>5</sequence>
			</hash_1000162847edc56a65520b49fb4502906b87fc>
			<hash_100016c6e41c42776fc4f991e184accb66a94d>
				<task_item_id>hash_08001624140062cfa9de88c593a71be9a40e0f</task_item_id>
				<color_id>0</color_id>
				<alpha>FF</alpha>
				<graph_type_id>9</graph_type_id>
				<consolidation_function_id>4</consolidation_function_id>
				<cdef_id>0</cdef_id>
				<value></value>
				<gprint_id>hash_060016e9c43831e54eca8069317a2ce8c6f751</gprint_id>
				<text_format>Now:</text_format>
				<hard_return></hard_return>
				<sequence>6</sequence>
			</hash_100016c6e41c42776fc4f991e184accb66a94d>
			<hash_1000160698540d26180f8b9cfcbd8fb4e4d777>
				<task_item_id>hash_08001624140062cfa9de88c593a71be9a40e0f</task_item_id>
				<color_id>0</color_id>
				<alpha>FF</alpha>
				<graph_type_id>9</graph_type_id>
				<consolidation_function_id>1</consolidation_function_id>
				<cdef_id>0</cdef_id>
				<value></value>
				<gprint_id>hash_060016e9c43831e54eca8069317a2ce8c6f751</gprint_id>
				<text_format>Avg:</text_format>
				<hard_return></hard_return>
				<sequence>7</sequence>
			</hash_1000160698540d26180f8b9cfcbd8fb4e4d777>
			<hash_100016799d4a164aa6bfe721c97520a2f659d6>
				<task_item_id>hash_08001624140062cfa9de88c593a71be9a40e0f</task_item_id>
				<color_id>0</color_id>
				<alpha>FF</alpha>
				<graph_type_id>9</graph_type_id>
				<consolidation_function_id>3</consolidation_function_id>
				<cdef_id>0</cdef_id>
				<value></value>
				<gprint_id>hash_060016e9c43831e54eca8069317a2ce8c6f751</gprint_id>
				<text_format>Max:</text_format>
				<hard_return>on</hard_return>
				<sequence>8</sequence>
			</hash_100016799d4a164aa6bfe721c97520a2f659d6>
			<hash_100016862bfd905333aaf128e3554b0f6fccf1>
				<task_item_id>hash_080016dca7bbae358416c8a86fd74cc83104d8</task_item_id>
				<color_id>FFF200</color_id>
				<alpha>FF</alpha>
				<graph_type_id>7</graph_type_id>
				<consolidation_function_id>1</consolidation_function_id>
				<cdef_id>0</cdef_id>
				<value></value>
				<gprint_id>hash_060016e9c43831e54eca8069317a2ce8c6f751</gprint_id>
				<text_format>InuseConn</text_format>
				<hard_return></hard_return>
				<sequence>9</sequence>
			</hash_100016862bfd905333aaf128e3554b0f6fccf1>
			<hash_100016474c6967780fa055ea1978443030158b>
				<task_item_id>hash_080016dca7bbae358416c8a86fd74cc83104d8</task_item_id>
				<color_id>0</color_id>
				<alpha>FF</alpha>
				<graph_type_id>9</graph_type_id>
				<consolidation_function_id>4</consolidation_function_id>
				<cdef_id>0</cdef_id>
				<value></value>
				<gprint_id>hash_060016e9c43831e54eca8069317a2ce8c6f751</gprint_id>
				<text_format>Now:</text_format>
				<hard_return></hard_return>
				<sequence>10</sequence>
			</hash_100016474c6967780fa055ea1978443030158b>
			<hash_1000169c9b88c77904394b6f986e4c1d7c550f>
				<task_item_id>hash_080016dca7bbae358416c8a86fd74cc83104d8</task_item_id>
				<color_id>0</color_id>
				<alpha>FF</alpha>
				<graph_type_id>9</graph_type_id>
				<consolidation_function_id>1</consolidation_function_id>
				<cdef_id>0</cdef_id>
				<value></value>
				<gprint_id>hash_060016e9c43831e54eca8069317a2ce8c6f751</gprint_id>
				<text_format>Avg:</text_format>
				<hard_return></hard_return>
				<sequence>11</sequence>
			</hash_1000169c9b88c77904394b6f986e4c1d7c550f>
			<hash_100016d1bf02c6483524d7c49f5a42f7a140bf>
				<task_item_id>hash_080016dca7bbae358416c8a86fd74cc83104d8</task_item_id>
				<color_id>0</color_id>
				<alpha>FF</alpha>
				<graph_type_id>9</graph_type_id>
				<consolidation_function_id>3</consolidation_function_id>
				<cdef_id>0</cdef_id>
				<value></value>
				<gprint_id>hash_060016e9c43831e54eca8069317a2ce8c6f751</gprint_id>
				<text_format>Max:</text_format>
				<hard_return>on</hard_return>
				<sequence>12</sequence>
			</hash_100016d1bf02c6483524d7c49f5a42f7a140bf>
			<hash_1000168d7dc073783d9d1ca3792a691a9f1990>
				<task_item_id>hash_080016dd80f6a8dac8166b110503ac3cdbe991</task_item_id>
				<color_id>FF0000</color_id>
				<alpha>FF</alpha>
				<graph_type_id>4</graph_type_id>
				<consolidation_function_id>1</consolidation_function_id>
				<cdef_id>0</cdef_id>
				<value></value>
				<gprint_id>hash_060016e9c43831e54eca8069317a2ce8c6f751</gprint_id>
				<text_format>WaitQDepth:</text_format>
				<hard_return></hard_return>
				<sequence>17</sequence>
			</hash_1000168d7dc073783d9d1ca3792a691a9f1990>
			<hash_10001695799553d57884eb493946e45f6765f5>
				<task_item_id>hash_080016dd80f6a8dac8166b110503ac3cdbe991</task_item_id>
				<color_id>0</color_id>
				<alpha>FF</alpha>
				<graph_type_id>9</graph_type_id>
				<consolidation_function_id>4</consolidation_function_id>
				<cdef_id>0</cdef_id>
				<value></value>
				<gprint_id>hash_060016e9c43831e54eca8069317a2ce8c6f751</gprint_id>
				<text_format>Now:</text_format>
				<hard_return></hard_return>
				<sequence>18</sequence>
			</hash_10001695799553d57884eb493946e45f6765f5>
			<hash_100016d1cbd5717a1716c1bed5cf8eeca4e377>
				<task_item_id>hash_080016dd80f6a8dac8166b110503ac3cdbe991</task_item_id>
				<color_id>0</color_id>
				<alpha>FF</alpha>
				<graph_type_id>9</graph_type_id>
				<consolidation_function_id>1</consolidation_function_id>
				<cdef_id>0</cdef_id>
				<value></value>
				<gprint_id>hash_060016e9c43831e54eca8069317a2ce8c6f751</gprint_id>
				<text_format>Avg:</text_format>
				<hard_return></hard_return>
				<sequence>19</sequence>
			</hash_100016d1cbd5717a1716c1bed5cf8eeca4e377>
			<hash_1000164daa3e9aaf8c673f50536ba33fda11c3>
				<task_item_id>hash_080016dd80f6a8dac8166b110503ac3cdbe991</task_item_id>
				<color_id>0</color_id>
				<alpha>FF</alpha>
				<graph_type_id>9</graph_type_id>
				<consolidation_function_id>3</consolidation_function_id>
				<cdef_id>0</cdef_id>
				<value></value>
				<gprint_id>hash_060016e9c43831e54eca8069317a2ce8c6f751</gprint_id>
				<text_format>Max:</text_format>
				<hard_return>on</hard_return>
				<sequence>20</sequence>
			</hash_1000164daa3e9aaf8c673f50536ba33fda11c3>
		</items>
		<inputs>
			<hash_09001688bcfe946ca142b3b9897d1147785f53>
				<name>Data Source [InuseConn]</name>
				<description></description>
				<column_name>task_item_id</column_name>
				<items>hash_000016862bfd905333aaf128e3554b0f6fccf1|hash_000016474c6967780fa055ea1978443030158b|hash_0000169c9b88c77904394b6f986e4c1d7c550f|hash_000016d1bf02c6483524d7c49f5a42f7a140bf</items>
			</hash_09001688bcfe946ca142b3b9897d1147785f53>
			<hash_0900163a0092d7dfedec449bfd35cd3e79431f>
				<name>Data Source [PoolSize]</name>
				<description></description>
				<column_name>task_item_id</column_name>
				<items>hash_0000162847edc56a65520b49fb4502906b87fc|hash_000016c6e41c42776fc4f991e184accb66a94d|hash_0000160698540d26180f8b9cfcbd8fb4e4d777|hash_000016799d4a164aa6bfe721c97520a2f659d6</items>
			</hash_0900163a0092d7dfedec449bfd35cd3e79431f>
			<hash_090016638e486a9fae9dc73ea8c125d031a79e>
				<name>Data Source [WaitQueueDepth]</name>
				<description></description>
				<column_name>task_item_id</column_name>
				<items>hash_0000168d7dc073783d9d1ca3792a691a9f1990|hash_00001695799553d57884eb493946e45f6765f5|hash_000016d1cbd5717a1716c1bed5cf8eeca4e377|hash_0000164daa3e9aaf8c673f50536ba33fda11c3</items>
			</hash_090016638e486a9fae9dc73ea8c125d031a79e>
		</inputs>
	</hash_000016022aa61c315e6588a6acd2c013fcf5c5>
	<hash_000016974ad3f65464268b1e61142e1d377048>
		<name>LiteSpeed: ExtApp: Requests</name>
		<graph>
			<t_title>on</t_title>
			<title></title>
			<t_image_format_id></t_image_format_id>
			<image_format_id>1</image_format_id>
			<t_height></t_height>
			<height>120</height>
			<t_width></t_width>
			<width>500</width>
			<t_slope_mode>0</t_slope_mode>
			<slope_mode>on</slope_mode>
			<t_auto_scale></t_auto_scale>
			<auto_scale>on</auto_scale>
			<t_auto_scale_opts></t_auto_scale_opts>
			<auto_scale_opts>2</auto_scale_opts>
			<t_auto_scale_log></t_auto_scale_log>
			<auto_scale_log></auto_scale_log>
			<t_scale_log_units>0</t_scale_log_units>
			<scale_log_units></scale_log_units>
			<t_auto_scale_rigid></t_auto_scale_rigid>
			<auto_scale_rigid>on</auto_scale_rigid>
			<t_auto_padding></t_auto_padding>
			<auto_padding>on</auto_padding>
			<t_export></t_export>
			<export>on</export>
			<t_upper_limit></t_upper_limit>
			<upper_limit>100</upper_limit>
			<t_lower_limit></t_lower_limit>
			<lower_limit>0</lower_limit>
			<t_base_value></t_base_value>
			<base_value>1000</base_value>
			<t_unit_value></t_unit_value>
			<unit_value></unit_value>
			<t_unit_exponent_value></t_unit_exponent_value>
			<unit_exponent_value></unit_exponent_value>
			<t_vertical_label></t_vertical_label>
			<vertical_label>requests per second</vertical_label>
		</graph>
		<items>
			<hash_100016e408d575f6fefa0f3ebb86bb1c421023>
				<task_item_id>hash_0800165d24f91f2b8d9e5598d1abd567b076f9</task_item_id>
				<color_id>96E78A</color_id>
				<alpha>FF</alpha>
				<graph_type_id>7</graph_type_id>
				<consolidation_function_id>1</consolidation_function_id>
				<cdef_id>0</cdef_id>
				<value></value>
				<gprint_id>hash_060016e9c43831e54eca8069317a2ce8c6f751</gprint_id>
				<text_format>ReqSecond</text_format>
				<hard_return></hard_return>
				<sequence>1</sequence>
			</hash_100016e408d575f6fefa0f3ebb86bb1c421023>
			<hash_1000167c06b950dc598b91af0b80857ff3e0ce>
				<task_item_id>hash_0800165d24f91f2b8d9e5598d1abd567b076f9</task_item_id>
				<color_id>0</color_id>
				<alpha>FF</alpha>
				<graph_type_id>9</graph_type_id>
				<consolidation_function_id>4</consolidation_function_id>
				<cdef_id>0</cdef_id>
				<value></value>
				<gprint_id>hash_060016e9c43831e54eca8069317a2ce8c6f751</gprint_id>
				<text_format>Now:</text_format>
				<hard_return></hard_return>
				<sequence>2</sequence>
			</hash_1000167c06b950dc598b91af0b80857ff3e0ce>
			<hash_10001672dd1f9361d79335392ab947a23a8672>
				<task_item_id>hash_0800165d24f91f2b8d9e5598d1abd567b076f9</task_item_id>
				<color_id>0</color_id>
				<alpha>FF</alpha>
				<graph_type_id>9</graph_type_id>
				<consolidation_function_id>1</consolidation_function_id>
				<cdef_id>0</cdef_id>
				<value></value>
				<gprint_id>hash_060016e9c43831e54eca8069317a2ce8c6f751</gprint_id>
				<text_format>Avg:</text_format>
				<hard_return></hard_return>
				<sequence>3</sequence>
			</hash_10001672dd1f9361d79335392ab947a23a8672>
			<hash_100016899845f77b8725ff772c41dc619208bf>
				<task_item_id>hash_0800165d24f91f2b8d9e5598d1abd567b076f9</task_item_id>
				<color_id>0</color_id>
				<alpha>FF</alpha>
				<graph_type_id>9</graph_type_id>
				<consolidation_function_id>3</consolidation_function_id>
				<cdef_id>0</cdef_id>
				<value></value>
				<gprint_id>hash_060016e9c43831e54eca8069317a2ce8c6f751</gprint_id>
				<text_format>Max:</text_format>
				<hard_return>on</hard_return>
				<sequence>4</sequence>
			</hash_100016899845f77b8725ff772c41dc619208bf>
		</items>
		<inputs>
			<hash_090016d0ce027da50790cad204ffee9aa9d5a3>
				<name>Data Source [Req_Second]</name>
				<description></description>
				<column_name>task_item_id</column_name>
				<items>hash_000016e408d575f6fefa0f3ebb86bb1c421023|hash_0000167c06b950dc598b91af0b80857ff3e0ce|hash_00001672dd1f9361d79335392ab947a23a8672|hash_000016899845f77b8725ff772c41dc619208bf</items>
			</hash_090016d0ce027da50790cad204ffee9aa9d5a3>
		</inputs>
	</hash_000016974ad3f65464268b1e61142e1d377048>
	<hash_000016bac5833ec4bd88e46603947c40f163dd>
		<name>LiteSpeed: Plain Traffic  (bits/sec)</name>
		<graph>
			<t_title>on</t_title>
			<title></title>
			<t_image_format_id></t_image_format_id>
			<image_format_id>1</image_format_id>
			<t_height></t_height>
			<height>120</height>
			<t_width></t_width>
			<width>500</width>
			<t_slope_mode>0</t_slope_mode>
			<slope_mode>on</slope_mode>
			<t_auto_scale></t_auto_scale>
			<auto_scale>on</auto_scale>
			<t_auto_scale_opts></t_auto_scale_opts>
			<auto_scale_opts>2</auto_scale_opts>
			<t_auto_scale_log></t_auto_scale_log>
			<auto_scale_log></auto_scale_log>
			<t_scale_log_units>0</t_scale_log_units>
			<scale_log_units></scale_log_units>
			<t_auto_scale_rigid></t_auto_scale_rigid>
			<auto_scale_rigid></auto_scale_rigid>
			<t_auto_padding></t_auto_padding>
			<auto_padding>on</auto_padding>
			<t_export></t_export>
			<export>on</export>
			<t_upper_limit></t_upper_limit>
			<upper_limit>100</upper_limit>
			<t_lower_limit></t_lower_limit>
			<lower_limit>0</lower_limit>
			<t_base_value></t_base_value>
			<base_value>1000</base_value>
			<t_unit_value></t_unit_value>
			<unit_value></unit_value>
			<t_unit_exponent_value></t_unit_exponent_value>
			<unit_exponent_value></unit_exponent_value>
			<t_vertical_label></t_vertical_label>
			<vertical_label>bits per second</vertical_label>
		</graph>
		<items>
			<hash_1000163a41a41ce3be052d2de210ad8664c53c>
				<task_item_id>hash_0800164a9cc0ba440529238c3bb8606e5991bd</task_item_id>
				<color_id>96E78A</color_id>
				<alpha>FF</alpha>
				<graph_type_id>7</graph_type_id>
				<consolidation_function_id>1</consolidation_function_id>
				<cdef_id>hash_05001662a7a53922548f4f6eac05cad69fbd2d</cdef_id>
				<value></value>
				<gprint_id>hash_060016e9c43831e54eca8069317a2ce8c6f751</gprint_id>
				<text_format>Out</text_format>
				<hard_return></hard_return>
				<sequence>1</sequence>
			</hash_1000163a41a41ce3be052d2de210ad8664c53c>
			<hash_100016591fb1dbdf84593b88aee5d817a10313>
				<task_item_id>hash_0800164a9cc0ba440529238c3bb8606e5991bd</task_item_id>
				<color_id>0</color_id>
				<alpha>FF</alpha>
				<graph_type_id>9</graph_type_id>
				<consolidation_function_id>4</consolidation_function_id>
				<cdef_id>hash_05001662a7a53922548f4f6eac05cad69fbd2d</cdef_id>
				<value></value>
				<gprint_id>hash_060016e9c43831e54eca8069317a2ce8c6f751</gprint_id>
				<text_format>Now:</text_format>
				<hard_return></hard_return>
				<sequence>2</sequence>
			</hash_100016591fb1dbdf84593b88aee5d817a10313>
			<hash_1000162e863f0b0e6929b59647fd12739ffb41>
				<task_item_id>hash_0800164a9cc0ba440529238c3bb8606e5991bd</task_item_id>
				<color_id>0</color_id>
				<alpha>FF</alpha>
				<graph_type_id>9</graph_type_id>
				<consolidation_function_id>1</consolidation_function_id>
				<cdef_id>hash_05001662a7a53922548f4f6eac05cad69fbd2d</cdef_id>
				<value></value>
				<gprint_id>hash_060016e9c43831e54eca8069317a2ce8c6f751</gprint_id>
				<text_format>Avg:</text_format>
				<hard_return></hard_return>
				<sequence>3</sequence>
			</hash_1000162e863f0b0e6929b59647fd12739ffb41>
			<hash_1000169e8d8db2a7c27fadac4c2493fd16b4a9>
				<task_item_id>hash_0800164a9cc0ba440529238c3bb8606e5991bd</task_item_id>
				<color_id>0</color_id>
				<alpha>FF</alpha>
				<graph_type_id>9</graph_type_id>
				<consolidation_function_id>3</consolidation_function_id>
				<cdef_id>hash_05001662a7a53922548f4f6eac05cad69fbd2d</cdef_id>
				<value></value>
				<gprint_id>hash_060016e9c43831e54eca8069317a2ce8c6f751</gprint_id>
				<text_format>Max:</text_format>
				<hard_return>on</hard_return>
				<sequence>4</sequence>
			</hash_1000169e8d8db2a7c27fadac4c2493fd16b4a9>
			<hash_100016fa7923d3e4a1d9b81714804672ef56bf>
				<task_item_id>hash_080016f9bc5dd109ed4ab674746e66a49df3d8</task_item_id>
				<color_id>0D006A</color_id>
				<alpha>FF</alpha>
				<graph_type_id>4</graph_type_id>
				<consolidation_function_id>1</consolidation_function_id>
				<cdef_id>hash_05001662a7a53922548f4f6eac05cad69fbd2d</cdef_id>
				<value></value>
				<gprint_id>hash_060016e9c43831e54eca8069317a2ce8c6f751</gprint_id>
				<text_format>In</text_format>
				<hard_return></hard_return>
				<sequence>5</sequence>
			</hash_100016fa7923d3e4a1d9b81714804672ef56bf>
			<hash_1000160194e34b5b8d59128e6d33d7da5c006d>
				<task_item_id>hash_080016f9bc5dd109ed4ab674746e66a49df3d8</task_item_id>
				<color_id>0</color_id>
				<alpha>FF</alpha>
				<graph_type_id>9</graph_type_id>
				<consolidation_function_id>4</consolidation_function_id>
				<cdef_id>hash_05001662a7a53922548f4f6eac05cad69fbd2d</cdef_id>
				<value></value>
				<gprint_id>hash_060016e9c43831e54eca8069317a2ce8c6f751</gprint_id>
				<text_format>Now:</text_format>
				<hard_return></hard_return>
				<sequence>6</sequence>
			</hash_1000160194e34b5b8d59128e6d33d7da5c006d>
			<hash_100016c522a9937e83fc55b48741b243053fb7>
				<task_item_id>hash_080016f9bc5dd109ed4ab674746e66a49df3d8</task_item_id>
				<color_id>0</color_id>
				<alpha>FF</alpha>
				<graph_type_id>9</graph_type_id>
				<consolidation_function_id>1</consolidation_function_id>
				<cdef_id>hash_05001662a7a53922548f4f6eac05cad69fbd2d</cdef_id>
				<value></value>
				<gprint_id>hash_060016e9c43831e54eca8069317a2ce8c6f751</gprint_id>
				<text_format>Avg:</text_format>
				<hard_return></hard_return>
				<sequence>7</sequence>
			</hash_100016c522a9937e83fc55b48741b243053fb7>
			<hash_100016253c17724a2ac0292de235d1a466009f>
				<task_item_id>hash_080016f9bc5dd109ed4ab674746e66a49df3d8</task_item_id>
				<color_id>0</color_id>
				<alpha>FF</alpha>
				<graph_type_id>9</graph_type_id>
				<consolidation_function_id>3</consolidation_function_id>
				<cdef_id>hash_05001662a7a53922548f4f6eac05cad69fbd2d</cdef_id>
				<value></value>
				<gprint_id>hash_060016e9c43831e54eca8069317a2ce8c6f751</gprint_id>
				<text_format>Max:</text_format>
				<hard_return></hard_return>
				<sequence>8</sequence>
			</hash_100016253c17724a2ac0292de235d1a466009f>
		</items>
		<inputs>
			<hash_0900164588568f92c69e95fc8352b920ce7f4f>
				<name>Data Source [bps_in]</name>
				<description></description>
				<column_name>task_item_id</column_name>
				<items>hash_000016fa7923d3e4a1d9b81714804672ef56bf|hash_0000160194e34b5b8d59128e6d33d7da5c006d|hash_000016c522a9937e83fc55b48741b243053fb7|hash_000016253c17724a2ac0292de235d1a466009f</items>
			</hash_0900164588568f92c69e95fc8352b920ce7f4f>
			<hash_0900165b8d6696ce886bdee684b44e22fff550>
				<name>Data Source [bps_out]</name>
				<description></description>
				<column_name>task_item_id</column_name>
				<items>hash_0000163a41a41ce3be052d2de210ad8664c53c|hash_000016591fb1dbdf84593b88aee5d817a10313|hash_0000162e863f0b0e6929b59647fd12739ffb41|hash_0000169e8d8db2a7c27fadac4c2493fd16b4a9</items>
			</hash_0900165b8d6696ce886bdee684b44e22fff550>
		</inputs>
	</hash_000016bac5833ec4bd88e46603947c40f163dd>
	<hash_0000164740ee10c62708a97452e64c39918381>
		<name>LiteSpeed: SSL Traffic  (bits/sec)</name>
		<graph>
			<t_title>on</t_title>
			<title></title>
			<t_image_format_id></t_image_format_id>
			<image_format_id>1</image_format_id>
			<t_height></t_height>
			<height>120</height>
			<t_width></t_width>
			<width>500</width>
			<t_slope_mode>0</t_slope_mode>
			<slope_mode>on</slope_mode>
			<t_auto_scale></t_auto_scale>
			<auto_scale>on</auto_scale>
			<t_auto_scale_opts></t_auto_scale_opts>
			<auto_scale_opts>2</auto_scale_opts>
			<t_auto_scale_log></t_auto_scale_log>
			<auto_scale_log></auto_scale_log>
			<t_scale_log_units>0</t_scale_log_units>
			<scale_log_units></scale_log_units>
			<t_auto_scale_rigid></t_auto_scale_rigid>
			<auto_scale_rigid></auto_scale_rigid>
			<t_auto_padding></t_auto_padding>
			<auto_padding>on</auto_padding>
			<t_export></t_export>
			<export>on</export>
			<t_upper_limit></t_upper_limit>
			<upper_limit>100</upper_limit>
			<t_lower_limit></t_lower_limit>
			<lower_limit>0</lower_limit>
			<t_base_value></t_base_value>
			<base_value>1000</base_value>
			<t_unit_value></t_unit_value>
			<unit_value></unit_value>
			<t_unit_exponent_value></t_unit_exponent_value>
			<unit_exponent_value></unit_exponent_value>
			<t_vertical_label></t_vertical_label>
			<vertical_label>bits per second</vertical_label>
		</graph>
		<items>
			<hash_100016f1d69f8e4c7b29f8fdea1d5ba158d9b6>
				<task_item_id>hash_0800164d9b25cf1a27c98599313c1000f001b0</task_item_id>
				<color_id>0D006A</color_id>
				<alpha>FF</alpha>
				<graph_type_id>4</graph_type_id>
				<consolidation_function_id>1</consolidation_function_id>
				<cdef_id>hash_05001662a7a53922548f4f6eac05cad69fbd2d</cdef_id>
				<value></value>
				<gprint_id>hash_060016e9c43831e54eca8069317a2ce8c6f751</gprint_id>
				<text_format>In</text_format>
				<hard_return></hard_return>
				<sequence>1</sequence>
			</hash_100016f1d69f8e4c7b29f8fdea1d5ba158d9b6>
			<hash_100016f3d829549cfc1473ac7b989ee539feab>
				<task_item_id>hash_0800164d9b25cf1a27c98599313c1000f001b0</task_item_id>
				<color_id>0</color_id>
				<alpha>FF</alpha>
				<graph_type_id>9</graph_type_id>
				<consolidation_function_id>3</consolidation_function_id>
				<cdef_id>hash_05001662a7a53922548f4f6eac05cad69fbd2d</cdef_id>
				<value></value>
				<gprint_id>hash_060016e9c43831e54eca8069317a2ce8c6f751</gprint_id>
				<text_format>Now:</text_format>
				<hard_return></hard_return>
				<sequence>2</sequence>
			</hash_100016f3d829549cfc1473ac7b989ee539feab>
			<hash_10001651eed8925c9aa32fd36e435fb09fa2b7>
				<task_item_id>hash_0800164d9b25cf1a27c98599313c1000f001b0</task_item_id>
				<color_id>0</color_id>
				<alpha>FF</alpha>
				<graph_type_id>9</graph_type_id>
				<consolidation_function_id>1</consolidation_function_id>
				<cdef_id>hash_05001662a7a53922548f4f6eac05cad69fbd2d</cdef_id>
				<value></value>
				<gprint_id>hash_060016e9c43831e54eca8069317a2ce8c6f751</gprint_id>
				<text_format>Avg:</text_format>
				<hard_return></hard_return>
				<sequence>3</sequence>
			</hash_10001651eed8925c9aa32fd36e435fb09fa2b7>
			<hash_100016abb20b0792470c07e2d81fc4ceac2a9e>
				<task_item_id>hash_0800164d9b25cf1a27c98599313c1000f001b0</task_item_id>
				<color_id>0</color_id>
				<alpha>FF</alpha>
				<graph_type_id>9</graph_type_id>
				<consolidation_function_id>3</consolidation_function_id>
				<cdef_id>hash_05001662a7a53922548f4f6eac05cad69fbd2d</cdef_id>
				<value></value>
				<gprint_id>hash_060016e9c43831e54eca8069317a2ce8c6f751</gprint_id>
				<text_format>Max:</text_format>
				<hard_return>on</hard_return>
				<sequence>4</sequence>
			</hash_100016abb20b0792470c07e2d81fc4ceac2a9e>
			<hash_100016c0ae1387b30b828537acf3d20f700738>
				<task_item_id>hash_080016b874ed68ddc80a0ea28275a7ebfd1c3e</task_item_id>
				<color_id>96E78A</color_id>
				<alpha>FF</alpha>
				<graph_type_id>4</graph_type_id>
				<consolidation_function_id>1</consolidation_function_id>
				<cdef_id>hash_05001662a7a53922548f4f6eac05cad69fbd2d</cdef_id>
				<value></value>
				<gprint_id>hash_060016e9c43831e54eca8069317a2ce8c6f751</gprint_id>
				<text_format>Out</text_format>
				<hard_return></hard_return>
				<sequence>7</sequence>
			</hash_100016c0ae1387b30b828537acf3d20f700738>
			<hash_100016f6485279a541756d622d84d348073dd9>
				<task_item_id>hash_080016b874ed68ddc80a0ea28275a7ebfd1c3e</task_item_id>
				<color_id>0</color_id>
				<alpha>FF</alpha>
				<graph_type_id>9</graph_type_id>
				<consolidation_function_id>4</consolidation_function_id>
				<cdef_id>hash_05001662a7a53922548f4f6eac05cad69fbd2d</cdef_id>
				<value></value>
				<gprint_id>hash_060016e9c43831e54eca8069317a2ce8c6f751</gprint_id>
				<text_format>Now:</text_format>
				<hard_return></hard_return>
				<sequence>8</sequence>
			</hash_100016f6485279a541756d622d84d348073dd9>
			<hash_100016d3ddbd4cceed4745c66d884a31549a02>
				<task_item_id>hash_080016b874ed68ddc80a0ea28275a7ebfd1c3e</task_item_id>
				<color_id>0</color_id>
				<alpha>FF</alpha>
				<graph_type_id>9</graph_type_id>
				<consolidation_function_id>1</consolidation_function_id>
				<cdef_id>hash_05001662a7a53922548f4f6eac05cad69fbd2d</cdef_id>
				<value></value>
				<gprint_id>hash_060016e9c43831e54eca8069317a2ce8c6f751</gprint_id>
				<text_format>Avg:</text_format>
				<hard_return></hard_return>
				<sequence>9</sequence>
			</hash_100016d3ddbd4cceed4745c66d884a31549a02>
			<hash_1000165fe98a5a8583b543d87976388c20d129>
				<task_item_id>hash_080016b874ed68ddc80a0ea28275a7ebfd1c3e</task_item_id>
				<color_id>0</color_id>
				<alpha>FF</alpha>
				<graph_type_id>9</graph_type_id>
				<consolidation_function_id>3</consolidation_function_id>
				<cdef_id>hash_05001662a7a53922548f4f6eac05cad69fbd2d</cdef_id>
				<value></value>
				<gprint_id>hash_060016e9c43831e54eca8069317a2ce8c6f751</gprint_id>
				<text_format>Max:</text_format>
				<hard_return></hard_return>
				<sequence>10</sequence>
			</hash_1000165fe98a5a8583b543d87976388c20d129>
		</items>
		<inputs>
			<hash_090016abd69137a381d82c1a0adb21b613a505>
				<name>Data Source [ssl_bps_in]</name>
				<description></description>
				<column_name>task_item_id</column_name>
				<items>hash_000016f1d69f8e4c7b29f8fdea1d5ba158d9b6|hash_000016f3d829549cfc1473ac7b989ee539feab|hash_00001651eed8925c9aa32fd36e435fb09fa2b7|hash_000016abb20b0792470c07e2d81fc4ceac2a9e</items>
			</hash_090016abd69137a381d82c1a0adb21b613a505>
			<hash_09001600ca15b42004adbb7e79341219339198>
				<name>Data Source [ssl_bps_out]</name>
				<description></description>
				<column_name>task_item_id</column_name>
				<items>hash_000016c0ae1387b30b828537acf3d20f700738|hash_000016f6485279a541756d622d84d348073dd9|hash_000016d3ddbd4cceed4745c66d884a31549a02|hash_0000165fe98a5a8583b543d87976388c20d129</items>
			</hash_09001600ca15b42004adbb7e79341219339198>
		</inputs>
	</hash_0000164740ee10c62708a97452e64c39918381>
	<hash_0000160ec40ca42977e0f88770a13629862650>
		<name>LiteSpeed: Plain Connections</name>
		<graph>
			<t_title>on</t_title>
			<title></title>
			<t_image_format_id></t_image_format_id>
			<image_format_id>1</image_format_id>
			<t_height></t_height>
			<height>120</height>
			<t_width></t_width>
			<width>500</width>
			<t_slope_mode></t_slope_mode>
			<slope_mode>on</slope_mode>
			<t_auto_scale></t_auto_scale>
			<auto_scale>on</auto_scale>
			<t_auto_scale_opts></t_auto_scale_opts>
			<auto_scale_opts>1</auto_scale_opts>
			<t_auto_scale_log></t_auto_scale_log>
			<auto_scale_log></auto_scale_log>
			<t_scale_log_units></t_scale_log_units>
			<scale_log_units></scale_log_units>
			<t_auto_scale_rigid></t_auto_scale_rigid>
			<auto_scale_rigid></auto_scale_rigid>
			<t_auto_padding></t_auto_padding>
			<auto_padding>on</auto_padding>
			<t_export></t_export>
			<export>on</export>
			<t_upper_limit></t_upper_limit>
			<upper_limit>100</upper_limit>
			<t_lower_limit></t_lower_limit>
			<lower_limit>0</lower_limit>
			<t_base_value></t_base_value>
			<base_value>1000</base_value>
			<t_unit_value></t_unit_value>
			<unit_value></unit_value>
			<t_unit_exponent_value></t_unit_exponent_value>
			<unit_exponent_value></unit_exponent_value>
			<t_vertical_label></t_vertical_label>
			<vertical_label>connections</vertical_label>
		</graph>
		<items>
			<hash_100016785326a40ea378166fa83335d2f40972>
				<task_item_id>hash_0800160c86937c02cb9d97697e1c811f428cb8</task_item_id>
				<color_id>FFF200</color_id>
				<alpha>FF</alpha>
				<graph_type_id>7</graph_type_id>
				<consolidation_function_id>1</consolidation_function_id>
				<cdef_id>0</cdef_id>
				<value></value>
				<gprint_id>hash_060016e9c43831e54eca8069317a2ce8c6f751</gprint_id>
				<text_format>Used</text_format>
				<hard_return></hard_return>
				<sequence>1</sequence>
			</hash_100016785326a40ea378166fa83335d2f40972>
			<hash_100016456cf906b1d321f2965e0cd393fd01be>
				<task_item_id>hash_0800160c86937c02cb9d97697e1c811f428cb8</task_item_id>
				<color_id>0</color_id>
				<alpha>FF</alpha>
				<graph_type_id>9</graph_type_id>
				<consolidation_function_id>4</consolidation_function_id>
				<cdef_id>0</cdef_id>
				<value></value>
				<gprint_id>hash_060016e9c43831e54eca8069317a2ce8c6f751</gprint_id>
				<text_format>Now:</text_format>
				<hard_return></hard_return>
				<sequence>2</sequence>
			</hash_100016456cf906b1d321f2965e0cd393fd01be>
			<hash_10001612ab61fa60ac33785eed66153f7d3d19>
				<task_item_id>hash_0800160c86937c02cb9d97697e1c811f428cb8</task_item_id>
				<color_id>0</color_id>
				<alpha>FF</alpha>
				<graph_type_id>9</graph_type_id>
				<consolidation_function_id>1</consolidation_function_id>
				<cdef_id>0</cdef_id>
				<value></value>
				<gprint_id>hash_060016e9c43831e54eca8069317a2ce8c6f751</gprint_id>
				<text_format>Avg:</text_format>
				<hard_return></hard_return>
				<sequence>3</sequence>
			</hash_10001612ab61fa60ac33785eed66153f7d3d19>
			<hash_10001621760afe12d7a229bcacc84034c0c142>
				<task_item_id>hash_0800160c86937c02cb9d97697e1c811f428cb8</task_item_id>
				<color_id>0</color_id>
				<alpha>FF</alpha>
				<graph_type_id>9</graph_type_id>
				<consolidation_function_id>3</consolidation_function_id>
				<cdef_id>0</cdef_id>
				<value></value>
				<gprint_id>hash_060016e9c43831e54eca8069317a2ce8c6f751</gprint_id>
				<text_format>Max:</text_format>
				<hard_return>on</hard_return>
				<sequence>4</sequence>
			</hash_10001621760afe12d7a229bcacc84034c0c142>
			<hash_100016c83277ba4420abf66568df10dbd12baa>
				<task_item_id>hash_080016614e73da69c6fa3034c159dfeb0b0362</task_item_id>
				<color_id>96E78A</color_id>
				<alpha>FF</alpha>
				<graph_type_id>8</graph_type_id>
				<consolidation_function_id>1</consolidation_function_id>
				<cdef_id>0</cdef_id>
				<value></value>
				<gprint_id>hash_060016e9c43831e54eca8069317a2ce8c6f751</gprint_id>
				<text_format>Available</text_format>
				<hard_return></hard_return>
				<sequence>5</sequence>
			</hash_100016c83277ba4420abf66568df10dbd12baa>
			<hash_100016b619d77e1ace0793b79219819ce45c2b>
				<task_item_id>hash_080016614e73da69c6fa3034c159dfeb0b0362</task_item_id>
				<color_id>0</color_id>
				<alpha>FF</alpha>
				<graph_type_id>9</graph_type_id>
				<consolidation_function_id>4</consolidation_function_id>
				<cdef_id>0</cdef_id>
				<value></value>
				<gprint_id>hash_060016e9c43831e54eca8069317a2ce8c6f751</gprint_id>
				<text_format>Now:</text_format>
				<hard_return></hard_return>
				<sequence>6</sequence>
			</hash_100016b619d77e1ace0793b79219819ce45c2b>
			<hash_100016c872db52d4083a6a2a01ecda02e4ed7d>
				<task_item_id>hash_080016614e73da69c6fa3034c159dfeb0b0362</task_item_id>
				<color_id>0</color_id>
				<alpha>FF</alpha>
				<graph_type_id>9</graph_type_id>
				<consolidation_function_id>1</consolidation_function_id>
				<cdef_id>0</cdef_id>
				<value></value>
				<gprint_id>hash_060016e9c43831e54eca8069317a2ce8c6f751</gprint_id>
				<text_format>Avg:</text_format>
				<hard_return></hard_return>
				<sequence>7</sequence>
			</hash_100016c872db52d4083a6a2a01ecda02e4ed7d>
			<hash_10001623c51b3457e37c971a7cb465a5bc898f>
				<task_item_id>hash_080016614e73da69c6fa3034c159dfeb0b0362</task_item_id>
				<color_id>0</color_id>
				<alpha>FF</alpha>
				<graph_type_id>9</graph_type_id>
				<consolidation_function_id>3</consolidation_function_id>
				<cdef_id>0</cdef_id>
				<value></value>
				<gprint_id>hash_060016e9c43831e54eca8069317a2ce8c6f751</gprint_id>
				<text_format>Max:</text_format>
				<hard_return></hard_return>
				<sequence>8</sequence>
			</hash_10001623c51b3457e37c971a7cb465a5bc898f>
		</items>
		<inputs>
			<hash_09001614ceda9914627c18cdffdee2db08cc06>
				<name>Data Source [plain_conn]</name>
				<description></description>
				<column_name>task_item_id</column_name>
				<items>hash_000016785326a40ea378166fa83335d2f40972|hash_000016456cf906b1d321f2965e0cd393fd01be|hash_00001612ab61fa60ac33785eed66153f7d3d19|hash_00001621760afe12d7a229bcacc84034c0c142</items>
			</hash_09001614ceda9914627c18cdffdee2db08cc06>
			<hash_090016471702edf91339a3181575b5e430ebbb>
				<name>Data Source [avail_conn]</name>
				<description></description>
				<column_name>task_item_id</column_name>
				<items>hash_000016c83277ba4420abf66568df10dbd12baa|hash_000016b619d77e1ace0793b79219819ce45c2b|hash_000016c872db52d4083a6a2a01ecda02e4ed7d|hash_00001623c51b3457e37c971a7cb465a5bc898f</items>
			</hash_090016471702edf91339a3181575b5e430ebbb>
		</inputs>
	</hash_0000160ec40ca42977e0f88770a13629862650>
	<hash_000016a85d4e176d782c3bef5da7ed00cce513>
		<name>LiteSpeed:  SSL Connections</name>
		<graph>
			<t_title>on</t_title>
			<title></title>
			<t_image_format_id></t_image_format_id>
			<image_format_id>1</image_format_id>
			<t_height></t_height>
			<height>120</height>
			<t_width></t_width>
			<width>500</width>
			<t_slope_mode>0</t_slope_mode>
			<slope_mode>on</slope_mode>
			<t_auto_scale></t_auto_scale>
			<auto_scale>on</auto_scale>
			<t_auto_scale_opts></t_auto_scale_opts>
			<auto_scale_opts>2</auto_scale_opts>
			<t_auto_scale_log></t_auto_scale_log>
			<auto_scale_log></auto_scale_log>
			<t_scale_log_units>0</t_scale_log_units>
			<scale_log_units></scale_log_units>
			<t_auto_scale_rigid></t_auto_scale_rigid>
			<auto_scale_rigid></auto_scale_rigid>
			<t_auto_padding></t_auto_padding>
			<auto_padding>on</auto_padding>
			<t_export></t_export>
			<export>on</export>
			<t_upper_limit></t_upper_limit>
			<upper_limit>100</upper_limit>
			<t_lower_limit></t_lower_limit>
			<lower_limit>0</lower_limit>
			<t_base_value></t_base_value>
			<base_value>1000</base_value>
			<t_unit_value></t_unit_value>
			<unit_value></unit_value>
			<t_unit_exponent_value></t_unit_exponent_value>
			<unit_exponent_value></unit_exponent_value>
			<t_vertical_label></t_vertical_label>
			<vertical_label>connections</vertical_label>
		</graph>
		<items>
			<hash_100016d5ffb9ffd21b1998560ae7f528b745f2>
				<task_item_id>hash_08001667c11e9d5c8ee24343108fa839c89ac6</task_item_id>
				<color_id>FFF200</color_id>
				<alpha>FF</alpha>
				<graph_type_id>7</graph_type_id>
				<consolidation_function_id>1</consolidation_function_id>
				<cdef_id>0</cdef_id>
				<value></value>
				<gprint_id>hash_060016e9c43831e54eca8069317a2ce8c6f751</gprint_id>
				<text_format>Used</text_format>
				<hard_return></hard_return>
				<sequence>1</sequence>
			</hash_100016d5ffb9ffd21b1998560ae7f528b745f2>
			<hash_1000168cb463086e6bfc9d15de0d60698a73d1>
				<task_item_id>hash_08001667c11e9d5c8ee24343108fa839c89ac6</task_item_id>
				<color_id>0</color_id>
				<alpha>FF</alpha>
				<graph_type_id>9</graph_type_id>
				<consolidation_function_id>4</consolidation_function_id>
				<cdef_id>0</cdef_id>
				<value></value>
				<gprint_id>hash_060016e9c43831e54eca8069317a2ce8c6f751</gprint_id>
				<text_format>Now:</text_format>
				<hard_return></hard_return>
				<sequence>2</sequence>
			</hash_1000168cb463086e6bfc9d15de0d60698a73d1>
			<hash_10001614eeede9629ac14185deb07358ca4046>
				<task_item_id>hash_08001667c11e9d5c8ee24343108fa839c89ac6</task_item_id>
				<color_id>0</color_id>
				<alpha>FF</alpha>
				<graph_type_id>9</graph_type_id>
				<consolidation_function_id>1</consolidation_function_id>
				<cdef_id>0</cdef_id>
				<value></value>
				<gprint_id>hash_060016e9c43831e54eca8069317a2ce8c6f751</gprint_id>
				<text_format>Avg:</text_format>
				<hard_return></hard_return>
				<sequence>3</sequence>
			</hash_10001614eeede9629ac14185deb07358ca4046>
			<hash_10001660d821aa4ddebf92ed43ca743e50fa53>
				<task_item_id>hash_08001667c11e9d5c8ee24343108fa839c89ac6</task_item_id>
				<color_id>0</color_id>
				<alpha>FF</alpha>
				<graph_type_id>9</graph_type_id>
				<consolidation_function_id>3</consolidation_function_id>
				<cdef_id>0</cdef_id>
				<value></value>
				<gprint_id>hash_060016e9c43831e54eca8069317a2ce8c6f751</gprint_id>
				<text_format>Max:</text_format>
				<hard_return>on</hard_return>
				<sequence>4</sequence>
			</hash_10001660d821aa4ddebf92ed43ca743e50fa53>
			<hash_100016be5ac8af8f5cb499b5d3e63d6739e40d>
				<task_item_id>hash_0800164cb690fe79ffeb845634b5e64bcedba7</task_item_id>
				<color_id>96E78A</color_id>
				<alpha>FF</alpha>
				<graph_type_id>8</graph_type_id>
				<consolidation_function_id>1</consolidation_function_id>
				<cdef_id>0</cdef_id>
				<value></value>
				<gprint_id>hash_060016e9c43831e54eca8069317a2ce8c6f751</gprint_id>
				<text_format>Available</text_format>
				<hard_return></hard_return>
				<sequence>5</sequence>
			</hash_100016be5ac8af8f5cb499b5d3e63d6739e40d>
			<hash_1000161ad1fcdcf047dc89bb140662335f4b8a>
				<task_item_id>hash_0800164cb690fe79ffeb845634b5e64bcedba7</task_item_id>
				<color_id>0</color_id>
				<alpha>FF</alpha>
				<graph_type_id>9</graph_type_id>
				<consolidation_function_id>4</consolidation_function_id>
				<cdef_id>0</cdef_id>
				<value></value>
				<gprint_id>hash_060016e9c43831e54eca8069317a2ce8c6f751</gprint_id>
				<text_format>Now:</text_format>
				<hard_return></hard_return>
				<sequence>6</sequence>
			</hash_1000161ad1fcdcf047dc89bb140662335f4b8a>
			<hash_100016af2a2a40063ef8da8b09a408f1e40d66>
				<task_item_id>hash_0800164cb690fe79ffeb845634b5e64bcedba7</task_item_id>
				<color_id>0</color_id>
				<alpha>FF</alpha>
				<graph_type_id>9</graph_type_id>
				<consolidation_function_id>1</consolidation_function_id>
				<cdef_id>0</cdef_id>
				<value></value>
				<gprint_id>hash_060016e9c43831e54eca8069317a2ce8c6f751</gprint_id>
				<text_format>Avg:</text_format>
				<hard_return></hard_return>
				<sequence>7</sequence>
			</hash_100016af2a2a40063ef8da8b09a408f1e40d66>
			<hash_100016596a4c338a17ef4db5873a61470048ea>
				<task_item_id>hash_0800164cb690fe79ffeb845634b5e64bcedba7</task_item_id>
				<color_id>0</color_id>
				<alpha>FF</alpha>
				<graph_type_id>9</graph_type_id>
				<consolidation_function_id>3</consolidation_function_id>
				<cdef_id>0</cdef_id>
				<value></value>
				<gprint_id>hash_060016e9c43831e54eca8069317a2ce8c6f751</gprint_id>
				<text_format>Max:</text_format>
				<hard_return></hard_return>
				<sequence>8</sequence>
			</hash_100016596a4c338a17ef4db5873a61470048ea>
		</items>
		<inputs>
			<hash_09001642abcbbbee7afdb87a68d2c0ba974b96>
				<name>Data Source [ssl_conn]</name>
				<description></description>
				<column_name>task_item_id</column_name>
				<items>hash_000016d5ffb9ffd21b1998560ae7f528b745f2|hash_0000168cb463086e6bfc9d15de0d60698a73d1|hash_00001614eeede9629ac14185deb07358ca4046|hash_00001660d821aa4ddebf92ed43ca743e50fa53</items>
			</hash_09001642abcbbbee7afdb87a68d2c0ba974b96>
			<hash_09001619e64318d6fefd1b5ef6a80c6a94deaf>
				<name>Data Source [avail_ssl_conn]</name>
				<description></description>
				<column_name>task_item_id</column_name>
				<items>hash_000016be5ac8af8f5cb499b5d3e63d6739e40d|hash_0000161ad1fcdcf047dc89bb140662335f4b8a|hash_000016af2a2a40063ef8da8b09a408f1e40d66|hash_000016596a4c338a17ef4db5873a61470048ea</items>
			</hash_09001619e64318d6fefd1b5ef6a80c6a94deaf>
		</inputs>
	</hash_000016a85d4e176d782c3bef5da7ed00cce513>
	<hash_0100164fa3bc9138bd7459ed6ed6e1eccd6d32>
		<name>LiteSpeed Vhost</name>
		<ds>
			<t_name>on</t_name>
			<name>|host_description| -  ls vhost</name>
			<data_input_id>hash_030016bf566c869ac6443b0c75d1c32b5a350e</data_input_id>
			<t_rra_id></t_rra_id>
			<t_rrd_step></t_rrd_step>
			<rrd_step>300</rrd_step>
			<t_active></t_active>
			<active>on</active>
			<rra_items>hash_150016c21df5178e5c955013591239eb0afd46|hash_1500160d9c0af8b8acdc7807943937b3208e29|hash_1500166fc2d038fb42950138b0ce3e9874cc60|hash_150016e36f3adb9f152adfa5dc50fd2b23337e|hash_150016283ea2bf1634d92ce081ec82a634f513</rra_items>
		</ds>
		<items>
			<hash_080016e5084b9e07fdcc5535637f75b8af3222>
				<t_data_source_name></t_data_source_name>
				<data_source_name>Req_Second</data_source_name>
				<t_rrd_minimum></t_rrd_minimum>
				<rrd_minimum>0</rrd_minimum>
				<t_rrd_maximum></t_rrd_maximum>
				<rrd_maximum>100000000</rrd_maximum>
				<t_data_source_type_id></t_data_source_type_id>
				<data_source_type_id>1</data_source_type_id>
				<t_rrd_heartbeat></t_rrd_heartbeat>
				<rrd_heartbeat>600</rrd_heartbeat>
				<t_data_input_field_id></t_data_input_field_id>
				<data_input_field_id>0</data_input_field_id>
			</hash_080016e5084b9e07fdcc5535637f75b8af3222>
			<hash_08001676fbeb01ef35493c81578394cdc9f453>
				<t_data_source_name></t_data_source_name>
				<data_source_name>Req_InProcess</data_source_name>
				<t_rrd_minimum></t_rrd_minimum>
				<rrd_minimum>0</rrd_minimum>
				<t_rrd_maximum></t_rrd_maximum>
				<rrd_maximum>100000000</rrd_maximum>
				<t_data_source_type_id></t_data_source_type_id>
				<data_source_type_id>1</data_source_type_id>
				<t_rrd_heartbeat></t_rrd_heartbeat>
				<rrd_heartbeat>600</rrd_heartbeat>
				<t_data_input_field_id></t_data_input_field_id>
				<data_input_field_id>0</data_input_field_id>
			</hash_08001676fbeb01ef35493c81578394cdc9f453>
			<hash_080016498655c335857fde3f504bb21f784273>
				<t_data_source_name></t_data_source_name>
				<data_source_name>Req_Total</data_source_name>
				<t_rrd_minimum></t_rrd_minimum>
				<rrd_minimum>0</rrd_minimum>
				<t_rrd_maximum></t_rrd_maximum>
				<rrd_maximum>100000000</rrd_maximum>
				<t_data_source_type_id></t_data_source_type_id>
				<data_source_type_id>2</data_source_type_id>
				<t_rrd_heartbeat></t_rrd_heartbeat>
				<rrd_heartbeat>600</rrd_heartbeat>
				<t_data_input_field_id></t_data_input_field_id>
				<data_input_field_id>0</data_input_field_id>
			</hash_080016498655c335857fde3f504bb21f784273>
		</items>
		<data>
			<item_000>
				<data_input_field_id>hash_070016e6deda7be0f391399c5130e7c4a48b28</data_input_field_id>
				<t_value>on</t_value>
				<value></value>
			</item_000>
			<item_001>
				<data_input_field_id>hash_070016cbbe5c1ddfb264a6e5d509ce1c78c95f</data_input_field_id>
				<t_value>on</t_value>
				<value></value>
			</item_001>
			<item_002>
				<data_input_field_id>hash_0700166027a919c7c7731fbe095b6f53ab127b</data_input_field_id>
				<t_value>on</t_value>
				<value></value>
			</item_002>
			<item_003>
				<data_input_field_id>hash_070016b5c23f246559df38662c255f4aa21d6b</data_input_field_id>
				<t_value></t_value>
				<value></value>
			</item_003>
			<item_004>
				<data_input_field_id>hash_0700161cc1493a6781af2c478fa4de971531cf</data_input_field_id>
				<t_value></t_value>
				<value></value>
			</item_004>
			<item_005>
				<data_input_field_id>hash_070016f4facc5e2ca7ebee621f09bc6d9fc792</data_input_field_id>
				<t_value></t_value>
				<value></value>
			</item_005>
			<item_006>
				<data_input_field_id>hash_070016acb449d1451e8a2a655c2c99d31142c7</data_input_field_id>
				<t_value></t_value>
				<value></value>
			</item_006>
			<item_007>
				<data_input_field_id>hash_070016617cdc8a230615e59f06f361ef6e7728</data_input_field_id>
				<t_value></t_value>
				<value></value>
			</item_007>
		</data>
	</hash_0100164fa3bc9138bd7459ed6ed6e1eccd6d32>
	<hash_01001626652071e652e251bc9f2cb68a65ce0f>
		<name>LiteSpeed ExtApp</name>
		<ds>
			<t_name>on</t_name>
			<name></name>
			<data_input_id>hash_030016bf566c869ac6443b0c75d1c32b5a350e</data_input_id>
			<t_rra_id></t_rra_id>
			<t_rrd_step></t_rrd_step>
			<rrd_step>300</rrd_step>
			<t_active></t_active>
			<active>on</active>
			<rra_items>hash_150016c21df5178e5c955013591239eb0afd46|hash_1500160d9c0af8b8acdc7807943937b3208e29|hash_1500166fc2d038fb42950138b0ce3e9874cc60|hash_150016e36f3adb9f152adfa5dc50fd2b23337e|hash_150016283ea2bf1634d92ce081ec82a634f513</rra_items>
		</ds>
		<items>
			<hash_080016dd80f6a8dac8166b110503ac3cdbe991>
				<t_data_source_name></t_data_source_name>
				<data_source_name>WaitQueueDepth</data_source_name>
				<t_rrd_minimum></t_rrd_minimum>
				<rrd_minimum>0</rrd_minimum>
				<t_rrd_maximum></t_rrd_maximum>
				<rrd_maximum>100000000</rrd_maximum>
				<t_data_source_type_id></t_data_source_type_id>
				<data_source_type_id>1</data_source_type_id>
				<t_rrd_heartbeat></t_rrd_heartbeat>
				<rrd_heartbeat>600</rrd_heartbeat>
				<t_data_input_field_id></t_data_input_field_id>
				<data_input_field_id>0</data_input_field_id>
			</hash_080016dd80f6a8dac8166b110503ac3cdbe991>
			<hash_080016a972198dd76a78359072a49e7b6d295e>
				<t_data_source_name></t_data_source_name>
				<data_source_name>ConfMaxConn</data_source_name>
				<t_rrd_minimum></t_rrd_minimum>
				<rrd_minimum>0</rrd_minimum>
				<t_rrd_maximum></t_rrd_maximum>
				<rrd_maximum>100000000</rrd_maximum>
				<t_data_source_type_id></t_data_source_type_id>
				<data_source_type_id>1</data_source_type_id>
				<t_rrd_heartbeat></t_rrd_heartbeat>
				<rrd_heartbeat>600</rrd_heartbeat>
				<t_data_input_field_id></t_data_input_field_id>
				<data_input_field_id>0</data_input_field_id>
			</hash_080016a972198dd76a78359072a49e7b6d295e>
			<hash_08001624140062cfa9de88c593a71be9a40e0f>
				<t_data_source_name></t_data_source_name>
				<data_source_name>PoolSize</data_source_name>
				<t_rrd_minimum></t_rrd_minimum>
				<rrd_minimum>0</rrd_minimum>
				<t_rrd_maximum></t_rrd_maximum>
				<rrd_maximum>100000000</rrd_maximum>
				<t_data_source_type_id></t_data_source_type_id>
				<data_source_type_id>1</data_source_type_id>
				<t_rrd_heartbeat></t_rrd_heartbeat>
				<rrd_heartbeat>600</rrd_heartbeat>
				<t_data_input_field_id></t_data_input_field_id>
				<data_input_field_id>0</data_input_field_id>
			</hash_08001624140062cfa9de88c593a71be9a40e0f>
			<hash_080016dca7bbae358416c8a86fd74cc83104d8>
				<t_data_source_name></t_data_source_name>
				<data_source_name>InuseConn</data_source_name>
				<t_rrd_minimum></t_rrd_minimum>
				<rrd_minimum>0</rrd_minimum>
				<t_rrd_maximum></t_rrd_maximum>
				<rrd_maximum>100000000</rrd_maximum>
				<t_data_source_type_id></t_data_source_type_id>
				<data_source_type_id>1</data_source_type_id>
				<t_rrd_heartbeat></t_rrd_heartbeat>
				<rrd_heartbeat>600</rrd_heartbeat>
				<t_data_input_field_id></t_data_input_field_id>
				<data_input_field_id>0</data_input_field_id>
			</hash_080016dca7bbae358416c8a86fd74cc83104d8>
			<hash_080016ca1f6af4ad148a9f858b9f9a4a3ab010>
				<t_data_source_name></t_data_source_name>
				<data_source_name>IdleConn</data_source_name>
				<t_rrd_minimum></t_rrd_minimum>
				<rrd_minimum>0</rrd_minimum>
				<t_rrd_maximum></t_rrd_maximum>
				<rrd_maximum>100000000</rrd_maximum>
				<t_data_source_type_id></t_data_source_type_id>
				<data_source_type_id>1</data_source_type_id>
				<t_rrd_heartbeat></t_rrd_heartbeat>
				<rrd_heartbeat>600</rrd_heartbeat>
				<t_data_input_field_id></t_data_input_field_id>
				<data_input_field_id>0</data_input_field_id>
			</hash_080016ca1f6af4ad148a9f858b9f9a4a3ab010>
			<hash_080016761fd20a96d97f909f6b4ec0241344ab>
				<t_data_source_name></t_data_source_name>
				<data_source_name>EffMaxConn</data_source_name>
				<t_rrd_minimum></t_rrd_minimum>
				<rrd_minimum>0</rrd_minimum>
				<t_rrd_maximum></t_rrd_maximum>
				<rrd_maximum>100000000</rrd_maximum>
				<t_data_source_type_id></t_data_source_type_id>
				<data_source_type_id>1</data_source_type_id>
				<t_rrd_heartbeat></t_rrd_heartbeat>
				<rrd_heartbeat>600</rrd_heartbeat>
				<t_data_input_field_id></t_data_input_field_id>
				<data_input_field_id>0</data_input_field_id>
			</hash_080016761fd20a96d97f909f6b4ec0241344ab>
			<hash_0800165d24f91f2b8d9e5598d1abd567b076f9>
				<t_data_source_name></t_data_source_name>
				<data_source_name>Req_Second</data_source_name>
				<t_rrd_minimum></t_rrd_minimum>
				<rrd_minimum>0</rrd_minimum>
				<t_rrd_maximum></t_rrd_maximum>
				<rrd_maximum>100000000</rrd_maximum>
				<t_data_source_type_id></t_data_source_type_id>
				<data_source_type_id>1</data_source_type_id>
				<t_rrd_heartbeat></t_rrd_heartbeat>
				<rrd_heartbeat>600</rrd_heartbeat>
				<t_data_input_field_id></t_data_input_field_id>
				<data_input_field_id>0</data_input_field_id>
			</hash_0800165d24f91f2b8d9e5598d1abd567b076f9>
			<hash_0800162cfde2a624b32fc964c5c830e711843d>
				<t_data_source_name></t_data_source_name>
				<data_source_name>Req_Total</data_source_name>
				<t_rrd_minimum></t_rrd_minimum>
				<rrd_minimum>0</rrd_minimum>
				<t_rrd_maximum></t_rrd_maximum>
				<rrd_maximum>100000000</rrd_maximum>
				<t_data_source_type_id></t_data_source_type_id>
				<data_source_type_id>2</data_source_type_id>
				<t_rrd_heartbeat></t_rrd_heartbeat>
				<rrd_heartbeat>600</rrd_heartbeat>
				<t_data_input_field_id></t_data_input_field_id>
				<data_input_field_id>0</data_input_field_id>
			</hash_0800162cfde2a624b32fc964c5c830e711843d>
		</items>
		<data>
			<item_000>
				<data_input_field_id>hash_070016e6deda7be0f391399c5130e7c4a48b28</data_input_field_id>
				<t_value>on</t_value>
				<value></value>
			</item_000>
			<item_001>
				<data_input_field_id>hash_070016cbbe5c1ddfb264a6e5d509ce1c78c95f</data_input_field_id>
				<t_value>on</t_value>
				<value></value>
			</item_001>
			<item_002>
				<data_input_field_id>hash_0700166027a919c7c7731fbe095b6f53ab127b</data_input_field_id>
				<t_value>on</t_value>
				<value></value>
			</item_002>
			<item_003>
				<data_input_field_id>hash_070016b5c23f246559df38662c255f4aa21d6b</data_input_field_id>
				<t_value></t_value>
				<value></value>
			</item_003>
			<item_004>
				<data_input_field_id>hash_0700161cc1493a6781af2c478fa4de971531cf</data_input_field_id>
				<t_value></t_value>
				<value></value>
			</item_004>
			<item_005>
				<data_input_field_id>hash_070016f4facc5e2ca7ebee621f09bc6d9fc792</data_input_field_id>
				<t_value></t_value>
				<value></value>
			</item_005>
			<item_006>
				<data_input_field_id>hash_070016acb449d1451e8a2a655c2c99d31142c7</data_input_field_id>
				<t_value></t_value>
				<value></value>
			</item_006>
			<item_007>
				<data_input_field_id>hash_070016617cdc8a230615e59f06f361ef6e7728</data_input_field_id>
				<t_value></t_value>
				<value></value>
			</item_007>
		</data>
	</hash_01001626652071e652e251bc9f2cb68a65ce0f>
	<hash_01001664f653d42cc6cf8398fa5d55e76c1387>
		<name>LiteSpeed General</name>
		<ds>
			<t_name>on</t_name>
			<name></name>
			<data_input_id>hash_030016bf566c869ac6443b0c75d1c32b5a350e</data_input_id>
			<t_rra_id></t_rra_id>
			<t_rrd_step></t_rrd_step>
			<rrd_step>300</rrd_step>
			<t_active></t_active>
			<active>on</active>
			<rra_items>hash_150016c21df5178e5c955013591239eb0afd46|hash_1500160d9c0af8b8acdc7807943937b3208e29|hash_1500166fc2d038fb42950138b0ce3e9874cc60|hash_150016e36f3adb9f152adfa5dc50fd2b23337e|hash_150016283ea2bf1634d92ce081ec82a634f513</rra_items>
		</ds>
		<items>
			<hash_080016f9bc5dd109ed4ab674746e66a49df3d8>
				<t_data_source_name></t_data_source_name>
				<data_source_name>bps_in</data_source_name>
				<t_rrd_minimum></t_rrd_minimum>
				<rrd_minimum>0</rrd_minimum>
				<t_rrd_maximum></t_rrd_maximum>
				<rrd_maximum>100000000</rrd_maximum>
				<t_data_source_type_id></t_data_source_type_id>
				<data_source_type_id>1</data_source_type_id>
				<t_rrd_heartbeat></t_rrd_heartbeat>
				<rrd_heartbeat>600</rrd_heartbeat>
				<t_data_input_field_id></t_data_input_field_id>
				<data_input_field_id>0</data_input_field_id>
			</hash_080016f9bc5dd109ed4ab674746e66a49df3d8>
			<hash_0800164a9cc0ba440529238c3bb8606e5991bd>
				<t_data_source_name></t_data_source_name>
				<data_source_name>bps_out</data_source_name>
				<t_rrd_minimum></t_rrd_minimum>
				<rrd_minimum>0</rrd_minimum>
				<t_rrd_maximum></t_rrd_maximum>
				<rrd_maximum>100000000</rrd_maximum>
				<t_data_source_type_id></t_data_source_type_id>
				<data_source_type_id>1</data_source_type_id>
				<t_rrd_heartbeat></t_rrd_heartbeat>
				<rrd_heartbeat>600</rrd_heartbeat>
				<t_data_input_field_id></t_data_input_field_id>
				<data_input_field_id>0</data_input_field_id>
			</hash_0800164a9cc0ba440529238c3bb8606e5991bd>
			<hash_0800164d9b25cf1a27c98599313c1000f001b0>
				<t_data_source_name></t_data_source_name>
				<data_source_name>ssl_bps_in</data_source_name>
				<t_rrd_minimum></t_rrd_minimum>
				<rrd_minimum>0</rrd_minimum>
				<t_rrd_maximum></t_rrd_maximum>
				<rrd_maximum>100000000</rrd_maximum>
				<t_data_source_type_id></t_data_source_type_id>
				<data_source_type_id>1</data_source_type_id>
				<t_rrd_heartbeat></t_rrd_heartbeat>
				<rrd_heartbeat>600</rrd_heartbeat>
				<t_data_input_field_id></t_data_input_field_id>
				<data_input_field_id>0</data_input_field_id>
			</hash_0800164d9b25cf1a27c98599313c1000f001b0>
			<hash_080016b874ed68ddc80a0ea28275a7ebfd1c3e>
				<t_data_source_name></t_data_source_name>
				<data_source_name>ssl_bps_out</data_source_name>
				<t_rrd_minimum></t_rrd_minimum>
				<rrd_minimum>0</rrd_minimum>
				<t_rrd_maximum></t_rrd_maximum>
				<rrd_maximum>100000000</rrd_maximum>
				<t_data_source_type_id></t_data_source_type_id>
				<data_source_type_id>1</data_source_type_id>
				<t_rrd_heartbeat></t_rrd_heartbeat>
				<rrd_heartbeat>600</rrd_heartbeat>
				<t_data_input_field_id></t_data_input_field_id>
				<data_input_field_id>0</data_input_field_id>
			</hash_080016b874ed68ddc80a0ea28275a7ebfd1c3e>
			<hash_08001637954d916d01010135b73acce4073f95>
				<t_data_source_name></t_data_source_name>
				<data_source_name>max_conn</data_source_name>
				<t_rrd_minimum></t_rrd_minimum>
				<rrd_minimum>0</rrd_minimum>
				<t_rrd_maximum></t_rrd_maximum>
				<rrd_maximum>100000000</rrd_maximum>
				<t_data_source_type_id></t_data_source_type_id>
				<data_source_type_id>1</data_source_type_id>
				<t_rrd_heartbeat></t_rrd_heartbeat>
				<rrd_heartbeat>600</rrd_heartbeat>
				<t_data_input_field_id></t_data_input_field_id>
				<data_input_field_id>0</data_input_field_id>
			</hash_08001637954d916d01010135b73acce4073f95>
			<hash_0800161169594439b0f82216e84a8799d61941>
				<t_data_source_name></t_data_source_name>
				<data_source_name>max_ssl_conn</data_source_name>
				<t_rrd_minimum></t_rrd_minimum>
				<rrd_minimum>0</rrd_minimum>
				<t_rrd_maximum></t_rrd_maximum>
				<rrd_maximum>100000000</rrd_maximum>
				<t_data_source_type_id></t_data_source_type_id>
				<data_source_type_id>1</data_source_type_id>
				<t_rrd_heartbeat></t_rrd_heartbeat>
				<rrd_heartbeat>600</rrd_heartbeat>
				<t_data_input_field_id></t_data_input_field_id>
				<data_input_field_id>0</data_input_field_id>
			</hash_0800161169594439b0f82216e84a8799d61941>
			<hash_0800160c86937c02cb9d97697e1c811f428cb8>
				<t_data_source_name></t_data_source_name>
				<data_source_name>plain_conn</data_source_name>
				<t_rrd_minimum></t_rrd_minimum>
				<rrd_minimum>0</rrd_minimum>
				<t_rrd_maximum></t_rrd_maximum>
				<rrd_maximum>100000000</rrd_maximum>
				<t_data_source_type_id></t_data_source_type_id>
				<data_source_type_id>1</data_source_type_id>
				<t_rrd_heartbeat></t_rrd_heartbeat>
				<rrd_heartbeat>600</rrd_heartbeat>
				<t_data_input_field_id></t_data_input_field_id>
				<data_input_field_id>0</data_input_field_id>
			</hash_0800160c86937c02cb9d97697e1c811f428cb8>
			<hash_080016614e73da69c6fa3034c159dfeb0b0362>
				<t_data_source_name></t_data_source_name>
				<data_source_name>avail_conn</data_source_name>
				<t_rrd_minimum></t_rrd_minimum>
				<rrd_minimum>0</rrd_minimum>
				<t_rrd_maximum></t_rrd_maximum>
				<rrd_maximum>100000000</rrd_maximum>
				<t_data_source_type_id></t_data_source_type_id>
				<data_source_type_id>1</data_source_type_id>
				<t_rrd_heartbeat></t_rrd_heartbeat>
				<rrd_heartbeat>600</rrd_heartbeat>
				<t_data_input_field_id></t_data_input_field_id>
				<data_input_field_id>0</data_input_field_id>
			</hash_080016614e73da69c6fa3034c159dfeb0b0362>
			<hash_080016b195a7bd55be8330011b893681bea93a>
				<t_data_source_name></t_data_source_name>
				<data_source_name>idle_conn</data_source_name>
				<t_rrd_minimum></t_rrd_minimum>
				<rrd_minimum>0</rrd_minimum>
				<t_rrd_maximum></t_rrd_maximum>
				<rrd_maximum>100000000</rrd_maximum>
				<t_data_source_type_id></t_data_source_type_id>
				<data_source_type_id>1</data_source_type_id>
				<t_rrd_heartbeat></t_rrd_heartbeat>
				<rrd_heartbeat>600</rrd_heartbeat>
				<t_data_input_field_id></t_data_input_field_id>
				<data_input_field_id>0</data_input_field_id>
			</hash_080016b195a7bd55be8330011b893681bea93a>
			<hash_08001667c11e9d5c8ee24343108fa839c89ac6>
				<t_data_source_name></t_data_source_name>
				<data_source_name>ssl_conn</data_source_name>
				<t_rrd_minimum></t_rrd_minimum>
				<rrd_minimum>0</rrd_minimum>
				<t_rrd_maximum></t_rrd_maximum>
				<rrd_maximum>100000000</rrd_maximum>
				<t_data_source_type_id></t_data_source_type_id>
				<data_source_type_id>1</data_source_type_id>
				<t_rrd_heartbeat></t_rrd_heartbeat>
				<rrd_heartbeat>600</rrd_heartbeat>
				<t_data_input_field_id></t_data_input_field_id>
				<data_input_field_id>0</data_input_field_id>
			</hash_08001667c11e9d5c8ee24343108fa839c89ac6>
			<hash_0800164cb690fe79ffeb845634b5e64bcedba7>
				<t_data_source_name></t_data_source_name>
				<data_source_name>avail_ssl_conn</data_source_name>
				<t_rrd_minimum></t_rrd_minimum>
				<rrd_minimum>0</rrd_minimum>
				<t_rrd_maximum></t_rrd_maximum>
				<rrd_maximum>100000000</rrd_maximum>
				<t_data_source_type_id></t_data_source_type_id>
				<data_source_type_id>1</data_source_type_id>
				<t_rrd_heartbeat></t_rrd_heartbeat>
				<rrd_heartbeat>600</rrd_heartbeat>
				<t_data_input_field_id></t_data_input_field_id>
				<data_input_field_id>0</data_input_field_id>
			</hash_0800164cb690fe79ffeb845634b5e64bcedba7>
		</items>
		<data>
			<item_000>
				<data_input_field_id>hash_070016e6deda7be0f391399c5130e7c4a48b28</data_input_field_id>
				<t_value>on</t_value>
				<value></value>
			</item_000>
			<item_001>
				<data_input_field_id>hash_070016cbbe5c1ddfb264a6e5d509ce1c78c95f</data_input_field_id>
				<t_value>on</t_value>
				<value></value>
			</item_001>
			<item_002>
				<data_input_field_id>hash_0700166027a919c7c7731fbe095b6f53ab127b</data_input_field_id>
				<t_value>on</t_value>
				<value></value>
			</item_002>
			<item_003>
				<data_input_field_id>hash_070016b5c23f246559df38662c255f4aa21d6b</data_input_field_id>
				<t_value></t_value>
				<value></value>
			</item_003>
			<item_004>
				<data_input_field_id>hash_0700161cc1493a6781af2c478fa4de971531cf</data_input_field_id>
				<t_value></t_value>
				<value></value>
			</item_004>
			<item_005>
				<data_input_field_id>hash_070016f4facc5e2ca7ebee621f09bc6d9fc792</data_input_field_id>
				<t_value></t_value>
				<value></value>
			</item_005>
			<item_006>
				<data_input_field_id>hash_070016acb449d1451e8a2a655c2c99d31142c7</data_input_field_id>
				<t_value></t_value>
				<value></value>
			</item_006>
			<item_007>
				<data_input_field_id>hash_070016617cdc8a230615e59f06f361ef6e7728</data_input_field_id>
				<t_value></t_value>
				<value></value>
			</item_007>
		</data>
	</hash_01001664f653d42cc6cf8398fa5d55e76c1387>
	<hash_030016bf566c869ac6443b0c75d1c32b5a350e>
		<name>Get SNMP Data (Indexed)</name>
		<type_id>3</type_id>
		<input_string></input_string>
		<fields>
			<hash_070016617cdc8a230615e59f06f361ef6e7728>
				<name>SNMP IP Address</name>
				<update_rra></update_rra>
				<regexp_match></regexp_match>
				<allow_nulls></allow_nulls>
				<type_code>hostname</type_code>
				<input_output>in</input_output>
				<data_name>management_ip</data_name>
			</hash_070016617cdc8a230615e59f06f361ef6e7728>
			<hash_070016acb449d1451e8a2a655c2c99d31142c7>
				<name>SNMP Community</name>
				<update_rra></update_rra>
				<regexp_match></regexp_match>
				<allow_nulls></allow_nulls>
				<type_code>snmp_community</type_code>
				<input_output>in</input_output>
				<data_name>snmp_community</data_name>
			</hash_070016acb449d1451e8a2a655c2c99d31142c7>
			<hash_070016f4facc5e2ca7ebee621f09bc6d9fc792>
				<name>SNMP Username (v3)</name>
				<update_rra></update_rra>
				<regexp_match></regexp_match>
				<allow_nulls>on</allow_nulls>
				<type_code>snmp_username</type_code>
				<input_output>in</input_output>
				<data_name>snmp_username</data_name>
			</hash_070016f4facc5e2ca7ebee621f09bc6d9fc792>
			<hash_0700161cc1493a6781af2c478fa4de971531cf>
				<name>SNMP Password (v3)</name>
				<update_rra></update_rra>
				<regexp_match></regexp_match>
				<allow_nulls>on</allow_nulls>
				<type_code>snmp_password</type_code>
				<input_output>in</input_output>
				<data_name>snmp_password</data_name>
			</hash_0700161cc1493a6781af2c478fa4de971531cf>
			<hash_070016b5c23f246559df38662c255f4aa21d6b>
				<name>SNMP Version (1, 2, or 3)</name>
				<update_rra></update_rra>
				<regexp_match></regexp_match>
				<allow_nulls></allow_nulls>
				<type_code>snmp_version</type_code>
				<input_output>in</input_output>
				<data_name>snmp_version</data_name>
			</hash_070016b5c23f246559df38662c255f4aa21d6b>
			<hash_0700166027a919c7c7731fbe095b6f53ab127b>
				<name>Index Type</name>
				<update_rra></update_rra>
				<regexp_match></regexp_match>
				<allow_nulls></allow_nulls>
				<type_code>index_type</type_code>
				<input_output>in</input_output>
				<data_name>index_type</data_name>
			</hash_0700166027a919c7c7731fbe095b6f53ab127b>
			<hash_070016cbbe5c1ddfb264a6e5d509ce1c78c95f>
				<name>Index Value</name>
				<update_rra></update_rra>
				<regexp_match></regexp_match>
				<allow_nulls></allow_nulls>
				<type_code>index_value</type_code>
				<input_output>in</input_output>
				<data_name>index_value</data_name>
			</hash_070016cbbe5c1ddfb264a6e5d509ce1c78c95f>
			<hash_070016e6deda7be0f391399c5130e7c4a48b28>
				<name>Output Type ID</name>
				<update_rra></update_rra>
				<regexp_match></regexp_match>
				<allow_nulls></allow_nulls>
				<type_code>output_type</type_code>
				<input_output>in</input_output>
				<data_name>output_type</data_name>
			</hash_070016e6deda7be0f391399c5130e7c4a48b28>
			<hash_070016c1f36ee60c3dc98945556d57f26e475b>
				<name>SNMP Port</name>
				<update_rra></update_rra>
				<regexp_match></regexp_match>
				<allow_nulls></allow_nulls>
				<type_code>snmp_port</type_code>
				<input_output>in</input_output>
				<data_name>snmp_port</data_name>
			</hash_070016c1f36ee60c3dc98945556d57f26e475b>
			<hash_0700162cf7129ad3ff819a7a7ac189bee48ce8>
				<name>SNMP Authenticaion Protocol (v3)</name>
				<update_rra></update_rra>
				<regexp_match></regexp_match>
				<allow_nulls></allow_nulls>
				<type_code>snmp_auth_protocol</type_code>
				<input_output>in</input_output>
				<data_name>snmp_auth_protocol</data_name>
			</hash_0700162cf7129ad3ff819a7a7ac189bee48ce8>
			<hash_0700166b13ac0a0194e171d241d4b06f913158>
				<name>SNMP Privacy Passphrase (v3)</name>
				<update_rra></update_rra>
				<regexp_match></regexp_match>
				<allow_nulls></allow_nulls>
				<type_code>snmp_priv_passphrase</type_code>
				<input_output>in</input_output>
				<data_name>snmp_priv_passphrase</data_name>
			</hash_0700166b13ac0a0194e171d241d4b06f913158>
			<hash_0700163a33d4fc65b8329ab2ac46a36da26b72>
				<name>SNMP Privacy Protocol (v3)</name>
				<update_rra></update_rra>
				<regexp_match></regexp_match>
				<allow_nulls></allow_nulls>
				<type_code>snmp_priv_protocol</type_code>
				<input_output>in</input_output>
				<data_name>snmp_priv_protocol</data_name>
			</hash_0700163a33d4fc65b8329ab2ac46a36da26b72>
		</fields>
	</hash_030016bf566c869ac6443b0c75d1c32b5a350e>
	<hash_150016c21df5178e5c955013591239eb0afd46>
		<name>Daily (5 Minute Average)</name>
		<x_files_factor>0.5</x_files_factor>
		<steps>1</steps>
		<rows>600</rows>
		<timespan>86400</timespan>
		<cf_items>1|3</cf_items>
	</hash_150016c21df5178e5c955013591239eb0afd46>
	<hash_1500160d9c0af8b8acdc7807943937b3208e29>
		<name>Weekly (30 Minute Average)</name>
		<x_files_factor>0.5</x_files_factor>
		<steps>6</steps>
		<rows>700</rows>
		<timespan>604800</timespan>
		<cf_items>1|3</cf_items>
	</hash_1500160d9c0af8b8acdc7807943937b3208e29>
	<hash_1500166fc2d038fb42950138b0ce3e9874cc60>
		<name>Monthly (2 Hour Average)</name>
		<x_files_factor>0.5</x_files_factor>
		<steps>24</steps>
		<rows>775</rows>
		<timespan>2678400</timespan>
		<cf_items>1|3</cf_items>
	</hash_1500166fc2d038fb42950138b0ce3e9874cc60>
	<hash_150016e36f3adb9f152adfa5dc50fd2b23337e>
		<name>Yearly (1 Day Average)</name>
		<x_files_factor>0.5</x_files_factor>
		<steps>288</steps>
		<rows>797</rows>
		<timespan>33053184</timespan>
		<cf_items>1|3</cf_items>
	</hash_150016e36f3adb9f152adfa5dc50fd2b23337e>
	<hash_150016283ea2bf1634d92ce081ec82a634f513>
		<name>Hourly (1 Minute Average)</name>
		<x_files_factor>0.5</x_files_factor>
		<steps>1</steps>
		<rows>500</rows>
		<timespan>14400</timespan>
		<cf_items>1|3</cf_items>
	</hash_150016283ea2bf1634d92ce081ec82a634f513>
	<hash_060016e9c43831e54eca8069317a2ce8c6f751>
		<name>Normal</name>
		<gprint_text>%8.2lf %s</gprint_text>
	</hash_060016e9c43831e54eca8069317a2ce8c6f751>
	<hash_05001662a7a53922548f4f6eac05cad69fbd2d>
		<name>Turn KBytes into Bits</name>
		<items>
			<hash_14001684771dca39335f5968c1556cc6b7a0ba>
				<sequence>1</sequence>
				<type>4</type>
				<value>CURRENT_DATA_SOURCE</value>
			</hash_14001684771dca39335f5968c1556cc6b7a0ba>
			<hash_1400162b6cd4a21242ab0f8088398fe92720c1>
				<sequence>2</sequence>
				<type>6</type>
				<value>8000</value>
			</hash_1400162b6cd4a21242ab0f8088398fe92720c1>
			<hash_140016de8bafcf7c4d48234113d12687d7cd24>
				<sequence>3</sequence>
				<type>2</type>
				<value>3</value>
			</hash_140016de8bafcf7c4d48234113d12687d7cd24>
		</items>
	</hash_05001662a7a53922548f4f6eac05cad69fbd2d>
	<hash_040016e423847310ebee7dc22eaf3938d709f9>
		<name>LiteSpeed Vhost</name>
		<description>LiteSpeed Vhost</description>
		<xml_path>&lt;path_cacti&gt;/resource/snmp_queries/litespeed_vhost.xml</xml_path>
		<data_input_id>hash_030016bf566c869ac6443b0c75d1c32b5a350e</data_input_id>
		<graphs>
			<hash_1100164e6e2c659f889978cc41c6c54d6de928>
				<name>Requests</name>
				<graph_template_id>hash_00001616ed2d0aa716489be372dd598afe0b9e</graph_template_id>
				<rrd>
					<item_000>
						<snmp_field_name>ReqProcessing</snmp_field_name>
						<data_template_id>hash_0100164fa3bc9138bd7459ed6ed6e1eccd6d32</data_template_id>
						<data_template_rrd_id>hash_08001676fbeb01ef35493c81578394cdc9f453</data_template_rrd_id>
					</item_000>
					<item_001>
						<snmp_field_name>ReqSecond</snmp_field_name>
						<data_template_id>hash_0100164fa3bc9138bd7459ed6ed6e1eccd6d32</data_template_id>
						<data_template_rrd_id>hash_080016e5084b9e07fdcc5535637f75b8af3222</data_template_rrd_id>
					</item_001>
				</rrd>
				<sv_graph>
					<hash_120016f56c103f7c9f54e880d7ebd90bdf03e3>
						<field_name>title</field_name>
						<sequence>8</sequence>
						<text>|host_description|: |query_Vhost|: Requests</text>
					</hash_120016f56c103f7c9f54e880d7ebd90bdf03e3>
				</sv_graph>
				<sv_data_source>
					<hash_130016216ebc3b35e38dca0b90ccfff9b2e673>
						<field_name>name</field_name>
						<data_template_id>hash_0100164fa3bc9138bd7459ed6ed6e1eccd6d32</data_template_id>
						<sequence>9</sequence>
						<text>|host_description|: |query_Vhost|: Requests</text>
					</hash_130016216ebc3b35e38dca0b90ccfff9b2e673>
				</sv_data_source>
			</hash_1100164e6e2c659f889978cc41c6c54d6de928>
		</graphs>
	</hash_040016e423847310ebee7dc22eaf3938d709f9>
	<hash_04001676d81d4e3c52dab62afa5205a9c517a2>
		<name>LiteSpeed ExtApp</name>
		<description>LiteSpeed ExtApp</description>
		<xml_path>&lt;path_cacti&gt;/resource/snmp_queries/litespeed_extapp.xml</xml_path>
		<data_input_id>hash_030016bf566c869ac6443b0c75d1c32b5a350e</data_input_id>
		<graphs>
			<hash_1100160f49f3d6424612167139e31dd23f8363>
				<name>Requests</name>
				<graph_template_id>hash_000016974ad3f65464268b1e61142e1d377048</graph_template_id>
				<rrd>
					<item_000>
						<snmp_field_name>Req_Second</snmp_field_name>
						<data_template_id>hash_01001626652071e652e251bc9f2cb68a65ce0f</data_template_id>
						<data_template_rrd_id>hash_0800165d24f91f2b8d9e5598d1abd567b076f9</data_template_rrd_id>
					</item_000>
				</rrd>
				<sv_graph>
					<hash_120016fd8568934db23ae9016ae7f171cc5a9f>
						<field_name>title</field_name>
						<sequence>1</sequence>
						<text>|host_description|: |query_Vhost|: |query_Type|: |query_ExtApp|: Reqs</text>
					</hash_120016fd8568934db23ae9016ae7f171cc5a9f>
				</sv_graph>
				<sv_data_source>
					<hash_130016cb61ccfc35b4c03fb31021a02dc22ba7>
						<field_name>name</field_name>
						<data_template_id>hash_01001626652071e652e251bc9f2cb68a65ce0f</data_template_id>
						<sequence>1</sequence>
						<text>|host_description|: |query_Vhost|: |query_Type|: |query_ExtApp|: Reqs</text>
					</hash_130016cb61ccfc35b4c03fb31021a02dc22ba7>
				</sv_data_source>
			</hash_1100160f49f3d6424612167139e31dd23f8363>
			<hash_110016d1ed72b429661243298658143189c3a9>
				<name>Connections</name>
				<graph_template_id>hash_000016022aa61c315e6588a6acd2c013fcf5c5</graph_template_id>
				<rrd>
					<item_000>
						<snmp_field_name>EffMaxConn</snmp_field_name>
						<data_template_id>hash_01001626652071e652e251bc9f2cb68a65ce0f</data_template_id>
						<data_template_rrd_id>hash_080016761fd20a96d97f909f6b4ec0241344ab</data_template_rrd_id>
					</item_000>
					<item_001>
						<snmp_field_name>IdleConn</snmp_field_name>
						<data_template_id>hash_01001626652071e652e251bc9f2cb68a65ce0f</data_template_id>
						<data_template_rrd_id>hash_080016ca1f6af4ad148a9f858b9f9a4a3ab010</data_template_rrd_id>
					</item_001>
					<item_002>
						<snmp_field_name>InuseConn</snmp_field_name>
						<data_template_id>hash_01001626652071e652e251bc9f2cb68a65ce0f</data_template_id>
						<data_template_rrd_id>hash_080016dca7bbae358416c8a86fd74cc83104d8</data_template_rrd_id>
					</item_002>
					<item_003>
						<snmp_field_name>PoolSize</snmp_field_name>
						<data_template_id>hash_01001626652071e652e251bc9f2cb68a65ce0f</data_template_id>
						<data_template_rrd_id>hash_08001624140062cfa9de88c593a71be9a40e0f</data_template_rrd_id>
					</item_003>
					<item_004>
						<snmp_field_name>ConfMaxConn</snmp_field_name>
						<data_template_id>hash_01001626652071e652e251bc9f2cb68a65ce0f</data_template_id>
						<data_template_rrd_id>hash_080016a972198dd76a78359072a49e7b6d295e</data_template_rrd_id>
					</item_004>
					<item_005>
						<snmp_field_name>WaitQueueDepth</snmp_field_name>
						<data_template_id>hash_01001626652071e652e251bc9f2cb68a65ce0f</data_template_id>
						<data_template_rrd_id>hash_080016dd80f6a8dac8166b110503ac3cdbe991</data_template_rrd_id>
					</item_005>
				</rrd>
				<sv_graph>
					<hash_120016940fd523f0d3fcc8f9f77417fac15cee>
						<field_name>title</field_name>
						<sequence>6</sequence>
						<text>|host_description|: |query_Vhost|: |query_Type|: |query_ExtApp|: Conn</text>
					</hash_120016940fd523f0d3fcc8f9f77417fac15cee>
				</sv_graph>
				<sv_data_source>
					<hash_130016fa9a2cf4c789fe45997b83d3f952f505>
						<field_name>name</field_name>
						<data_template_id>hash_01001626652071e652e251bc9f2cb68a65ce0f</data_template_id>
						<sequence>6</sequence>
						<text>|host_description|: |query_Vhost|: |query_Type|: |query_ExtApp|: Conn</text>
					</hash_130016fa9a2cf4c789fe45997b83d3f952f505>
				</sv_data_source>
			</hash_110016d1ed72b429661243298658143189c3a9>
		</graphs>
	</hash_04001676d81d4e3c52dab62afa5205a9c517a2>
	<hash_040016c6bc8ced2a4d8fac0fde1c0cead29779>
		<name>LiteSpeed General</name>
		<description>LiteSpeed General</description>
		<xml_path>&lt;path_cacti&gt;/resource/snmp_queries/litespeed_general.xml</xml_path>
		<data_input_id>hash_030016bf566c869ac6443b0c75d1c32b5a350e</data_input_id>
		<graphs>
			<hash_11001688768d5a7041b45563933ad1624fd913>
				<name>Plain Traffic</name>
				<graph_template_id>hash_000016bac5833ec4bd88e46603947c40f163dd</graph_template_id>
				<rrd>
					<item_000>
						<snmp_field_name>BpsIn</snmp_field_name>
						<data_template_id>hash_01001664f653d42cc6cf8398fa5d55e76c1387</data_template_id>
						<data_template_rrd_id>hash_080016f9bc5dd109ed4ab674746e66a49df3d8</data_template_rrd_id>
					</item_000>
					<item_001>
						<snmp_field_name>BpsOut</snmp_field_name>
						<data_template_id>hash_01001664f653d42cc6cf8398fa5d55e76c1387</data_template_id>
						<data_template_rrd_id>hash_0800164a9cc0ba440529238c3bb8606e5991bd</data_template_rrd_id>
					</item_001>
				</rrd>
				<sv_graph>
					<hash_120016cfacff2f189000b9719efe2c35ccc236>
						<field_name>title</field_name>
						<sequence>7</sequence>
						<text>|host_description|: Plain Traffic (bits/sec)</text>
					</hash_120016cfacff2f189000b9719efe2c35ccc236>
				</sv_graph>
				<sv_data_source>
					<hash_1300164bdb40074dbdf62463c1c9b206711da3>
						<field_name>name</field_name>
						<data_template_id>hash_01001664f653d42cc6cf8398fa5d55e76c1387</data_template_id>
						<sequence>6</sequence>
						<text>|host_description|: Plain Traffic (bits/sec)</text>
					</hash_1300164bdb40074dbdf62463c1c9b206711da3>
				</sv_data_source>
			</hash_11001688768d5a7041b45563933ad1624fd913>
			<hash_110016090b866bab410ebc060c7bdca5f394a5>
				<name>SSL Traffic</name>
				<graph_template_id>hash_0000164740ee10c62708a97452e64c39918381</graph_template_id>
				<rrd>
					<item_000>
						<snmp_field_name>SSLBpsIn</snmp_field_name>
						<data_template_id>hash_01001664f653d42cc6cf8398fa5d55e76c1387</data_template_id>
						<data_template_rrd_id>hash_0800164d9b25cf1a27c98599313c1000f001b0</data_template_rrd_id>
					</item_000>
					<item_001>
						<snmp_field_name>SSLBpsOut</snmp_field_name>
						<data_template_id>hash_01001664f653d42cc6cf8398fa5d55e76c1387</data_template_id>
						<data_template_rrd_id>hash_080016b874ed68ddc80a0ea28275a7ebfd1c3e</data_template_rrd_id>
					</item_001>
				</rrd>
				<sv_graph>
					<hash_120016e198e435431d755f9c1eeb59641fc3f7>
						<field_name>title</field_name>
						<sequence>7</sequence>
						<text>|host_description|: SSL Traffic (bits/sec)</text>
					</hash_120016e198e435431d755f9c1eeb59641fc3f7>
				</sv_graph>
				<sv_data_source>
					<hash_1300162c70fb38675dc5ae80dc43533b5fa18a>
						<field_name>name</field_name>
						<data_template_id>hash_01001664f653d42cc6cf8398fa5d55e76c1387</data_template_id>
						<sequence>7</sequence>
						<text>|host_description|: SSL Traffic</text>
					</hash_1300162c70fb38675dc5ae80dc43533b5fa18a>
				</sv_data_source>
			</hash_110016090b866bab410ebc060c7bdca5f394a5>
			<hash_1100168ba5d8af10bf1df03f9b5b6df0f41dee>
				<name>Plain Connections</name>
				<graph_template_id>hash_0000160ec40ca42977e0f88770a13629862650</graph_template_id>
				<rrd>
					<item_000>
						<snmp_field_name>PlainConn</snmp_field_name>
						<data_template_id>hash_01001664f653d42cc6cf8398fa5d55e76c1387</data_template_id>
						<data_template_rrd_id>hash_0800160c86937c02cb9d97697e1c811f428cb8</data_template_rrd_id>
					</item_000>
					<item_001>
						<snmp_field_name>AvailConn</snmp_field_name>
						<data_template_id>hash_01001664f653d42cc6cf8398fa5d55e76c1387</data_template_id>
						<data_template_rrd_id>hash_080016614e73da69c6fa3034c159dfeb0b0362</data_template_rrd_id>
					</item_001>
				</rrd>
				<sv_graph>
					<hash_12001604dd2a73a1cfc25d1306e9791ea063cf>
						<field_name>title</field_name>
						<sequence>1</sequence>
						<text>|host_description|: Plain Connections</text>
					</hash_12001604dd2a73a1cfc25d1306e9791ea063cf>
				</sv_graph>
				<sv_data_source>
					<hash_13001631e782c46a6548ecee5e92c92c780183>
						<field_name>name</field_name>
						<data_template_id>hash_01001664f653d42cc6cf8398fa5d55e76c1387</data_template_id>
						<sequence>1</sequence>
						<text>|host_description|: Plain Connections</text>
					</hash_13001631e782c46a6548ecee5e92c92c780183>
				</sv_data_source>
			</hash_1100168ba5d8af10bf1df03f9b5b6df0f41dee>
			<hash_1100166fb5df7bf50d2b6bd0edddac15fbb80c>
				<name>SSL Connections</name>
				<graph_template_id>hash_000016a85d4e176d782c3bef5da7ed00cce513</graph_template_id>
				<rrd>
					<item_000>
						<snmp_field_name>SSLConn</snmp_field_name>
						<data_template_id>hash_01001664f653d42cc6cf8398fa5d55e76c1387</data_template_id>
						<data_template_rrd_id>hash_08001667c11e9d5c8ee24343108fa839c89ac6</data_template_rrd_id>
					</item_000>
					<item_001>
						<snmp_field_name>AvailSSLConn</snmp_field_name>
						<data_template_id>hash_01001664f653d42cc6cf8398fa5d55e76c1387</data_template_id>
						<data_template_rrd_id>hash_0800164cb690fe79ffeb845634b5e64bcedba7</data_template_rrd_id>
					</item_001>
				</rrd>
				<sv_graph>
					<hash_12001648449841eac4644908a17652e894297d>
						<field_name>title</field_name>
						<sequence>1</sequence>
						<text>|host_description|: SSL Connections</text>
					</hash_12001648449841eac4644908a17652e894297d>
				</sv_graph>
				<sv_data_source>
					<hash_130016d0c13a2a9acdc09ba2c52f675214450e>
						<field_name>name</field_name>
						<data_template_id>hash_01001664f653d42cc6cf8398fa5d55e76c1387</data_template_id>
						<sequence>1</sequence>
						<text>|host_description|: SSL Connections</text>
					</hash_130016d0c13a2a9acdc09ba2c52f675214450e>
				</sv_data_source>
			</hash_1100166fb5df7bf50d2b6bd0edddac15fbb80c>
		</graphs>
	</hash_040016c6bc8ced2a4d8fac0fde1c0cead29779>
</cacti>snmp_monitoring/sample.php000064400000001742150545647700012001 0ustar00<?php

/*--------------------------------
assuming  following entry in /etc/snmp/snmpd.conf

pass .1.3.6.1.4.1.22253 /usr/bin/php smaple.php

if you change the default parent oid node: .1.3.6.1.4.1.22253, you must also modify the OID entries .xml files.
--------------------------------*/

error_reporting(E_ALL);
require_once("class.litespeed_snmp_bridge.php");

$processes = 1; //<-- value of > 1 only valid LiteSpeed Enterprise (num of cpus licensed)
$report_path = "/tmp/lshttpd/"; //<-- path to .rtreport folder. Default is /tmp/lshttpd/

$cache_time = 0; //<-- seconds to cache parsed data
$cache_file = "/tmp/_lsws_sampe_cache.txt"; //<-- cache file..full path.


//get params from snmpd pass mechanism
if(array_key_exists(1,$_SERVER["argv"]) && array_key_exists(2,$_SERVER["argv"])) {
	$type = trim($_SERVER["argv"][1]);
	$oid = trim($_SERVER["argv"][2]);

	$bridge = new litespeed_snmp_bridge($processes, $report_path, $cache_time, $cache_file);
	$bridge->process($type, $oid);

}

?>
snmp_monitoring/litespeed_vhost.xml000064400000003632150545647700013732 0ustar00<interface>
        <name>Get LiteSpeed Vhosts</name>
        <description>list litespeed virtual hosts</description>
        <oid_index>.1.3.6.1.4.1.22253.200</oid_index>
        <index_order>Vhost:Index</index_order>
        <index_order_type>numeric</index_order_type>
        <index_title_format>|chosen_order_field|</index_title_format>

        <fields>
                <Index>
                        <name>Index</name>
                        <method>walk</method>
                        <source>value</source>
                        <direction>input</direction>
                        <oid>.1.3.6.1.4.1.22253.200</oid>
                </Index>
                <Vhost>
                        <name>Vhost Name</name>
                        <method>walk</method>
                        <source>value</source>
                        <direction>input</direction>
                        <oid>.1.3.6.1.4.1.22253.201</oid>
                </Vhost>
                <ReqProcessing>
                        <name>Requests Processing</name>
                        <method>walk</method>
                        <source>value</source>
                        <direction>output</direction>
                        <oid>.1.3.6.1.4.1.22253.202</oid>
                </ReqProcessing>
                <ReqSecond>
                        <name>Requests Per Second</name>
                        <method>walk</method>
                        <source>value</source>
                        <direction>output</direction>
                        <oid>.1.3.6.1.4.1.22253.203</oid>
                </ReqSecond>
                <ReqTotal>
                        <name>Requests Total</name>
                        <method>walk</method>
                        <source>value</source>
                        <direction>output</direction>
                        <oid>.1.3.6.1.4.1.22253.204</oid>
                </ReqTotal>       
		</fields>
</interface>snmp_monitoring/litespeed_general.xml000064400000012343150545647700014203 0ustar00<interface>
        <name>Get LiteSpeed General</name>
        <description>list litespeed general</description>
        <oid_index>.1.3.6.1.4.1.22253.100</oid_index>
        <index_order>Index</index_order>
        <index_order_type>numeric</index_order_type>
        <index_title_format>|chosen_order_field|</index_title_format>

        <fields>
                <Index>
                        <name>Index</name>
                        <method>walk</method>
                        <source>value</source>
                        <direction>input</direction>
                        <oid>.1.3.6.1.4.1.22253.100</oid>
                </Index>
                <Product>
                        <name>Product</name>
                        <method>walk</method>
                        <source>value</source>
                        <direction>input</direction>
                        <oid>.1.3.6.1.4.1.22253.101</oid>
                </Product>
                <Edition>
                        <name>Edition</name>
                        <method>walk</method>
                        <source>value</source>
                        <direction>input</direction>
                        <oid>.1.3.6.1.4.1.22253.102</oid>
                </Edition>
                <Version>
                        <name>Version</name>
                        <method>walk</method>
                        <source>value</source>
                        <direction>input</direction>
                        <oid>.1.3.6.1.4.1.22253.103</oid>
                </Version>  
                <UpTime>
                        <name>UpTime</name>
                        <method>walk</method>
                        <source>value</source>
                        <direction>input</direction>
                        <oid>.1.3.6.1.4.1.22253.104</oid>
                </UpTime> 
                <BpsIn>
                        <name>Bps (In)</name>
                        <method>walk</method>
                        <source>value</source>
                        <direction>output</direction>
                        <oid>.1.3.6.1.4.1.22253.105</oid>
                </BpsIn> 
                <BpsOut>
                        <name>Bps (Out)</name>
                        <method>walk</method>
                        <source>value</source>
                        <direction>output</direction>
                        <oid>.1.3.6.1.4.1.22253.106</oid>
                </BpsOut>
                <SSLBpsIn>
                        <name>SSL Bps (In)</name>
                        <method>walk</method>
                        <source>value</source>
                        <direction>output</direction>
                        <oid>.1.3.6.1.4.1.22253.107</oid>
                </SSLBpsIn> 
                <SSLBpsOut>
                        <name>SSL Bps (Out)</name>
                        <method>walk</method>
                        <source>value</source>
                        <direction>output</direction>
                        <oid>.1.3.6.1.4.1.22253.108</oid>
                </SSLBpsOut> 
                <MaxConn>
                        <name>Max Connections</name>
                        <method>walk</method>
                        <source>value</source>
                        <direction>output</direction>
                        <oid>.1.3.6.1.4.1.22253.109</oid>
                </MaxConn>  
                <MaxSSLConn>
                        <name>Max SSL Connections</name>
                        <method>walk</method>
                        <source>value</source>
                        <direction>output</direction>
                        <oid>.1.3.6.1.4.1.22253.110</oid>
                </MaxSSLConn>  
                <PlainConn>
                        <name>Plain Connections</name>
                        <method>walk</method>
                        <source>value</source>
                        <direction>output</direction>
                        <oid>.1.3.6.1.4.1.22253.111</oid>
                </PlainConn> 
                <AvailConn>
                        <name>Available Plain Connections</name>
                        <method>walk</method>
                        <source>value</source>
                        <direction>output</direction>
                        <oid>.1.3.6.1.4.1.22253.112</oid>
                </AvailConn> 
                <IdleConn>
                        <name>Idle Connections</name>
                        <method>walk</method>
                        <source>value</source>
                        <direction>output</direction>
                        <oid>.1.3.6.1.4.1.22253.113</oid>
                </IdleConn> 
                <SSLConn>
                        <name>SSL Connections</name>
                        <method>walk</method>
                        <source>value</source>
                        <direction>output</direction>
                        <oid>.1.3.6.1.4.1.22253.114</oid>
                </SSLConn> 
                <AvailSSLConn>
                        <name>Available SSL Connections</name>
                        <method>walk</method>
                        <source>value</source>
                        <direction>output</direction>
                        <oid>.1.3.6.1.4.1.22253.115</oid>
                </AvailSSLConn> 
		</fields>
</interface>snmp_monitoring/litespeed_extapp.xml000064400000007755150545647700014102 0ustar00<interface>
        <name>Get LiteSpeed External Applications</name>
        <oid_index>.1.3.6.1.4.1.22253.300</oid_index>
        <index_order>ExtApp:Type:Vhost:Index</index_order>
        <index_order_type>numeric</index_order_type>
        <index_title_format>|chosen_order_field|</index_title_format>

        <fields>
                <Index>
                        <name>Index</name>
                        <method>walk</method>
                        <source>value</source>
                        <direction>input</direction>
                        <oid>.1.3.6.1.4.1.22253.300</oid>
                </Index>
                <Vhost>
                        <name>Vhost Name</name>
                        <method>walk</method>
                        <source>value</source>
                        <direction>input</direction>
                        <oid>.1.3.6.1.4.1.22253.301</oid>
                </Vhost>
                <Type>
                        <name>Type</name>
                        <method>walk</method>
                        <source>value</source>
                        <direction>input</direction>
                        <oid>.1.3.6.1.4.1.22253.302</oid>
                </Type>
                <ExtApp>
                        <name>Ext App</name>
                        <method>walk</method>
                        <source>value</source>
                        <direction>input</direction>
                        <oid>.1.3.6.1.4.1.22253.303</oid>
                </ExtApp>
                <ConfMaxConn>
                        <name>Config Max Conn</name>
                        <method>walk</method>
                        <source>value</source>
                        <direction>output</direction>
                        <oid>.1.3.6.1.4.1.22253.304</oid>
                </ConfMaxConn>
                <EffMaxConn>
                        <name>Effective Max Conn</name>
                        <method>walk</method>
                        <source>value</source>
                        <direction>output</direction>
                        <oid>.1.3.6.1.4.1.22253.305</oid>
                </EffMaxConn>
                <PoolSize>
                        <name>Pool Size</name>
                        <method>walk</method>
                        <source>value</source>
                        <direction>output</direction>
                        <oid>.1.3.6.1.4.1.22253.306</oid>
                </PoolSize>
                <InuseConn>
                        <name>InUse Conn</name>
                        <method>walk</method>
                        <source>value</source>
                        <direction>output</direction>
                        <oid>.1.3.6.1.4.1.22253.307</oid>
                </InuseConn>
                <IdleConn>
                        <name>Idle Conn</name>
                        <method>walk</method>
                        <source>value</source>
                        <direction>output</direction>
                        <oid>.1.3.6.1.4.1.22253.308</oid>
                </IdleConn>
                <WaitQueueDepth>
                        <name>Wait-Queue Depth</name>
                        <method>walk</method>
                        <source>value</source>
                        <direction>output</direction>
                        <oid>.1.3.6.1.4.1.22253.309</oid>
                </WaitQueueDepth>
                <Req_Second>
                        <name>Requests Per Second</name>
                        <method>walk</method>
                        <source>value</source>
                        <direction>output</direction>
                        <oid>.1.3.6.1.4.1.22253.310</oid>
                </Req_Second>
                <Req_Total>
                        <name>Requests Total</name>
                        <method>walk</method>
                        <source>value</source>
                        <direction>output</direction>
                        <oid>.1.3.6.1.4.1.22253.311</oid>
                </Req_Total>
               
		</fields>
</interface>snmp_monitoring/class.litespeed_stats.php000064400000017146150545647700015025 0ustar00<?php

/*----------------------------------------
LiteSpeed_Stats class and subclasses. Parse Real-Time data for LiteSpeed Products

Copyright (C) 2006 LiteSpeed Technologies, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library 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
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

Version: 1.0 @ 08/23/2006
Contact: bug@litespeedtech.com
Url: http://www.litespeedtech.com

Requirement:

1)LiteSpeed Web Server version >= 2.1.18
2)PHP 5+
----------------------------------------*/


class litespeed_stats {

	public $product = null;
	public $edition = null;
	public $version = null;
	public $uptime = null;
	public $load_avg = NULL;

	public $bps_in = 0;
	public $bps_out = 0;
	public $ssl_bps_in = 0;
	public $ssl_bps_out = 0;

	public $max_conn = 0;
	public $max_ssl_conn = 0;

	public $plain_conn = 0;
	public $avail_conn = 0;
	public $idle_conn = 0;

	public $ssl_conn = 0;
	public $avail_ssl_conn = 0;

  public $blocked_ip;
	public $vhosts = array();
	public $serv = NULL;

	//misc settings

	//full path to .rtreports files. different products have different paths
	public $report_path = "/tmp/lshttpd/";

	//processes..enterprise version can spawn proccess = cpu cores
	public $processes = 1;

	public function litespeed_stats($processes = 1, $report_path = "/tmp/lshttpd/") {
		$this->processes = (int) $processes;
		$this->report_path = trim($report_path);

	}

	public function parse() {

		for ( $i = 1 ; $i <= $this->processes ; $i++ )
		{
			if ( $i > 1 ) {
				$content = file_get_contents("{$this->report_path}.rtreport.{$i}");
			}
			else {
				$content = file_get_contents("{$this->report_path}.rtreport");
			}
		}
		$result = array();
		$this->blocked_ip = array();
		$found = 0;

		$found = preg_match_all("/VERSION: ([a-zA-Z0-9\ ]+)\/([a-zA-Z]*)\/([a-zA-Z0-9\.]+)\nUPTIME: ([0-9A-Za-z\ \:]+)\nBPS_IN:([0-9\ ]+), BPS_OUT:([0-9\ ]+), SSL_BPS_IN:([0-9\ ]+), SSL_BPS_OUT:([0-9\ ]+)\nMAXCONN:([0-9\ ]+), MAXSSL_CONN:([0-9\ ]+), PLAINCONN:([0-9\ ]+), AVAILCONN:([0-9\ ]+), IDLECONN:([0-9\ ]+), SSLCONN:([0-9\ ]+), AVAILSSL:([0-9\ ]+)/i", $content, $result);
		for($f = 0; $f < $found; $f++) {
			$this->product = trim($result[1][$f]);
			$this->edition = trim($result[2][$f]);
			$this->version = trim($result[3][$f]);
			$this->uptime = trim($result[4][$f]);
			$this->bps_in += (int) $result[5][$f];
			$this->bps_out += (int) $result[6][$f];
			$this->ssl_bps_in += (int) $result[7][$f];
			$this->ssl_bps_out += (int) $result[8][$f];
			$this->max_conn += (int) $result[9][$f];
			$this->max_ssl_conn += (int) $result[10][$f];
			$this->plain_conn += (int) $result[11][$f];
			$this->avail_conn += (int) $result[12][$f];
			$this->idle_conn += (int) $result[13][$f];
			$this->ssl_conn += (int) $result[14][$f];
			$this->avail_ssl_conn += (int) $result[15][$f];
		}
		$result = array();
		$found = 0;

		$found = preg_match_all("/BLOCKED_IP: ([0-9 \[\]\.,]*)/", $content, $result);
		for($f = 0; $f < $found; $f++) {
			$ips = trim($result[1][$f]);
			if ($ips != "") {
				$iplist = preg_split("/[\s,]+/", $ips, -1, PREG_SPLIT_NO_EMPTY);
				$this->blocked_ip = array_merge($this->blocked_ip, $iplist);
			}
		}
		$result = array();
		$found = 0;

		$found = preg_match_all("/REQ_RATE \[(.*)\]: REQ_PROCESSING: ([0-9]+), REQ_PER_SEC: ([0-9\.]+), TOT_REQS: ([0-9]+), PUB_CACHE_HITS_PER_SEC: ([0-9\.]+), TOTAL_PUB_CACHE_HITS: ([0-9]+), PRIVATE_CACHE_HITS_PER_SEC: ([0-9\.]+), TOTAL_PRIVATE_CACHE_HITS: ([0-9]+), STATIC_HITS_PER_SEC: ([0-9\.]+), TOTAL_STATIC_HITS: ([0-9]+)/i",$content,$result);
		for($f = 0; $f < $found; $f++) {
			$vhost = trim($result[1][$f]);

			if($vhost == "") {
				$vhost = "_Server";
			}

			if(!array_key_exists($vhost,$this->vhosts)) {
				$this->vhosts[$vhost] = new litespeed_stats_vhost($vhost);
			}

			$temp = $this->vhosts[$vhost];
			$temp->req_processing += (int) $result[2][$f];
			$temp->req_per_sec += doubleval($result[3][$f]);
			$temp->req_total += doubleval($result[4][$f]);
			$temp->cache_hits_per_sec += doubleval($result[5][$f]);
			$temp->total_cache_hits += doubleval($result[6][$f]);
      $temp->private_cache_hits_per_sec += doubleval($result[7][$f]);
      $temp->total_private_cache_hits += (int) $result[8][$f];
      $temp->static_hits_per_sec += doubleval($result[9][$f]);
      $temp->total_static_hits += doubleval($result[10][$f]);

		}
		$result = array();
		$found = 0;

		$found = preg_match_all("/EXTAPP \[([^\]]*)\] \[(.*)\] \[([^\]]*)\]: CMAXCONN: ([0-9]+), EMAXCONN: ([0-9]+), POOL_SIZE: ([0-9]+), INUSE_CONN: ([0-9]+), IDLE_CONN: ([0-9]+), WAITQUE_DEPTH: ([0-9]+), REQ_PER_SEC: ([0-9\.]+), TOT_REQS: ([0-9]+)/i",$content,$result);
		for($f = 0; $f < $found; $f++) {
			$vhost = trim($result[2][$f]);
			$extapp = trim($result[3][$f]);

			if($vhost == "") {
				$vhost = "_Server";
			}

			if(!array_key_exists($vhost,$this->vhosts)) {
				$this->vhosts[$vhost] = new litespeed_stats_vhost($vhost);
			}

			if(!array_key_exists($extapp,$this->vhosts[$vhost]->extapps)) {
				$this->vhosts[$vhost]->extapps[$extapp] = new litespeed_stats_vhost_extapp($extapp, $vhost);
				$this->vhosts[$vhost]->eap_count ++;
				$this->vhosts[$vhost]->eap_process ++;
			}

			$temp = $this->vhosts[$vhost]->extapps[$extapp];
			$temp->type = trim($result[1][$f]);
			$temp->config_max_conn += (int) $result[4][$f];
			$temp->effect_max_conn += (int) $result[5][$f];
			$temp->pool_size += (int) $result[6][$f];
			$temp->inuse_conn += (int) $result[7][$f];
			$temp->idle_conn += (int) $result[8][$f];
			$temp->waitqueue_depth += (int) $result[9][$f];
			$temp->req_per_sec += (int) $result[10][$f];
			$temp->req_total += (int) $result[11][$f];
			$this->vhosts[$vhost]->eap_inuse += (int) $result[7][$f];
			$this->vhosts[$vhost]->eap_idle += (int) $result[8][$f];
			$this->vhosts[$vhost]->eap_waitQ += (int) $result[9][$f];
			$this->vhosts[$vhost]->eap_req_per_sec += doubleval($result[10][$f]);
			$this->vhosts[$vhost]->eap_req_total += doubleval($result[11][$f]);
		}
		if (count($this->blocked_ip) > 2) {
			sort($this->blocked_ip);
		}
		$this->serv = $this->vhosts['_Server'];
	}
}

class liteSpeed_stats_vhost {
	public $req_processing = 0;
	public $req_per_sec = 0.0;
	public $req_total = 0;
	public $cache_hits_per_sec = 0.0;
	public $total_cache_hits = 0;
	public $private_cache_hits_per_sec = 0.0;
  public $total_private_cache_hits = 0;
  public $static_hits_per_sec = 0.0;
  public $total_static_hits = 0;
	public $eap_count = 0;
	public $eap_process = 0;
	public $eap_inuse = 0;
	public $eap_idle = 0;
	public $eap_waitQ = 0;
	public $eap_req_per_sec = 0.0;
	public $eap_req_total = 0;
	public $extapps = array();

	public function litespeed_stats_vhost($vhost = null) {
		$this->vhost = trim($vhost);
	}
}

class litespeed_stats_vhost_extapp {
	public function litespeed_stats_vhost_extApp($extapp = null, $vhost = null) {
		$this->extapp = trim($extapp);
		$this->vhost = trim($vhost);
	}

	public $vhost = null;
	public $type = null;
	public $extapp = null;
	public $config_max_conn = 0;
	public $effect_max_conn = 0;
	public $pool_size = 0;
	public $inuse_conn = 0;
	public $idle_conn = 0;
	public $waitqueue_depth = 0;
	public $req_per_sec = 0;
	public $req_total = 0;
}
?>
snmp_monitoring/class.litespeed_snmp_bridge.php000064400000014431150545647700016152 0ustar00<?php

/*----------------------------------------
LiteSpeed_Stats to SNMP bridge. Relay stats to SNMPD.

Copyright (C) 2006 LiteSpeed Technologies, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library 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
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

Version: 1.0 @ 08/23/2006
Contact: bug@litespeedtech.com
Url: http://www.litespeedtech.com

Requirement:

1)LiteSpeed Web Server version >= 2.1.18
2)PHP 5+

----------------------------------------*/

require_once("class.litespeed_stats.php");


class litespeed_snmp_bridge {
	public $processes = 1;
	public $report_path = "/tmp/lshttpd/";
	public $cache_time = 0;
	public $cache_file = null;

	public $stats = null;

	public function litespeed_snmp_bridge($processes = 1, $report_path = "/tmp/lshttpd/", $cache_time = 0, $cache_file = null) {
		$this->processes = (int) $processes;
		$this->report_path = trim($report_path);

		//prepare parser
		if($this->cache_time > 0 && strlen($this->cache_file) > 0) {
			if(file_exists($this->cache_file) && time() - filemtime($this->cache_file) <= $this->cache_time) {
				$unserial = unserialize(file_get_contents($this->cache_file));

				if(is_a($unserial,"litespeed_stats")) {
					$this->stats = $unserial;
				}
				else {
					$this->stats = new litespeed_stats($this->processes,$this->report_path);
					$this->stats->parse();
					$this->save_cache($this->cache_file, $this->stats);
				}
			}
			else {
				$this->stats = new litespeed_stats($this->processes,$this->report_path);
				$this->stats->parse();
				$this->save_cache($this->cache_file, $this->stats);
			}
		}
		else {
			$this->stats = new litespeed_stats($this->processes,$this->report_path);
			$this->stats->parse();
		}
	}

	//generate snmp compatible response
	public function format_response($oid, $type, $data) {
		return "{$oid}\n{$type}\n{$data}\n";
	}

	//aggregate oid info from 1 to 7 sector
	public function oid_part($tarray = null) {
		$str = "";
		for($i=1; $i <= 7; $i++) {
			$str .= "." . $tarray[$i];
		}

		return $str;
	}

	//retrieve single oid data
	public function oid_get($super, $oid) {


		$parsed = explode(".",$oid);

		//error..invalid oid parse
		if(count($parsed) < 9) {
			return;
		}

		$major = (int) $parsed[8];

		if(count($parsed) < 10) {
			$minor = 1;
		}
		else {
			$minor =  (int) $parsed[9];
		}

		foreach($super as $key => $value) {
			$sanitized_major = (int) substr($major,0,1) . "00";

			//index only
			if( $major == (int) $key ) {
				return $this->format_response($this->oid_part($parsed) . "." . $major . "." . $minor,"integer",$minor);

			}

			//non-index value
			if( $sanitized_major == (int) $key) {
				$size = count($value[0]);

				$map = $value[1];

				if($size <= 0) {
					return null;
				}

				if(count($parsed) == 10) {

					if($minor > 0 && $minor <= $size) {
						$tempkeys = array_keys($value[0]);
						$temp = $value[0][$tempkeys[$minor-1]];
						list($format,$itemkey) = explode(",",$value[1][$major]);
						return $this->format_response($oid, $format, $temp->$itemkey);
					}
				}
			}
		}
	}


	public function save_cache($file, $data) {
		file_put_contents($file, serialize($data));
	}


	public function process($type, $oid) {

		//setup oid to var maps
		$vh_map = array(
		"201" => "string,vhost",
		"202" => "gauge,req_processing",
		"203" => "gauge,req_per_sec",
		"204" => "counter,req_total"
		);

		$ext_map = array(
		"301" => "string,vhost",
		"302" => "string,type",
		"303" => "string,extapp",
		"304" => "gauge,config_max_conn",
		"305" => "gauge,effect_max_conn",
		"306" => "gauge,pool_size",
		"307" => "gauge,inuse_conn",
		"308" => "gauge,idle_conn",
		"309" => "gauge,waitqueue_depth",
		"310" => "gauge,req_per_sec",
		"311" => "counter,req_total"
		);

		$gen_map = array(
		"101" => "string,product",
		"102" => "string,edition",
		"103" => "string,version",
		"104" => "string,uptime",
		"105" => "gauge,bps_in",
		"106" => "gauge,bps_out",
		"107" => "gauge,ssl_bps_in",
		"108" => "gauge,ssl_bps_out",
		"109" => "gauge,max_conn",
		"110" => "gauge,max_ssl_conn",
		"111" => "gauge,plain_conn",
		"112" => "gauge,avail_conn",
		"113" => "gauge,idle_conn",
		"114" => "gauge,ssl_conn",
		"115" => "gauge,avail_ssl_conn"
		);


		//setup pointers
		$super = array();
		$super["100"] = array(array($this->stats), $gen_map);
		$super["200"] = array($this->stats->vhosts, $vh_map);

		//put alll extapps to single array
		$extapps = array();
		foreach($this->stats->vhosts as $value) {
			foreach($value->extapps as $vextapp) {
				$extapps[] = $vextapp;
			}
		}

		$super["300"] = array($extapps, $ext_map);

		//get single method
		if($type == "-g") {
			echo $this->oid_get($super, $oid);
			return;
		}

		//snmp walk traversal
		else if($type == "-n") {
			//build traversal nodes/oids
			$parsed = explode(".",$oid);
			$major = $parsed[8];


			foreach($super as $key => $value) {

				//form index walk
				if($major == $key) {
					$size = count($value[0]);

					if($size <= 0) {
						return;
					}

					if(count($parsed) == 10) {
						$minor = (int) $parsed[9];

						if($minor > 0 && $minor < $size) {
							echo $this->format_response($this->oid_part($parsed).".{$key}.".($minor+1),"integer",$minor+1);

						}
					}
					else if(count($parsed) == 9){
						echo $this->format_response("{$oid}.1","integer",1);
					}

				}

				//data walk
				else if(array_key_exists($major,$value[1])) {
					$size = count($value[0]);

					if($size <= 0) {
						return;
					}

					if(count($parsed) == 10) {
						$minor = (int) $parsed[9];

						if($minor > 0 && $minor < $size) {
							echo $this->oid_get($super, $this->oid_part($parsed).".{$major}.".($minor+1));


						}
					}
					else if(count($parsed) == 9){
						echo $this->oid_get($super, $this->oid_part($parsed).".{$major}.".(1));
					}

				}
			}
		}
	}

}

?>
snmp_monitoring/README000064400000000503150545647700010661 0ustar00LiteSpeed SNMPD Bridge + Cacti Templates
----------------------------------------

For the most up-to-date installation documentation, please refer to our online "SNMP Monitoring" wiki:

http://www.litespeedtech.com/support/wiki/doku.php?id=litespeed_wiki:snmp_cacti_monitoring

Release Log:
-----------
1.0  08-23-2006 


cpanel/lsws_whm_plugin/lsws_whm_plugin_install.sh000075500000030505150545647700016555 0ustar00#!/bin/sh

# /********************************************
# LiteSpeed Web Server Plugin for WHM
#
# @author LiteSpeed Technologies, Inc. (https://www.litespeedtech.com)
# @copyright (c) 2008-2021
# *********************************************/

#
# If from lsws install, 3 params
# WHM_PLUGIN_SRCDIR=$1
# LSWS_HOME=$2
# CPANEL_PLUGIN_AUTOINSTALL=$3
#

WHM_PLUGIN_TEMPDIR="/usr/src/lsws_whm"
WHM_DOCROOT="/usr/local/cpanel/whostmgr/docroot"
WHM_PLUGIN_CGIDIR="${WHM_DOCROOT}/cgi"
WHM_PLUGIN_ICONDIR="${WHM_DOCROOT}/addon_plugins"
WHM_PLUGIN_INSDIR="${WHM_PLUGIN_CGIDIR}/lsws"
WHM_PLUGIN_TMPL_INSDIR="${WHM_DOCROOT}/templates/lsws"
WHM_PLUGIN_LSCWP_SRC_DIR="/usr/src/litespeed-wp-plugin"
WHM_PLUGIN_HTTPDIR="http://www.litespeedtech.com/packages/cpanel"
THEME_JUPITER_PLUGIN_DIR="/usr/local/cpanel/base/frontend/jupiter/ls_web_cache_manager"
THEME_PAPER_LANTERN_PLUGIN_DIR="/usr/local/cpanel/base/frontend/paper_lantern/ls_web_cache_manager"
CPANEL_PLUGIN_CAPABLE=0

if [ ! -d "${WHM_PLUGIN_CGIDIR}" ] ; then
    exit
fi

WHM_PLUGIN_INST_USER=$(id)
WHM_PLUGIN_INST_USER=$(expr "${WHM_PLUGIN_INST_USER}" : 'uid=.*(\(.*\)) gid=.*')

if [ "${WHM_PLUGIN_INST_USER}" != "root" ]  ; then
    echo "Require root permission to install this plugin. Abort!"
    exit
fi

if [ "x${2}" = "x" ] ; then
    LSWS_HOME="/usr/local/lsws"
else
    LSWS_HOME="${2}"
fi

WEBCACHE_MGR_DATA_DIR="${LSWS_HOME}/admin/lscdata"
CPANEL_PLUGIN_AUTOINSTALL_DISABLE_FLAG="${WHM_PLUGIN_INSDIR}/cpanel_autoinstall_off"
TMP_CPANEL_PLUGIN_AUTOINSTALL_DISABLE_FLAG="/tmp/cpanel_autoinstall_off"
WHM_PLUGIN_DATA_DIR="${WHM_PLUGIN_INSDIR}/data"
TMP_WHM_PLUGIN_DATA_DIR="/tmp/lsws_whm_plugin_data_tmp"
WHM_PLUGIN_LSWS_HOME_FILE="${WHM_PLUGIN_INSDIR}/LSWS_HOME.config"
TMP_WHM_PLUGIN_LSWS_HOME_FILE="/tmp/LSWS_HOME.config"

whmPluginNeedsUpdate()
{
    CURR_WHM_VER="${1}"

    if ! LATEST_WHM_VER=$(wget -qO- "${WHM_PLUGIN_HTTPDIR}/WHM_LATEST_VER"); then
        echo "Failed to query latest WHM plugin version. Abort!"
        exit;
    fi

    CURR_MAJOR=$(echo "${CURR_WHM_VER}" | awk -F"." '{print $1}')
    LATEST_MAJOR=$(echo "${LATEST_WHM_VER}" | awk -F"." '{print $1}')

    if [ "${CURR_MAJOR}" -lt "${LATEST_MAJOR}" ] ; then
        return 0
    elif [ "${CURR_MAJOR}" -gt "${LATEST_MAJOR}" ] ; then
        return 1
    fi

    CURR_MINOR=$(echo "${CURR_WHM_VER}" | awk -F"." '{print $2}')
    LATEST_MINOR=$(echo "${LATEST_WHM_VER}" | awk -F"." '{print $2}')

    if [ "${CURR_MINOR}" -lt "${LATEST_MINOR}" ] ; then
        return 0
    elif [ "${CURR_MINOR}" -gt "${LATEST_MINOR}" ] ; then
        return 1
    fi

    CURR_IMPROVEMENT=$(echo "${CURR_WHM_VER}" | awk -F"." '{print match($3, /[^ ]/) ? $3 : 0}')
    LATEST_IMPROVEMENT=$(echo "${LATEST_WHM_VER}" | awk -F"." '{print match($3, /[^ ]/) ? $3 : 0}')

    if [ "${CURR_IMPROVEMENT}" -lt "${LATEST_IMPROVEMENT}" ] ; then
        return 0
    elif [ "${CURR_IMPROVEMENT}" -gt "${LATEST_IMPROVEMENT}" ] ; then
        return 1
    fi

    CURR_PATCH=$(echo "${CURR_WHM_VER}" | awk -F"." '{print match($4, /[^ ]/) ? $4 : 0}')
    LATEST_PATCH=$(echo "${LATEST_WHM_VER}" | awk -F"." '{print match($4, /[^ ]/) ? $4 : 0}')

    if [ "${CURR_PATCH}" -lt "${LATEST_PATCH}" ] ; then
        return 0
    elif [ "${CURR_PATCH}" -gt "${LATEST_PATCH}" ] ; then
        return 1
    fi

    return 1
}

echo ""
echo " Install LiteSpeed Web Server Plugin for WHM"
echo "=============================================="
echo ""

CURR_WHM_VER_FILE="${WHM_PLUGIN_INSDIR}/VERSION"

if [ -e "${CURR_WHM_VER_FILE}" ] ; then

    CURR_WHM_VER=$(cat "${CURR_WHM_VER_FILE}")

    if ! whmPluginNeedsUpdate "${CURR_WHM_VER}" ; then
        echo "Installed WHM Plugin version already up-to-date. Abort!"
        exit;
    fi
fi

if [ "x${1}" = "x" ] ; then
    echo "... creating directories ..."

    # Create temp directory to install
    if [ ! -e "${WHM_PLUGIN_TEMPDIR}" ] ; then
        mkdir -v -p "${WHM_PLUGIN_TEMPDIR}"
        echo "  Temp directory created"
    fi

    cd "${WHM_PLUGIN_TEMPDIR}"

    echo "... downloading latest version of the plugin ..."



    if ! wget \
            "--output-document=${WHM_PLUGIN_TEMPDIR}/lsws_whm_plugin.tar.gz" \
            "${WHM_PLUGIN_HTTPDIR}/lsws_whm_plugin.tar.gz"
    then
        /bin/rm -rf "${WHM_PLUGIN_TEMPDIR}"

        echo ""
        echo "Failed to download lsws_whm_plugin.tar.gz. Abort!"
        exit;
    fi

    echo "Done downloading."
    echo ""

    echo "... extracting ..."



    if ! tar -zxf lsws_whm_plugin.tar.gz; then
        /bin/rm -rf "${WHM_PLUGIN_TEMPDIR}"

        echo ""
        echo "Failed to to extract lsws_whm_plugin.tar.gz. Abort!"
        exit;
    fi

    echo ""
fi

# Create working directories for WHM PHP files and backup any existing data
if [ -e "${WHM_PLUGIN_INSDIR}" ] ; then

    if [ -e "${WHM_PLUGIN_CGIDIR}/addon_lsws.cgi" ] ; then
        echo "  Removing old entry script addon_lsws.cgi"
        /bin/rm -f "${WHM_PLUGIN_CGIDIR}/addon_lsws.cgi"
    fi

    if [ ! -e "${WEBCACHE_MGR_DATA_DIR}" ] ; then

        if [ -e "${LSWS_HOME}/admin" ] ; then
            mkdir "${WEBCACHE_MGR_DATA_DIR}"
        fi
    fi

    if [ -e "${CPANEL_PLUGIN_AUTOINSTALL_DISABLE_FLAG}" ] ; then
        /bin/mv "${CPANEL_PLUGIN_AUTOINSTALL_DISABLE_FLAG}" "${TMP_CPANEL_PLUGIN_AUTOINSTALL_DISABLE_FLAG}"
    fi

    if [ -e "${WHM_PLUGIN_DATA_DIR}" ] ; then
        /bin/mv "${WHM_PLUGIN_DATA_DIR}" "${TMP_WHM_PLUGIN_DATA_DIR}"
    fi

    if [ -e "${WHM_PLUGIN_LSWS_HOME_FILE}" ] ; then
        /bin/mv "${WHM_PLUGIN_LSWS_HOME_FILE}" "${TMP_WHM_PLUGIN_LSWS_HOME_FILE}"
    fi

    echo "  Removing old working directory ${WHM_PLUGIN_INSDIR}"
    /bin/rm -rf "${WHM_PLUGIN_INSDIR}"
fi

if [ -e "${WHM_PLUGIN_TMPL_INSDIR}" ] ; then
    echo " Removing old template directory ${WHM_PLUGIN_TMPL_INSDIR}"
    /bin/rm -rf "${WHM_PLUGIN_TMPL_INSDIR}"
fi

#Cleanup old lsc data from installs < 2.1.12
if [ -e "${LSWS_HOME}/add-ons/webcachemgr/shared/lsc_versions_data" ] ; then
    /bin/rm -f "${LSWS_HOME}/add-ons/webcachemgr/shared/lsc_versions_data"
fi

if [ -e "${LSWS_HOME}/add-ons/webcachemgr/shared/lsc_manager_data" ] ; then
    /bin/rm -f "${LSWS_HOME}/add-ons/webcachemgr/shared/lsc_manager_data"
fi

#cleanup old lsc data/files from installs < 3.0.0
if [ -e "${WEBCACHE_MGR_DATA_DIR}/lsc_manager_data" ] ; then
    /bin/rm -f "${WEBCACHE_MGR_DATA_DIR}/lsc_manager_data"
fi

if [ -e "${WEBCACHE_MGR_DATA_DIR}/lsc_versions_data" ] ; then
    /bin/rm -f "${WEBCACHE_MGR_DATA_DIR}/lsc_versions_data"
fi

#force new data files permissions
if [ -e "${WEBCACHE_MGR_DATA_DIR}/lscm.data" ] ; then
    chmod 600 "${WEBCACHE_MGR_DATA_DIR}/lscm.data"
fi

if [ -e "${WEBCACHE_MGR_DATA_DIR}/lscm.data.cust" ] ; then
    chmod 600 "${WEBCACHE_MGR_DATA_DIR}/lscm.data.cust"
fi

mkdir -v "${WHM_PLUGIN_INSDIR}"
mkdir -v "${WHM_PLUGIN_TMPL_INSDIR}"

if [ -e "${TMP_CPANEL_PLUGIN_AUTOINSTALL_DISABLE_FLAG}" ] ; then
    /bin/mv "${TMP_CPANEL_PLUGIN_AUTOINSTALL_DISABLE_FLAG}" "${CPANEL_PLUGIN_AUTOINSTALL_DISABLE_FLAG}"
    echo "  Retained disable cPanel plugin auto install flag file"
fi

if [ -e "${TMP_WHM_PLUGIN_DATA_DIR}" ] ; then
    /bin/mv "${TMP_WHM_PLUGIN_DATA_DIR}" "${WHM_PLUGIN_DATA_DIR}"
    echo "  Retained WHM plugin data dir files"
fi

if [ -e "${TMP_WHM_PLUGIN_LSWS_HOME_FILE}" ] ; then
    /bin/mv "${TMP_WHM_PLUGIN_LSWS_HOME_FILE}" "${WHM_PLUGIN_LSWS_HOME_FILE}"
    echo "  Retained LSWS_HOME.config file"
fi

echo ""


if [ "x${1}" = "x" ] ; then
    WHM_PLUGIN_SRCDIR="${WHM_PLUGIN_TEMPDIR}/lsws_whm_plugin"
    /bin/cp -r "${WHM_PLUGIN_SRCDIR}"/* "${WHM_PLUGIN_INSDIR}/"

    cd "${WHM_PLUGIN_INSDIR}"
#    # Removes install files
    /bin/rm -rf "${WHM_PLUGIN_TEMPDIR}"
else
    # install from lsws addon
    WHM_PLUGIN_SRCDIR="${1}"
    /bin/cp -r "${WHM_PLUGIN_SRCDIR}"/* "${WHM_PLUGIN_INSDIR}/"
    echo "LSWS_HOME=${LSWS_HOME}" > "${WHM_PLUGIN_LSWS_HOME_FILE}"
fi

echo "... moving files ..."

if [ ! -e "${WHM_PLUGIN_ICONDIR}" ] ; then
    mkdir -v "${WHM_PLUGIN_ICONDIR}"
fi

/bin/cp -f "${WHM_PLUGIN_INSDIR}/lsws_icon.png" "${WHM_PLUGIN_ICONDIR}/"
/bin/mv -f "${WHM_PLUGIN_INSDIR}/lsws.html.tt" "${WHM_PLUGIN_TMPL_INSDIR}/"

echo "... setting permission to files ..."
chmod -R 600 "${WHM_PLUGIN_INSDIR}"
chmod 700 "${WHM_PLUGIN_INSDIR}"/*.cgi
chmod 700 "${WHM_PLUGIN_INSDIR}"/*.sh
chmod 700 "${WHM_PLUGIN_INSDIR}/bin"
chmod 700 "${WHM_PLUGIN_INSDIR}"/bin/*.sh

if [ -e "${WHM_PLUGIN_INSDIR}/res/ls_web_cache_mgr" ] ; then
    chmod 700 "${WHM_PLUGIN_INSDIR}"/res/ls_web_cache_mgr/*.sh
    CPANEL_PLUGIN_CAPABLE=1;
fi

# update easyapache hooks
"${WHM_PLUGIN_INSDIR}/bin/whm_eahook.sh" REFRESH

sed -i 's/target=mainFrame/target=_self/' "${WHM_PLUGIN_INSDIR}/lsws.conf"

if [ -e "/usr/local/cpanel/bin/register_appconfig" ] ; then
    REGISTERED=$(/usr/local/cpanel/bin/is_registered_with_appconfig whostmgr lsws)

    if [ "x${REGISTERED}" != "x1" ] ; then
        echo "Register LSWS Plugin ..."

        if [ ! -e "/var/cpanel/apps" ] ; then
            mkdir -v "/var/cpanel/apps"
            echo "  apps registration directory created"
        fi
    else
        # check if config changed
        CHANGED=$(diff /var/cpanel/apps/lsws.conf "${WHM_PLUGIN_INSDIR}/lsws.conf")

        if [ "${CHANGED}" != "" ] ; then
            REGISTERED=0
        fi
    fi

    if [ "x${REGISTERED}" != "x1" ] ; then
        /usr/local/cpanel/bin/register_appconfig "${WHM_PLUGIN_INSDIR}/lsws.conf"
    fi

    /bin/rm -f "${WHM_PLUGIN_INSDIR}/addon_lsws.cgi"
else
    echo "old version no AppConfig, place entry at parent dir"
    /bin/mv -f "${WHM_PLUGIN_INSDIR}/addon_lsws.cgi" "${WHM_PLUGIN_CGIDIR}/"
    /bin/rm -f "${WHM_PLUGIN_INSDIR}/lsws.cgi"
fi

#Create and add needed LSCWP source directory
if [ ! -e "${WHM_PLUGIN_LSCWP_SRC_DIR}" ] ; then
    mkdir -m 755 "${WHM_PLUGIN_LSCWP_SRC_DIR}"
fi

#CageFs remount for $WHM_PLUGIN_LSCWP_SRC_DIR handled in fix_cagefs.sh
if [ -f "/etc/cagefs/cagefs.mp" ] ; then
    FORCE_REMOUNT=0



    if ! grep -v 'deleted' /proc/mounts | grep -q 'litespeed-wp-plugin' ; then
        FORCE_REMOUNT=1

        if  ! grep -Eq "^${WHM_PLUGIN_LSCWP_SRC_DIR}$" /etc/cagefs/cagefs.mp; then
            # shellcheck disable=SC1003
            sed -i -e '$a\' /etc/cagefs/cagefs.mp
            echo "${WHM_PLUGIN_LSCWP_SRC_DIR}" >> /etc/cagefs/cagefs.mp
        fi
    fi

    THIS_DIR=$( cd "$( dirname "${0}" )" && pwd )

    if [ -f "${LSWS_HOME}/admin/misc/fix_cagefs.sh" ] ; then
        #If CageFS, add LSWS to cage if missing.
        "${LSWS_HOME}/admin/misc/fix_cagefs.sh" "${FORCE_REMOUNT}"

    elif [ -f "${THIS_DIR}/../../../admin/misc/fix_cagefs.sh" ] ; then
        #LSWS not installed yet, run package relative script.
        "${THIS_DIR}/../../../admin/misc/fix_cagefs.sh" "${FORCE_REMOUNT}"

    else
        echo "Could not find fix_cagefs.sh! Script was not executed."
    fi
fi

#Exclude LSCache files from backup
CP_BACKUP_EXCLUDE_MASTER=/usr/local/cpanel/etc/cpbackup-exclude.conf
CP_BACKUP_EXCLUDE_GLOBAL=/etc/cpbackup-exclude.conf

if [ ! -f "${CP_BACKUP_EXCLUDE_GLOBAL}" ] && [ -f "${CP_BACKUP_EXCLUDE_MASTER}" ] ; then
    cp "${CP_BACKUP_EXCLUDE_MASTER}" "${CP_BACKUP_EXCLUDE_GLOBAL}"
fi

if [ -f "${CP_BACKUP_EXCLUDE_GLOBAL}" ] ; then
    grep -Fxq "lscache/" "${CP_BACKUP_EXCLUDE_GLOBAL}"
    FOUND="${?}"
fi

if [ ! -f "${CP_BACKUP_EXCLUDE_GLOBAL}" ] || [ "${FOUND}" -ne 0 ] ; then
    echo "lscache/" >> "${CP_BACKUP_EXCLUDE_GLOBAL}"
fi

##
# Install/Update cPanel Plugin if found
##
if [ "${CPANEL_PLUGIN_CAPABLE}" -eq 1 ] ; then
    CPANEL_PLUGIN_AUTOINSTALL=1

    if [ "x${3}" = "x"  ] ; then

        if [ -e "${CPANEL_PLUGIN_AUTOINSTALL_DISABLE_FLAG}" ] ; then
            CPANEL_PLUGIN_AUTOINSTALL=0
        fi
    else
        CPANEL_PLUGIN_AUTOINSTALL="${3}"

        if [ "${CPANEL_PLUGIN_AUTOINSTALL}" -eq 1 ] ; then

            if [ -e "${CPANEL_PLUGIN_AUTOINSTALL_DISABLE_FLAG}" ] ; then
                /bin/rm -f "${CPANEL_PLUGIN_AUTOINSTALL_DISABLE_FLAG}"
            fi
        else
            touch "${CPANEL_PLUGIN_AUTOINSTALL_DISABLE_FLAG}"
        fi
    fi

    LSCMCTL_SCRIPT="${LSWS_HOME}/admin/misc/lscmctl"

    if [ -e "${LSCMCTL_SCRIPT}" ] ; then

        if "${LSCMCTL_SCRIPT}" --help | grep -q 'cpanelplugin' \
                && [ "${CPANEL_PLUGIN_AUTOINSTALL}" -eq 1 ] \
                || [ -e "${THEME_JUPITER_PLUGIN_DIR}" ] \
                || [ -e "${THEME_PAPER_LANTERN_PLUGIN_DIR}" ]
        then
            "${LSCMCTL_SCRIPT}" cpanelplugin --install
        fi
    fi
fi

echo ""
echo " LiteSpeed WHM Plugin Installed Successfully."
echo "=============================================="

cpanel/httpd_config.xml000064400000013660150545647700011223 0ustar00<?xml version="1.0" encoding="UTF-8"?>
<httpServerConfig>
  <serverName>$HOSTNAME</serverName>
  <user>nobody</user>
  <group>nobody</group>
  <priority>0</priority>
  <chrootPath>/</chrootPath>
  <enableChroot>0</enableChroot>
  <inMemBufSize>60M</inMemBufSize>
  <swappingDir>/tmp/lshttpd/swap</swappingDir>
  <autoRestart>1</autoRestart>
  <autoFix503>0</autoFix503>
  <loadApacheConf>1</loadApacheConf>
  <autoReloadApacheConf>2</autoReloadApacheConf>
  <apacheBinPath>/usr/local/apache/bin/httpd</apacheBinPath>
  <apacheConfFile>/usr/local/apache/conf/httpd.conf</apacheConfFile>
  <apachePortOffset>%AP_PORT_OFFSET%</apachePortOffset>
  <apacheIpOffset>0</apacheIpOffset>
  <apacheIgnoredModules></apacheIgnoredModules>
  <phpSuExec>%PHP_SUEXEC%</phpSuExec>
  <phpSuExecMaxConn>10</phpSuExecMaxConn>
  <mime>$SERVER_ROOT/conf/mime.properties</mime>
  <disableInitLogRotation>1</disableInitLogRotation>
  <showVersionNumber>0</showVersionNumber>
  <enableIpGeo></enableIpGeo>
  <useIpInProxyHeader>2</useIpInProxyHeader>
  <autoUpdateInterval>86400</autoUpdateInterval>
  <autoUpdateDownloadPkg>1</autoUpdateDownloadPkg>
  <adminEmails>%ADMIN_EMAIL%</adminEmails>
  <adminRoot>$SERVER_ROOT/admin/</adminRoot>
  <logging>
    <log>
      <fileName>/usr/local/apache/logs/error_log</fileName>
      <logLevel>DEBUG</logLevel>
      <debugLevel>0</debugLevel>
      <rollingSize>2000M</rollingSize>
      <enableStderrLog>1</enableStderrLog>
      <enableAioLog>1</enableAioLog>
    </log>
    <accessLog>
      <fileName>$SERVER_ROOT/logs/access.log</fileName>
      <rollingSize>2000M</rollingSize>
      <keepDays>30</keepDays>
      <compressArchive>0</compressArchive>
    </accessLog>
  </logging>
  <indexFiles>index.html, index.php, index.htm</indexFiles>
  <autoIndex></autoIndex>
  <autoIndexURI></autoIndexURI>
  <htAccess>
    <allowOverride>31</allowOverride>
    <accessFileName>.htaccess</accessFileName>
  </htAccess>
  <expires>
    <enableExpires>1</enableExpires>
    <expiresByType>image/*=A604800, text/css=A604800, application/x-javascript=A604800, application/javascript=A604800</expiresByType>
  </expires>
  <tuning>
    <maxConnections>10000</maxConnections>
    <maxSSLConnections>10000</maxSSLConnections>
    <connTimeout>120</connTimeout>
    <maxKeepAliveReq>10000</maxKeepAliveReq>
    <smartKeepAlive>0</smartKeepAlive>
    <keepAliveTimeout>10</keepAliveTimeout>
    <sndBufSize>0</sndBufSize>
    <rcvBufSize>0</rcvBufSize>
    <eventDispatcher>best</eventDispatcher>
    <maxCachedFileSize>4096</maxCachedFileSize>
    <totalInMemCacheSize>20M</totalInMemCacheSize>
    <maxMMapFileSize>256K</maxMMapFileSize>
    <totalMMapCacheSize>40M</totalMMapCacheSize>
    <useSendfile>1</useSendfile>
    <useAIO>1</useAIO>
    <AIOBlockSize>4</AIOBlockSize>
    <etagNoInode>1</etagNoInode>
    <SSLCryptoDevice>null</SSLCryptoDevice>
    <maxReqURLLen>8192</maxReqURLLen>
    <maxReqHeaderSize>16380</maxReqHeaderSize>
    <maxReqBodySize>500M</maxReqBodySize>
    <maxDynRespHeaderSize>8K</maxDynRespHeaderSize>
    <maxDynRespSize>500M</maxDynRespSize>
    <enableGzipCompress>1</enableGzipCompress>
    <enableDynGzipCompress>1</enableDynGzipCompress>
    <compressibleTypes>default</compressibleTypes>
    <gzipAutoUpdateStatic>1</gzipAutoUpdateStatic>
    <gzipCacheDir></gzipCacheDir>
  </tuning>
  <security>
    <fileAccessControl>
      <followSymbolLink>1</followSymbolLink>
      <checkSymbolLink>0</checkSymbolLink>
      <forceStrictOwnership>1</forceStrictOwnership>
      <requiredPermissionMask>000</requiredPermissionMask>
      <restrictedPermissionMask>000</restrictedPermissionMask>
      <restrictedScriptPermissionMask>000</restrictedScriptPermissionMask>
      <restrictedDirPermissionMask>000</restrictedDirPermissionMask>
    </fileAccessControl>
    <perClientConnLimit>
      <staticReqPerSec>0</staticReqPerSec>
      <dynReqPerSec>0</dynReqPerSec>
      <outBandwidth>0</outBandwidth>
      <inBandwidth>0</inBandwidth>
      <softLimit>10000</softLimit>
      <hardLimit>10000</hardLimit>
      <gracePeriod>15</gracePeriod>
      <banPeriod>300</banPeriod>
    </perClientConnLimit>
    <CGIRLimit>
      <maxCGIInstances>200</maxCGIInstances>
      <minUID>11</minUID>
      <minGID>10</minGID>
      <priority>0</priority>
      <CPUSoftLimit>60</CPUSoftLimit>
      <CPUHardLimit>120</CPUHardLimit>
      <memSoftLimit>1450M</memSoftLimit>
      <memHardLimit>1500M</memHardLimit>
      <procSoftLimit>400</procSoftLimit>
      <procHardLimit>450</procHardLimit>
    </CGIRLimit>
    <censorshipControl>
      <enableCensorship>0</enableCensorship>
      <logLevel>0</logLevel>
      <defaultAction>deny,log,status:403</defaultAction>
      <scanPOST>1</scanPOST>
    </censorshipControl>
    <accessDenyDir>
      <dir>/</dir>
      <dir>/etc/*</dir>
      <dir>/dev/*</dir>
      <dir>$SERVER_ROOT/conf/*</dir>
      <dir>$SERVER_ROOT/admin/conf/*</dir>
    </accessDenyDir>
    <accessControl>
      <allow>ALL</allow>
      <deny></deny>
    </accessControl>
  </security>

  <phpConfig>
    <maxConns>35</maxConns>
    <env>PHP_LSAPI_CHILDREN=35</env>
    <initTimeout>60</initTimeout>
    <retryTimeout>0</retryTimeout>
    <pcKeepAliveTimeout>1</pcKeepAliveTimeout>
    <respBuffer>0</respBuffer>
    <extMaxIdleTime>60</extMaxIdleTime>
    <memSoftLimit></memSoftLimit>
    <memHardLimit></memHardLimit>
    <procSoftLimit>1400</procSoftLimit>
    <procHardLimit>1500</procHardLimit>
  </phpConfig>
  <railsDefaults>
    <rubyBin></rubyBin>
    <railsEnv>1</railsEnv>
    <maxConns>5</maxConns>
    <env>LSAPI_MAX_IDLE=60</env>
    <initTimeout>60</initTimeout>
    <retryTimeout>0</retryTimeout>
    <pcKeepAliveTimeout>60</pcKeepAliveTimeout>
    <respBuffer>0</respBuffer>
    <backlog>50</backlog>
    <runOnStartUp>1</runOnStartUp>
    <extMaxIdleTime>300</extMaxIdleTime>
    <priority>3</priority>
    <memSoftLimit></memSoftLimit>
    <memHardLimit></memHardLimit>
    <procSoftLimit>400</procSoftLimit>
    <procHardLimit>500</procHardLimit>
  </railsDefaults>
</httpServerConfig>
cpanel/httpd_config.xml.ea4000064400000014077150545647700011676 0ustar00<?xml version="1.0" encoding="UTF-8"?>
<httpServerConfig>
  <serverName>$HOSTNAME</serverName>
  <user>nobody</user>
  <group>nobody</group>
  <priority>0</priority>
  <chrootPath>/</chrootPath>
  <enableChroot>0</enableChroot>
  <inMemBufSize>60M</inMemBufSize>
  <swappingDir>/tmp/lshttpd/swap</swappingDir>
  <autoRestart>1</autoRestart>
  <autoFix503>0</autoFix503>
  <loadApacheConf>1</loadApacheConf>
  <autoReloadApacheConf>2</autoReloadApacheConf>
  <apacheBinPath>/usr/sbin/httpd</apacheBinPath>
  <apacheConfFile>/etc/apache2/conf/httpd.conf</apacheConfFile>
  <apachePortOffset>%AP_PORT_OFFSET%</apachePortOffset>
  <apacheIpOffset>0</apacheIpOffset>
  <apacheIgnoredModules></apacheIgnoredModules>
  <phpSuExec>%PHP_SUEXEC%</phpSuExec>
  <phpSuExecMaxConn>10</phpSuExecMaxConn>
  <mime>$SERVER_ROOT/conf/mime.properties</mime>
  <disableInitLogRotation>1</disableInitLogRotation>
  <showVersionNumber>0</showVersionNumber>
  <enableIpGeo></enableIpGeo>
  <useIpInProxyHeader>2</useIpInProxyHeader>
  <autoUpdateInterval>86400</autoUpdateInterval>
  <autoUpdateDownloadPkg>1</autoUpdateDownloadPkg>
  <adminEmails>%ADMIN_EMAIL%</adminEmails>
  <adminRoot>$SERVER_ROOT/admin/</adminRoot>
  <logging>
    <log>
      <fileName>/var/log/apache2/error_log</fileName>
      <logLevel>DEBUG</logLevel>
      <debugLevel>0</debugLevel>
      <rollingSize>2000M</rollingSize>
      <enableStderrLog>1</enableStderrLog>
      <enableAioLog>1</enableAioLog>
    </log>
    <accessLog>
      <fileName>$SERVER_ROOT/logs/access.log</fileName>
      <rollingSize>2000M</rollingSize>
      <keepDays>30</keepDays>
      <compressArchive>0</compressArchive>
    </accessLog>
  </logging>
  <indexFiles>index.html, index.php, index.htm</indexFiles>
  <autoIndex></autoIndex>
  <autoIndexURI></autoIndexURI>
  <htAccess>
    <allowOverride>31</allowOverride>
    <accessFileName>.htaccess</accessFileName>
  </htAccess>
  <expires>
    <enableExpires>1</enableExpires>
    <expiresByType>image/*=A604800,text/css=A604800,application/x-javascript=A604800,application/javascript=A604800,font/*=A604800,application/x-font-ttf=A604800</expiresByType>
  </expires>
  <tuning>
    <maxConnections>10000</maxConnections>
    <maxSSLConnections>10000</maxSSLConnections>
    <connTimeout>120</connTimeout>
    <maxKeepAliveReq>10000</maxKeepAliveReq>
    <smartKeepAlive>0</smartKeepAlive>
    <keepAliveTimeout>10</keepAliveTimeout>
    <sndBufSize>0</sndBufSize>
    <rcvBufSize>0</rcvBufSize>
    <eventDispatcher>best</eventDispatcher>
    <maxCachedFileSize>4096</maxCachedFileSize>
    <totalInMemCacheSize>20M</totalInMemCacheSize>
    <maxMMapFileSize>256K</maxMMapFileSize>
    <totalMMapCacheSize>40M</totalMMapCacheSize>
    <useSendfile>1</useSendfile>
    <useAIO>1</useAIO>
    <AIOBlockSize>4</AIOBlockSize>
    <etagNoInode>1</etagNoInode>
    <SSLCryptoDevice>null</SSLCryptoDevice>
    <maxReqURLLen>8192</maxReqURLLen>
    <maxReqHeaderSize>16380</maxReqHeaderSize>
    <maxReqBodySize>500M</maxReqBodySize>
    <maxDynRespHeaderSize>8K</maxDynRespHeaderSize>
    <maxDynRespSize>500M</maxDynRespSize>
    <enableGzipCompress>1</enableGzipCompress>
    <enableDynGzipCompress>1</enableDynGzipCompress>
    <compressibleTypes>default</compressibleTypes>
    <gzipAutoUpdateStatic>1</gzipAutoUpdateStatic>
    <gzipCacheDir></gzipCacheDir>
  </tuning>
  <security>
    <fileAccessControl>
      <followSymbolLink>1</followSymbolLink>
      <checkSymbolLink>0</checkSymbolLink>
      <forceStrictOwnership>1</forceStrictOwnership>
      <requiredPermissionMask>000</requiredPermissionMask>
      <restrictedPermissionMask>000</restrictedPermissionMask>
      <restrictedScriptPermissionMask>000</restrictedScriptPermissionMask>
      <restrictedDirPermissionMask>000</restrictedDirPermissionMask>
    </fileAccessControl>
    <perClientConnLimit>
      <staticReqPerSec>0</staticReqPerSec>
      <dynReqPerSec>0</dynReqPerSec>
      <outBandwidth>0</outBandwidth>
      <inBandwidth>0</inBandwidth>
      <softLimit>10000</softLimit>
      <hardLimit>10000</hardLimit>
      <gracePeriod>15</gracePeriod>
      <banPeriod>300</banPeriod>
    </perClientConnLimit>
    <CGIRLimit>
      <maxCGIInstances>200</maxCGIInstances>
      <minUID>11</minUID>
      <minGID>10</minGID>
      <priority>0</priority>
      <CPUSoftLimit>60</CPUSoftLimit>
      <CPUHardLimit>120</CPUHardLimit>
      <memSoftLimit>1450M</memSoftLimit>
      <memHardLimit>1500M</memHardLimit>
      <procSoftLimit>1400</procSoftLimit>
      <procHardLimit>1450</procHardLimit>
    </CGIRLimit>
    <censorshipControl>
      <enableCensorship>0</enableCensorship>
      <logLevel>0</logLevel>
      <defaultAction>deny,log,status:403</defaultAction>
      <scanPOST>1</scanPOST>
    </censorshipControl>
    <accessDenyDir>
      <dir>/</dir>
      <dir>/etc/*</dir>
      <dir>/dev/*</dir>
      <dir>$SERVER_ROOT/conf/*</dir>
      <dir>$SERVER_ROOT/admin/conf/*</dir>
    </accessDenyDir>
    <accessControl>
      <allow>ALL</allow>
      <deny></deny>
    </accessControl>
  </security>
  <extProcessorList>
  </extProcessorList>
  <scriptHandlerList>
  </scriptHandlerList>
  <phpConfig>
    <maxConns>35</maxConns>
    <env>PHP_LSAPI_CHILDREN=35</env>
    <initTimeout>60</initTimeout>
    <retryTimeout>0</retryTimeout>
    <pcKeepAliveTimeout>1</pcKeepAliveTimeout>
    <respBuffer>0</respBuffer>
    <extMaxIdleTime>60</extMaxIdleTime>
    <memSoftLimit></memSoftLimit>
    <memHardLimit></memHardLimit>
    <procSoftLimit>1400</procSoftLimit>
    <procHardLimit>1500</procHardLimit>
  </phpConfig>
  <railsDefaults>
    <rubyBin>/usr/local/lsws/fcgi-bin/ea-ruby27</rubyBin>
    <railsEnv>1</railsEnv>
    <maxConns>5</maxConns>
    <env>LSAPI_MAX_IDLE=60</env>
    <initTimeout>60</initTimeout>
    <retryTimeout>0</retryTimeout>
    <pcKeepAliveTimeout>60</pcKeepAliveTimeout>
    <respBuffer>0</respBuffer>
    <backlog>50</backlog>
    <runOnStartUp>0</runOnStartUp>
    <extMaxIdleTime>300</extMaxIdleTime>
    <priority>3</priority>
    <memSoftLimit></memSoftLimit>
    <memHardLimit></memHardLimit>
    <procSoftLimit>400</procSoftLimit>
    <procHardLimit>500</procHardLimit>
  </railsDefaults>
</httpServerConfig>
ispmanager/httpd_config.xml000064400000013727150545647700012113 0ustar00<?xml version="1.0" encoding="UTF-8"?>
<httpServerConfig>
  <serverName>$HOSTNAME</serverName>
  <user>apache</user>
  <group>apache</group>
  <priority>0</priority>
  <chrootPath>/</chrootPath>
  <enableChroot>0</enableChroot>
  <inMemBufSize>60M</inMemBufSize>
  <swappingDir>/tmp/lshttpd/swap</swappingDir>
  <autoRestart>1</autoRestart>
  <autoFix503>0</autoFix503>
  <loadApacheConf>1</loadApacheConf>
  <autoReloadApacheConf>1</autoReloadApacheConf>
  <apacheBinPath>/usr/sbin/httpd</apacheBinPath>
  <apacheConfFile>/etc/httpd/conf/httpd.conf</apacheConfFile>
  <apachePortOffset>%AP_PORT_OFFSET%</apachePortOffset>
  <apacheIpOffset></apacheIpOffset>
  <apacheHandledContent>/manager/,/mancgi/</apacheHandledContent>
  <phpSuExec>%PHP_SUEXEC%</phpSuExec>
  <phpSuExecMaxConn>10</phpSuExecMaxConn>
  <mime>$SERVER_ROOT/conf/mime.properties</mime>
  <disableInitLogRotation></disableInitLogRotation>
  <showVersionNumber>0</showVersionNumber>
  <enableIpGeo></enableIpGeo>
  <useIpInProxyHeader>2</useIpInProxyHeader>
  <autoUpdateInterval>86400</autoUpdateInterval>
  <autoUpdateDownloadPkg>1</autoUpdateDownloadPkg>
  <adminEmails>%ADMIN_EMAIL%</adminEmails>
  <adminRoot>$SERVER_ROOT/admin/</adminRoot>
  <logging>
    <log>
      <fileName>$SERVER_ROOT/logs/error.log</fileName>
      <logLevel>DEBUG</logLevel>
      <debugLevel>0</debugLevel>
      <rollingSize>2000M</rollingSize>
      <enableStderrLog>1</enableStderrLog>
    </log>
    <accessLog>
      <fileName>$SERVER_ROOT/logs/access.log</fileName>
      <rollingSize>10M</rollingSize>
      <keepDays>30</keepDays>
      <compressArchive>0</compressArchive>
    </accessLog>
  </logging>
  <indexFiles>index.html, index.php, index.htm</indexFiles>
  <autoIndex></autoIndex>
  <autoIndexURI></autoIndexURI>
  <htAccess>
    <allowOverride>31</allowOverride>
    <accessFileName>.htaccess</accessFileName>
  </htAccess>
  <expires>
    <enableExpires>1</enableExpires>
    <expiresByType>image/*=A604800, text/css=A604800, application/x-javascript=A604800, application/javascript=A604800</expiresByType>
  </expires>
  <tuning>
    <maxConnections>10000</maxConnections>
    <maxSSLConnections>10000</maxSSLConnections>
    <connTimeout>120</connTimeout>
    <maxKeepAliveReq>10000</maxKeepAliveReq>
    <smartKeepAlive>0</smartKeepAlive>
    <keepAliveTimeout>10</keepAliveTimeout>
    <sndBufSize>0</sndBufSize>
    <rcvBufSize>0</rcvBufSize>
    <eventDispatcher>best</eventDispatcher>
    <maxCachedFileSize>4096</maxCachedFileSize>
    <totalInMemCacheSize>20M</totalInMemCacheSize>
    <maxMMapFileSize>256K</maxMMapFileSize>
    <totalMMapCacheSize>40M</totalMMapCacheSize>
    <useSendfile>1</useSendfile>
    <useAIO>1</useAIO>
    <AIOBlockSize>4</AIOBlockSize>
    <etagNoInode>1</etagNoInode>
    <SSLCryptoDevice>null</SSLCryptoDevice>
    <maxReqURLLen>8192</maxReqURLLen>
    <maxReqHeaderSize>16380</maxReqHeaderSize>
    <maxReqBodySize>500M</maxReqBodySize>
    <maxDynRespHeaderSize>4K</maxDynRespHeaderSize>
    <maxDynRespSize>500M</maxDynRespSize>
    <enableGzipCompress>1</enableGzipCompress>
    <enableDynGzipCompress>1</enableDynGzipCompress>
    <compressibleTypes>default</compressibleTypes>
    <gzipAutoUpdateStatic>1</gzipAutoUpdateStatic>
    <gzipCacheDir></gzipCacheDir>
  </tuning>
  <security>
    <fileAccessControl>
      <followSymbolLink>1</followSymbolLink>
      <checkSymbolLink>0</checkSymbolLink>
      <forceStrictOwnership>1</forceStrictOwnership>
      <requiredPermissionMask>000</requiredPermissionMask>
      <restrictedPermissionMask>000</restrictedPermissionMask>
      <restrictedScriptPermissionMask>002</restrictedScriptPermissionMask>
      <restrictedDirPermissionMask>002</restrictedDirPermissionMask>
    </fileAccessControl>
    <perClientConnLimit>
      <staticReqPerSec>0</staticReqPerSec>
      <dynReqPerSec>0</dynReqPerSec>
      <outBandwidth>0</outBandwidth>
      <inBandwidth>0</inBandwidth>
      <softLimit>10000</softLimit>
      <hardLimit>10000</hardLimit>
      <gracePeriod>15</gracePeriod>
      <banPeriod>300</banPeriod>
    </perClientConnLimit>
    <CGIRLimit>
      <maxCGIInstances>20</maxCGIInstances>
      <minUID>11</minUID>
      <minGID>10</minGID>
      <priority>0</priority>
      <CPUSoftLimit>60</CPUSoftLimit>
      <CPUHardLimit>120</CPUHardLimit>
      <memSoftLimit>1250M</memSoftLimit>
      <memHardLimit>1300M</memHardLimit>
      <procSoftLimit>400</procSoftLimit>
      <procHardLimit>450</procHardLimit>
    </CGIRLimit>
    <censorshipControl>
      <enableCensorship>0</enableCensorship>
      <logLevel>0</logLevel>
      <defaultAction>deny,log,status:403</defaultAction>
      <scanPOST>1</scanPOST>
    </censorshipControl>
    <accessDenyDir>
      <dir>/</dir>
      <dir>/etc/*</dir>
      <dir>/dev/*</dir>
      <dir>$SERVER_ROOT/conf/*</dir>
      <dir>$SERVER_ROOT/admin/conf/*</dir>
    </accessDenyDir>
    <accessControl>
      <allow>ALL</allow>
      <deny></deny>
    </accessControl>
  </security>
  <extProcessorList>
  </extProcessorList>
  <scriptHandlerList>
  </scriptHandlerList>
  <phpConfig>
    <maxConns>35</maxConns>
    <env>PHP_LSAPI_CHILDREN=35</env>
    <initTimeout>60</initTimeout>
    <retryTimeout>0</retryTimeout>
    <pcKeepAliveTimeout>1</pcKeepAliveTimeout>
    <respBuffer>0</respBuffer>
    <extMaxIdleTime>60</extMaxIdleTime>
    <memSoftLimit></memSoftLimit>
    <memHardLimit></memHardLimit>
    <procSoftLimit>1400</procSoftLimit>
    <procHardLimit>1500</procHardLimit>
  </phpConfig>
  <railsDefaults>
    <rubyBin></rubyBin>
    <railsEnv>1</railsEnv>
    <maxConns>5</maxConns>
    <env>LSAPI_MAX_IDLE=60</env>
    <initTimeout>60</initTimeout>
    <retryTimeout>0</retryTimeout>
    <pcKeepAliveTimeout>60</pcKeepAliveTimeout>
    <respBuffer>0</respBuffer>
    <backlog>50</backlog>
    <runOnStartUp>1</runOnStartUp>
    <extMaxIdleTime>300</extMaxIdleTime>
    <priority>3</priority>
    <memSoftLimit></memSoftLimit>
    <memHardLimit></memHardLimit>
    <procSoftLimit>400</procSoftLimit>
    <procHardLimit>500</procHardLimit>
  </railsDefaults>
</httpServerConfig>
modsec/inspectmulti.sh000055500000000232150545647700011105 0ustar00#!/bin/sh
if [ $# -lt 2 ] ; then 
    echo "miss parameter."
else
    RUNAVCMD=$1
    shift
    for var in "$@"
    do
        $RUNAVCMD $var
    done
fi
hsphere/httpd_config.xml000064400000013250150545647700011412 0ustar00<?xml version="1.0" encoding="UTF-8"?>
<httpServerConfig>
  <serverName>$HOSTNAME</serverName>
  <user>httpd</user>
  <group>httpd</group>
  <priority>0</priority>
  <chrootPath>/</chrootPath>
  <enableChroot>0</enableChroot>
  <inMemBufSize>60M</inMemBufSize>
  <swappingDir>/tmp/lshttpd/swap</swappingDir>
  <autoRestart>1</autoRestart>
  <autoFix503>0</autoFix503>
  <loadApacheConf>1</loadApacheConf>
  <autoReloadApacheConf>1</autoReloadApacheConf>
  <apacheConfFile>/hsphere/local/config/httpd/httpd.conf</apacheConfFile>
  <apachePortOffset>%AP_PORT_OFFSET%</apachePortOffset>
  <apacheIpOffset>0</apacheIpOffset>
  <phpSuExec>%PHP_SUEXEC%</phpSuExec>
  <phpSuExecMaxConn>10</phpSuExecMaxConn>
  <mime>$SERVER_ROOT/conf/mime.properties</mime>
  <disableInitLogRotation></disableInitLogRotation>
  <showVersionNumber>0</showVersionNumber>
  <enableIpGeo></enableIpGeo>
  <useIpInProxyHeader>2</useIpInProxyHeader>
  <autoUpdateInterval>86400</autoUpdateInterval>
  <autoUpdateDownloadPkg>1</autoUpdateDownloadPkg>
  <adminEmails>%ADMIN_EMAIL%</adminEmails>
  <adminRoot>$SERVER_ROOT/admin/</adminRoot>
  <logging>
    <log>
      <fileName>$SERVER_ROOT/logs/error.log</fileName>
      <logLevel>DEBUG</logLevel>
      <debugLevel>0</debugLevel>
      <rollingSize>10M</rollingSize>
      <enableStderrLog>1</enableStderrLog>
    </log>
    <accessLog>
      <fileName>$SERVER_ROOT/logs/access.log</fileName>
      <rollingSize>10M</rollingSize>
      <keepDays>30</keepDays>
      <compressArchive>0</compressArchive>
    </accessLog>
  </logging>
  <indexFiles>index.html, index.php, index.htm</indexFiles>
  <autoIndex></autoIndex>
  <autoIndexURI></autoIndexURI>
  <htAccess>
    <allowOverride>31</allowOverride>
    <accessFileName>.htaccess</accessFileName>
  </htAccess>
  <expires>
    <enableExpires>1</enableExpires>
    <expiresByType>image/*=A604800, text/css=A604800, application/x-javascript=A604800, application/javascript=A604800</expiresByType>
  </expires>
  <tuning>
    <maxConnections>10000</maxConnections>
    <maxSSLConnections>10000</maxSSLConnections>
    <connTimeout>120</connTimeout>
    <maxKeepAliveReq>10000</maxKeepAliveReq>
    <smartKeepAlive>0</smartKeepAlive>
    <keepAliveTimeout>10</keepAliveTimeout>
    <sndBufSize>0</sndBufSize>
    <rcvBufSize>0</rcvBufSize>
    <eventDispatcher>best</eventDispatcher>
    <maxCachedFileSize>4096</maxCachedFileSize>
    <totalInMemCacheSize>20M</totalInMemCacheSize>
    <maxMMapFileSize>256K</maxMMapFileSize>
    <totalMMapCacheSize>40M</totalMMapCacheSize>
    <useSendfile>1</useSendfile>
    <useAIO>1</useAIO>
    <AIOBlockSize>4</AIOBlockSize>
    <etagNoInode>1</etagNoInode>
    <SSLCryptoDevice>null</SSLCryptoDevice>
    <maxReqURLLen>8192</maxReqURLLen>
    <maxReqHeaderSize>16380</maxReqHeaderSize>
    <maxReqBodySize>500M</maxReqBodySize>
    <maxDynRespHeaderSize>4K</maxDynRespHeaderSize>
    <maxDynRespSize>500M</maxDynRespSize>
    <enableGzipCompress>1</enableGzipCompress>
    <enableDynGzipCompress>1</enableDynGzipCompress>
    <compressibleTypes>default</compressibleTypes>
    <gzipAutoUpdateStatic>1</gzipAutoUpdateStatic>
    <gzipCacheDir></gzipCacheDir>
  </tuning>
  <security>
    <fileAccessControl>
      <followSymbolLink>1</followSymbolLink>
      <checkSymbolLink>0</checkSymbolLink>
      <requiredPermissionMask>000</requiredPermissionMask>
      <restrictedPermissionMask>000</restrictedPermissionMask>
    </fileAccessControl>
    <perClientConnLimit>
      <staticReqPerSec>0</staticReqPerSec>
      <dynReqPerSec>0</dynReqPerSec>
      <outBandwidth>0</outBandwidth>
      <inBandwidth>0</inBandwidth>
      <softLimit>10000</softLimit>
      <hardLimit>10000</hardLimit>
      <gracePeriod>15</gracePeriod>
      <banPeriod>300</banPeriod>
    </perClientConnLimit>
    <CGIRLimit>
      <maxCGIInstances>20</maxCGIInstances>
      <minUID>11</minUID>
      <minGID>10</minGID>
      <priority>0</priority>
      <CPUSoftLimit>60</CPUSoftLimit>
      <CPUHardLimit>120</CPUHardLimit>
      <memSoftLimit>1250M</memSoftLimit>
      <memHardLimit>1300M</memHardLimit>
      <procSoftLimit>400</procSoftLimit>
      <procHardLimit>450</procHardLimit>
    </CGIRLimit>
    <censorshipControl>
      <enableCensorship>0</enableCensorship>
      <logLevel>0</logLevel>
      <defaultAction>deny,log,status:403</defaultAction>
      <scanPOST>1</scanPOST>
    </censorshipControl>
    <accessDenyDir>
      <dir>/</dir>
      <dir>/etc/*</dir>
      <dir>/dev/*</dir>
      <dir>$SERVER_ROOT/conf/*</dir>
      <dir>$SERVER_ROOT/admin/conf/*</dir>
    </accessDenyDir>
    <accessControl>
      <allow>ALL</allow>
      <deny></deny>
    </accessControl>
  </security>
  <extProcessorList>
  </extProcessorList>
  <scriptHandlerList>
  </scriptHandlerList>
  <phpConfig>
    <maxConns>35</maxConns>
    <env>PHP_LSAPI_CHILDREN=35</env>
    <initTimeout>60</initTimeout>
    <retryTimeout>0</retryTimeout>
    <pcKeepAliveTimeout>1</pcKeepAliveTimeout>
    <respBuffer>0</respBuffer>
    <extMaxIdleTime>60</extMaxIdleTime>
    <memSoftLimit></memSoftLimit>
    <memHardLimit></memHardLimit>
    <procSoftLimit>1400</procSoftLimit>
    <procHardLimit>1500</procHardLimit>
  </phpConfig>
  <railsDefaults>
    <rubyBin></rubyBin>
    <railsEnv>1</railsEnv>
    <maxConns>5</maxConns>
    <env>LSAPI_MAX_IDLE=60</env>
    <initTimeout>60</initTimeout>
    <retryTimeout>0</retryTimeout>
    <pcKeepAliveTimeout>60</pcKeepAliveTimeout>
    <respBuffer>0</respBuffer>
    <backlog>50</backlog>
    <runOnStartUp>1</runOnStartUp>
    <extMaxIdleTime>300</extMaxIdleTime>
    <priority>3</priority>
    <memSoftLimit></memSoftLimit>
    <memHardLimit></memHardLimit>
    <procSoftLimit>200</procSoftLimit>
    <procHardLimit>300</procHardLimit>
  </railsDefaults>
</httpServerConfig>
rrdgraph/rrdgraph_install.sh000075500000006311150545647700012271 0ustar00#!/bin/sh

#1. specify destination dir
#2. specify lsphp5 location
#3. download from litespeedtech web server(like lsapi)

cat <<EOF

RRDtool PHP package for litespeed

RRDtool is the OpenSource industry standard, high performance data 
logging and graphing system for time series data. Serverstats
(http://serverstats.berlios.de/) is a simple tool(in PHP) for creating 
graphs using rrdtool

This PHP package is Serverstats configured for litespeed.
it can save years' real-time stats data in litespeed and disply them 
in graph at any time.

Note: Before you install this php package, to be sure you've installed
	rrdtool. in Redhat/CentOS, you can do this through
	yum install rrdtool.i386 (for 32-bit x86) or
	yum install rrdtool.x86_64 (for 64-bit x86_64)

EOF

printf "%s" "Have you installed rrdtool [y/N]? "

read PHPACC
echo    

if [ "x$PHPACC" = "x" ]; then 
		PHPACC=n
fi      
if [ `expr "$PHPACC" : '[Yy]'` -eq 0 ]; then
		echo "then install rrdtool first !"
		exit 1
fi      

SUCC=0
DEST_RECOM="/usr/local/lsws/DEFAULT/html"
while [ $SUCC -eq "0" ];  do
	cat <<EOF

Please specify the destination directory. You must have permissions to 
create and manage the directory. It is recommended to install the rrd php package 
under document root of a virtual host.

EOF
	printf "%s" "Destination [$DEST_RECOM]: "
	read DEST_DIR
	echo ""
	if [ "x$DEST_DIR" = "x" ]; then
		DEST_DIR=$DEST_RECOM
	fi
	SUCC=1
	if [ ! -d "$DEST_DIR" ]; then
		mkdir -p "$DEST_DIR"
		if [ ! $? -eq 0 ]; then
			SUCC=0
			echo "Failed to create the directory, try again"
		fi
	fi
done

SUCC=0
PHP_RECOM="/usr/local/lsws/fcgi-bin/lsphp5"
while [ $SUCC -eq "0" ];  do
	cat <<EOF

Please specify the full path of lsphp5 binary. It is used to update rrd database
in cron job. php version must be 5.0 or above.

EOF
	printf "%s" "lsphp5 location: [$PHP_RECOM]"
	read PHP_BIN
	echo ""
	if [ "x$PHP_BIN" = "x" ]; then
		PHP_BIN=$PHP_RECOM
	fi
	SUCC=1
	if [ ! -f "$PHP_BIN" ]; then
		SUCC=0
		echo "$PHP_BIN not exist, please specify again"
	fi
done

cd $DEST_DIR
RRDPKG=ls_stats.tar.gz
if [ -f $DEST_DIR/ls_stats/graph.php ]; then 
	echo "[INFO] Found rrd php package at $DEST_DIR/ls_stats/"
else
	if [ ! -f $DEST_DIR/$RRDPKG ]; then 
		wget --timeout=5 -O $RRDPKG "http://www.litespeedtech.com/packages/rrdtool/$RRDPKG"
		if [ $? -ne 0 ]; then 
			echo "WGET failed, try curl"
			curl -L "http://www.litespeedtech.com/packages/rrdtool/$RRDPKG" -o $RRDPKG
			if [ $? -ne 0 ]; then
				cat <<EOF

[ERROR] Failed to download rrd php package, please download
        it manually from http://www.litespeedtech.com/packages/rrdtool/$RRDPKG to 
        '$DEST_DIR' directory, then expand the package there.

EOF
				exit 1
			fi              
		fi              
	fi              
	gunzip -c $RRDPKG | tar xf -
	if [ $? -ne 0 ]; then
		cat <<EOF
[ERROR] Failed to expand $DEST_DIR/$RRDPKG
                Please expand it manually.

EOF
		exit 1
	fi

fi
cat <<EOF

final step: create a cron job to update web server stats 1 time / per minute.
run "crontab -e", add following line:
* * * * * $PHP_BIN $DEST_DIR/ls_stats/update.php

to view the rrd graph at any time later, access
http://virtual-host-domain/ls_stats/index.php

[OK] rrd php package for litespeed has been successfully installed. 

EOF
cwp/httpd_config.xml000064400000013573150545647700010555 0ustar00<?xml version="1.0" encoding="UTF-8"?>
<httpServerConfig>
  <serverName>$HOSTNAME</serverName>
  <user>nobody</user>
  <group>nobody</group>
  <priority>0</priority>
  <chrootPath>/</chrootPath>
  <enableChroot>0</enableChroot>
  <inMemBufSize>60M</inMemBufSize>
  <swappingDir>/tmp/lshttpd/swap</swappingDir>
  <autoRestart>1</autoRestart>
  <autoFix503>0</autoFix503>
  <loadApacheConf>1</loadApacheConf>
  <autoReloadApacheConf>2</autoReloadApacheConf>
  <apacheBinPath>/usr/local/apache/bin/httpd</apacheBinPath>
  <apacheConfFile>/usr/local/apache/conf/httpd.conf</apacheConfFile>
  <apachePortOffset>0</apachePortOffset>
  <apacheIpOffset>0</apacheIpOffset>
  <apacheIgnoredModules></apacheIgnoredModules>
  <phpSuExec>%PHP_SUEXEC%</phpSuExec>
  <phpSuExecMaxConn>10</phpSuExecMaxConn>
  <mime>$SERVER_ROOT/conf/mime.properties</mime>
  <disableInitLogRotation>1</disableInitLogRotation>
  <showVersionNumber>0</showVersionNumber>
  <enableIpGeo></enableIpGeo>
  <useIpInProxyHeader>2</useIpInProxyHeader>
  <autoUpdateInterval>86400</autoUpdateInterval>
  <autoUpdateDownloadPkg>1</autoUpdateDownloadPkg>
  <adminEmails>%ADMIN_EMAIL%</adminEmails>
  <adminRoot>$SERVER_ROOT/admin/</adminRoot>
  <logging>
    <log>
      <fileName>/usr/local/apache/logs/error_log</fileName>
      <logLevel>DEBUG</logLevel>
      <debugLevel>0</debugLevel>
      <rollingSize>2000M</rollingSize>
      <enableStderrLog>1</enableStderrLog>
    </log>
    <accessLog>
      <fileName>$SERVER_ROOT/logs/access.log</fileName>
      <rollingSize>2000M</rollingSize>
      <keepDays>30</keepDays>
      <compressArchive>0</compressArchive>
    </accessLog>
  </logging>
  <indexFiles>index.html, index.php, index.htm</indexFiles>
  <autoIndex></autoIndex>
  <autoIndexURI></autoIndexURI>
  <htAccess>
    <allowOverride>31</allowOverride>
    <accessFileName>.htaccess</accessFileName>
  </htAccess>
  <expires>
    <enableExpires>1</enableExpires>
    <expiresByType>image/*=A604800, text/css=A604800, application/x-javascript=A604800, application/javascript=A604800</expiresByType>
  </expires>
  <tuning>
    <maxConnections>10000</maxConnections>
    <maxSSLConnections>10000</maxSSLConnections>
    <connTimeout>120</connTimeout>
    <maxKeepAliveReq>10000</maxKeepAliveReq>
    <smartKeepAlive>0</smartKeepAlive>
    <keepAliveTimeout>10</keepAliveTimeout>
    <sndBufSize>0</sndBufSize>
    <rcvBufSize>0</rcvBufSize>
    <eventDispatcher>best</eventDispatcher>
    <maxCachedFileSize>4096</maxCachedFileSize>
    <totalInMemCacheSize>20M</totalInMemCacheSize>
    <maxMMapFileSize>256K</maxMMapFileSize>
    <totalMMapCacheSize>40M</totalMMapCacheSize>
    <useSendfile>1</useSendfile>
    <useAIO>1</useAIO>
    <AIOBlockSize>4</AIOBlockSize>
    <etagNoInode>1</etagNoInode>
    <SSLCryptoDevice>null</SSLCryptoDevice>
    <maxReqURLLen>8192</maxReqURLLen>
    <maxReqHeaderSize>16380</maxReqHeaderSize>
    <maxReqBodySize>500M</maxReqBodySize>
    <maxDynRespHeaderSize>8K</maxDynRespHeaderSize>
    <maxDynRespSize>500M</maxDynRespSize>
    <enableGzipCompress>1</enableGzipCompress>
    <enableDynGzipCompress>1</enableDynGzipCompress>
    <compressibleTypes>default</compressibleTypes>
    <gzipAutoUpdateStatic>1</gzipAutoUpdateStatic>
    <gzipCacheDir></gzipCacheDir>
  </tuning>
  <security>
    <fileAccessControl>
      <followSymbolLink>1</followSymbolLink>
      <checkSymbolLink>0</checkSymbolLink>
      <forceStrictOwnership>1</forceStrictOwnership>
      <requiredPermissionMask>000</requiredPermissionMask>
      <restrictedPermissionMask>000</restrictedPermissionMask>
      <restrictedScriptPermissionMask>000</restrictedScriptPermissionMask>
      <restrictedDirPermissionMask>000</restrictedDirPermissionMask>
    </fileAccessControl>
    <perClientConnLimit>
      <staticReqPerSec>0</staticReqPerSec>
      <dynReqPerSec>0</dynReqPerSec>
      <outBandwidth>0</outBandwidth>
      <inBandwidth>0</inBandwidth>
      <softLimit>10000</softLimit>
      <hardLimit>10000</hardLimit>
      <gracePeriod>15</gracePeriod>
      <banPeriod>300</banPeriod>
    </perClientConnLimit>
    <CGIRLimit>
      <maxCGIInstances>200</maxCGIInstances>
      <minUID>11</minUID>
      <minGID>10</minGID>
      <priority>0</priority>
      <CPUSoftLimit>60</CPUSoftLimit>
      <CPUHardLimit>120</CPUHardLimit>
      <memSoftLimit>1450M</memSoftLimit>
      <memHardLimit>1500M</memHardLimit>
      <procSoftLimit>400</procSoftLimit>
      <procHardLimit>450</procHardLimit>
    </CGIRLimit>
    <censorshipControl>
      <enableCensorship>0</enableCensorship>
      <logLevel>0</logLevel>
      <defaultAction>deny,log,status:403</defaultAction>
      <scanPOST>1</scanPOST>
    </censorshipControl>
    <accessDenyDir>
      <dir>/</dir>
      <dir>/etc/*</dir>
      <dir>/dev/*</dir>
      <dir>$SERVER_ROOT/conf/*</dir>
      <dir>$SERVER_ROOT/admin/conf/*</dir>
    </accessDenyDir>
    <accessControl>
      <allow>ALL</allow>
      <deny></deny>
    </accessControl>
  </security>
  <phpConfig>
    <maxConns>35</maxConns>
    <env>PHP_LSAPI_CHILDREN=35</env>
    <initTimeout>60</initTimeout>
    <retryTimeout>0</retryTimeout>
    <pcKeepAliveTimeout>1</pcKeepAliveTimeout>
    <respBuffer>0</respBuffer>
    <extMaxIdleTime>60</extMaxIdleTime>
    <memSoftLimit></memSoftLimit>
    <memHardLimit></memHardLimit>
    <procSoftLimit>1400</procSoftLimit>
    <procHardLimit>1500</procHardLimit>
  </phpConfig>
  <railsDefaults>
    <rubyBin></rubyBin>
    <railsEnv>1</railsEnv>
    <maxConns>5</maxConns>
    <env>LSAPI_MAX_IDLE=60</env>
    <initTimeout>60</initTimeout>
    <retryTimeout>0</retryTimeout>
    <pcKeepAliveTimeout>60</pcKeepAliveTimeout>
    <respBuffer>0</respBuffer>
    <backlog>50</backlog>
    <runOnStartUp>1</runOnStartUp>
    <extMaxIdleTime>300</extMaxIdleTime>
    <priority>3</priority>
    <memSoftLimit></memSoftLimit>
    <memHardLimit></memHardLimit>
    <procSoftLimit>400</procSoftLimit>
    <procHardLimit>500</procHardLimit>
  </railsDefaults>
</httpServerConfig>
lxadmin/httpd_config.xml000064400000013321150545647700011407 0ustar00<?xml version="1.0" encoding="UTF-8"?>
<httpServerConfig>
  <serverName>$HOSTNAME</serverName>
  <user>apache</user>
  <group>apache</group>
  <priority>0</priority>
  <chrootPath>/</chrootPath>
  <enableChroot>0</enableChroot>
  <inMemBufSize>60M</inMemBufSize>
  <swappingDir>/tmp/lshttpd/swap</swappingDir>
  <autoRestart>1</autoRestart>
  <autoFix503>0</autoFix503>
  <loadApacheConf>1</loadApacheConf>
  <autoReloadApacheConf>1</autoReloadApacheConf>
  <apacheBinPath>/usr/sbin/httpd</apacheBinPath>
  <apacheConfFile>/etc/httpd/conf/httpd.conf</apacheConfFile>
  <apachePortOffset>%AP_PORT_OFFSET%</apachePortOffset>
  <apacheIpOffset>0</apacheIpOffset>
  <phpSuExec>%PHP_SUEXEC%</phpSuExec>
  <phpSuExecMaxConn>10</phpSuExecMaxConn>
  <mime>$SERVER_ROOT/conf/mime.properties</mime>
  <disableInitLogRotation></disableInitLogRotation>
  <showVersionNumber>0</showVersionNumber>
  <enableIpGeo></enableIpGeo>
  <useIpInProxyHeader>2</useIpInProxyHeader>
  <autoUpdateInterval>86400</autoUpdateInterval>
  <autoUpdateDownloadPkg>1</autoUpdateDownloadPkg>
  <adminEmails>%ADMIN_EMAIL%</adminEmails>
  <adminRoot>$SERVER_ROOT/admin/</adminRoot>
  <logging>
    <log>
      <fileName>$SERVER_ROOT/logs/error.log</fileName>
      <logLevel>DEBUG</logLevel>
      <debugLevel>0</debugLevel>
      <rollingSize>2000M</rollingSize>
      <enableStderrLog>1</enableStderrLog>
    </log>
    <accessLog>
      <fileName>$SERVER_ROOT/logs/access.log</fileName>
      <rollingSize>10M</rollingSize>
      <keepDays>30</keepDays>
      <compressArchive>0</compressArchive>
    </accessLog>
  </logging>
  <indexFiles>index.html, index.php, index.htm</indexFiles>
  <autoIndex></autoIndex>
  <autoIndexURI></autoIndexURI>
  <htAccess>
    <allowOverride>31</allowOverride>
    <accessFileName>.htaccess</accessFileName>
  </htAccess>
  <expires>
    <enableExpires>1</enableExpires>
    <expiresByType>image/*=A604800, text/css=A604800, application/x-javascript=A604800, application/javascript=A604800</expiresByType>
  </expires>
  <tuning>
    <maxConnections>10000</maxConnections>
    <maxSSLConnections>10000</maxSSLConnections>
    <connTimeout>120</connTimeout>
    <maxKeepAliveReq>10000</maxKeepAliveReq>
    <smartKeepAlive>0</smartKeepAlive>
    <keepAliveTimeout>10</keepAliveTimeout>
    <sndBufSize>0</sndBufSize>
    <rcvBufSize>0</rcvBufSize>
    <eventDispatcher>best</eventDispatcher>
    <maxCachedFileSize>4096</maxCachedFileSize>
    <totalInMemCacheSize>20M</totalInMemCacheSize>
    <maxMMapFileSize>256K</maxMMapFileSize>
    <totalMMapCacheSize>40M</totalMMapCacheSize>
    <useSendfile>1</useSendfile>
    <useAIO>1</useAIO>
    <AIOBlockSize>4</AIOBlockSize>
    <etagNoInode>1</etagNoInode>
    <SSLCryptoDevice>null</SSLCryptoDevice>
    <maxReqURLLen>8192</maxReqURLLen>
    <maxReqHeaderSize>16380</maxReqHeaderSize>
    <maxReqBodySize>500M</maxReqBodySize>
    <maxDynRespHeaderSize>4K</maxDynRespHeaderSize>
    <maxDynRespSize>500M</maxDynRespSize>
    <enableGzipCompress>1</enableGzipCompress>
    <enableDynGzipCompress>1</enableDynGzipCompress>
    <compressibleTypes>default</compressibleTypes>
    <gzipAutoUpdateStatic>1</gzipAutoUpdateStatic>
    <gzipCacheDir></gzipCacheDir>
  </tuning>
  <security>
    <fileAccessControl>
      <followSymbolLink>1</followSymbolLink>
      <checkSymbolLink>0</checkSymbolLink>
      <requiredPermissionMask>000</requiredPermissionMask>
      <restrictedPermissionMask>000</restrictedPermissionMask>
    </fileAccessControl>
    <perClientConnLimit>
      <staticReqPerSec>0</staticReqPerSec>
      <dynReqPerSec>0</dynReqPerSec>
      <outBandwidth>0</outBandwidth>
      <inBandwidth>0</inBandwidth>
      <softLimit>10000</softLimit>
      <hardLimit>10000</hardLimit>
      <gracePeriod>15</gracePeriod>
      <banPeriod>300</banPeriod>
    </perClientConnLimit>
    <CGIRLimit>
      <maxCGIInstances>20</maxCGIInstances>
      <minUID>11</minUID>
      <minGID>10</minGID>
      <priority>0</priority>
      <CPUSoftLimit>60</CPUSoftLimit>
      <CPUHardLimit>120</CPUHardLimit>
      <memSoftLimit>1250M</memSoftLimit>
      <memHardLimit>1300M</memHardLimit>
      <procSoftLimit>400</procSoftLimit>
      <procHardLimit>450</procHardLimit>
    </CGIRLimit>
    <censorshipControl>
      <enableCensorship>0</enableCensorship>
      <logLevel>0</logLevel>
      <defaultAction>deny,log,status:403</defaultAction>
      <scanPOST>1</scanPOST>
    </censorshipControl>
    <accessDenyDir>
      <dir>/</dir>
      <dir>/etc/*</dir>
      <dir>/dev/*</dir>
      <dir>$SERVER_ROOT/conf/*</dir>
      <dir>$SERVER_ROOT/admin/conf/*</dir>
    </accessDenyDir>
    <accessControl>
      <allow>ALL</allow>
      <deny></deny>
    </accessControl>
  </security>
  <extProcessorList>
  </extProcessorList>
  <scriptHandlerList>
  </scriptHandlerList>
  <phpConfig>
    <maxConns>35</maxConns>
    <env>PHP_LSAPI_CHILDREN=35</env>
    <initTimeout>60</initTimeout>
    <retryTimeout>0</retryTimeout>
    <pcKeepAliveTimeout>1</pcKeepAliveTimeout>
    <respBuffer>0</respBuffer>
    <extMaxIdleTime>60</extMaxIdleTime>
    <memSoftLimit></memSoftLimit>
    <memHardLimit></memHardLimit>
    <procSoftLimit>1400</procSoftLimit>
    <procHardLimit>1500</procHardLimit>
  </phpConfig>
  <railsDefaults>
    <rubyBin></rubyBin>
    <railsEnv>1</railsEnv>
    <maxConns>5</maxConns>
    <env>LSAPI_MAX_IDLE=60</env>
    <initTimeout>60</initTimeout>
    <retryTimeout>0</retryTimeout>
    <pcKeepAliveTimeout>60</pcKeepAliveTimeout>
    <respBuffer>0</respBuffer>
    <backlog>50</backlog>
    <runOnStartUp>1</runOnStartUp>
    <extMaxIdleTime>300</extMaxIdleTime>
    <priority>3</priority>
    <memSoftLimit></memSoftLimit>
    <memHardLimit></memHardLimit>
    <procSoftLimit>400</procSoftLimit>
    <procHardLimit>500</procHardLimit>
  </railsDefaults>
</httpServerConfig>
directadmin/httpd_config.xml000064400000014102150545647700012234 0ustar00<?xml version="1.0" encoding="UTF-8"?>
<httpServerConfig>
  <serverName>$HOSTNAME</serverName>
  <user>apache</user>
  <group>apache</group>
  <priority>0</priority>
  <chrootPath>/</chrootPath>
  <enableChroot>0</enableChroot>
  <inMemBufSize>60M</inMemBufSize>
  <swappingDir>/tmp/lshttpd/swap</swappingDir>
  <autoRestart>1</autoRestart>
  <autoFix503>0</autoFix503>
  <loadApacheConf>1</loadApacheConf>
  <autoReloadApacheConf>1</autoReloadApacheConf>
  <apacheConfFile>/etc/httpd/conf/httpd.conf</apacheConfFile>
  <apachePortOffset>%AP_PORT_OFFSET%</apachePortOffset>
  <apacheIpOffset>0</apacheIpOffset>
  <phpSuExec>%PHP_SUEXEC%</phpSuExec>
  <phpSuExecMaxConn>10</phpSuExecMaxConn>
  <mime>$SERVER_ROOT/conf/mime.properties</mime>
  <disableInitLogRotation></disableInitLogRotation>
  <showVersionNumber>0</showVersionNumber>
  <enableIpGeo></enableIpGeo>
  <useIpInProxyHeader>2</useIpInProxyHeader>
  <autoUpdateInterval>86400</autoUpdateInterval>
  <autoUpdateDownloadPkg>1</autoUpdateDownloadPkg>
  <adminEmails>%ADMIN_EMAIL%</adminEmails>
  <adminRoot>$SERVER_ROOT/admin/</adminRoot>
  <logging>
    <log>
      <fileName>$SERVER_ROOT/logs/error.log</fileName>
      <logLevel>DEBUG</logLevel>
      <debugLevel>0</debugLevel>
      <rollingSize>2000M</rollingSize>
      <enableStderrLog>1</enableStderrLog>
      <enableAioLog>1</enableAioLog>
    </log>
    <accessLog>
      <fileName>$SERVER_ROOT/logs/access.log</fileName>
      <rollingSize>10M</rollingSize>
      <keepDays>30</keepDays>
      <compressArchive>0</compressArchive>
    </accessLog>
  </logging>
  <indexFiles>index.html, index.php, index.htm</indexFiles>
  <autoIndex></autoIndex>
  <autoIndexURI></autoIndexURI>
  <htAccess>
    <allowOverride>31</allowOverride>
    <accessFileName>.htaccess</accessFileName>
  </htAccess>
  <expires>
    <enableExpires>1</enableExpires>
    <expiresByType>image/*=A604800, text/css=A604800, application/x-javascript=A604800, application/javascript=A604800,font/*=A604800,application/x-font-ttf=A604800</expiresByType>
  </expires>
  <tuning>
    <maxConnections>10000</maxConnections>
    <maxSSLConnections>10000</maxSSLConnections>
    <connTimeout>120</connTimeout>
    <maxKeepAliveReq>10000</maxKeepAliveReq>
    <smartKeepAlive>0</smartKeepAlive>
    <keepAliveTimeout>10</keepAliveTimeout>
    <sndBufSize>0</sndBufSize>
    <rcvBufSize>0</rcvBufSize>
    <eventDispatcher>best</eventDispatcher>
    <maxCachedFileSize>4096</maxCachedFileSize>
    <totalInMemCacheSize>20M</totalInMemCacheSize>
    <maxMMapFileSize>256K</maxMMapFileSize>
    <totalMMapCacheSize>40M</totalMMapCacheSize>
    <useSendfile>1</useSendfile>
    <useAIO>1</useAIO>
    <AIOBlockSize>4</AIOBlockSize>
    <etagNoInode>1</etagNoInode>
    <SSLCryptoDevice>null</SSLCryptoDevice>
    <maxReqURLLen>8192</maxReqURLLen>
    <maxReqHeaderSize>16380</maxReqHeaderSize>
    <maxReqBodySize>500M</maxReqBodySize>
    <maxDynRespHeaderSize>4K</maxDynRespHeaderSize>
    <maxDynRespSize>500M</maxDynRespSize>
    <enableGzipCompress>1</enableGzipCompress>
    <enableDynGzipCompress>1</enableDynGzipCompress>
    <compressibleTypes>default</compressibleTypes>
    <gzipAutoUpdateStatic>1</gzipAutoUpdateStatic>
    <gzipCacheDir></gzipCacheDir>
  </tuning>
  <security>
    <fileAccessControl>
      <followSymbolLink>1</followSymbolLink>
      <checkSymbolLink>0</checkSymbolLink>
      <forceStrictOwnership>1</forceStrictOwnership>
      <requiredPermissionMask>000</requiredPermissionMask>
      <restrictedPermissionMask>000</restrictedPermissionMask>
      <restrictedScriptPermissionMask>000</restrictedScriptPermissionMask>
      <restrictedDirPermissionMask>000</restrictedDirPermissionMask>
    </fileAccessControl>
    <perClientConnLimit>
      <staticReqPerSec>0</staticReqPerSec>
      <dynReqPerSec>0</dynReqPerSec>
      <outBandwidth>0</outBandwidth>
      <inBandwidth>0</inBandwidth>
      <softLimit>10000</softLimit>
      <hardLimit>10000</hardLimit>
      <gracePeriod>15</gracePeriod>
      <banPeriod>300</banPeriod>
    </perClientConnLimit>
    <CGIRLimit>
      <maxCGIInstances>200</maxCGIInstances>
      <minUID>11</minUID>
      <minGID>10</minGID>
      <priority>0</priority>
      <CPUSoftLimit>60</CPUSoftLimit>
      <CPUHardLimit>120</CPUHardLimit>
      <memSoftLimit>1450M</memSoftLimit>
      <memHardLimit>1500M</memHardLimit>
      <procSoftLimit>1400</procSoftLimit>
      <procHardLimit>1450</procHardLimit>
    </CGIRLimit>
    <censorshipControl>
      <enableCensorship>0</enableCensorship>
      <logLevel>0</logLevel>
      <defaultAction>deny,log,status:403</defaultAction>
      <scanPOST>1</scanPOST>
    </censorshipControl>
    <accessDenyDir>
      <dir>/</dir>
      <dir>/etc/*</dir>
      <dir>/dev/*</dir>
      <dir>$SERVER_ROOT/conf/*</dir>
      <dir>$SERVER_ROOT/admin/conf/*</dir>
    </accessDenyDir>
    <accessControl>
      <allow>ALL</allow>
      <deny></deny>
    </accessControl>
  </security>
  <extProcessorList>
  </extProcessorList>
  <scriptHandlerList>
  </scriptHandlerList>
  <phpConfig>
    <phpHandler>
      <id>php</id>
      <command>/usr/local/bin/lsphp</command>
    </phpHandler>
    <maxConns>35</maxConns>
    <env>PHP_LSAPI_CHILDREN=35</env>
    <initTimeout>60</initTimeout>
    <retryTimeout>0</retryTimeout>
    <pcKeepAliveTimeout>1</pcKeepAliveTimeout>
    <respBuffer>0</respBuffer>
    <extMaxIdleTime>60</extMaxIdleTime>
    <memSoftLimit></memSoftLimit>
    <memHardLimit></memHardLimit>
    <procSoftLimit>1400</procSoftLimit>
    <procHardLimit>1500</procHardLimit>
  </phpConfig>
  <railsDefaults>
    <rubyBin></rubyBin>
    <railsEnv>1</railsEnv>
    <maxConns>5</maxConns>
    <env>LSAPI_MAX_REQS=1000</env>
    <env>LSAPI_MAX_IDLE=60</env>
    <initTimeout>60</initTimeout>
    <retryTimeout>0</retryTimeout>
    <pcKeepAliveTimeout>60</pcKeepAliveTimeout>
    <respBuffer>0</respBuffer>
    <backlog>50</backlog>
    <runOnStartUp>1</runOnStartUp>
    <extMaxIdleTime>300</extMaxIdleTime>
    <priority>3</priority>
    <memSoftLimit></memSoftLimit>
    <memHardLimit></memHardLimit>
    <procSoftLimit>400</procSoftLimit>
    <procHardLimit>500</procHardLimit>
  </railsDefaults>
</httpServerConfig>
directadmin/php.ini000064400000115654150545647710010351 0ustar00[PHP]

;;;;;;;;;;;
; WARNING ;
;;;;;;;;;;;
; This is the default settings file for new PHP installations.
; By default, PHP installs itself with a configuration suitable for
; development purposes, and *NOT* for production purposes.
; For several security-oriented considerations that should be taken
; before going online with your site, please consult php.ini-recommended
; and http://php.net/manual/en/security.php.


;;;;;;;;;;;;;;;;;;;
; About this file ;
;;;;;;;;;;;;;;;;;;;
; This file controls many aspects of PHP's behavior.  In order for PHP to
; read it, it must be named 'php.ini'.  PHP looks for it in the current
; working directory, in the path designated by the environment variable
; PHPRC, and in the path that was defined in compile time (in that order).
; Under Windows, the compile-time path is the Windows directory.  The
; path in which the php.ini file is looked for can be overridden using
; the -c argument in command line mode.
;
; The syntax of the file is extremely simple.  Whitespace and Lines
; beginning with a semicolon are silently ignored (as you probably guessed).
; Section headers (e.g. [Foo]) are also silently ignored, even though
; they might mean something in the future.
;
; Directives are specified using the following syntax:
; directive = value
; Directive names are *case sensitive* - foo=bar is different from FOO=bar.
;
; The value can be a string, a number, a PHP constant (e.g. E_ALL or M_PI), one
; of the INI constants (On, Off, True, False, Yes, No and None) or an expression
; (e.g. E_ALL & ~E_NOTICE), or a quoted string ("foo").
;
; Expressions in the INI file are limited to bitwise operators and parentheses:
; |        bitwise OR
; &        bitwise AND
; ~        bitwise NOT
; !        boolean NOT
;
; Boolean flags can be turned on using the values 1, On, True or Yes.
; They can be turned off using the values 0, Off, False or No.
;
; An empty string can be denoted by simply not writing anything after the equal
; sign, or by using the None keyword:
;
;  foo =         ; sets foo to an empty string
;  foo = none    ; sets foo to an empty string
;  foo = "none"  ; sets foo to the string 'none'
;
; If you use constants in your value, and these constants belong to a
; dynamically loaded extension (either a PHP extension or a Zend extension),
; you may only use these constants *after* the line that loads the extension.
;
; All the values in the php.ini-dist file correspond to the builtin
; defaults (that is, if no php.ini is used, or if you delete these lines,
; the builtin defaults will be identical).


;;;;;;;;;;;;;;;;;;;;
; Language Options ;
;;;;;;;;;;;;;;;;;;;;

; Enable the PHP scripting language engine under Apache.
engine = On

; Allow the <? tag.  Otherwise, only <?php and <script> tags are recognized.  
; NOTE: Using short tags should be avoided when developing applications or
; libraries that are meant for redistribution, or deployment on PHP
; servers which are not under your control, because short tags may not
; be supported on the target server. For portable, redistributable code,
; be sure not to use short tags.
short_open_tag = On

; Allow ASP-style <% %> tags.
asp_tags = Off

; The number of significant digits displayed in floating point numbers.
precision    =  12

; Enforce year 2000 compliance (will cause problems with non-compliant browsers)
y2k_compliance = On

; Output buffering allows you to send header lines (including cookies) even
; after you send body content, at the price of slowing PHP's output layer a
; bit.  You can enable output buffering during runtime by calling the output
; buffering functions.  You can also enable output buffering for all files by
; setting this directive to On.  If you wish to limit the size of the buffer
; to a certain size - you can use a maximum number of bytes instead of 'On', as
; a value for this directive (e.g., output_buffering=4096).
output_buffering = Off

; You can redirect all of the output of your scripts to a function.  For
; example, if you set output_handler to "mb_output_handler", character
; encoding will be transparently converted to the specified encoding.
; Setting any output handler automatically turns on output buffering.
; Note: People who wrote portable scripts should not depend on this ini
;       directive. Instead, explicitly set the output handler using ob_start().
;       Using this ini directive may cause problems unless you know what script 
;       is doing.
; Note: You cannot use both "mb_output_handler" with "ob_iconv_handler"
;       and you cannot use both "ob_gzhandler" and "zlib.output_compression". 
;output_handler =

; Transparent output compression using the zlib library
; Valid values for this option are 'off', 'on', or a specific buffer size
; to be used for compression (default is 4KB)
; Note: Resulting chunk size may vary due to nature of compression. PHP 
;       outputs chunks that are few hundreds bytes each as a result of 
;       compression. If you prefer a larger chunk size for better 
;       performance, enable output_buffering in addition.
; Note: You need to use zlib.output_handler instead of the standard
;       output_handler, or otherwise the output will be corrupted.
zlib.output_compression = Off

; You cannot specify additional output handlers if zlib.output_compression
; is activated here. This setting does the same as output_handler but in
; a different order.
;zlib.output_handler =

; Implicit flush tells PHP to tell the output layer to flush itself
; automatically after every output block.  This is equivalent to calling the
; PHP function flush() after each and every call to print() or echo() and each
; and every HTML block.  Turning this option on has serious performance
; implications and is generally recommended for debugging purposes only.
implicit_flush = Off

; The unserialize callback function will be called (with the undefined class'
; name as parameter), if the unserializer finds an undefined class
; which should be instantiated.
; A warning appears if the specified function is not defined, or if the
; function doesn't include/implement the missing class.
; So only set this entry, if you really want to implement such a 
; callback-function.
unserialize_callback_func=

; When floats & doubles are serialized store serialize_precision significant
; digits after the floating point. The default value ensures that when floats
; are decoded with unserialize, the data will remain the same.
serialize_precision = 100

; Whether to enable the ability to force arguments to be passed by reference
; at function call time.  This method is deprecated and is likely to be
; unsupported in future versions of PHP/Zend.  The encouraged method of
; specifying which arguments should be passed by reference is in the function
; declaration.  You're encouraged to try and turn this option Off and make
; sure your scripts work properly with it in order to ensure they will work
; with future versions of the language (you will receive a warning each time
; you use this feature, and the argument will be passed by value instead of by
; reference).
allow_call_time_pass_reference = On

; Safe Mode
;
safe_mode = Off

; By default, Safe Mode does a UID compare check when
; opening files. If you want to relax this to a GID compare,
; then turn on safe_mode_gid.
safe_mode_gid = Off

; When safe_mode is on, UID/GID checks are bypassed when
; including files from this directory and its subdirectories.
; (directory must also be in include_path or full path must
; be used when including)
safe_mode_include_dir =								

; When safe_mode is on, only executables located in the safe_mode_exec_dir
; will be allowed to be executed via the exec family of functions.
safe_mode_exec_dir =

; Setting certain environment variables may be a potential security breach.
; This directive contains a comma-delimited list of prefixes.  In Safe Mode,
; the user may only alter environment variables whose names begin with the
; prefixes supplied here.  By default, users will only be able to set
; environment variables that begin with PHP_ (e.g. PHP_FOO=BAR).
;
; Note:  If this directive is empty, PHP will let the user modify ANY
; environment variable!
safe_mode_allowed_env_vars = PHP_

; This directive contains a comma-delimited list of environment variables that
; the end user won't be able to change using putenv().  These variables will be
; protected even if safe_mode_allowed_env_vars is set to allow to change them.
safe_mode_protected_env_vars = LD_LIBRARY_PATH

; open_basedir, if set, limits all file operations to the defined directory
; and below.  This directive makes most sense if used in a per-directory
; or per-virtualhost web server configuration file. This directive is
; *NOT* affected by whether Safe Mode is turned On or Off.
;open_basedir =

; This directive allows you to disable certain functions for security reasons.
; It receives a comma-delimited list of function names. This directive is
; *NOT* affected by whether Safe Mode is turned On or Off.
disable_functions = 

; This directive allows you to disable certain classes for security reasons.
; It receives a comma-delimited list of class names. This directive is
; *NOT* affected by whether Safe Mode is turned On or Off.
disable_classes =

; Colors for Syntax Highlighting mode.  Anything that's acceptable in
; <font color="??????"> would work.
;highlight.string  = #DD0000
;highlight.comment = #FF9900
;highlight.keyword = #007700
;highlight.bg      = #FFFFFF
;highlight.default = #0000BB
;highlight.html    = #000000


;
; Misc
;
; Decides whether PHP may expose the fact that it is installed on the server
; (e.g. by adding its signature to the Web server header).  It is no security
; threat in any way, but it makes it possible to determine whether you use PHP
; on your server or not.
expose_php = Off


;;;;;;;;;;;;;;;;;;;
; Resource Limits ;
;;;;;;;;;;;;;;;;;;;

max_execution_time = 30     ; Maximum execution time of each script, in seconds
max_input_time = 60	; Maximum amount of time each script may spend parsing request data
memory_limit = 32M      ; Maximum amount of memory a script may consume (8MB)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Error handling and logging ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

; error_reporting is a bit-field.  Or each number up to get desired error
; reporting level
; E_ALL             - All errors and warnings
; E_ERROR           - fatal run-time errors
; E_WARNING         - run-time warnings (non-fatal errors)
; E_PARSE           - compile-time parse errors
; E_NOTICE          - run-time notices (these are warnings which often result
;                     from a bug in your code, but it's possible that it was
;                     intentional (e.g., using an uninitialized variable and
;                     relying on the fact it's automatically initialized to an
;                     empty string)
; E_CORE_ERROR      - fatal errors that occur during PHP's initial startup
; E_CORE_WARNING    - warnings (non-fatal errors) that occur during PHP's
;                     initial startup
; E_COMPILE_ERROR   - fatal compile-time errors
; E_COMPILE_WARNING - compile-time warnings (non-fatal errors)
; E_USER_ERROR      - user-generated error message
; E_USER_WARNING    - user-generated warning message
; E_USER_NOTICE     - user-generated notice message
;
; Examples:
;
;   - Show all errors, except for notices
;
;error_reporting = E_ALL & ~E_NOTICE
;
;   - Show only errors
;
;error_reporting = E_COMPILE_ERROR|E_ERROR|E_CORE_ERROR
;
;   - Show all errors except for notices
;
error_reporting  =  E_ALL & ~E_NOTICE & ~E_WARNING

; Print out errors (as a part of the output).  For production web sites,
; you're strongly encouraged to turn this feature off, and use error logging
; instead (see below).  Keeping display_errors enabled on a production web site
; may reveal security information to end users, such as file paths on your Web
; server, your database schema or other information.
display_errors = On

; Even when display_errors is on, errors that occur during PHP's startup
; sequence are not displayed.  It's strongly recommended to keep
; display_startup_errors off, except for when debugging.
display_startup_errors = Off

; Log errors into a log file (server-specific log, stderr, or error_log (below))
; As stated above, you're strongly advised to use error logging in place of
; error displaying on production web sites.
log_errors = Off

; Set maximum length of log_errors. In error_log information about the source is
; added. The default is 1024 and 0 allows to not apply any maximum length at all.
log_errors_max_len = 1024

; Do not log repeated messages. Repeated errors must occur in same file on same
; line until ignore_repeated_source is set true.
ignore_repeated_errors = Off

; Ignore source of message when ignoring repeated messages. When this setting 
; is On you will not log errors with repeated messages from different files or
; sourcelines.
ignore_repeated_source = Off

; If this parameter is set to Off, then memory leaks will not be shown (on
; stdout or in the log). This has only effect in a debug compile, and if 
; error reporting includes E_WARNING in the allowed list
report_memleaks = On

; Store the last error/warning message in $php_errormsg (boolean).
track_errors = Off

; Disable the inclusion of HTML tags in error messages.
;html_errors = Off
  
; If html_errors is set On PHP produces clickable error messages that direct 
; to a page describing the error or function causing the error in detail.
; You can download a copy of the PHP manual from http://www.php.net/docs.php 
; and change docref_root to the base URL of your local copy including the
; leading '/'. You must also specify the file extension being used including 
; the dot.
;docref_root = "/phpmanual/"
;docref_ext = .html
  
; String to output before an error message.
;error_prepend_string = "<font color=ff0000>"

; String to output after an error message.
;error_append_string = "</font>"

; Log errors to specified file.
;error_log = filename

; Log errors to syslog (Event Log on NT, not valid in Windows 95).
;error_log = syslog


;;;;;;;;;;;;;;;;;
; Data Handling ;
;;;;;;;;;;;;;;;;;
;
; Note - track_vars is ALWAYS enabled as of PHP 4.0.3

; The separator used in PHP generated URLs to separate arguments.
; Default is "&". 
;arg_separator.output = "&amp;"

; List of separator(s) used by PHP to parse input URLs into variables.
; Default is "&". 
; NOTE: Every character in this directive is considered as separator!
;arg_separator.input = ";&"

; This directive describes the order in which PHP registers GET, POST, Cookie,
; Environment and Built-in variables (G, P, C, E & S respectively, often
; referred to as EGPCS or GPC).  Registration is done from left to right, newer
; values override older values.
variables_order = "EGPCS"

; Whether or not to register the EGPCS variables as global variables.  You may
; want to turn this off if you don't want to clutter your scripts' global scope
; with user data.  This makes most sense when coupled with track_vars - in which
; case you can access all of the GPC variables through the $HTTP_*_VARS[],
; variables.
;
; You should do your best to write your scripts so that they do not require
; register_globals to be on;  Using form variables as globals can easily lead
; to possible security problems, if the code is not very well thought of.
register_globals = Off

; This directive tells PHP whether to declare the argv&argc variables (that
; would contain the GET information).  If you don't use these variables, you
; should turn it off for increased performance.
register_argc_argv = On

; Maximum size of POST data that PHP will accept.
post_max_size = 8M

; This directive is deprecated.  Use variables_order instead.
gpc_order = "GPC"

; Magic quotes
;

; Magic quotes for incoming GET/POST/Cookie data.
magic_quotes_gpc = On

; Magic quotes for runtime-generated data, e.g. data from SQL, from exec(), etc.
magic_quotes_runtime = Off    

; Use Sybase-style magic quotes (escape ' with '' instead of \').
magic_quotes_sybase = Off

; Automatically add files before or after any PHP document.
auto_prepend_file =
auto_append_file =

; As of 4.0b4, PHP always outputs a character encoding by default in
; the Content-type: header.  To disable sending of the charset, simply
; set it to be empty.
;
; PHP's built-in default is text/html
default_mimetype = "text/html"
;default_charset = "iso-8859-1"

; Always populate the $HTTP_RAW_POST_DATA variable.
;always_populate_raw_post_data = On


;;;;;;;;;;;;;;;;;;;;;;;;;
; Paths and Directories ;
;;;;;;;;;;;;;;;;;;;;;;;;;

; UNIX: "/path1:/path2"  
;include_path = ".:/php/includes"
;
; Windows: "\path1;\path2"
;include_path = ".;c:\php\includes"

; The root of the PHP pages, used only if nonempty.
; if PHP was not compiled with FORCE_REDIRECT, you SHOULD set doc_root
; if you are running php as a CGI under any web server (other than IIS)
; see documentation for security issues.  The alternate is to use the
; cgi.force_redirect configuration below
doc_root =

; The directory under which PHP opens the script using /~username used only
; if nonempty.
user_dir =

; Directory in which the loadable extensions (modules) reside.
extension_dir = /opt/lsws/lib

; Whether or not to enable the dl() function.  The dl() function does NOT work
; properly in multithreaded servers, such as IIS or Zeus, and is automatically
; disabled on them.
enable_dl = Off

; cgi.force_redirect is necessary to provide security running PHP as a CGI under
; most web servers.  Left undefined, PHP turns this on by default.  You can
; turn it off here AT YOUR OWN RISK
; **You CAN safely turn this off for IIS, in fact, you MUST.**
; cgi.force_redirect = 1

; if cgi.nph is enabled it will force cgi to always sent Status: 200 with
; every request.
; cgi.nph = 1

; if cgi.force_redirect is turned on, and you are not running under Apache or Netscape 
; (iPlanet) web servers, you MAY need to set an environment variable name that PHP
; will look for to know it is OK to continue execution.  Setting this variable MAY
; cause security issues, KNOW WHAT YOU ARE DOING FIRST.
; cgi.redirect_status_env = ;

; cgi.fix_pathinfo provides *real* PATH_INFO/PATH_TRANSLATED support for CGI.  PHP's
; previous behaviour was to set PATH_TRANSLATED to SCRIPT_FILENAME, and to not grok
; what PATH_INFO is.  For more information on PATH_INFO, see the cgi specs.  Setting
; this to 1 will cause PHP CGI to fix it's paths to conform to the spec.  A setting
; of zero causes PHP to behave as before.  Default is zero.  You should fix your scripts
; to use SCRIPT_FILENAME rather than PATH_TRANSLATED.
; cgi.fix_pathinfo=0

; FastCGI under IIS (on WINNT based OS) supports the ability to impersonate
; security tokens of the calling client.  This allows IIS to define the
; security context that the request runs under.  mod_fastcgi under Apache
; does not currently support this feature (03/17/2002)
; Set to 1 if running under IIS.  Default is zero.
; fastcgi.impersonate = 1;

; Disable logging through FastCGI connection
; fastcgi.log = 0

; cgi.rfc2616_headers configuration option tells PHP what type of headers to
; use when sending HTTP response code. If it's set 0 PHP sends Status: header that
; is supported by Apache. When this option is set to 1 PHP will send
; RFC2616 compliant header.
; Default is zero.
;cgi.rfc2616_headers = 0 
 

;;;;;;;;;;;;;;;;
; File Uploads ;
;;;;;;;;;;;;;;;;

; Whether to allow HTTP file uploads.
file_uploads = On

; Temporary directory for HTTP uploaded files (will use system default if not
; specified).
;upload_tmp_dir =

; Maximum allowed size for uploaded files.
upload_max_filesize = 16M


;;;;;;;;;;;;;;;;;;
; Fopen wrappers ;
;;;;;;;;;;;;;;;;;;

; Whether to allow the treatment of URLs (like http:// or ftp://) as files.
allow_url_fopen = On

; Define the anonymous ftp password (your email address)
;from="john@doe.com"

; Define the User-Agent string
; user_agent="PHP"

; Default timeout for socket based streams (seconds)
default_socket_timeout = 60

; If your scripts have to deal with files from Macintosh systems,
; or you are running on a Mac and need to deal with files from
; unix or win32 systems, setting this flag will cause PHP to
; automatically detect the EOL character in those files so that
; fgets() and file() will work regardless of the source of the file.
; auto_detect_line_endings = Off


;;;;;;;;;;;;;;;;;;;;;;
; Dynamic Extensions ;
;;;;;;;;;;;;;;;;;;;;;;
;
; If you wish to have an extension loaded automatically, use the following
; syntax:
;
;   extension=modulename.extension
;
; For example, on Windows:
;
;   extension=msql.dll
;
; ... or under UNIX:
;
;   extension=msql.so
;
; Note that it should be the name of the module only; no directory information 
; needs to go here.  Specify the location of the extension with the
; extension_dir directive above.

;Windows Extensions
;Note that MySQL and ODBC support is now built in, so no dll is needed for it.
;
;extension=php_mbstring.dll
;extension=php_bz2.dll
;extension=php_cpdf.dll
;extension=php_crack.dll
;extension=php_curl.dll
;extension=php_db.dll
;extension=php_dba.dll
;extension=php_dbase.dll
;extension=php_dbx.dll
;extension=php_domxml.dll
;extension=php_exif.dll
;extension=php_fdf.dll
;extension=php_filepro.dll
;extension=php_gd2.dll
;extension=php_gettext.dll
;extension=php_hyperwave.dll
;extension=php_iconv.dll
;extension=php_ifx.dll
;extension=php_iisfunc.dll
;extension=php_imap.dll
;extension=php_interbase.dll
;extension=php_java.dll
;extension=php_ldap.dll
;extension=php_mcrypt.dll
;extension=php_mhash.dll
;extension=php_mime_magic.dll
;extension=php_ming.dll
;extension=php_mssql.dll
;extension=php_msql.dll
;extension=php_oci8.dll
;extension=php_openssl.dll
;extension=php_oracle.dll
;extension=php_pdf.dll
;extension=php_pgsql.dll
;extension=php_printer.dll
;extension=php_shmop.dll
;extension=php_snmp.dll
;extension=php_sockets.dll
;extension=php_sybase_ct.dll
;extension=php_w32api.dll
;extension=php_xmlrpc.dll
;extension=php_xslt.dll
;extension=php_yaz.dll
;extension=php_zip.dll


;;;;;;;;;;;;;;;;;;;
; Module Settings ;
;;;;;;;;;;;;;;;;;;;

[Syslog]
; Whether or not to define the various syslog variables (e.g. $LOG_PID,
; $LOG_CRON, etc.).  Turning it off is a good idea performance-wise.  In
; runtime, you can define these variables by calling define_syslog_variables().
define_syslog_variables  = Off

[mail function]
; For Win32 only.
SMTP = localhost
smtp_port = 25

; For Win32 only.
;sendmail_from = me@example.com

; For Unix only.  You may supply arguments as well (default: "sendmail -t -i").
;sendmail_path =

[Java]
;java.class.path = .\php_java.jar
;java.home = c:\jdk
;java.library = c:\jdk\jre\bin\hotspot\jvm.dll 
;java.library.path = .\

[SQL]
sql.safe_mode = Off

[ODBC]
;odbc.default_db    =  Not yet implemented
;odbc.default_user  =  Not yet implemented
;odbc.default_pw    =  Not yet implemented

; Allow or prevent persistent links.
odbc.allow_persistent = On

; Check that a connection is still valid before reuse.
odbc.check_persistent = On

; Maximum number of persistent links.  -1 means no limit.
odbc.max_persistent = -1

; Maximum number of links (persistent + non-persistent).  -1 means no limit.
odbc.max_links = -1  

; Handling of LONG fields.  Returns number of bytes to variables.  0 means
; passthru.
odbc.defaultlrl = 4096  

; Handling of binary data.  0 means passthru, 1 return as is, 2 convert to char.
; See the documentation on odbc_binmode and odbc_longreadlen for an explanation
; of uodbc.defaultlrl and uodbc.defaultbinmode
odbc.defaultbinmode = 1  

[MySQL]
; Allow or prevent persistent links.
mysql.allow_persistent = On

; Maximum number of persistent links.  -1 means no limit.
mysql.max_persistent = -1

; Maximum number of links (persistent + non-persistent).  -1 means no limit.
mysql.max_links = -1

; Default port number for mysql_connect().  If unset, mysql_connect() will use
; the $MYSQL_TCP_PORT or the mysql-tcp entry in /etc/services or the
; compile-time value defined MYSQL_PORT (in that order).  Win32 will only look
; at MYSQL_PORT.
mysql.default_port =

; Default socket name for local MySQL connects.  If empty, uses the built-in
; MySQL defaults.
mysql.default_socket =

; Default host for mysql_connect() (doesn't apply in safe mode).
mysql.default_host =

; Default user for mysql_connect() (doesn't apply in safe mode).
mysql.default_user =

; Default password for mysql_connect() (doesn't apply in safe mode).
; Note that this is generally a *bad* idea to store passwords in this file.
; *Any* user with PHP access can run 'echo get_cfg_var("mysql.default_password")
; and reveal this password!  And of course, any users with read access to this
; file will be able to reveal the password as well.
mysql.default_password =

; Maximum time (in seconds) for connect timeout. -1 means no limit
mysql.connect_timeout = 60

; Trace mode. When trace_mode is active (=On), warnings for table/index scans and
; SQL-Errors will be displayed.
mysql.trace_mode = Off

[mSQL]
; Allow or prevent persistent links.
msql.allow_persistent = On

; Maximum number of persistent links.  -1 means no limit.
msql.max_persistent = -1

; Maximum number of links (persistent+non persistent).  -1 means no limit.
msql.max_links = -1

[PostgresSQL]
; Allow or prevent persistent links.
pgsql.allow_persistent = On

; Detect broken persistent links always with pg_pconnect(). Need a little overhead.
pgsql.auto_reset_persistent = Off 

; Maximum number of persistent links.  -1 means no limit.
pgsql.max_persistent = -1

; Maximum number of links (persistent+non persistent).  -1 means no limit.
pgsql.max_links = -1

; Ignore PostgreSQL backends Notice message or not.
pgsql.ignore_notice = 0

; Log PostgreSQL backends Noitce message or not.
; Unless pgsql.ignore_notice=0, module cannot log notice message.
pgsql.log_notice = 0

[Sybase]
; Allow or prevent persistent links.
sybase.allow_persistent = On

; Maximum number of persistent links.  -1 means no limit.
sybase.max_persistent = -1

; Maximum number of links (persistent + non-persistent).  -1 means no limit.
sybase.max_links = -1

;sybase.interface_file = "/usr/sybase/interfaces"

; Minimum error severity to display.
sybase.min_error_severity = 10

; Minimum message severity to display.
sybase.min_message_severity = 10

; Compatability mode with old versions of PHP 3.0.
; If on, this will cause PHP to automatically assign types to results according
; to their Sybase type, instead of treating them all as strings.  This
; compatibility mode will probably not stay around forever, so try applying
; whatever necessary changes to your code, and turn it off.
sybase.compatability_mode = Off

[Sybase-CT]
; Allow or prevent persistent links.
sybct.allow_persistent = On

; Maximum number of persistent links.  -1 means no limit.
sybct.max_persistent = -1

; Maximum number of links (persistent + non-persistent).  -1 means no limit.
sybct.max_links = -1

; Minimum server message severity to display.
sybct.min_server_severity = 10

; Minimum client message severity to display.
sybct.min_client_severity = 10

[dbx]
; returned column names can be converted for compatibility reasons
; possible values for dbx.colnames_case are
; "unchanged" (default, if not set)
; "lowercase"
; "uppercase"
; the recommended default is either upper- or lowercase, but
; unchanged is currently set for backwards compatibility
dbx.colnames_case = "unchanged"

[bcmath]
; Number of decimal digits for all bcmath functions.
bcmath.scale = 0

[browscap]
;browscap = extra/browscap.ini

[Informix]
; Default host for ifx_connect() (doesn't apply in safe mode).
ifx.default_host =

; Default user for ifx_connect() (doesn't apply in safe mode).
ifx.default_user =

; Default password for ifx_connect() (doesn't apply in safe mode).
ifx.default_password =

; Allow or prevent persistent links.
ifx.allow_persistent = On

; Maximum number of persistent links.  -1 means no limit.
ifx.max_persistent = -1

; Maximum number of links (persistent + non-persistent).  -1 means no limit.
ifx.max_links = -1

; If on, select statements return the contents of a text blob instead of its id.
ifx.textasvarchar = 0

; If on, select statements return the contents of a byte blob instead of its id.
ifx.byteasvarchar = 0

; Trailing blanks are stripped from fixed-length char columns.  May help the
; life of Informix SE users.
ifx.charasvarchar = 0

; If on, the contents of text and byte blobs are dumped to a file instead of
; keeping them in memory.
ifx.blobinfile = 0

; NULL's are returned as empty strings, unless this is set to 1.  In that case,
; NULL's are returned as string 'NULL'.
ifx.nullformat = 0

[Session]
; Handler used to store/retrieve data.
session.save_handler = files

; Argument passed to save_handler.  In the case of files, this is the path
; where data files are stored. Note: Windows users have to change this 
; variable in order to use PHP's session functions.
; As of PHP 4.0.1, you can define the path as:
;     session.save_path = "N;/path"
; where N is an integer.  Instead of storing all the session files in 
; /path, what this will do is use subdirectories N-levels deep, and 
; store the session data in those directories.  This is useful if you 
; or your OS have problems with lots of files in one directory, and is 
; a more efficient layout for servers that handle lots of sessions.
; NOTE 1: PHP will not create this directory structure automatically.
;         You can use the script in the ext/session dir for that purpose.
; NOTE 2: See the section on garbage collection below if you choose to
;         use subdirectories for session storage
;session.save_path = /tmp

; Whether to use cookies.
session.use_cookies = 1

; This option enables administrators to make their users invulnerable to
; attacks which involve passing session ids in URLs; defaults to 0.
; session.use_only_cookies = 1

; Name of the session (used as cookie name).
session.name = PHPSESSID

; Initialize session on request startup.
session.auto_start = 0

; Lifetime in seconds of cookie or, if 0, until browser is restarted.
session.cookie_lifetime = 0

; The path for which the cookie is valid.
session.cookie_path = /

; The domain for which the cookie is valid.
session.cookie_domain =

; Handler used to serialize data.  php is the standard serializer of PHP.
session.serialize_handler = php

; Define the probability that the 'garbage collection' process is started
; on every session initialization.
; The probability is calculated by using gc_probability/gc_divisor,
; e.g. 1/100 means there is a 1% chance that the GC process starts
; on each request.

session.gc_probability = 1
session.gc_divisor     = 100

; After this number of seconds, stored data will be seen as 'garbage' and
; cleaned up by the garbage collection process.
session.gc_maxlifetime = 1440

; NOTE: If you are using the subdirectory option for storing session files
;       (see session.save_path above), then garbage collection does *not*
;       happen automatically.  You will need to do your own garbage 
;       collection through a shell script, cron entry, or some other method. 
;       For example, the following script would is the equivalent of
;       setting session.gc_maxlifetime to 1440 (1440 seconds = 24 minutes):
;          cd /path/to/sessions; find -cmin +24 | xargs rm

; PHP 4.2 and less have an undocumented feature/bug that allows you to
; to initialize a session variable in the global scope, albeit register_globals
; is disabled.  PHP 4.3 and later will warn you, if this feature is used.
; You can disable the feature and the warning separately. At this time,
; the warning is only displayed, if bug_compat_42 is enabled.

session.bug_compat_42 = 1
session.bug_compat_warn = 1

; Check HTTP Referer to invalidate externally stored URLs containing ids.
; HTTP_REFERER has to contain this substring for the session to be
; considered as valid.
session.referer_check =

; How many bytes to read from the file.
session.entropy_length = 0

; Specified here to create the session id.
session.entropy_file =

;session.entropy_length = 16

;session.entropy_file = /dev/urandom

; Set to {nocache,private,public,} to determine HTTP caching aspects
; or leave this empty to avoid sending anti-caching headers.
session.cache_limiter = nocache

; Document expires after n minutes.
session.cache_expire = 180

; trans sid support is disabled by default.
; Use of trans sid may risk your users security. 
; Use this option with caution.
; - User may send URL contains active session ID
;   to other person via. email/irc/etc.
; - URL that contains active session ID may be stored
;   in publically accessible computer.
; - User may access your site with the same session ID
;   always using URL stored in browser's history or bookmarks.
session.use_trans_sid = 0

; The URL rewriter will look for URLs in a defined set of HTML tags.
; form/fieldset are special; if you include them here, the rewriter will
; add a hidden <input> field with the info which is otherwise appended
; to URLs.  If you want XHTML conformity, remove the form entry.
; Note that all valid entries require a "=", even if no value follows.
url_rewriter.tags = "a=href,area=href,frame=src,input=src,form=,fieldset="

[MSSQL]
; Allow or prevent persistent links.
mssql.allow_persistent = On

; Maximum number of persistent links.  -1 means no limit.
mssql.max_persistent = -1

; Maximum number of links (persistent+non persistent).  -1 means no limit.
mssql.max_links = -1

; Minimum error severity to display.
mssql.min_error_severity = 10

; Minimum message severity to display.
mssql.min_message_severity = 10

; Compatability mode with old versions of PHP 3.0.
mssql.compatability_mode = Off

; Connect timeout
;mssql.connect_timeout = 5

; Query timeout
;mssql.timeout = 60

; Valid range 0 - 2147483647.  Default = 4096.
;mssql.textlimit = 4096

; Valid range 0 - 2147483647.  Default = 4096.
;mssql.textsize = 4096

; Limits the number of records in each batch.  0 = all records in one batch.
;mssql.batchsize = 0

; Specify how datetime and datetim4 columns are returned
; On => Returns data converted to SQL server settings
; Off => Returns values as YYYY-MM-DD hh:mm:ss
;mssql.datetimeconvert = On

; Use NT authentication when connecting to the server
mssql.secure_connection = Off

; Specify max number of processes. -1 = library default
; msdlib defaults to 25
; FreeTDS defaults to 4096
;mssql.max_procs = -1

[Assertion]
; Assert(expr); active by default.
;assert.active = On

; Issue a PHP warning for each failed assertion.
;assert.warning = On

; Don't bail out by default.
;assert.bail = Off

; User-function to be called if an assertion fails.
;assert.callback = 0

; Eval the expression with current error_reporting().  Set to true if you want
; error_reporting(0) around the eval().
;assert.quiet_eval = 0

[Ingres II]
; Allow or prevent persistent links.
ingres.allow_persistent = On

; Maximum number of persistent links.  -1 means no limit.
ingres.max_persistent = -1

; Maximum number of links, including persistents.  -1 means no limit.
ingres.max_links = -1

; Default database (format: [node_id::]dbname[/srv_class]).
ingres.default_database =

; Default user.
ingres.default_user =

; Default password.
ingres.default_password =

[Verisign Payflow Pro]
; Default Payflow Pro server.
pfpro.defaulthost = "test-payflow.verisign.com"

; Default port to connect to.
pfpro.defaultport = 443

; Default timeout in seconds.
pfpro.defaulttimeout = 30

; Default proxy IP address (if required).
;pfpro.proxyaddress =

; Default proxy port.
;pfpro.proxyport =

; Default proxy logon.
;pfpro.proxylogon =

; Default proxy password.
;pfpro.proxypassword =

[com]
; path to a file containing GUIDs, IIDs or filenames of files with TypeLibs
;com.typelib_file = 
; allow Distributed-COM calls
;com.allow_dcom = true
; autoregister constants of a components typlib on com_load()
;com.autoregister_typelib = true
; register constants casesensitive
;com.autoregister_casesensitive = false
; show warnings on duplicate constat registrations
;com.autoregister_verbose = true

[Printer]
;printer.default_printer = ""

[mbstring]
; language for internal character representation.
;mbstring.language = Japanese

; internal/script encoding.
; Some encoding cannot work as internal encoding.
; (e.g. SJIS, BIG5, ISO-2022-*)
;mbstring.internal_encoding = EUC-JP

; http input encoding.
;mbstring.http_input = auto

; http output encoding. mb_output_handler must be
; registered as output buffer to function
;mbstring.http_output = SJIS

; enable automatic encoding translation according to 
; mbstring.internal_encoding setting. Input chars are
; converted to internal encoding by setting this to On.
; Note: Do _not_ use automatic encoding translation for
;       portable libs/applications.
;mbstring.encoding_translation = Off

; automatic encoding detection order.
; auto means 
;mbstring.detect_order = auto

; substitute_character used when character cannot be converted
; one from another
;mbstring.substitute_character = none;

; overload(replace) single byte functions by mbstring functions.
; mail(), ereg(), etc are overloaded by mb_send_mail(), mb_ereg(),
; etc. Possible values are 0,1,2,4 or combination of them.
; For example, 7 for overload everything.
; 0: No overload
; 1: Overload mail() function
; 2: Overload str*() functions
; 4: Overload ereg*() functions
;mbstring.func_overload = 0

[FrontBase]
;fbsql.allow_persistent = On
;fbsql.autocommit = On
;fbsql.default_database = 
;fbsql.default_database_password =
;fbsql.default_host =
;fbsql.default_password =
;fbsql.default_user = "_SYSTEM"
;fbsql.generate_warnings = Off
;fbsql.max_connections = 128
;fbsql.max_links = 128
;fbsql.max_persistent = -1
;fbsql.max_results = 128
;fbsql.batchSize = 1000

[Crack]
; Modify the setting below to match the directory location of the cracklib
; dictionary files.  Include the base filename, but not the file extension.
; crack.default_dictionary = "c:\php\lib\cracklib_dict"

[exif]
; Exif UNICODE user comments are handled as UCS-2BE/UCS-2LE and JIS as JIS. 
; With mbstring support this will automatically be converted into the encoding
; given by corresponding encode setting. When empty mbstring.internal_encoding 
; is used. For the decode settings you can distinguish between motorola and 
; intel byte order. A decode setting cannot be empty.
;exif.encode_unicode = ISO-8859-15
;exif.decode_unicode_motorola = UCS-2BE
;exif.decode_unicode_intel    = UCS-2LE
;exif.encode_jis = 
;exif.decode_jis_motorola = JIS
;exif.decode_jis_intel    = JIS

; Local Variables:
; tab-width: 4
; End:frontpage/conf/srm.conf000064400000000000150545647710011132 0ustar00frontpage/conf/httpd.conf000064400000000000150545647710011454 0ustar00frontpage/conf/access.conf000064400000000000150545647710011572 0ustar00interworx/httpd_config.xml000064400000013543150545647710012023 0ustar00<?xml version="1.0" encoding="UTF-8"?>
<httpServerConfig>
  <serverName>$HOSTNAME</serverName>
  <user>apache</user>
  <group>apache</group>
  <priority>0</priority>
  <chrootPath>/</chrootPath>
  <enableChroot>0</enableChroot>
  <inMemBufSize>60M</inMemBufSize>
  <swappingDir>/tmp/lshttpd/swap</swappingDir>
  <autoRestart>1</autoRestart>
  <autoFix503>0</autoFix503>
  <loadApacheConf>1</loadApacheConf>
  <autoReloadApacheConf>1</autoReloadApacheConf>
  <apacheConfFile>/etc/httpd/conf/httpd.conf</apacheConfFile>
  <apachePortOffset>%AP_PORT_OFFSET%</apachePortOffset>
  <apacheIpOffset>0</apacheIpOffset>
  <phpSuExec>%PHP_SUEXEC%</phpSuExec>
  <phpSuExecMaxConn>10</phpSuExecMaxConn>
  <mime>$SERVER_ROOT/conf/mime.properties</mime>
  <disableInitLogRotation></disableInitLogRotation>
  <showVersionNumber>0</showVersionNumber>
  <enableIpGeo></enableIpGeo>
  <useIpInProxyHeader>2</useIpInProxyHeader>
  <autoUpdateInterval>86400</autoUpdateInterval>
  <autoUpdateDownloadPkg>1</autoUpdateDownloadPkg>
  <adminEmails>%ADMIN_EMAIL%</adminEmails>
  <adminRoot>$SERVER_ROOT/admin/</adminRoot>
  <logging>
    <log>
      <fileName>$SERVER_ROOT/logs/error.log</fileName>
      <logLevel>DEBUG</logLevel>
      <debugLevel>0</debugLevel>
      <rollingSize>10M</rollingSize>
      <enableStderrLog>1</enableStderrLog>
    </log>
    <accessLog>
      <fileName>$SERVER_ROOT/logs/access.log</fileName>
      <rollingSize>10M</rollingSize>
      <keepDays>30</keepDays>
      <compressArchive>0</compressArchive>
    </accessLog>
  </logging>
  <indexFiles>index.html, index.php, index.htm</indexFiles>
  <autoIndex></autoIndex>
  <autoIndexURI></autoIndexURI>
  <htAccess>
    <allowOverride>31</allowOverride>
    <accessFileName>.htaccess</accessFileName>
  </htAccess>
  <expires>
    <enableExpires>1</enableExpires>
    <expiresByType>image/*=A604800, text/css=A604800, application/x-javascript=A604800, application/javascript=A604800</expiresByType>
  </expires>
  <tuning>
    <maxConnections>10000</maxConnections>
    <maxSSLConnections>10000</maxSSLConnections>
    <connTimeout>120</connTimeout>
    <maxKeepAliveReq>10000</maxKeepAliveReq>
    <smartKeepAlive>0</smartKeepAlive>
    <keepAliveTimeout>10</keepAliveTimeout>
    <sndBufSize>0</sndBufSize>
    <rcvBufSize>0</rcvBufSize>
    <eventDispatcher>best</eventDispatcher>
    <maxCachedFileSize>4096</maxCachedFileSize>
    <totalInMemCacheSize>20M</totalInMemCacheSize>
    <maxMMapFileSize>256K</maxMMapFileSize>
    <totalMMapCacheSize>40M</totalMMapCacheSize>
    <useSendfile>1</useSendfile>
    <useAIO>1</useAIO>
    <AIOBlockSize>4</AIOBlockSize>
    <etagNoInode>1</etagNoInode>
    <SSLCryptoDevice>null</SSLCryptoDevice>
    <maxReqURLLen>8192</maxReqURLLen>
    <maxReqHeaderSize>16380</maxReqHeaderSize>
    <maxReqBodySize>500M</maxReqBodySize>
    <maxDynRespHeaderSize>4K</maxDynRespHeaderSize>
    <maxDynRespSize>500M</maxDynRespSize>
    <enableGzipCompress>1</enableGzipCompress>
    <enableDynGzipCompress>1</enableDynGzipCompress>
    <compressibleTypes>default</compressibleTypes>
    <gzipAutoUpdateStatic>1</gzipAutoUpdateStatic>
    <gzipCacheDir></gzipCacheDir>
  </tuning>
  <security>
    <fileAccessControl>
      <followSymbolLink>1</followSymbolLink>
      <checkSymbolLink>0</checkSymbolLink>
      <forceStrictOwnership>1</forceStrictOwnership>
      <requiredPermissionMask>000</requiredPermissionMask>
      <restrictedPermissionMask>000</restrictedPermissionMask>
      <restrictedScriptPermissionMask>002</restrictedScriptPermissionMask>
      <restrictedDirPermissionMask>002</restrictedDirPermissionMask>
    </fileAccessControl>
    <perClientConnLimit>
      <staticReqPerSec>0</staticReqPerSec>
      <dynReqPerSec>0</dynReqPerSec>
      <outBandwidth>0</outBandwidth>
      <inBandwidth>0</inBandwidth>
      <softLimit>10000</softLimit>
      <hardLimit>10000</hardLimit>
      <gracePeriod>15</gracePeriod>
      <banPeriod>300</banPeriod>
    </perClientConnLimit>
    <CGIRLimit>
      <maxCGIInstances>20</maxCGIInstances>
      <minUID>11</minUID>
      <minGID>10</minGID>
      <priority>0</priority>
      <CPUSoftLimit>60</CPUSoftLimit>
      <CPUHardLimit>120</CPUHardLimit>
      <memSoftLimit>1250M</memSoftLimit>
      <memHardLimit>1300M</memHardLimit>
      <procSoftLimit>400</procSoftLimit>
      <procHardLimit>450</procHardLimit>
    </CGIRLimit>
    <censorshipControl>
      <enableCensorship>0</enableCensorship>
      <logLevel>0</logLevel>
      <defaultAction>deny,log,status:403</defaultAction>
      <scanPOST>1</scanPOST>
    </censorshipControl>
    <accessDenyDir>
      <dir>/</dir>
      <dir>/etc/*</dir>
      <dir>/dev/*</dir>
      <dir>$SERVER_ROOT/conf/*</dir>
      <dir>$SERVER_ROOT/admin/conf/*</dir>
    </accessDenyDir>
    <accessControl>
      <allow>ALL</allow>
      <deny></deny>
    </accessControl>
  </security>
  <extProcessorList>
  </extProcessorList>
  <scriptHandlerList>
  </scriptHandlerList>
  <phpConfig>
    <maxConns>35</maxConns>
    <env>PHP_LSAPI_CHILDREN=35</env>
    <initTimeout>60</initTimeout>
    <retryTimeout>0</retryTimeout>
    <pcKeepAliveTimeout>1</pcKeepAliveTimeout>
    <respBuffer>0</respBuffer>
    <extMaxIdleTime>60</extMaxIdleTime>
    <memSoftLimit></memSoftLimit>
    <memHardLimit></memHardLimit>
    <procSoftLimit>1400</procSoftLimit>
    <procHardLimit>1500</procHardLimit>
  </phpConfig>
  <railsDefaults>
    <rubyBin></rubyBin>
    <railsEnv>1</railsEnv>
    <maxConns>5</maxConns>
    <env>LSAPI_MAX_IDLE=60</env>
    <initTimeout>60</initTimeout>
    <retryTimeout>0</retryTimeout>
    <pcKeepAliveTimeout>60</pcKeepAliveTimeout>
    <respBuffer>0</respBuffer>
    <backlog>50</backlog>
    <runOnStartUp>1</runOnStartUp>
    <extMaxIdleTime>300</extMaxIdleTime>
    <priority>3</priority>
    <memSoftLimit></memSoftLimit>
    <memHardLimit></memHardLimit>
    <procSoftLimit>200</procSoftLimit>
    <procHardLimit>300</procHardLimit>
  </railsDefaults>
</httpServerConfig>
webcachemgr/src/PluginVersion.php000066400000053645150545647710013154 0ustar00<?php

/** *********************************************
 * LiteSpeed Web Server Cache Manager
 *
 * @author Michael Alegre
 * @copyright (c) 2018-2023 LiteSpeed Technologies, Inc.
 * *******************************************
 */

namespace Lsc\Wp;

use Lsc\Wp\Context\Context;
use LsUserPanel\Lsc\UserLSCMException;

class PluginVersion
{

    /**
     * @var string
     */
    const DEFAULT_PLUGIN_PATH = '/wp-content/plugins/litespeed-cache';

    /**
     * @deprecated 1.9
     * @var string
     */
    const DOWNLOAD_DIR = '/usr/src/litespeed-wp-plugin';

    /**
     * @var string
     */
    const LSCWP_DEFAULTS_INI_FILE_NAME = 'const.default.ini';

    /**
     * @var string
     */
    const PLUGIN_NAME = 'litespeed-cache';

    /**
     * @var string
     */
    const TRANSLATION_CHECK_FLAG_BASE = '.ls_translation_check';

    /**
     * @var string
     */
    const VER_MD5 = 'lscwp_md5';

    /**
     * @deprecated 4.1.3  Will be removed in favor of $this->shortVersions.
     * @var string[]
     */
    protected $knownVersions = array();

    /**
     * @since 4.1.3
     * @var string[]
     */
    protected $shortVersions = array();

    /**
     * @var string[]
     */
    protected $allowedVersions = array();

    /**
     * @var string
     */
    protected $currVersion = '';

    /**
     * @var string
     */
    protected $versionFile;

    /**
     * @var string
     */
    protected $activeFile;

    /**
     * @var null|PluginVersion
     */
    protected static $instance;

    /**
     *
     * @throws LSCMException  Thrown indirectly by $this->init() call.
     */
    protected function __construct()
    {
        $this->init();
    }

    /**
     *
     * @throws LSCMException  Thrown indirectly by Context::isPrivileged() call.
     * @throws LSCMException  Thrown indirectly by $this->refreshVersionList()
     *     call.
     */
    protected function init()
    {
        $this->setVersionFiles();

        if ( Context::isPrivileged() ) {
            $this->refreshVersionList();
        }
    }

    /**
     *
     * @return PluginVersion
     *
     * @throws LSCMException  Thrown indirectly by Context::getOption() call.
     */
    public static function getInstance()
    {
        if ( self::$instance == null ) {
            $className = Context::getOption()->getLscwpVerClass();

            self::$instance = new $className();
        }

        return self::$instance;
    }

    /**
     *
     * @deprecated 4.1.3  Use "$formatted = true" equivalent function
     *     $this->getShortVersions() instead. Un-formatted version of this list
     *     will no longer be available once this function is removed.
     *
     * @param bool $formatted
     *
     * @return string[]
     *
     * @throws LSCMException  Thrown indirectly by $this->setKnownVersions()
     *     call.
     */
    public function getKnownVersions( $formatted = false )
    {
        if ( empty($this->knownVersions) ) {
            $this->setKnownVersions();
        }

        if ( $formatted ) {
            $knownVers = $this->knownVersions;

            $prevVer = '';

            foreach ( $knownVers as &$ver ) {

                if ( $prevVer !== '' ) {
                    $ver1 = explode('.', $prevVer);
                    $ver2 = explode('.', $ver);

                    if ( $ver1[0] !== $ver2[0] || $ver1[1] !== $ver2[1] ) {
                        $ver = "$ver2[0].$ver2[1].x";
                    }
                }

                $prevVer = $ver;
            }

            return $knownVers;
        }

        return $this->knownVersions;
    }

    /**
     *
     * @return string[]
     *
     * @throws LSCMException  Thrown indirectly by $this->setAllowedVersions()
     *     call.
     */
    public function getAllowedVersions()
    {
        if ( empty($this->allowedVersions) ) {
            $this->setAllowedVersions();
        }

        return $this->allowedVersions;
    }

    /**
     *
     * @since 4.1.3
     *
     * @return string[]
     *
     * @throws LSCMException  Thrown indirectly by $this->setShortVersions()
     *     call.
     */
    public function getShortVersions()
    {
        if ( empty($this->shortVersions) ) {
            $this->setShortVersions();
        }

        return $this->shortVersions;
    }

    /**
     *
     * @return string
     *
     * @throws LSCMException  Thrown indirectly by $this->getAllowedVersions()
     *     call.
     */
    public function getLatestVersion()
    {
        $allowedVers = $this->getAllowedVersions();

        return (isset($allowedVers[0])) ? $allowedVers[0] : '';
    }

    /**
     *
     * @return string
     *
     * @throws LSCMException  Thrown indirectly by self::getInstance() call.
     * @throws LSCMException  Thrown indirectly by
     *     $instance->setCurrentVersion() call.
     */
    public static function getCurrentVersion()
    {
        $instance = self::getInstance();

        if ( $instance->currVersion == '' ) {
            $instance->setCurrentVersion();
        }

        return $instance->currVersion;
    }

    /**
     *
     * @since 1.9
     */
    protected function createDownloadDir()
    {
        mkdir(Context::LOCAL_PLUGIN_DIR, 0755);
    }

    protected function setVersionFiles()
    {
        $this->versionFile = Context::LOCAL_PLUGIN_DIR . '/lscwp_versions_v2';
        $this->activeFile = Context::LOCAL_PLUGIN_DIR . '/lscwp_active_version';
    }

    /**
     * Temporary function for handling the active version file and versions
     * file move in the short term.
     *
     * @deprecated 1.9
     * @since 1.9
     *
     * @throws LSCMException  Thrown indirectly by Context::getLSCMDataDir()
     *     call.
     */
    protected function checkOldVersionFiles()
    {
        $dataDir = Context::getLSCMDataDir();
        $oldActiveFile = "$dataDir/lscwp_active_version";

        if ( file_exists($oldActiveFile) ) {

            if ( !file_exists(Context::LOCAL_PLUGIN_DIR) ) {
                $this->createDownloadDir();
            }

            rename($oldActiveFile, $this->activeFile);
            unlink("$dataDir/lscwp_versions");
        }
    }

    /**
     *
     * @throws LSCMException  Thrown indirectly by $this->checkOldVersionFiles()
     *     call.
     * @throws LSCMException  Thrown indirectly by Logger::debug() call.
     * @throws LSCMException  Thrown indirectly by Logger::debug() call.
     * @throws LSCMException  Thrown indirectly by Logger::debug() call.
     */
    public function setCurrentVersion()
    {
        $this->checkOldVersionFiles();

        if ( ($activeVersion = $this->getActiveVersion()) == '' ) {
            Logger::debug('Active LSCWP version not found.');
        }
        elseif ( ! $this->hasDownloadedVersion($activeVersion) ) {
            $activeVersion = '';
            unlink($this->activeFile);
            Logger::debug('Valid LSCWP download not found.');
        }

        if ( $activeVersion == '' ) {

            try {
                $activeVersion = self::getLatestVersion();
            }
            catch ( LSCMException $e ) {
                Logger::debug($e->getMessage());
            }
        }

        $this->currVersion = $activeVersion;
    }

    /**
     *
     * @since 1.11
     *
     * @return string
     */
    private function getActiveVersion()
    {
        if ( file_exists($this->activeFile)
                && ($content = file_get_contents($this->activeFile)) ) {

            return trim($content);
        }

        return '';
    }

    /**
     *
     * @deprecated 4.1.3  This function will be removed in favor of
     *     pre-formatted $this->setShortVersions().
     *
     * @throws LSCMException  Thrown when LSCWP version list cannot be found.
     * @throws LSCMException  Thrown when read LSCWP version list command fails.
     * @throws LSCMException  Thrown when match against LSCWP version list
     *     content fails.
     */
    protected function setKnownVersions()
    {
        if ( !file_exists($this->versionFile) ) {
            throw new LSCMException(
                'Cannot find LSCWP version list.',
                LSCMException::E_NON_FATAL
            );
        }

        if ( ($content = file_get_contents($this->versionFile)) === false ) {
            throw new LSCMException(
                'Failed to read LSCWP version list content.',
                LSCMException::E_NON_FATAL
            );
        }

        if ( preg_match('/old\s{(.*)}/sU', trim($content), $m) != 1 ) {
            throw new LSCMException(
                'Failed to get known versions from LSCWP version list content.',
                LSCMException::E_NON_FATAL
            );
        }

        $this->knownVersions = explode("\n", trim($m[1]));
    }

    /**
     *
     * @throws LSCMException  Thrown when LSCWP version list cannot be found.
     * @throws LSCMException  Thrown when read LSCWP version list command fails.
     * @throws LSCMException  Thrown when LSCWP version list content is empty.
     */
    protected function setAllowedVersions()
    {
        if ( !file_exists($this->versionFile) ) {
            throw new LSCMException(
                'Cannot find LSCWP version list.',
                LSCMException::E_NON_FATAL
            );
        }

        if ( ($content = file_get_contents($this->versionFile)) === false ) {
            throw new LSCMException(
                'Failed to read LSCWP version list content.',
                LSCMException::E_NON_FATAL
            );
        }

        $matchFound = preg_match(
            '/allowed\s{(.*)}/sU',
            trim($content),
            $m
        );

        if ( !$matchFound || ($list = trim($m[1])) == '' ) {
            throw new LSCMException(
                'LSCWP version list is empty.',
                LSCMException::E_NON_FATAL
            );
        }

        $this->allowedVersions = explode("\n", $list);
    }

    /**
     *
     * @since 4.1.3
     *
     * @throws LSCMException  Thrown when LSCWP version list cannot be found.
     * @throws LSCMException  Thrown when read LSCWP version list command fails.
     * @throws LSCMException  Thrown when LSCWP version list content is empty.
     */
    protected function setShortVersions()
    {
        if ( !file_exists($this->versionFile) ) {
            throw new LSCMException(
                'Cannot find LSCWP version list.',
                LSCMException::E_NON_FATAL
            );
        }

        if ( ($content = file_get_contents($this->versionFile)) === false ) {
            throw new LSCMException(
                'Failed to read LSCWP version list content.',
                LSCMException::E_NON_FATAL
            );
        }

        $matchFound = preg_match(
            '/short\s{(.*)}/sU',
            trim($content),
            $m
        );

        if ( !$matchFound || ($list = trim($m[1])) == '' ) {
            throw new LSCMException(
                'LSCWP version list is empty.',
                LSCMException::E_NON_FATAL
            );
        }

        $this->shortVersions = explode("\n", $list);

    }

    /**
     *
     * @param string $version  Valid LSCWP version.
     * @param bool   $init     True when trying to set initial active version.
     *
     * @throws LSCMException  Thrown indirectly by $this->getAllowedVersions()
     *     call.
     * @throws LSCMException  Thrown indirectly by Logger::error() call.
     * @throws LSCMException  Thrown indirectly by $this->downloadVersion()
     *     call.
     * @throws LSCMException  Thrown indirectly by Logger::notice() call.
     */
    public function setActiveVersion( $version, $init = false )
    {
        $allowedVers = $this->getAllowedVersions();

        if ( in_array($version, $allowedVers) ) {
            $activeVer = $version;
        }
        else {

            try {
                $currVer = ($init) ? '' : $this->getCurrentVersion();
            }
            catch ( LSCMException $e ) {
                $currVer = '';
            }

            if ( $currVer != '' ) {
                $activeVer = $currVer;
            }
            else {
                $activeVer = $allowedVers[0];
            }

            Logger::error(
                "Version $version not in allowed list, reset active "
                    . "version to $activeVer."
            );
        }

        if ( $activeVer != $this->getActiveVersion() ) {

            if ( !$this->hasDownloadedVersion($activeVer) ) {
                $this->downloadVersion($activeVer);
            }

            $this->currVersion = $activeVer;
            file_put_contents($this->activeFile, $activeVer);
            Logger::notice("Current active LSCWP version is now $activeVer.");
        }
    }

    /**
     *
     * @param bool $isforced
     *
     * @throws LSCMException  Thrown indirectly by Logger::info() call.
     */
    protected function refreshVersionList( $isforced = false )
    {
        clearstatcache();

        if ( $isforced || !file_exists($this->versionFile)
                || (time() - filemtime($this->versionFile)) > 86400 ) {

            if ( !file_exists(Context::LOCAL_PLUGIN_DIR) ) {
                $this->createDownloadDir();
            }

            $url = 'https://www.litespeedtech.com/packages/lswpcache'
                . '/version_list_v2';

            $content = Util::get_url_contents($url);

            if ( empty($content) || substr($content, 0, 7) != 'allowed' ) {
                /**
                 * Try again using cli curl directly to bypass potential
                 * reCAPTCHA issues.
                 */
                $content = Util::getUrlContentsUsingExecCurl($url);

                if ( empty($content) || substr($content, 0, 7) != 'allowed' ) {
                    touch($this->versionFile);
                    return;
                }
            }

            file_put_contents($this->versionFile, $content);
            Logger::info('LSCache for WordPress version list updated');
        }
    }

    /**
     * Filter out any versionList versions that do not meet specific criteria.
     *
     * @deprecated 4.1.3  No longer used.
     *
     * @param string $ver  Version string.
     *
     * @return bool
     */
    protected function filterVerList( $ver )
    {
        return Util::betterVersionCompare($ver, '1.2.2', '>');
    }

    /**
     * Checks the current installation for existing LSCWP plugin files and
     * copies them to the installation's plugins directory if not found.
     * This function should only be run as the user.
     *
     * @param string $pluginDir  The WordPress plugin directory.
     * @param string $version    The version of LSCWP to be used when copying
     *     over plugin files.
     *
     * @return bool  True when new LSCWP plugin files are used.
     *
     * @throws LSCMException  Thrown when LSCWP source package is not available
     *     for the provided version.
     * @throws LSCMException  Thrown when LSCWP plugin files could not be copied
     *     to plugin directory.
     * @throws LSCMException  Thrown indirectly by self::getInstance() call.
     * @throws LSCMException  Thrown indirectly by
     *     $instance->getCurrentVersion() call.
     * @throws LSCMException  Thrown indirectly by Logger::debug() call.
     */
    public static function prepareUserInstall( $pluginDir, $version = '' )
    {
        $lscwp_plugin = "$pluginDir/litespeed-cache/litespeed-cache.php";

        if ( file_exists($lscwp_plugin) ) {
            /**
             * Existing installation detected.
             */
            return false;
        }

        $instance = self::getInstance();

        if ( $version == '' ) {
            $version = $instance->getCurrentVersion();
        }

        if ( !$instance->hasDownloadedVersion($version) ) {
            throw new LSCMException(
                "Source Package not available for version $version.",
                LSCMException::E_NON_FATAL
            );
        }

        exec(
            '/bin/cp --preserve=mode -rf '
                . Context::LOCAL_PLUGIN_DIR . "/$version/" . self::PLUGIN_NAME
                . " $pluginDir"
        );

        if ( !file_exists($lscwp_plugin) ) {
            throw new LSCMException(
                "Failed to copy plugin files to $pluginDir.",
                LSCMException::E_NON_FATAL
            );
        }

        $customIni = Context::LOCAL_PLUGIN_DIR . '/'
            . self::LSCWP_DEFAULTS_INI_FILE_NAME;

        if ( file_exists($customIni) ) {
            copy(
                $customIni,
                "$pluginDir/litespeed-cache/data/"
                    . self::LSCWP_DEFAULTS_INI_FILE_NAME
            );
        }

        Logger::debug(
            'Copied LSCache for WordPress plugin files into plugins directory '
                . $pluginDir
        );

        return true;
    }

    /**
     *
     * @param string $version
     *
     * @return bool
     */
    protected function hasDownloadedVersion( $version )
    {
        $dir = Context::LOCAL_PLUGIN_DIR . "/$version";
        $md5file = "$dir/" . self::VER_MD5;
        $plugin = "$dir/" . self::PLUGIN_NAME;

        if ( !file_exists($md5file) || !is_dir($plugin) ) {
            return false;
        }

        return ( file_get_contents($md5file) == Util::DirectoryMd5($plugin) );
    }

    /**
     *
     * @param string $version
     * @param string $dir
     * @param bool   $saveMD5
     *
     * @throws LSCMException  Thrown when wget command for downloaded LSCWP
     *     version fails.
     * @throws LSCMException  Thrown when unable to unzip LSCWP zip file.
     * @throws LSCMException  Thrown when unzipped LSCWP files do not contain
     *     expected test file.
     * @throws LSCMException  Thrown indirectly by Logger::info() call.
     * @throws LSCMException  Thrown indirectly by Util::unzipFile() call.
     */
    protected function wgetPlugin( $version, $dir, $saveMD5 = false )
    {
        Logger::info("Downloading LSCache for WordPress v$version...");

        $zipFile = self::PLUGIN_NAME . ".$version.zip";

        exec(
            'wget -q --tries=1 --no-check-certificate '
                . "https://downloads.wordpress.org/plugin/$zipFile -P $dir",
            $output,
            $return_var
        );

        if ( $return_var !== 0 ) {
            throw new LSCMException(
                "Failed to download LSCWP v$version with wget exit status "
                    . "$return_var.",
                LSCMException::E_NON_FATAL
            );
        }

        $localZipFile = "$dir/$zipFile";

        $extractedZip = Util::unzipFile($localZipFile, $dir);
        unlink($localZipFile);

        if ( !$extractedZip ) {
            throw new LSCMException(
                "Unable to unzip $localZipFile",
                LSCMException::E_NON_FATAL
            );
        }

        $plugin = "$dir/" . self::PLUGIN_NAME;

        if ( !file_exists("$plugin/" . self::PLUGIN_NAME . '.php') ) {
            throw new LSCMException(
                "Test file not found. Downloaded LSCWP v$version is invalid.",
                LSCMException::E_NON_FATAL
            );
        }

        if ( $saveMD5 ) {
            file_put_contents(
                "$dir/" . self::VER_MD5,
                Util::DirectoryMd5($plugin)
            );
        }
    }

    /**
     *
     * @param string $version
     *
     * @throws LSCMException  Thrown when download dir could not be created.
     * @throws LSCMException  Thrown indirectly by $this->wgetPlugin() call.
     */
    protected function downloadVersion( $version )
    {
        $dir = Context::LOCAL_PLUGIN_DIR . "/$version";

        if ( !file_exists($dir) ) {

            if ( !mkdir($dir, 0755, true) ) {
                throw new LSCMException(
                    "Failed to create download dir $dir.",
                    LSCMException::E_NON_FATAL
                );
            }
        }
        else {
            exec("/bin/rm -rf $dir/*");
        }

        $this->wgetPlugin($version, $dir, true);
    }

    /**
     *
     * @param string $locale
     * @param string $pluginVer
     *
     * @return bool
     *
     * @throws LSCMException  Thrown indirectly by Logger::info() call.
     * @throws LSCMException  Thrown indirectly by Util::unzipFile() call.
     */
    public static function retrieveTranslation( $locale, $pluginVer )
    {
        Logger::info(
            "Downloading LSCache for WordPress $locale translation..."
        );

        $translationDir =
            Context::LOCAL_PLUGIN_DIR . "/$pluginVer/translations";

        if ( !file_exists($translationDir) ) {
            mkdir($translationDir, 0755);
        }

        touch(
            "$translationDir/" . self::TRANSLATION_CHECK_FLAG_BASE . "_$locale"
        );

        /**
         * downloads.wordpress.org looks to always return a '200 OK' status,
         * even when serving a 404 page. As such invalid downloads can only be
         * checked through user failure to unzip through WP func unzip_file()
         * as we do not assume that root has the ability to unzip.
         */
        exec(
            'wget -q --tries=1 --no-check-certificate '
                . 'https://downloads.wordpress.org/translation/plugin/'
                . "litespeed-cache/$pluginVer/$locale.zip "
                . "-P $translationDir",
            $output,
            $return_var
        );

        if ( $return_var !== 0 ) {
            return false;
        }

        /**
         * The WordPress user can unzip for us if this call fails.
         */
        Util::unzipFile("$translationDir/$locale.zip", $translationDir);

        return true;
    }

    /**
     *
     * @param string $locale
     * @param string $pluginVer
     *
     * @throws LSCMException  Thrown indirectly by Logger::info() call.
     */
    public static function removeTranslationZip( $locale, $pluginVer )
    {
        Logger::info("Removing LSCache for WordPress $locale translation...");

        $zipFile = realpath(
            Context::LOCAL_PLUGIN_DIR . "/$pluginVer/translations/$locale.zip"
        );

        $realPathStart = substr($zipFile, 0, strlen(Context::LOCAL_PLUGIN_DIR));

        if ( $realPathStart === Context::LOCAL_PLUGIN_DIR ) {
            unlink($zipFile);
        }
    }

}
webcachemgr/src/CliController.php000066400000121421150545647710013107 0ustar00<?php

/** ******************************************
 * LiteSpeed Web Server Cache Manager
 *
 * @author Michael Alegre
 * @copyright (c) 2018-2023 LiteSpeed Technologies, Inc.
 * ******************************************* */

namespace Lsc\Wp;

use Exception;
use Lsc\Wp\Context\Context;
use Lsc\Wp\Panel\ControlPanel;
use Lsc\Wp\Panel\CPanel;

class CliController
{

    /**
     * @since 1.13.5
     * @var string
     */
    const SPECIAL_CMD_CPANEL_PLUGIN_AUTOINSTALL_OFF = 'cpanelPluginAutoInstallOff';

    /**
     * @since 1.13.5
     * @var string
     */
    const SPECIAL_CMD_CPANEL_PLUGIN_AUTOINSTALL_ON = 'cpanelPluginAutoInstallOn';

    /**
     * @since 1.13.5
     * @var string
     */
    const SPECIAL_CMD_CPANEL_PLUGIN_AUTOINSTALL_STATUS = 'cpanelPluginAutoInstallStatus';

    /**
     * @since 1.13.5
     * @var string
     */
    const SPECIAL_CMD_CPANEL_PLUGIN_FIX_CONF = 'cpanelPluginFixConf';

    /**
     * @since 1.13.5
     * @var string
     */
    const SPECIAL_CMD_CPANEL_PLUGIN_INSTALL = 'cpanelPluginInstall';

    /**
     * @since 1.13.5
     * @var string
     */
    const SPECIAL_CMD_CPANEL_PLUGIN_UNINSTALL = 'cpanelPluginUninstall';

    /**
     * @var string[]
     */
    private $cacheRootCmds = array();

    /**
     * @var string[]
     */
    private $commands = array();

    /**
     * @var string
     */
    private $svrCacheRootParam = '';

    /**
     * @var string
     */
    private $vhCacheRootParam = '';

    /**
     * @var bool
     */
    private $displayCacheRoots = false;

    /**
     * @var null|string
     */
    private $currWpPath;

    /**
     * @var null|string
     */
    private $versionCmd;

    /**
     * @var null|string
     */
    private $specialCmd;

    /**
     * Holds any additional command input for use after parseCommands().
     *
     * @var null|array
     */
    private $input;

    /**
     *
     * @throws LSCMException  Thrown when script argument count is less than
     *     expected.
     */
    public function __construct()
    {
        if ( empty($_SERVER['argv']) || $_SERVER['argc'] < 3 ) {
            throw new LSCMException('Cli Illegal entrance!');
        }

        $args = $_SERVER['argv'];

        /**
         * shift out script name
         */
        array_shift($args);

        $this->parseCommands($args);
    }

    /**
     * Checks if current $wpInstallStorage object is capable of having the
     * given non-scan action performed.
     *
     * @param string           $action
     * @param WPInstallStorage $wpInstallStorage
     *
     * @return void
     *
     * @throws LSCMException  Thrown when scan data cannot be read.
     * @throws LSCMException  Thrown when expected scan data format has changed.
     * @throws LSCMException  Thrown when attempting to execute a "mass"
     *     operation without any discovered installations.
     */
    private function checkDataFile(
                         $action,
        WPInstallStorage $wpInstallStorage )
    {
        if ( $action == WPInstallStorage::CMD_SCAN2 ) {

            /**
             * Always allowed.
             */
            return;
        }

        if ( ($err = $wpInstallStorage->getError()) ) {

            switch ($err) {

                case WPInstallStorage::ERR_NOT_EXIST:
                case WPInstallStorage::ERR_CORRUPTED:
                case WPInstallStorage::ERR_VERSION_HIGH:
                    throw new LSCMException(
                        'Scan data could not be read! Please scan again '
                            . '(without the \'-n\' flag) before attempting any '
                            . "cache operations.\n"
                    );

                case WPInstallStorage::ERR_VERSION_LOW:
                    throw new LSCMException(
                        'Scan data file format has been changed for this '
                            . 'version. Please scan again (without the \'-n\' '
                            . "flag) before attempting any cache operations.\n"
                    );

                //no default
            }
        }
        elseif ( strpos($action,'mass_') === 0
                && $wpInstallStorage->getCount() == 0 ) {

            throw new LSCMException(
                'No WordPress installations discovered in the previous scan. '
                    . 'If you have any newly installed WordPress '
                    . 'installations, please scan again or add them with '
                    . "command 'addinstalls'.\n"
            );
        }
    }

    /**
     *
     * @param WPInstall $wpInstall
     */
    private function printStatusMsg( WPInstall $wpInstall )
    {
        $msg = "$this->currWpPath - Status: ";

        $status = $wpInstall->getStatus();

        if ( $status & WPInstall::ST_PLUGIN_ACTIVE ) {
            $msg .= 'enabled';

            if ( !$status & WPInstall::ST_LSC_ADVCACHE_DEFINED ) {
                $msg .= ', not caching';
            }
        }
        else {
            $msg .= 'disabled';
        }

        $msg .= ' | Flagged: ';
        $msg .= ($status & WPInstall::ST_FLAGGED) ? 'yes' : 'no';

        $msg .= ' | Error: ';

        if ( $status & WPInstall::ST_ERR_SITEURL ) {
            $msg .= 'Could not retrieve WordPress siteURL.';
        }
        elseif ( $status & WPInstall::ST_ERR_DOCROOT ) {
            $msg .= 'Could not match WordPress siteURL to a known control '
                . 'panel docroot.';
        }
        elseif ( $status & WPInstall::ST_ERR_EXECMD ) {
            $msg .= 'WordPress fatal error encountered during action '
                . 'execution. This is most likely caused by custom code in '
                . 'this WordPress installation.';
        }
        elseif ( $status & WPInstall::ST_ERR_EXECMD_DB ) {
            $msg .= 'Error establishing WordPress database connection.';
        }
        elseif ( $status & WPInstall::ST_ERR_TIMEOUT ) {
            $msg .= 'Timeout occurred during action execution.';
        }
        elseif ( $status & WPInstall::ST_ERR_WPCONFIG ) {
            $msg .= 'Could not find a valid wp-config.php file.';
        }

        echo "$msg\n\n";
    }

    /**
     *
     * @param string[] $args
     *
     * @return void
     *
     * @throws LSCMException  Thrown when -svr parameter is passed without a
     *     value.
     * @throws LSCMException  Thrown when -svr parameter value points to a
     *     non-empty directory.
     * @throws LSCMException  Thrown when -vh parameter is passed without a
     *     value.
     * @throws LSCMException  Thrown when -vh parameter value contains invalid
     *     character '$'.
     * @throws LSCMException  Thrown when -vh parameter value points to a
     *     non-empty directory.
     * @throws LSCMException  Thrown indirectly by
     *     ControlPanel::getClassInstance() call.
     * @throws LSCMException  Thrown indirectly by
     *     $controlPanel->getServerCacheRoot() call.
     * @throws LSCMException  Thrown indirectly by
     *     $controlPanel->getVHCacheRoot() call.
     */
    private function handleSetCacheRootInput( array &$args )
    {
        if ( empty($args) ) {
            $this->cacheRootCmds[] = 'listCacheRoots';
            return;
        }

        $controlPanel = ControlPanel::getClassInstance();

        if ( ($key = array_search('-svr', $args)) !== false ) {

            if ( empty($args[$key + 1])
                    || ($this->svrCacheRootParam = trim($args[$key + 1])) == '' ) {

                throw new LSCMException(
                    'Invalid Command, missing server cache root value.'
                );
            }

            $currSvrCacheRoot = $controlPanel->getServerCacheRoot();

            if ( $this->svrCacheRootParam != $currSvrCacheRoot ) {

                if ( !Util::is_dir_empty($this->svrCacheRootParam) ) {
                    throw new LSCMException(
                        'Provided server level cache root must be an empty '
                            . 'directory.'
                    );
                }

                $this->cacheRootCmds[] = 'setSvrCacheRoot';
            }

            unset($args[$key], $args[$key + 1]);
        }

        if ( ($key = array_search('-vh', $args)) !== false ) {
            $setvhCacheRoot = false;

            if ( empty($args[$key + 1])
                    || ($this->vhCacheRootParam = trim($args[$key + 1])) == '' ) {

                throw new LSCMException(
                    'Invalid Command, missing virtual host cache root value.'
                );
            }

            if ( strpos($this->vhCacheRootParam, '$') !== false ) {
                throw new LSCMException(
                    'Invalid Command, virtual host cache root value cannot '
                        . 'contain any \'$\' characters. \'$vh_user\' will be '
                        . 'automatically added to the end of virtual host '
                        . 'cache root values starting with a \'/\'.'
                );
            }

            $currVHCacheRoot = $controlPanel->getVHCacheRoot();

            if ( $this->vhCacheRootParam[0] == '/' ) {
                $updatedVhCacheRoot =
                    rtrim($this->vhCacheRootParam, '/') . '/$vh_user';

                if ( $updatedVhCacheRoot != $currVHCacheRoot
                        && ! Util::is_dir_empty($this->vhCacheRootParam) ) {

                    throw new LSCMException(
                        'Provided absolute path for virtual host level cache '
                            . 'root must be an empty directory.'
                    );
                }

                $this->vhCacheRootParam = $updatedVhCacheRoot;
                $setvhCacheRoot = true;
            }
            elseif ( $this->vhCacheRootParam != $currVHCacheRoot ) {
                $setvhCacheRoot = true;
            }

            unset($args[$key], $args[$key + 1]);

            if ( $setvhCacheRoot ) {
                $this->cacheRootCmds[] = 'setVHCacheRoot';
            }
        }
    }

    /**
     *
     * @param string[] $args
     *
     * @return void
     *
     * @throws LSCMException  Thrown when passed version set value is invalid.
     */
    private function handleSetVersionInput( array &$args )
    {
        if ( ($key = array_search('--list', $args)) !== false ) {
            unset($args[$key]);
            $this->versionCmd = 'list';
            return;
        }

        if ( ($key = array_search('--latest', $args)) !== false ) {
            unset($args[$key]);
            $this->versionCmd = 'latest';
            return;
        }

        if ( empty($args) ) {
            $this->versionCmd = 'active';
            return;
        }

        $v = array_shift($args);

        if ( preg_match('/[1-9]\.\d(?:\.\d)*(?:\.\d)*/', $v) !== 1 ) {
            throw new LSCMException("Invalid version number ($v).");
        }

        $this->versionCmd = $v;
    }

    /**
     *
     * @param string[] $args
     */
    private function handleScanInput( array &$args )
    {
        if ( ($key = array_search('-n', $args)) !== false ) {
            unset($args[$key]);
            $this->commands[] = WPInstallStorage::CMD_DISCOVER_NEW2;
        }
        else {
            $this->commands[] = WPInstallStorage::CMD_SCAN2;
        }

        if ( ($key = array_search('-e', $args)) !== false ) {
            unset($args[$key]);
            $this->commands[] = UserCommand::CMD_MASS_ENABLE;
        }
    }

    /**
     *
     * @param string[] $args
     */
    private function handleScanNewInput( array &$args )
    {
        if ( ($key = array_search('-en', $args)) !== false ) {
            unset($args[$key]);
            $this->commands[] = WPInstallStorage::CMD_DISCOVER_NEW_AND_ENABLE;
        }
        else {
            $this->commands[] = WPInstallStorage::CMD_DISCOVER_NEW2;
        }
    }

    /**
     *
     * @param string[] $args
     *
     * @return bool
     */
    private function isMassOperation( array &$args )
    {
        if ( ($key = array_search('-m', $args)) !== false ) {
            unset($args[$key]);
            return true;
        }

        return false;
    }

    /**
     *
     * @param string   $cmd
     * @param string[] $args
     *
     * @throws LSCMException  Thrown when expected WP path value is not
     *     provided.
     * @throws LSCMException  Thrown when provided an invalid WP path value.
     */
    private function handleSingleOperationInput( $cmd, array &$args )
    {
        $path = array_shift($args);

        if ( $path == null ) {
            throw new LSCMException('Invalid Command, missing WP path.');
        }

        $wpInstall = new WPInstall($path);

        if ( !$wpInstall->hasValidPath() ) {
            throw new LSCMException("Invalid WP Path: $path.");
        }

        $this->commands[] = $cmd;
        $this->currWpPath = rtrim($path, '/');
    }

    /**
     *
     * @param string   $cmdType
     * @param string[] $args
     *
     * @throws LSCMException  Thrown when neither -m nor -wppath parameters are
     *     provided in notify command.
     * @throws LSCMException  Thrown when -wppath parameter is passed without a
     *     value in notify command.
     * @throws LSCMException  Thrown when provided -wppath parameter value is
     *     invalid in notify command.
     * @throws LSCMException  Thrown when -msgfile parameter is passed without a
     *     value in notify command.
     * @throws LSCMException  Thrown when provided -msgfile parameter value
     *     points to a non-existent file in notify command.
     * @throws LSCMException  Thrown when unable to get file contents of the
     *     file pointed to by provided -msgfile value in notify command.
     * @throws LSCMException  Thrown when neither -msgfile nor -msg parameters
     *     are provided in notify command.
     * @throws LSCMException  Thrown when parameter -msg is passed without a
     *     value in notify command.
     * @throws LSCMException  Thrown when expected -plugin parameter is not
     *     provided in notify command.
     * @throws LSCMException  Thrown when provided -plugin parameter value does
     *     not a known plugin slug in notify command.
     * @throws LSCMException  Thrown when neither -m flag nor WP path value are
     *     provided in remove command.
     * @throws LSCMException  Thrown when provided WP path value is invalid in
     *     remove command.
     */
    private function handleDashNotifyInput( $cmdType, array &$args )
    {
        if ( $cmdType == 'notify' ) {

            if ( ($key = array_search('-m', $args)) !== false ) {
                unset($args[$key]);
                $this->commands[] = UserCommand::CMD_MASS_DASH_NOTIFY;
            }
            else {

                if ( ($key = array_search('-wppath', $args)) === false ) {
                    throw new LSCMException(
                        'Invalid Command, missing required \'-m\' or '
                            . '\'-wppath\' parameter.'
                    );
                }

                if ( empty($args[$key + 1]) ) {
                    throw new LSCMException(
                        'Invalid Command, missing \'-wppath\' value.'
                    );
                }

                $path = $args[$key + 1];

                $wpInstall = new WPInstall($path);

                if ( !$wpInstall->hasValidPath() ) {
                    throw new LSCMException("Invalid WP Path: $path.");
                }

                $this->commands[] = UserCommand::CMD_DASH_NOTIFY;
                $this->currWpPath = rtrim($path, '/');

                unset($args[$key], $args[$key + 1]);
            }

            if ( ($key = array_search('-msgfile', $args)) !== false ) {

                if ( empty($args[$key + 1]) ) {
                    throw new LSCMException(
                        'Invalid Command, missing \'-msgfile\' value.'
                    );
                }

                $msgFilePath = $args[$key + 1];

                if ( !file_exists($msgFilePath) ) {
                    throw new LSCMException(
                        'Provided message file does not exist.'
                    );
                }

                if ( ($message = file_get_contents($msgFilePath)) === false ) {
                    throw new LSCMException(
                        'Unable to retrieve provided message file content.'
                    );
                }
            }
            else {

                if ( ($key = array_search('-msg', $args)) === false ) {
                    throw new LSCMException(
                        'Invalid Command, missing required \'-msgfile\' or '
                            . '\'-msg\' parameter.'
                    );
                }

                if ( empty($args[$key + 1]) ) {
                    throw new LSCMException(
                        'Invalid Command, missing \'-msg\' value.'
                    );
                }

                $message = $args[$key + 1];
            }

            $dashInput = array( 'msg' => $message );

            unset($args[$key], $args[$key + 1]);

            if ( ($key = array_search('-plugin', $args)) !== false ) {

                if ( empty($args[$key + 1]) ) {
                    throw new LSCMException(
                        'Invalid Command, missing \'-plugin\' value.'
                    );
                }

                $slug = $args[$key + 1];

                $pluginInfoJSON = Util::get_url_contents(
                    "https://api.wordpress.org/plugins/info/1.0/$slug.json"
                );

                $pluginInfo = json_decode($pluginInfoJSON, true);

                if ( empty($pluginInfo['name']) ) {
                    throw new LSCMException(
                        'Could not find a plugin matching the provided plugin '
                            . 'slug.'
                    );
                }

                $dashInput['slug'] = $slug;

                unset($args[$key], $args[$key + 1]);
            }

            $this->input = $dashInput;
        }
        elseif ( $cmdType == 'remove' ) {
            $arg1 = array_shift($args);

            if ( $arg1 == '-m' ) {
                $this->commands[] = UserCommand::CMD_MASS_DASH_DISABLE;
            }
            else {
                $path = $arg1;

                if ( $path == null ) {
                    throw new LSCMException(
                        'Invalid Command, missing \'-m\' flag or WP path value.'
                    );
                }

                $wpInstall = new WPInstall($path);

                if ( !$wpInstall->hasValidPath() ) {
                    throw new LSCMException("Invalid WP Path: $path.");
                }

                $this->commands[] = UserCommand::CMD_DASH_DISABLE;
                $this->currWpPath = rtrim($path, '/');
            }
        }
    }

    /**
     *
     * @param string[] $args
     *
     * @throws LSCMException  Thrown when command 'cpanelplugin' is used in a
     *     non-cPanel environment.
     * @throws LSCMException  Thrown indirectly by
     *     ControlPanel::getClassInstance() call.
     */
    private function handleCpanelPluginInput( array &$args )
    {
        $controlPanel = ControlPanel::getClassInstance();

        if ( !($controlPanel instanceof CPanel) ) {
            throw new LSCMException(
                'Command \'cpanelplugin\' cannot be used in a non-cPanel '
                    . 'environment.'
            );
        }

        switch ($args[0]) {

            case '--install':
                $this->specialCmd = self::SPECIAL_CMD_CPANEL_PLUGIN_INSTALL;
                unset($args[0]);
                break;

            case '--uninstall':
                $this->specialCmd = self::SPECIAL_CMD_CPANEL_PLUGIN_UNINSTALL;
                unset($args[0]);
                break;

            case '-autoinstall':

                if ( !isset($args[1]) ) {
                    $this->specialCmd =
                        self::SPECIAL_CMD_CPANEL_PLUGIN_AUTOINSTALL_STATUS;
                }
                elseif ( "$args[1]" === '1' ) {
                    $this->specialCmd =
                        self::SPECIAL_CMD_CPANEL_PLUGIN_AUTOINSTALL_ON;
                    unset($args[1]);
                }
                elseif ( "$args[1]" === '0' ) {
                    $this->specialCmd =
                        self::SPECIAL_CMD_CPANEL_PLUGIN_AUTOINSTALL_OFF;
                    unset($args[1]);
                }

                unset($args[0]);
                break;

            case '--fixconf':
                $this->specialCmd = self::SPECIAL_CMD_CPANEL_PLUGIN_FIX_CONF;
                unset($args[0]);
                break;

            //no default
        }
    }

    /**
     *
     * @param string[] $args
     *
     * @throws LSCMException  Thrown when -wpinstall parameter is passed without
     *     a value.
     * @throws LSCMException  Thrown when expected 'docroot' value is not
     *     provided when using parameter -wpinstall.
     * @throws LSCMException  Thrown when expected 'server name' value is not
     *     provided when using parameter -wpinstall.
     * @throws LSCMException  Thrown when expected 'site url' value is not
     *     provided when using parameter -wpinstall.
     * @throws LSCMException  Thrown when -wpinstallsfile parameter is passed
     *     without a value.
     * @throws LSCMException  Thrown when provided -wpinstallsfile parameter
     *     value points to a non-existent file.
     * @throws LSCMException  Thrown when unable to get file contents of the
     *     file pointed to by provided -wpinstallsfile parameter value.
     */
    private function handleAddInstallsInput( array &$args )
    {
        switch ($args[0]) {

            case '-wpinstall':

                if ( empty($args[1]) ) {
                    throw new LSCMException(
                        'Invalid Command, missing \'<wp path>\' value.'
                    );
                }

                $wpInstallsInfo = "$args[1]";

                if ( empty($args[2]) ) {
                    throw new LSCMException(
                        'Invalid Command, missing \'<docroot>\' value.'
                    );
                }

                $wpInstallsInfo .= " $args[2]";

                if ( empty($args[3]) ) {
                    throw new LSCMException(
                        'Invalid Command, missing \'<server name>\' value.'
                    );
                }

                $wpInstallsInfo .= " $args[3]";

                if ( empty($args[4]) ) {
                    throw new LSCMException(
                        'Invalid Command, missing \'<site url>\' value.'
                    );
                }

                $wpInstallsInfo .= " $args[4]";

                $this->commands[] = WPInstallStorage::CMD_ADD_CUST_WPINSTALLS;

                $this->input =
                    array( 'addInstallsInfo' => array($wpInstallsInfo) );

                unset($args[0], $args[1], $args[2], $args[3], $args[4]);
                break;

            case '-wpinstallsfile':

                if ( empty($args[1]) ) {
                    throw new LSCMException(
                        'Invalid Command, missing \'-wpinstallsfile\' value.'
                    );
                }

                $wpInstallsFile = $args[1];

                if ( !file_exists($wpInstallsFile) ) {
                    throw new LSCMException(
                        'Provided wpinstalls file does not exist.'
                    );
                }

                $fileContent = file_get_contents($wpInstallsFile);

                if ( $fileContent === false ) {
                    throw new LSCMException(
                        'Could not read wpinstalls file content.'
                    );
                }

                $this->commands[] = WPInstallStorage::CMD_ADD_CUST_WPINSTALLS;

                $this->input = array(
                    'addInstallsInfo' => explode("\n", trim($fileContent))
                );

                unset($args[0], $args[1]);
                break;

            // no default
        }
    }

    /**
     *
     * @throws LSCMException  Thrown indirectly by
     *     ControlPanel::getClassInstance() call.
     * @throws LSCMException  Thrown indirectly by
     *     $controlPanel->getServerCacheRoot() call.
     * @throws LSCMException  Thrown indirectly by
     *     $controlPanel->getVHCacheRoot() call.
     */
    private function displayCacheRoots()
    {
       $controlPanel = ControlPanel::getClassInstance();

       $svrCacheRoot = $controlPanel->getServerCacheRoot();
       $vhCacheRoot = $controlPanel->getVHCacheRoot();

       if ( $svrCacheRoot == ControlPanel::NOT_SET ) {
           $svrCacheRoot = 'Not Set';
       }

       if ( $vhCacheRoot == ControlPanel::NOT_SET) {
           $vhCacheRoot = 'Not Set';
       }

       echo <<<EOF

Server Cache Root:        $svrCacheRoot
Virtual Host Cache Root:  $vhCacheRoot


EOF;
    }

    /**
     *
     * @param string[] $args
     *
     * @throws LSCMException  Thrown when command setcacheroot is used in the
     *     CustomPanel context.
     * @throws LSCMException  Thrown when an unrecognized command is provided.
     * @throws LSCMException  Thrown when not all provided command arguments are
     *     recognized or used when provided with a valid command.
     * @throws LSCMException  Thrown indirectly by
     *     ControlPanel::getClassInstance() call.
     * @throws LSCMException  Thrown indirectly by
     *     $this->handleSetCacheRootInput() call.
     * @throws LSCMException  Thrown indirectly by
     *     $this->handleSetVersionInput() call.
     * @throws LSCMException  Thrown indirectly by
     *     $this->handleSingleOperationInput() call.
     * @throws LSCMException  Thrown indirectly by
     *     $this->handleDashNotifyInput() call.
     * @throws LSCMException  Thrown indirectly by
     *     $this->handleDashNotifyInput() call.
     * @throws LSCMException  Thrown indirectly by
     *     $this->handleCpanelPluginInput() call.
     * @throws LSCMException  Thrown indirectly by
     *     $this->handleAddInstallsInput() call.
     */
    private function parseCommands( array $args )
    {
        $panelClassName = array_shift($args);

        /**
         * Initialize ControlPanel instance.
         */
        ControlPanel::getClassInstance($panelClassName);

        $cmd = array_shift($args);

        switch ( $cmd ) {

            case 'setcacheroot':

                if ( $panelClassName == 'custom' ) {
                    throw new LSCMException(
                        'Command \'setcacheroot\' cannot be used in the '
                            . 'CustomPanel context.'
                    );
                }

                $this->handleSetCacheRootInput($args);
                break;

            case 'setversion':
                $this->handleSetVersionInput($args);
                break;

            case 'scan':
                $this->handleScanInput($args);
                break;

            case 'scannew':
                $this->handleScanNewInput($args);
                break;

            case 'enable':
            case 'disable':
            case 'upgrade':
            /** @noinspection PhpMissingBreakStatementInspection */
            case 'unflag':

                if ( $this->isMassOperation($args) ) {
                    $this->commands[] = "mass_$cmd";
                    break;
                }

            //fall through

            case 'flag':
            case 'status':
                $this->handleSingleOperationInput($cmd, $args);
                break;

            case 'dashnotify':
                $this->handleDashNotifyInput('notify', $args);
                break;

            case 'dashnotifyremove':
                $this->handleDashNotifyInput('remove', $args);
                break;

            case 'cpanelplugin':
                $this->handleCpanelPluginInput($args);
                break;

            case 'addinstalls':
                $this->handleAddInstallsInput($args);
                break;

            default:
                throw new LSCMException('Invalid Command, Try --help.');
        }

        if ( !empty($args) ) {
            throw new LSCMException('Invalid Command, Try --help.');
        }
    }

    /**
     *
     * @param string $action
     *
     * @throws LSCMException  Thrown indirectly by
     *     ControlPanel::getClassInstance() call.
     * @throws LSCMException  Thrown indirectly by
     *     $controlPanel->setServerCacheRoot() call.
     * @throws LSCMException  Thrown indirectly by
     *     $controlPanel->setVHCacheRoot() call.
     * @throws LSCMException  Thrown indirectly by Util::restartLsws() call.
     * @throws LSCMException  Thrown indirectly by
     *     $controlPanel->getVHCacheRoot() call.
     */
    private function doCacheRootCommand( $action )
    {
        $restartRequired = false;

        $controlPanel = ControlPanel::getClassInstance();

        switch ( $action ) {

            case 'setSvrCacheRoot':
                $controlPanel->setServerCacheRoot($this->svrCacheRootParam);
                $restartRequired = true;
                break;

            case 'setVHCacheRoot':
                $controlPanel->setVHCacheRoot($this->vhCacheRootParam);
                $restartRequired = true;
                break;

            case 'listCacheRoots':
                /**
                 * Wait until after verifyCacheSetup() has been run.
                 */
                $this->displayCacheRoots = true;
                break;

            //no default
        }

        if ( $restartRequired ) {
            Util::restartLsws();
        }

        Util::ensureVHCacheRootInCage($controlPanel->getVHCacheRoot());
    }

    /**
     *
     * @throws LSCMException  Thrown indirectly by
     *     ControlPanel::getClassInstance() call.
     * @throws LSCMException  Thrown indirectly by
     *     $controlPanel->installCpanelPlugin() call.
     * @throws LSCMException  Thrown indirectly by
     *     CPanel::uninstallCpanelPlugin() call.
     * @throws LSCMException  Thrown indirectly by
     *     $controlPanel->updateCoreCpanelPluginConfSettings() call.
     */
    private function doSpecialCommand()
    {
        $controlPanel = ControlPanel::getClassInstance();

        switch($this->specialCmd) {

            case self::SPECIAL_CMD_CPANEL_PLUGIN_INSTALL:
                /* @var $controlPanel CPanel */

                switch ( $controlPanel->installCpanelPlugin() ) {

                    case 'update':
                        echo 'Updated LiteSpeed cPanel plugin to current '
                            . "version\n\n";
                        break;

                    case 'new':
                        echo 'LiteSpeed cPanel plugin installed, auto install '
                            . "turned on.\n\n";
                        break;

                    //no default
                }

                break;

            case self::SPECIAL_CMD_CPANEL_PLUGIN_UNINSTALL:
                CPanel::uninstallCpanelPlugin();

                echo 'LiteSpeed cPanel plugin uninstalled successfully, auto '
                    . "install turned off.\n\n";
                break;

            case self::SPECIAL_CMD_CPANEL_PLUGIN_AUTOINSTALL_STATUS:
                $state = (CPanel::isCpanelPluginAutoInstallOn()) ? 'On' : 'Off';

                echo "Auto install is currently $state for the LiteSpeed "
                    . "cPanel plugin.\n";
                echo 'Use command \'cpanelplugin -autoinstall {0 | 1}\' to '
                    . "turn auto install off/on respectively.\n\n";
                break;

            case self::SPECIAL_CMD_CPANEL_PLUGIN_AUTOINSTALL_ON:

                if ( CPanel::turnOnCpanelPluginAutoInstall() ) {
                    echo 'Auto install is now On for LiteSpeed cPanel plugin.'
                        . "\n\n";
                }
                else {
                    echo 'Failed to turn off auto install for LiteSpeed cPanel '
                        . "plugin.\n\n";
                }

                break;

            case self::SPECIAL_CMD_CPANEL_PLUGIN_AUTOINSTALL_OFF:

                if ( CPanel::turnOffCpanelPluginAutoInstall() ) {
                    echo 'Auto install is now Off for LiteSpeed cPanel plugin.'
                        . "\n\n";
                }
                else {
                    echo 'Failed to turn on auto install for LiteSpeed cPanel '
                        . "plugin.\n\n";
                }

                break;

            case self::SPECIAL_CMD_CPANEL_PLUGIN_FIX_CONF:
                /* @var $controlPanel CPanel */
                $controlPanel->updateCoreCpanelPluginConfSettings();

                echo "Attempted to fix user-end cPanel Plugin conf.\n\n";
                break;

            //no default
        }
    }

    /**
     *
     * @throws LSCMException  Thrown indirectly by PluginVersion::getInstance()
     *     call.
     * @throws LSCMException  Thrown indirectly by
     *     $pluginVerInstance->getAllowedVersions() call.
     * @throws LSCMException  Thrown indirectly by
     *     $pluginVerInstance->getLatestVersion() call.
     * @throws LSCMException  Thrown indirectly by
     *     $pluginVerInstance->setActiveVersion() call.
     * @throws LSCMException  Thrown indirectly by
     *     $pluginVerInstance->getCurrentVersion() call.
     * @throws LSCMException  Thrown indirectly by
     *     $pluginVerInstance->setActiveVersion() call.
     */
    private function doVersionCommand()
    {
        $pluginVerInstance = PluginVersion::getInstance();

        switch ( $this->versionCmd ) {

            case 'list':

                echo "Available versions are: \n"
                    . implode("\n",$pluginVerInstance->getAllowedVersions())
                    . "\n";
                break;

            case 'latest':
                $latest = $pluginVerInstance->getLatestVersion();

                try {
                    $currVer = $pluginVerInstance->getCurrentVersion();
                }
                catch ( LSCMException $e ) {
                    $currVer = '';
                }

                if ( $latest == $currVer ) {
                    echo "Current version, $latest, is already the latest "
                        . "version.\n";
                }
                else {
                    $pluginVerInstance->setActiveVersion($latest);
                }

                break;

            case 'active':

                echo "Current active version is "
                    . $pluginVerInstance->getCurrentVersion()
                    .  ".\n";
                break;

            default:
                $pluginVerInstance->setActiveVersion($this->versionCmd);
        }
    }

    /**
     *
     * @throws LSCMException  Thrown indirectly by Context::getLSCMDataFiles()
     *     call.
     * @throws LSCMException  Thrown indirectly by "new WPInstallStorage()"
     *     call.
     * @throws LSCMException  Thrown indirectly by $this->checkDataFile() call.
     * @throws LSCMException  Thrown indirectly by PluginVersion::getInstance()
     *     call.
     * @throws LSCMException  Thrown indirectly by
     *     $pluginVerInstance->getShortVersions() call.
     * @throws LSCMException  Thrown indirectly by
     *     $pluginVerInstance->getCurrentVersion() call.
     * @throws LSCMException  Thrown indirectly by
     *     DashNotifier::prepLocalDashPluginFiles() call.
     * @throws LSCMException  Thrown indirectly by
     *     ControlPanel::getClassInstance() call.
     * @throws LSCMException  Thrown indirectly by
     *     ControlPanel::getClassInstance()->getDocRoots() call.
     * @throws LSCMException  Thrown indirectly by $wpInstallStorage->scan2()
     *     call.
     * @throws LSCMException  Thrown indirectly by $wpInstallStorage->doAction()
     *     call.
     */
    private function doWPInstallStorageAction()
    {
        $extraArgs = array();
        $list = null;
        $originalAction = null;

        $lscmDataFiles = Context::getLSCMDataFiles();

        $wpInstallStorage = new WPInstallStorage(
            $lscmDataFiles['dataFile'],
            $lscmDataFiles['custDataFile']
        );

        if ( $this->currWpPath ) {
            $list = array( $this->currWpPath );
        }

        foreach ( $this->commands as $action ) {
            $this->checkDataFile($action, $wpInstallStorage);

            echo "\nPerforming $action operation. Please be patient...\n\n";

            switch ( $action ) {

                case UserCommand::CMD_UPGRADE:
                case UserCommand::CMD_MASS_UPGRADE:
                    $pluginVerInstance = PluginVersion::getInstance();

                    $extraArgs[] = implode(
                        ',',
                        $pluginVerInstance->getShortVersions()
                    );
                    $extraArgs[] = $pluginVerInstance->getCurrentVersion();

                    break;

                case UserCommand::CMD_DASH_NOTIFY:
                case UserCommand::CMD_MASS_DASH_NOTIFY:
                    DashNotifier::prepLocalDashPluginFiles();

                    $slug = '';

                    if ( isset($this->input['slug']) ) {
                        $slug = $this->input['slug'];
                    }

                    $msgInfoJSON = json_encode(
                        array(
                            'msg' => $this->input['msg'],
                            'plugin' => $slug,
                            'plugin_name' => ''
                        )
                    );

                    $extraArgs[] = base64_encode($msgInfoJSON);

                    break;

                case WPInstallStorage::CMD_ADD_CUST_WPINSTALLS:
                    $list = array();
                    $extraArgs[] = $this->input['addInstallsInfo'];

                    break;

                case WPInstallStorage::CMD_SCAN2:
                case WPInstallStorage::CMD_DISCOVER_NEW2:
                case WPInstallStorage::CMD_DISCOVER_NEW_AND_ENABLE:
                    $wpPaths = array();
                    $docroots = ControlPanel::getClassInstance()->getDocRoots();

                    foreach ( $docroots as $docroot ) {
                        $wpPaths = array_merge(
                            $wpPaths,
                            WPInstallStorage::scan2($docroot)
                        );
                    }

                    $list = array();

                    if ( $action == WPInstallStorage::CMD_DISCOVER_NEW2
                            || $action == WPInstallStorage::CMD_DISCOVER_NEW_AND_ENABLE ) {

                        foreach( $wpPaths as $wpPath ) {

                            if ( $wpInstallStorage->getWPInstall($wpPath) == null ) {
                                $list[] = $wpPath;
                            }
                        }
                    }
                    else {
                        $list = array_merge($list, $wpPaths);
                    }

                    $originalAction = $action;
                    $action = WPInstallStorage::CMD_ADD_NEW_WPINSTALL;

                    break;

                // no default case
            }

            $wpInstallStorage->doAction($action, $list, $extraArgs);

            if ( $originalAction == WPInstallStorage::CMD_DISCOVER_NEW_AND_ENABLE ) {
                $wpInstallStorage->doAction(
                    UserCommand::CMD_MASS_ENABLE,
                    $list
                );
            }

            if ( $action == UserCommand::CMD_STATUS ) {
                $wpInstall = $wpInstallStorage->getWPInstall($this->currWpPath);

                $this->printStatusMsg($wpInstall);
            }

            if ( $originalAction != null ) {
                $action = $originalAction;
            }

            echo "\n$action complete!\n\n";
        }
    }

    /**
     *
     * @throws LSCMException  Thrown indirectly by $this->doCacheRootCommand()
     *     call.
     * @throws LSCMException  Thrown indirectly by
     *     ControlPanel::getClassInstance() call.
     * @throws LSCMException  Thrown indirectly by
     *     $controlPanel->verifyCacheSetup() call.
     * @throws LSCMException  Thrown indirectly by $this->displayCacheRoots()
     *     call.
     * @throws LSCMException  Thrown indirectly by $this->doSpecialCommand()
     *     call.
     * @throws LSCMException  Thrown indirectly by $this->doVersionCommand()
     *     call.
     * @throws LSCMException  Thrown indirectly by
     *     $this->doWPInstallStorageAction() call.
     */
    private function runCommand()
    {
        foreach ( $this->cacheRootCmds as $action ) {
            $this->doCacheRootCommand($action);
        }

        $controlPanel = ControlPanel::getClassInstance();
        $controlPanel->verifyCacheSetup();

        if ( $this->displayCacheRoots ) {
            $this->displayCacheRoots();
        }

        if ( $this->specialCmd ) {
            $this->doSpecialCommand();
        }
        elseif ( $this->versionCmd ) {
            $this->doVersionCommand();
        }
        else {
            $this->doWPInstallStorageAction();
        }
    }

    public static function run()
    {
        try {
            $cli = new self();
            $cli->runCommand();
        }
        catch ( Exception $e ) {
            echo "[ERROR] {$e->getMessage()}\n\n";
            exit(1);
        }
    }

}
webcachemgr/src/Context/RootCLIContextOption.php000066400000001633150545647710015773 0ustar00<?php

/** ******************************************
 * LiteSpeed Web Server Cache Manager
 *
 * @author LiteSpeed Technologies, Inc. (https://www.litespeedtech.com)
 * @copyright (c) 2018
 * ******************************************* */

namespace Lsc\Wp\Context;

use \Lsc\Wp\Context\ContextOption;
use \Lsc\Wp\Logger;

class RootCLIContextOption extends ContextOption
{

    public function __construct()
    {
        $invokerName = 'lscmctl';
        $invokerType = parent::FROM_CLI;
        $isRoot = parent::IS_ROOT;
        $logFileLvl = Logger::L_DEBUG;//Logger::L_INFO;
        $logEchoLvl = Logger::L_INFO;
        $bufferedWrite = true;
        $bufferedEcho = false;
        parent::__construct($invokerName, $invokerType, $isRoot, $logFileLvl,
                $logEchoLvl, $bufferedWrite, $bufferedEcho);
        $this->scanDepth = 2;
        $this->batchTimeout = 0;
        $this->batchSize = 0;
    }

}
webcachemgr/src/Context/UserCLIContextOption.php000066400000002077150545647710015771 0ustar00<?php

/* * ******************************************
 * LiteSpeed Web Server Cache Manager
 * @Author: LiteSpeed Technologies, Inc. (https://www.litespeedtech.com)
 * @Copyright: (c) 2018-2019
 * ******************************************* */

namespace Lsc\Wp\Context;

use \Lsc\Wp\Context\ContextOption;
use \Lsc\Wp\Logger;

class UserCLIContextOption extends ContextOption
{

    public function __construct( $invokerName )
    {
        $invokerType = parent::FROM_CLI;
        $isRoot = parent::IS_NOT_ROOT;

        /**
         * Do not change log levels as it will break UserCommand output format.
         */
        $logFileLvl = Logger::L_NONE;
        $logEchoLvl = Logger::L_NONE;

        $bufferedWrite = false;
        $bufferedEcho = false;
        parent::__construct($invokerName, $invokerType, $isRoot, $logFileLvl,
                $logEchoLvl, $bufferedWrite, $bufferedEcho);

        $this->expectedPermissions = self::IS_NOT_ROOT;
        $this->scanDepth = 2;
        $this->batchTimeout = 0;
        $this->batchSize = 0;
        $this->logFile = '';
    }

}
webcachemgr/src/Context/ContextOption.php000066400000013023150545647710014573 0ustar00<?php

/** ******************************************
 * LiteSpeed Web Server Cache Manager
 *
 * @author    Michael Alegre
 * @copyright 2018-2025  LiteSpeed Technologies, Inc.
 * ******************************************* */

namespace Lsc\Wp\Context;

class ContextOption
{

    const FROM_CONTROL_PANEL = 'panel';
    const FROM_CLI           = 'cli';
    const LOG_FILE_NAME = 'webcachemgr.log';
    const IS_NOT_ROOT         = 0;

    /**
     * IS_ROOT_ESCALATABLE depends on panel implemented escalation.
     */
    const IS_ROOT_ESCALATABLE = 1;
    const IS_ROOT             = 2;

    /**
     * @var string
     */
    protected $invokerName;

    /**
     * @var string
     */
    protected $invokerType;

    /**
     * @var int
     */
    protected $isRoot;

    /**
     * @var int
     */
    protected $expectedPermissions;

    /**
     * @var string  Logger class name used during initialization. Child classes
     *              that need escalation should override this class name.
     */
    protected $loggerClass;

    /**
     * @var string  If set, must be writable.
     */
    protected $logFile;

    /**
     * @var int  Log to file level.
     */
    protected $logFileLvl;

    /**
     * @var int  Echo to user interface level.
     */
    protected $logEchoLvl;

    /**
     * @var bool
     */
    protected $bufferedWrite;

    /**
     * @var bool
     */
    protected $bufferedEcho;

    /**
     * @var string  PluginVersion class name used during initialization. Child
     *              classes that need escalation should override this class
     *              name.
     */
    protected $lscwpVerClass;

    /**
     * @var int
     */
    protected $scanDepth = 2;

    /**
     * @var int
     */
    protected $batchTimeout = 0;

    /**
     * @var int
     */
    protected $batchSize = 0;

    /**
     * @var string
     */
    protected $iconDir = '';

    /**
     * @var string
     */
    protected $sharedTplDir = '';

    /**
     *
     * @param string $invokerName
     * @param string $invokerType
     * @param int    $isRoot
     * @param int    $logFileLvl
     * @param int    $logEchoLvl
     * @param bool   $bufferedWrite
     * @param bool   $bufferedEcho
     */
    protected function __construct(
        $invokerName,
        $invokerType,
        $isRoot,
        $logFileLvl,
        $logEchoLvl,
        $bufferedWrite,
        $bufferedEcho
    )
    {
        $this->invokerName = $invokerName;
        $this->invokerType = $invokerType;
        $this->isRoot = $isRoot;
        $this->expectedPermissions = self::IS_ROOT;

        if ( $isRoot == self::IS_ROOT ) {
            $this->logFile = realpath(__DIR__ . '/../../../..') . '/logs/'
                    . self::LOG_FILE_NAME;
        }

        $this->loggerClass = '\Lsc\Wp\Logger';
        $this->lscwpVerClass ='\Lsc\Wp\PluginVersion';
        $this->logFileLvl = $logFileLvl;
        $this->logEchoLvl = $logEchoLvl;
        $this->bufferedWrite = $bufferedWrite;
        $this->bufferedEcho = $bufferedEcho;
    }

    /**
     *
     * @return int
     */
    public function isRoot()
    {
        return $this->isRoot;
    }

    /**
     *
     * @return int
     */
    public function getExpectedPermissions()
    {
        return $this->expectedPermissions;
    }

    /**
     *
     * @return string
     */
    public function getLoggerClass()
    {
        return $this->loggerClass;
    }

    /**
     * Returns the default log file path for this ContextOption. This can be
     * changed in the Logger class itself later on.
     *
     * @return string
     */
    public function getDefaultLogFile()
    {
        return $this->logFile;
    }

    /**
     *
     * @return int
     */
    public function getLogFileLvl()
    {
        return $this->logFileLvl;
    }

    /**
     *
     * @return int
     */
    public function getLogEchoLvl()
    {
        return $this->logEchoLvl;
    }

    /**
     *
     * @return bool
     */
    public function isBufferedWrite()
    {
        return $this->bufferedWrite;
    }

    /**
     *
     * @return bool
     */
    public function isBufferedEcho()
    {
        return $this->bufferedEcho;
    }

    /**
     *
     * @return string
     */
    public function getLscwpVerClass()
    {
        return $this->lscwpVerClass;
    }

    /**
     *
     * @return int
     */
    public function getScanDepth()
    {
        return $this->scanDepth;
    }

    /**
     *
     * @return string
     */
    public function getInvokerType()
    {
        return $this->invokerType;
    }

    /**
     *
     * @return string
     */
    public function getInvokerName()
    {
        return $this->invokerName;
    }

    /**
     *
     * @return int
     */
    public function getBatchSize()
    {
        return $this->batchSize;
    }

    /**
     *
     * @return int
     */
    public function getBatchTimeout()
    {
        return $this->batchTimeout;
    }

    /**
     *
     * @param int $timeout
     *
     * @return int
     */
    public function setBatchTimeout( $timeout )
    {
        if ( is_int($timeout) ) {
            $this->batchTimeout = $timeout;
        }

        return $this->batchTimeout;
    }

    /**
     *
     * @param string $iconDir
     */
    public function setIconDir( $iconDir )
    {
        $this->iconDir = $iconDir;
    }

    /**
     *
     * @return string
     */
    public function getIconDir()
    {
        return $this->iconDir;
    }

    /**
     *
     * @return string
     */
    public function getSharedTplDir()
    {
        return $this->sharedTplDir;
    }

}
webcachemgr/src/Context/RootPanelContextOption.php000066400000002222150545647710016416 0ustar00<?php

/** ******************************************
 * LiteSpeed Web Server Cache Manager
 *
 * @author    Michael Alegre
 * @copyright 2018-2025 LiteSpeed Technologies, Inc.
 * ******************************************* */

namespace Lsc\Wp\Context;

use Lsc\Wp\Logger;

class RootPanelContextOption extends ContextOption
{

    /**
     *
     * @param string $panelName
     */
    public function __construct( $panelName )
    {
        $logFileLvl    = Logger::L_INFO;
        $logEchoLvl    = Logger::L_NONE;
        $bufferedWrite = true;
        $bufferedEcho  = true;

        parent::__construct(
            $panelName,
            parent::FROM_CONTROL_PANEL,
            parent::IS_ROOT,
            $logFileLvl,
            $logEchoLvl,
            $bufferedWrite,
            $bufferedEcho
        );

        $this->scanDepth    = 2;
        $this->batchTimeout = 60;
        $this->batchSize    = 10;

        $sharedTplDir = realpath(__DIR__ . '/../View/Tpl');

        if ( !is_string($sharedTplDir) ) {
            $sharedTplDir = '/usr/local/lsws/add-ons/webcachemgr/src/View/Tpl';
        }

        $this->sharedTplDir = $sharedTplDir;
    }

}
webcachemgr/src/Context/Context.php000066400000023674150545647710013417 0ustar00<?php

/** ******************************************
 * LiteSpeed Web Server Cache Manager
 *
 * @author    LiteSpeed Technologies, Inc.
 * @copyright 2018-2025 LiteSpeed Technologies, Inc.
 * ******************************************* */

namespace Lsc\Wp\Context;

use Lsc\Wp\LSCMException;
use Lsc\Wp\Logger;

/**
 * Context is a singleton
 */
class Context
{

    const LOCAL_PLUGIN_DIR = '/usr/src/litespeed-wp-plugin';

    /**
     * @var int
     */
    protected $isRoot;

    /**
     * @var ContextOption
     */
    protected $options;

    /**
     * @var string
     */
    protected $dataDir;

    /**
     * @var string
     */
    protected $dataFile;

    /**
     * @var string
     */
    protected $customDataFile;

    /**
     * @var null|string
     */
    protected $flagContent;

    /**
     *
     * @var null|Context
     */
    protected static $instance;

    /**
     *
     * @param ContextOption  $contextOption
     */
    protected function __construct( ContextOption $contextOption )
    {
        $this->options = $contextOption;

        $this->init();
    }

    protected function init()
    {
        $this->dataDir        =
            realpath(__DIR__ . '/../../../..') . '/admin/lscdata';
        $this->dataFile       = "$this->dataDir/lscm.data";
        $this->customDataFile = "$this->dataDir/lscm.data.cust";
        $this->isRoot         = $this->options->isRoot();
    }

    /**
     *
     * @since 1.9
     *
     * @return void
     *
     * @throws LSCMException  Thrown indirectly by Logger::debug() call.
     * @throws LSCMException  Thrown indirectly by Logger::debug() call.
     * @throws LSCMException  Thrown indirectly by Logger::notice() call.
     * @throws LSCMException  Thrown indirectly by Logger::notice() call.
     * @throws LSCMException  Thrown indirectly by Logger::debug() call.
     */
    protected function checkLocalPluginDirInCageFS()
    {
        $mpFile    = '/etc/cagefs/cagefs.mp';
        $mountFile = '/proc/mounts';

        if ( !file_exists($mpFile) ) {
            return;
        }

        Logger::debug('Detected cagefs.mp file.');

        $localPluginDir = self::LOCAL_PLUGIN_DIR;

        $pattern      = "=^((?!deleted).)*$localPluginDir((?!deleted).)*$=m";
        $result       = preg_grep($pattern, file($mountFile));
        $procMountSet = !empty($result);

        if ( ! $procMountSet ) {
            Logger::debug("Data dir not set in $mountFile.");

            $pattern     = "=^.*$localPluginDir.*$=m";
            $result      = preg_grep($pattern, file($mpFile));
            $setInMpFile = !empty($result);

            if ( ! $setInMpFile ) {
                file_put_contents(
                    $mpFile,
                    "\n$localPluginDir",
                    FILE_APPEND
                );

                Logger::notice('Added data dir to cagefs.mp.');
            }

            exec('/usr/sbin/cagefsctl --remount-all');

            Logger::notice('Remounted CageFS.');
        }
        else {
            Logger::debug('Data dir already added to CageFS.');
        }
    }

    /**
     *
     * @throws LSCMException  Thrown when unable to create data dir.
     */
    protected function createDataDir()
    {
        if ( !file_exists($this->dataDir) && !mkdir($this->dataDir, 0755) ) {
            throw new LSCMException(
                "Fail to create data directory $this->dataDir.",
                LSCMException::E_PERMISSION
            );
        }
    }

    /**
     *
     * @since 1.9
     *
     * @throws LSCMException  Thrown when unable to create local plugin dir.
     */
    protected function createLocalPluginDir()
    {
        if (
                !file_exists(Context::LOCAL_PLUGIN_DIR)
                &&
                !mkdir(Context::LOCAL_PLUGIN_DIR, 0755)
        ) {
            throw new LSCMException(
                "Fail to create local plugin directory "
                    . Context::LOCAL_PLUGIN_DIR . '.',
                LSCMException::E_PERMISSION
            );
        }
    }

    /**
     *
     * @return ContextOption
     *
     * @throws LSCMException  Thrown indirectly by self::me() call.
     */
    public static function getOption()
    {
        return self::me(true)->options;
    }

    /**
     *
     * @since 1.9.1  Added optional parameter $loggerObj.
     *
     * @param ContextOption $contextOption
     * @param object        $loggerObj      Object implementing all public
     *     Logger class functions.
     *
     * @throws LSCMException  Thrown when Context is already initialized.
     * @throws LSCMException  Thrown indirectly by Logger::setInstance() call.
     * @throws LSCMException  Thrown indirectly by
     *     self::$instance->createDataDir() call.
     * @throws LSCMException  Thrown indirectly by
     *     self::$instance->createLocalPluginDir() call.
     * @throws LSCMException  Thrown indirectly by
     *     self::$instance->checkLocalPluginDirInCageFS() call.
     */
    public static function initialize(
        ContextOption $contextOption,
                      $loggerObj = null
    )
    {
        if ( self::$instance != null ) {
            /**
             * Do not allow, must initialize first.
             */
            throw new LSCMException(
                'Context cannot be initialized twice.',
                LSCMException::E_PROGRAM
            );
        }

        self::$instance = new self($contextOption);

        if ( $loggerObj != null ) {
            Logger::setInstance($loggerObj);
        }
        else {
            $loggerClass = $contextOption->getLoggerClass();
            $loggerClass::Initialize($contextOption);
        }

        if ( self::$instance->isRoot == ContextOption::IS_ROOT ) {
            self::$instance->createDataDir();
            self::$instance->createLocalPluginDir();
            self::$instance->checkLocalPluginDirInCageFS();
        }
    }

    /**
     * Checks if the current instance is lacking the expected level of
     * permissions.
     *
     * @return bool
     */
    protected function hasInsufficentPermissions()
    {
        $expectedPermissions =
            self::$instance->options->getExpectedPermissions();

        return (self::$instance->isRoot < $expectedPermissions);
    }

    /**
     *
     * @param bool $checkPerms
     *
     * @return Context
     *
     * @throws LSCMException  Thrown when Context is not initialized.
     * @throws LSCMException  Thrown when required permissions not met.
     */
    protected static function me( $checkPerms = false )
    {
        if ( self::$instance == null ) {
            /**
             * Do not allow, must initialize first.
             */
            throw new LSCMException(
                'Uninitialized context.',
                LSCMException::E_NON_FATAL
            );
        }

        if ( $checkPerms && self::$instance->hasInsufficentPermissions() ) {
            throw new LSCMException(
                'Access denied: Insufficient permissions.',
                LSCMException::E_NON_FATAL
            );
        }

        return self::$instance;
    }

    /**
     *
     * @return string
     *
     * @throws LSCMException  Thrown indirectly by self::me() call.
     */
    public static function getLSCMDataDir()
    {
        return self::me()->dataDir;
    }


    /**
     * Deprecated 06/19/19. Shift to using getLSCMDataFiles() instead.
     *
     * @deprecated
     *
     * @return string
     *
     * @throws LSCMException  Thrown indirectly by self::getLSCMDataFiles()
     *     call.
     */
    public static function getLSCMDataFile()
    {
        $dataFiles = self::getLSCMDataFiles();

        return $dataFiles['dataFile'];
    }

    /**
     *
     * @return string[]
     *
     * @throws LSCMException  Re-thrown when self::me() calls throw an
     *     exception.
     * @throws LSCMException  Thrown indirectly by Logger::debug() call.
     */
    public static function getLSCMDataFiles()
    {
        try {
            $dataFile     = self::me(true)->dataFile;
            $custDataFile = self::me(true)->customDataFile;
        }
        catch ( LSCMException $e ) {
            $msg = "{$e->getMessage()} Could not get data file paths.";
            Logger::debug($msg);

            throw new LSCMException($msg);
        }

        return array(
            'dataFile'     => $dataFile,
            'custDataFile' => $custDataFile
        );
    }

    /**
     *
     * @return int
     *
     * @throws LSCMException  Thrown indirectly by self::me() call.
     */
    public static function isRoot()
    {
        return self::me()->isRoot;
    }

    /**
     *
     * @return bool
     *
     * @throws LSCMException  Thrown indirectly by self::me() call.
     */
    public static function isPrivileged()
    {
        return (self::me()->isRoot > ContextOption::IS_NOT_ROOT);
    }

    /**
     *
     * @return int
     *
     * @throws LSCMException  Thrown indirectly by self::me() call.
     */
    public static function getScanDepth()
    {
        return self::me()->options->getScanDepth();
    }

    /**
     *
     * @return int
     *
     * @throws LSCMException Thrown indirectly by self::me() call.
     */
    public static function getActionTimeout()
    {
        $timeout = self::me()->options->getBatchTimeout();

        if ( $timeout > 1 ) {
            return time() + $timeout;
        }

        /**
         * No timeout.
         */
        return 0;
    }

    /**
     *
     * @return string
     *
     * @throws LSCMException  Thrown indirectly by self::me() call.
     */
    public static function getFlagFileContent()
    {
        $m = self::me();

        if ( $m->flagContent == null ) {
            $m->flagContent = <<<CONTENT
This file was created by LiteSpeed Web Cache Manager

When this file exists, your LiteSpeed Cache plugin for WordPress will NOT be affected
by Mass Enable/Disable operations performed through LiteSpeed Web Cache Manager.

Please DO NOT ATTEMPT to remove this file unless you understand the above.

CONTENT;
        }

        return $m->flagContent;
    }

}
webcachemgr/src/Logger.php000066400000043712150545647710011561 0ustar00<?php

/** *********************************************
 * LiteSpeed Web Server Cache Manager
 *
 * @author    Michael Alegre
 * @copyright 2018-2023 LiteSpeed Technologies, Inc.
 * *******************************************
 */

namespace Lsc\Wp;

use Lsc\Wp\Context\ContextOption;

/**
 * Logger is a pseudo singleton.
 *
 * Public Logger functions starting with 'p_' are intended for internal use to
 * account for $instance sometimes being of a different non-extending logger
 * class.
 */
class Logger
{

    /**
     * @var int
     */
    const L_NONE = 0;

    /**
     * @var int
     */
    const L_ERROR = 1;

    /**
     * @var int
     */
    const L_WARN = 2;

    /**
     * @var int
     */
    const L_NOTICE = 3;

    /**
     * @var int
     */
    const L_INFO = 4;

    /**
     * @var int
     */
    const L_VERBOSE = 5;

    /**
     * @var int
     */
    const L_DEBUG = 9;

    /**
     * @var int
     */
    const UI_INFO = 0;

    /**
     * @var int
     */
    const UI_SUCC = 1;

    /**
     * @var int
     */
    const UI_ERR = 2;

    /**
     * @var int
     */
    const UI_WARN = 3;

    /**
     * @var null|Logger|object  Object that implements all Logger class public
     *     functions (minus setInstance()). Caution, this requirement is not
     *     enforced in the code.
     */
    protected static $instance;

    /**
     * @var int  Highest log message level allowed to be logged. Set to the
     *     higher value between $this->logFileLvl and $this->logEchoLvl.
     */
    protected $logLvl;

    /**
     * @var string  File that log messages will be written to (if writable).
     */
    protected $logFile;

    /**
     * @var int  Highest log message level allowed to be written to the log
     *     file.
     */
    protected $logFileLvl;

    /**
     * @var string  Additional tag to be added at the start of any log messages.
     */
    protected $addTagInfo = '';

    /**
     * @var bool  When set to true, log messages will not be written to the log
     *     file until this logger object is destroyed.
     */
    protected $bufferedWrite;

    /**
     * @var LogEntry[]|object[]  Stores created objects that implement all
     *     LogEntry class public functions.
     */
    protected $msgQueue = array();

    /**
     * @var int  Highest log message level allowed to echo.
     */
    protected $logEchoLvl;

    /**
     * @var bool  When set to true, echoing of log messages is suppressed.
     */
    protected $bufferedEcho;

    /**
     * @var string[][]  Leveraged by control panel GUI to store and retrieve
     *     display messages. Also used as temporary storage for display only
     *     messages by UserCommand.
     */
    protected $uiMsgs = array(
        self::UI_INFO => array(),
        self::UI_SUCC => array(),
        self::UI_ERR  => array(),
        self::UI_WARN => array()
    );

    /**
     *
     * @param ContextOption $ctxOption
     */
    final protected function __construct( ContextOption $ctxOption )
    {
        $this->logFile       = $ctxOption->getDefaultLogFile();
        $this->logFileLvl    = $ctxOption->getLogFileLvl();
        $this->bufferedWrite = $ctxOption->isBufferedWrite();
        $this->logEchoLvl    = $ctxOption->getLogEchoLvl();
        $this->bufferedEcho  = $ctxOption->isBufferedEcho();
        $this->logLvl        = max($this->logEchoLvl, $this->logFileLvl);
    }

    /**
     *
     * @throws LSCMException  Thrown indirectly by $this->writeToFile() call.
     */
    public function __destruct()
    {
        if ( $this->bufferedWrite ) {
            $this->writeToFile($this->msgQueue);
        }
    }

    /**
     *
     * @param ContextOption $contextOption
     *
     * @throws LSCMException  Thrown when a static Logger instance has already
     *     been initialized.
     */
    public static function Initialize( ContextOption $contextOption )
    {
        if ( static::$instance != null ) {
            throw new LSCMException(
                'Logger cannot be initialized twice.',
                LSCMException::E_PROGRAM
            );
        }

        static::$instance = new static($contextOption);
    }

    /**
     * Set static::$instance to a pre-created logger object.
     *
     * This function is intended as an alternative to Initialize() and will
     * throw an exception if static::$instance is already set.
     *
     * @since 1.9.1
     *
     * @param object $loggerObj
     *
     * @throws LSCMException  Thrown when Logger instance is already set.
     */
    public static function setInstance( $loggerObj )
    {
        if ( static::$instance != null ) {
            throw new LSCMException(
                'Logger instance already set.',
                LSCMException::E_PROGRAM
            );
        }

        static::$instance = $loggerObj;
    }

    /**
     *
     * @since 1.9
     *
     * @param string $logFile
     *
     * @throws LSCMException  Thrown indirectly by static::me() call.
     */
    public static function changeLogFileUsed( $logFile )
    {
        static::me()->p_setLogFile($logFile);
    }

    /**
     *
     * @since 1.9
     *
     * @param string $addInfo
     *
     * @throws LSCMException  Thrown indirectly by static::me() call.
     */
    public static function setAdditionalTagInfo( $addInfo )
    {
        static::me()->p_setAddTagInfo($addInfo);
    }

    /**
     *
     * @since 1.9.1
     *
     * @param string $msg
     * @param int    $type
     */
    public function p_addUiMsg( $msg, $type )
    {
        switch ($type) {
            case static::UI_INFO:
            case static::UI_SUCC:
            case static::UI_ERR:
            case static::UI_WARN:
                $this->uiMsgs[$type][] = $msg;
                break;
            //no default
        }
    }

    /**
     *
     * @since 1.9.1
     *
     * @param LogEntry[]|object[] $entries  Array of objects that implement all
     *     LogEntry class public functions.
     *
     * @throws LSCMException  Thrown indirectly by $this->echoEntries() call.
     */
    public function p_echoEntries( array $entries )
    {
        $this->echoEntries($entries);
    }

    /**
     *
     * @since 1.9.1
     *
     * @return string
     */
    public function p_getAddTagInfo()
    {
        return $this->addTagInfo;
    }

    /**
     *
     * @since 1.9.1
     *
     * @return bool
     */
    public function p_getBufferedEcho()
    {
        return $this->bufferedEcho;
    }

    /**
     *
     * @since 1.9.1
     *
     * @return bool
     */
    public function p_getBufferedWrite()
    {
        return $this->bufferedWrite;
    }

    /**
     *
     * @since 1.9.1
     *
     * @return string
     */
    public function p_getLogFile()
    {
        return $this->logFile;
    }

    /**
     *
     * @since 1.9.1
     *
     * @return LogEntry[]|object[]
     */
    public function p_getMsgQueue()
    {
        return $this->msgQueue;
    }

    /**
     *
     * @since 1.9.1
     *
     * @param int $type
     *
     * @return string[]
     */
    public function p_getUiMsgs( $type )
    {
        switch ($type) {
            case static::UI_INFO:
            case static::UI_SUCC:
            case static::UI_ERR:
            case static::UI_WARN:
                return $this->uiMsgs[$type];

            default:
                return array();
        }
    }

    /**
     *
     * @since 1.9.1
     *
     * @param string $msg
     * @param int    $lvl
     *
     * @throws LSCMException  Thrown indirectly by $this->log() call.
     */
    public function p_log( $msg, $lvl )
    {
        $this->log($msg, $lvl);
    }

    /**
     *
     * @since 1.9.1
     *
     * @param string $addInfo
     */
    public function p_setAddTagInfo( $addInfo )
    {
        $this->addTagInfo = $addInfo;
    }

    /**
     *
     * @since 1.9.1
     *
     * @param string $logFile
     */
    public function p_setLogFile( $logFile )
    {
        $this->logFile = $logFile;
    }

    /**
     *
     * @since 1.9.1
     *
     * @param int $logFileLvl
     */
    public function p_setLogFileLvl( $logFileLvl )
    {
        $this->logFileLvl = $logFileLvl;
    }

    /**
     *
     * @since 1.9.1
     *
     * @param LogEntry[]|object[] $msgQueue
     */
    public function p_setMsgQueue( array $msgQueue )
    {
        $this->msgQueue = $msgQueue;
    }

    /**
     *
     * @since 1.9.1
     *
     * @param LogEntry[]|object[] $entries  Array of objects that implement all
     *     LogEntry class public functions.
     *
     * @throws LSCMException  Thrown indirectly by $this->writeToFile() call.
     */
    public function p_writeToFile( array $entries )
    {
        $this->writeToFile($entries);
    }

    /**
     *
     * @since 1.9
     *
     * @return string
     *
     * @throws LSCMException  Thrown indirectly by static::me() call.
     */
    public static function getAdditionalTagInfo()
    {
        return static::me()->p_getAddTagInfo();
    }

    /**
     *
     * @since 1.9
     *
     * @return string
     *
     * @throws LSCMException  Thrown indirectly by static::me() call.
     */
    public static function getLogFilePath()
    {
        return static::me()->p_getLogFile();
    }

    /**
     *
     * @since 1.9
     *
     * @return LogEntry[]|object[]  Array of objects that implement all LogEntry
     *     class public functions.
     *
     * @throws LSCMException  Thrown indirectly by static::me() call.
     */
    public static function getLogMsgQueue()
    {
        return static::me()->p_getMsgQueue();
    }

    /**
     *
     * @param int $type
     *
     * @return string[]
     *
     * @throws LSCMException  Thrown indirectly by static::me() call.
     */
    public static function getUiMsgs( $type )
    {
        return static::me()->p_getUiMsgs($type);
    }

    /**
     * Processes any buffered output, writing it to the log file, echoing it
     * out, or both.
     *
     * @throws LSCMException  Thrown indirectly by static::me() call.
     * @throws LSCMException  Thrown indirectly by $m->p_writeToFile() call.
     * @throws LSCMException  Thrown indirectly by $m->p_echoEntries() call.
     */
    public static function processBuffer()
    {
        $clear = false;

        $m = static::me();

        if ( $m->p_getBufferedWrite() ) {
            $m->p_writeToFile($m->p_getMsgQueue());
            $clear = true;
        }

        if ( $m->p_getBufferedEcho() ) {
            $m->p_echoEntries($m->p_getMsgQueue());
            $clear = true;
        }

        if ( $clear ) {
            $m->p_setMsgQueue(array());
        }
    }

    /**
     * Deprecated 06/25/19. Visibility going to be changed to "protected".
     *
     * @deprecated
     *
     * @param string $msg
     * @param int    $type
     *
     * @throws LSCMException  Thrown indirectly by static::me() call.
     */
    public static function addUiMsg( $msg, $type )
    {
        static::me()->p_addUiMsg($msg, $type);
    }

    /**
     * Calls addUiMsg() with message level static::UI_INFO.
     *
     * @param string $msg
     *
     * @throws LSCMException  Thrown indirectly by static::addUiMsg() call.
     */
    public static function uiInfo( $msg )
    {
        static::addUiMsg($msg, static::UI_INFO);
    }

    /**
     * Calls addUiMsg() with message level static::UI_SUCC.
     *
     * @param string $msg
     *
     * @throws LSCMException  Thrown indirectly by static::addUiMsg() call.
     */
    public static function uiSuccess( $msg )
    {
        static::addUiMsg($msg, static::UI_SUCC);
    }

    /**
     * Calls addUiMsg() with message level static::UI_ERR.
     *
     * @param string $msg
     *
     * @throws LSCMException  Thrown indirectly by static::addUiMsg() call.
     */
    public static function uiError( $msg )
    {
        static::addUiMsg($msg, static::UI_ERR);
    }

    /**
     * Calls addUiMsg() with message level static::UI_WARN.
     *
     * @param string $msg
     *
     * @throws LSCMException  Thrown indirectly by static::addUiMsg() call.
     */
    public static function uiWarning( $msg )
    {
        static::addUiMsg($msg, static::UI_WARN);
    }

    /**
     *
     * @param string $msg
     * @param int    $lvl
     *
     * @throws LSCMException  Thrown indirectly by static::me() call.
     * @throws LSCMException  Thrown indirectly by static::me()->p_log() call.
     */
    public static function logMsg( $msg, $lvl )
    {
        static::me()->p_log($msg, $lvl);
    }

    /**
     * Calls logMsg() with message level static::L_ERROR.
     *
     * @param string $msg
     *
     * @throws LSCMException  Thrown indirectly by static::logMsg() call.
     */
    public static function error( $msg )
    {
        static::logMsg($msg, static::L_ERROR);
    }

    /**
     * Calls logMsg() with message level static::L_WARN.
     *
     * @param string $msg
     *
     * @throws LSCMException  Thrown indirectly by static::logMsg() call.
     */
    public static function warn( $msg )
    {
        static::logMsg($msg, static::L_WARN);
    }

    /**
     * Calls logMsg() with message level static::L_NOTICE.
     *
     * @param string $msg
     *
     * @throws LSCMException  Thrown indirectly by static::logMsg() call.
     */
    public static function notice( $msg )
    {
        static::logMsg($msg, static::L_NOTICE);
    }

    /**
     * Calls logMsg() with message level static::L_INFO.
     *
     * @param string $msg
     *
     * @throws LSCMException  Thrown indirectly by static::logMsg() call.
     */
    public static function info( $msg )
    {
        static::logMsg($msg, static::L_INFO);
    }

    /**
     * Calls logMsg() with message level static::L_VERBOSE.
     *
     * @param string $msg
     *
     * @throws LSCMException  Thrown indirectly by static::logMsg() call.
     */
    public static function verbose( $msg )
    {
        static::logMsg($msg, static::L_VERBOSE);
    }

    /**
     * Calls logMsg() with message level static::L_DEBUG.
     *
     * @param string $msg
     *
     * @throws LSCMException  Thrown indirectly by static::logMsg() call.
     */
    public static function debug( $msg )
    {
        static::logMsg($msg, static::L_DEBUG);
    }

    /**
     *
     * @return Logger|object  Object that implements all Logger class public
     *     functions.
     *
     * @throws LSCMException  Thrown when Logger instance has not yet been
     *     initialized.
     */
    protected static function me()
    {
        if ( static::$instance == null ) {
            throw new LSCMException(
                'Logger Uninitialized.',
                LSCMException::E_PROGRAM
            );
        }

        return static::$instance;
    }

    /**
     *
     * @param string $msg
     * @param int    $lvl
     *
     * @throws LSCMException  Thrown indirectly by $this->writeToFile() call.
     * @throws LSCMException  Thrown indirectly by $this->echoEntries() call.
     */
    protected function log( $msg, $lvl )
    {
        $entry = new LogEntry($msg, $lvl);

        $this->msgQueue[] = $entry;

        if ( !$this->bufferedWrite ) {
            $this->writeToFile(array( $entry ));
        }

        if ( !$this->bufferedEcho ) {
            $this->echoEntries(array( $entry ));
        }
    }

    /**
     *
     * @param LogEntry[]|object[] $entries  Array of objects that implements all
     *     LogEntry class public functions.
     *
     * @throws LSCMException  Thrown indirectly by $e->getOutput() call.
     */
    protected function writeToFile( array $entries )
    {
        $content = '';

        foreach ( $entries as $e ) {
            $content .= $e->getOutput($this->logFileLvl);
        }

        if ( $content != '' ) {

            if ( $this->logFile ) {
                file_put_contents(
                    $this->logFile,
                    $content,
                    FILE_APPEND | LOCK_EX
                );
            }
            else {
                error_log($content);
            }
        }
    }

    /**
     *
     * @param LogEntry[]|object[] $entries  Array of objects that implement all
     *     LogEntry class public functions.
     *
     * @throws LSCMException  Thrown indirectly by $entry->getOutput() call.
     */
    protected function echoEntries( array $entries )
    {
        foreach ( $entries as $entry ) {

            if ( ($msg = $entry->getOutput($this->logEchoLvl)) !== '' ) {
                echo $msg;
            }
        }
    }

    /**
     *
     * @param int $lvl
     *
     * @return string
     */
    public static function getLvlDescr( $lvl )
    {
        switch ($lvl) {

            case static::L_ERROR:
                return 'ERROR';

            case static::L_WARN:
                return 'WARN';

            case static::L_NOTICE:
                return 'NOTICE';

            case static::L_INFO:
                return 'INFO';

            case static::L_VERBOSE:
                return 'DETAIL';

            case static::L_DEBUG:
                return 'DEBUG';

            default:
                /**
                 * Do silently.
                 */
                return '';
        }
    }

    /**
     * Not used yet. Added for later cases where shared log level should be
     * changed to match panel log level.
     *
     * @deprecated 1.9.1  Deprecated on 11/22/19. Function is likely not needed
     *     after recent logger changes.
     *
     * @param int $lvl
     *
     * @return bool
     *
     * @throws LSCMException  Thrown indirectly by static::me() call.
     */
    public static function setLogFileLvl( $lvl )
    {
        $lvl = (int)$lvl;

        if ( static::isValidLogFileLvl($lvl) ) {

            if ( $lvl > static::L_DEBUG ) {
                $lvl = static::L_DEBUG;
            }

            static::me()->p_setLogFileLvl($lvl);

            return true;
        }

        return false;
    }

    /**
     *
     * @param int $lvl
     *
     * @return bool
     */
    protected static function isValidLogFileLvl( $lvl )
    {
        if ( is_int($lvl) && $lvl >= 0 ) {
            return true;
        }

        return false;
    }

    /**
     * Prevent cloning here and in extending classes.
     */
    final protected function __clone() {}

}
webcachemgr/src/LogEntry.php000066400000003342150545647710012100 0ustar00<?php

/** *********************************************
 * LiteSpeed Web Server Cache Manager
 *
 * @author LiteSpeed Technologies, Inc. (https://www.litespeedtech.com)
 * @copyright (c) 2018-2019
 * *******************************************
 */

namespace Lsc\Wp;

class LogEntry
{

    /**
     * @var int
     */
    protected $lvl;

    /**
     * @var string
     */
    protected $msg;

    /**
     *
     * @var null|string
     */
    protected $prefix;

    /**
     *
     * @var int[]
     */
    protected $timestamp;

    /**
     *
     * @param string  $msg
     * @param int     $lvl
     */
    public function __construct( $msg, $lvl )
    {
        $this->msg = $msg;
        $this->lvl = $lvl;
        $this->timestamp = time();
    }

    /**
     *
     * @param string  $msg
     */
    public function append( $msg )
    {
        $this->msg .= $msg;
    }

    /**
     *
     * @return int
     */
    public function getLvl()
    {
        return $this->lvl;
    }

    /**
     *
     * @return string
     */
    public function getMsg()
    {
        $msg = ($this->prefix == null) ? '' : "{$this->prefix} ";

        if ( $this->msg ) {
            $msg .= $this->msg;
        }

        return $msg;
    }

    /**
     *
     * @param int  $logLvl
     * @return string
     * @throws LSCMException  Thrown indirectly.
     */
    public function getOutput( $logLvl )
    {
        if ( $this->lvl > $logLvl ) {
            return '';
        }


        $timestamp = date('Y-m-d H:i:s', $this->timestamp);
        $addTagInfo = Logger::getAdditionalTagInfo();
        $lvl = '[' . Logger::getLvlDescr($this->lvl) . ']';
        $msg = $this->getMsg();

        return "{$timestamp} {$addTagInfo} {$lvl}  {$msg}\n";
    }

}
webcachemgr/src/Util.php000066400000044236150545647710011261 0ustar00<?php

/** *********************************************
 * LiteSpeed Web Server Cache Manager
 *
 * @author    Michael Alegre
 * @copyright 2018-2025 LiteSpeed Technologies, Inc.
 * *******************************************
 */

namespace Lsc\Wp;


use ZipArchive;

class Util
{

    /**
     *
     * @param string $tag
     *
     * @return string
     */
    public static function get_request_var( $tag )
    {
        if ( isset($_REQUEST[$tag]) ) {
            return trim($_REQUEST[$tag]);
        }

        /**
         * Request var not found in $_REQUEST, try checking POST and
         * QUERY_STRING environment variables.
         */
        if ( $_SERVER['REQUEST_METHOD'] === 'POST' ) {
            $querystring = urldecode(getenv('POST'));
        }
        else {
            $querystring = urldecode(getenv('QUERY_STRING'));
        }

        if ( $querystring != ''
                && preg_match("/(?:^|\?|&)$tag=([^&]+)/", $querystring, $m) ) {

            return trim($m[1]);
        }

        return null;
    }

    /**
     *
     * @param string $tag
     *
     * @return array
     */
    public static function get_request_list( $tag )
    {
        $varValue = null;

        if ( isset($_REQUEST[$tag]) ) {
            $varValue = $_REQUEST[$tag];
        }
        else {
            /**
             * Request var not found in $_REQUEST, try checking POST and
             * QUERY_STRING environment variables.
             */
            if ( $_SERVER['REQUEST_METHOD'] === 'POST' ) {
                $querystring = urldecode(getenv('POST'));
            }
            else {
                $querystring = urldecode(getenv('QUERY_STRING'));
            }

            if ( $querystring != ''
                    && preg_match_all("/(?:^|\?|&)$tag\[]=([^&]+)/", $querystring, $m) ) {

                $varValue = $m[1];
            }
        }

        return (is_array($varValue)) ? $varValue : null;
    }

    /**
     *
     * @throws LSCMException  Thrown indirectly by Logger::info() call.
     */
    public static function restartLsws()
    {
        Logger::info('Performing a Graceful Restart to apply changes...');

        /**
         * @noinspection PhpMethodParametersCountMismatchInspection  Suppress
         *     for PHP 5.x.
         */
        if ( php_uname('s') == 'FreeBSD' ) {
            $lswsCtl = '/usr/local/etc/rc.d/lsws.sh';
        }
        else {
            $lswsCtl = '/sbin/service lsws';
        }

        exec("$lswsCtl restart");
    }

    /**
     * @since 2.1.15
     *
     * @param int $startTime
     * @param int $timeout
     *
     * @return bool
     */
    public static function timedOut( $startTime, $timeout )
    {
        return ((time() - $startTime) > $timeout);
    }

    /**
     * This function is used to get the file owner by name. Useful in cases
     * where UID is not accepted or setting a files group to match its owner
     * (It is not safe to assume UID == GID or GID exists for username 'x').
     *
     * @since 2.2.0
     *
     * @param string $filepath
     *
     * @return array  Keys are id, name, group_id
     */
    public static function populateOwnerInfo( $filepath )
    {
        clearstatcache();
        $ownerID = fileowner($filepath);
        $ownerInfo = posix_getpwuid($ownerID);

        return array(
            'user_id'   => $ownerID,
            'user_name' => $ownerInfo['name'],
            'group_id'  => filegroup($filepath)
        );
    }

    /**
     *
     * @param string $file
     * @param string $owner
     * @param string $group
     */
    public static function changeUserGroup( $file, $owner, $group )
    {
        chown($file, $owner);
        chgrp($file, $group);
    }

    /**
     * Set file permissions of $file2 to match those of $file1.
     *
     * @since 2.2.0
     *
     * @param string $file1
     * @param string $file2
     */
    public static function matchPermissions( $file1, $file2 )
    {
        /**
         * convert fileperms() returned dec to oct
         */
        chmod($file2, (fileperms($file1) & 0777));
    }

    /**
     *
     * @since 1.14.3
     *
     * @param string $url
     * @param bool   $headerOnly
     *
     * @return string
     */
    public static function getUrlContentsUsingFileGetContents(
        $url,
        $headerOnly = false )
    {
        if ( ini_get('allow_url_fopen') ) {
            /**
             * silence warning when OpenSSL missing while getting LSCWP ver
             * file.
             */
            $url_content = @file_get_contents($url);

            if ( $url_content !== false ) {

                if ( $headerOnly ) {
                    return implode("\n", $http_response_header);
                }

                return $url_content;
            }
        }

        return '';
    }

    /**
     *
     * @since 1.14.3
     *
     * @param string $url
     * @param bool   $headerOnly
     *
     * @return string
     */
    public static function getUrlContentsUsingPhpCurl(
        $url,
        $headerOnly = false )
    {
        if ( function_exists('curl_version') ) {
            $ch = curl_init();

            curl_setopt_array(
                $ch,
                array(
                    CURLOPT_URL            => $url,
                    CURLOPT_RETURNTRANSFER => true,
                    CURLOPT_HEADER         => $headerOnly,
                    CURLOPT_NOBODY         => $headerOnly,
                    CURLOPT_HTTP_VERSION   => CURL_HTTP_VERSION_1_1
                )
            );

            $url_content = curl_exec($ch);
            curl_close($ch);

            if ( $url_content !== false ) {
                return $url_content;
            }
        }

        return '';
    }

    /**
     *
     * @since 1.14.3
     *
     * @param string $url
     * @param string $headerOnly
     *
     * @return string
     */
    public static function getUrlContentsUsingExecCurl(
        $url,
        $headerOnly = false )
    {
        $cmd = 'curl -s';

        if ( $headerOnly ) {
            $cmd .= ' -I';
        }

        exec("$cmd $url", $output, $ret);

        if ( $ret === 0 ) {
            return implode("\n", $output);
        }

        return '';
    }

    /**
     *
     * @param string $url
     * @param bool   $headerOnly
     *
     * @return string
     */
    public static function get_url_contents( $url, $headerOnly = false )
    {
        $content = self::getUrlContentsUsingFileGetContents($url, $headerOnly);

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

        $content = self::getUrlContentsUsingPhpCurl($url, $headerOnly);

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

        return self::getUrlContentsUsingExecCurl($url, $headerOnly);
    }

    /**
     *
     * @param string $dir
     *
     * @return false|string
     */
    public static function DirectoryMd5( $dir )
    {
        if ( !is_dir($dir) ) {
            return false;
        }

        $fileMd5s = array();
        $d = dir($dir);

        while ( ($entry = $d->read()) !== false ) {

            if ( $entry != '.' && $entry != '..' ) {
                $currEntry = "$dir/$entry";

                if ( is_dir($currEntry) ) {
                    $fileMd5s[] = self::DirectoryMd5($currEntry);
                }
                else {
                    $fileMd5s[] = md5_file($currEntry);
                }
            }
        }

        $d->close();
        return md5(implode('', $fileMd5s));
    }

    /**
     *
     * @param string $file
     * @param string $backup
     *
     * @return bool
     *
     * @throws LSCMException  Thrown indirectly by Logger::debug() call.
     * @throws LSCMException  Thrown indirectly by Logger::debug() call.
     */
    private static function matchFileSettings( $file, $backup )
    {
        clearstatcache();
        $ownerID = fileowner($file);
        $groupID = filegroup($file);

        if ( $ownerID === false || $groupID === false ) {
            Logger::debug("Could not get owner/group of file $file");

            unlink($backup);

            Logger::debug("Removed file $backup");
            return false;
        }

        self::changeUserGroup($backup, $ownerID, $groupID);
        self::matchPermissions($file, $backup);

        return true;
    }

    /**
     *
     * @param string $filepath
     * @param string $bak
     *
     * @return string
     */
    private static function getBackupSuffix(
        $filepath,
        $bak = '_lscachebak_orig' )
    {
        $i = 1;

        if ( file_exists($filepath . $bak) ) {
            $bak = sprintf("_lscachebak_%02d", $i);

            while ( file_exists($filepath . $bak) ) {
                $i++;
                $bak = sprintf("_lscachebak_%02d", $i);
            }
        }

        return $bak;
    }

    /**
     *
     * @param string $filepath
     *
     * @return bool
     *
     * @throws LSCMException  Thrown indirectly by Logger::debug() call.
     * @throws LSCMException  Thrown indirectly by Logger::verbose() call.
     * @throws LSCMException  Thrown indirectly by self::matchFileSettings()
     *     call.
     * @throws LSCMException  Thrown indirectly by Logger::debug() call.
     * @throws LSCMException  Thrown indirectly by Logger::debug() call.
     * @throws LSCMException  Thrown indirectly by Logger::info() call.
     */
    public static function createBackup( $filepath )
    {
        $backup = $filepath . self::getBackupSuffix($filepath);

        if ( !copy($filepath, $backup) ) {
            Logger::debug(
                "Could not backup file $filepath to location $backup"
            );

            return false;
        }

        Logger::verbose("Created file $backup");

        if ( !self::matchFileSettings($filepath, $backup) ) {
            Logger::debug(
                "Could not backup file $filepath to location $backup"
            );

            return false;
        }

        Logger::debug('Matched owner/group setting for both files');
        Logger::info(
            "Successfully backed up file $filepath to location $backup"
        );

        return true;
    }

    /**
     *
     * @param string $zipFile
     * @param string $dest
     *
     * @return bool
     *
     * @throws LSCMException  Thrown indirectly by Logger::debug() call.
     * @throws LSCMException  Thrown indirectly by Logger::debug() call.
     */
    public static function unzipFile( $zipFile, $dest )
    {
        if ( class_exists('\ZipArchive') ) {
            $zipArchive = new ZipArchive();

            if ( $zipArchive->open($zipFile) === true ) {
                $extracted = $zipArchive->extractTo($dest);
                $zipArchive->close();

                if ( $extracted ) {
                    return true;
                }
            }

            Logger::debug("Could not unzip $zipFile using ZipArchive.");
        }

        $output = array();

        exec(
            "unzip $zipFile -d $dest > /dev/null 2>&1",
            $output,
            $return_var
        );

        if ( $return_var == 0 ) {
            return true;
        }
        else {
            Logger::debug("Could not unzip $zipFile from cli.");
        }

        return false;
    }

    /**
     * Check if a given directory is empty.
     *
     * @param string $dir
     *
     * @return bool
     */
    public static function is_dir_empty( $dir )
    {
        if ( !($handle = @opendir($dir)) ) {
            return true;
        }

        while ( ($entry = readdir($handle)) !== false ) {

            if ( $entry != '.' && $entry != '..' ) {
                return false;
            }
        }

        return true;
    }

    /**
     *
     * @param string $vhCacheRoot
     */
    public static function ensureVHCacheRootInCage( $vhCacheRoot )
    {
        $cageFsFile = '/etc/cagefs/cagefs.mp';

        if ( file_exists($cageFsFile) ) {

            if ( $vhCacheRoot[0] == '/' ) {
                $cageVhCacheRoot =
                    '%' . str_replace('/$vh_user', '', $vhCacheRoot);

                $matchFound = preg_grep(
                    "!^\s*" . str_replace('!', '\!', $cageVhCacheRoot) . "!im",
                    file($cageFsFile)
                );

                if ( !$matchFound ) {
                    file_put_contents(
                        $cageFsFile,
                        "\n$cageVhCacheRoot",
                        FILE_APPEND
                    );

                    exec('/usr/sbin/cagefsctl --remount-all');
                }
            }
        }
    }

    /**
     * Recursively a directory's contents and optionally the directory itself.
     *
     * @param string $dir        Directory path
     * @param bool   $keepParent Only remove directory contents when true.
     *
     * @return bool
     */
    public static function rrmdir( $dir, $keepParent = false )
    {
        if ( $dir != '' && is_dir($dir) ) {

            if ( ($matches = glob("$dir/*")) === false ) {
                return false;
            }

            foreach ( $matches as $file ) {

                if ( is_dir($file) ) {
                    self::rrmdir($file);
                }
                else {
                    unlink($file);
                }
            }

            if ( !$keepParent ) {
                rmdir($dir);
            }

            return true;
        }

        return false;
    }

    /**
     * Wrapper for idn_to_utf8() function call to avoid "undefined" exceptions
     * when PHP intl module is not installed and enabled.
     *
     * @since 1.13.13.1
     *
     * @param string     $domain
     * @param int        $flags
     * @param int|null   $variant
     * @param array|null $idna_info
     *
     * @return false|string
     */
    public static function tryIdnToUtf8(
        $domain,
        $flags = 0,
        $variant = null,
        &$idna_info = null
    )
    {
        if ( empty($domain) || !function_exists('idn_to_utf8') ) {
            return $domain;
        }

        if ( $variant == null ) {
            $variant = INTL_IDNA_VARIANT_UTS46;
        }

        return idn_to_utf8($domain, $flags, $variant, $idna_info);
    }

    /**
     * Wrapper for idn_to_ascii() function call to avoid "undefined" exceptions
     * when PHP intl module is not installed and enabled.
     *
     * @since 1.13.13.1
     *
     * @param string     $domain
     * @param int|null   $flags
     * @param int|null   $variant
     * @param array|null $idna_info
     *
     * @return false|string
     */
   public static function tryIdnToAscii(
       $domain,
       $flags = null,
       $variant = null,
       &$idna_info = null
   )
   {
       if ( empty($domain) || !function_exists('idn_to_ascii') ) {
           return $domain;
       }

       if ( $flags == null ) {
           $flags = IDNA_DEFAULT;
       }

       if ( $variant == null ) {
           $variant = INTL_IDNA_VARIANT_UTS46;
       }

       return idn_to_ascii($domain, $flags, $variant, $idna_info);
   }

    /**
     * Version comparison function capable of properly comparing versions with
     * trailing ".0" groups such as '6.1' which is equal to '6.1.0' which is
     * equal to '6.1.000.0' etc.
     *
     * @since 1.14.2
     *
     * @param string      $ver1
     * @param string      $ver2
     * @param string|null $operator
     *
     * @return bool|int
     */
    public static function betterVersionCompare(
        $ver1,
        $ver2,
        $operator = null )
    {
        $pattern = '/(\.0+)+($|-)/';

        return version_compare(
            preg_replace($pattern, '', $ver1),
            preg_replace($pattern, '', $ver2),
            $operator
        );
    }

    /**
     *
     * @since 1.15.0.1
     *
     * @param string                           $constantName
     * @param array|bool|float|int|null|string $value
     * @param bool                             $caseInsensitive  Optional
     *     parameter used for define calls in PHP versions below 7.3.
     *
     * @return bool
     *
     * @noinspection PhpDeprecationInspection  Ignore deprecation of define()
     *     parameter $case_insensitive for PHP versions below 7.3.
     * @noinspection RedundantSuppression
     */
    public static function define_wrapper(
        $constantName,
        $value,
        $caseInsensitive = false )
    {
        if ( PHP_VERSION_ID < 70300 ) {
            return define($constantName, $value, $caseInsensitive);
        }
        else {
            return define($constantName, $value);
        }
    }

    /**
     *
     * @since 1.17.1.1
     *
     * @param int $wpStatus
     *
     * @return string[]  [ stateMsg => string, link => string ]
     */
    public static function getFatalErrorStateMessageAndLink( $wpStatus )
    {
        $stateMsg = $anchor = '';

        if ( $wpStatus & WPInstall::ST_ERR_EXECMD ) {
            $stateMsg = 'WordPress fatal error encountered during action '
                . 'execution. This is most likely caused by custom code in '
                . 'this WordPress installation.';
            $anchor   = '#fatal-error-encountered-during-action-execution';
        }
        if ( $wpStatus & WPInstall::ST_ERR_EXECMD_DB ) {
            $stateMsg = 'Error establishing WordPress database connection.';
        }
        elseif ( $wpStatus & WPInstall::ST_ERR_TIMEOUT ) {
            $stateMsg = 'Timeout occurred during action execution.';
            $anchor   = '#timeout-occurred-during-action-execution';
        }
        elseif ( $wpStatus & WPInstall::ST_ERR_SITEURL ) {
            $stateMsg = 'Could not retrieve WordPress siteURL.';
            $anchor   = '#could-not-retrieve-wordpress-siteurl';
        }
        elseif ( $wpStatus & WPInstall::ST_ERR_DOCROOT ) {
            $stateMsg = 'Could not match WordPress siteURL to a known '
                . 'control panel docroot.';
            $anchor   = '#could-not-match-wordpress-siteurl-to-a-known-'
                . 'cpanel-docroot';
        }
        elseif ( $wpStatus & WPInstall::ST_ERR_WPCONFIG ) {
            $stateMsg = 'Could not find a valid wp-config.php file.';
            $anchor   = '#could-not-find-a-valid-wp-configphp-file';
        }

        $stateMsg .= ' Click for more information.';

        return array(
            'stateMsg' => $stateMsg,
            'link'     => 'https://docs.litespeedtech.com/lsws/cp/cpanel/'
                . "whm-litespeed-plugin/troubleshooting/$anchor"
        );
    }
}
webcachemgr/src/ThirdParty/Polyfill/Utf8.php000066400000003764150545647710015057 0ustar00<?php

/**
 * This file contains paired-down/modified code originally found in Symfony
 * package file Php72.php, used here as a PHP standard replacement for now
 * deprecated PHP functions utf8_encode() and utf8_decode().
 *
 * Modified by: Michael Alegre (LiteSpeed Technologies, Inc.), 2023
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Lsc\Wp\ThirdParty\Polyfill;

/**
 * @since 1.16.1
 */
class Utf8
{
    /**
     *
     * @since 1.16.1
     *
     * @param $s
     *
     * @return false|string
     */
    public static function encode($s)
    {
        $s .= $s;
        $len = strlen($s);

        for ($i = $len >> 1, $j = 0; $i < $len; ++$i, ++$j) {

            if ( $s[$i] < "\x80" ) {
                $s[$j] = $s[$i];
            }
            elseif ( $s[$i] < "\xC0" ) {
                $s[$j] = "\xC2";
                $s[++$j] = $s[$i];
            }
            else {
                $s[$j] = "\xC3";
                $s[++$j] = chr(ord($s[$i]) - 64);
            }
        }

        return substr($s, 0, $j);
    }

    /**
     *
     * @since 1.16.1
     *
     * @param $s
     *
     * @return false|string
     */
    public static function decode($s)
    {
        $s = (string) $s;
        $len = strlen($s);

        for ($i = 0, $j = 0; $i < $len; ++$i, ++$j) {

            switch ($s[$i] & "\xF0") {
                case "\xC0":
                case "\xD0":
                    $c = (ord($s[$i] & "\x1F") << 6) | ord($s[++$i] & "\x3F");
                    $s[$j] = $c < 256 ? chr($c) : '?';
                    break;

                case "\xF0":
                    ++$i;
                // fallthrough

                case "\xE0":
                    $s[$j] = '?';
                    $i += 2;
                    break;

                default:
                    $s[$j] = $s[$i];
            }
        }

        return substr($s, 0, $j);
    }

}webcachemgr/src/ThirdParty/Polyfill/LICENSE000066400000002053150545647710014513 0ustar00Copyright (c) 2015-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.webcachemgr/src/LSCMException.php000066400000001213150545647710012745 0ustar00<?php

/** ******************************************
 * LiteSpeed Web Server Cache Manager
 * @author: LiteSpeed Technologies, Inc. (https://www.litespeedtech.com)
 * @copyright: (c) 2018
 * ******************************************* */

namespace Lsc\Wp;

class LSCMException extends \Exception
{

    const E_ERROR = 0;

    /**
     * show trace msg
     */
    const E_PROGRAM = 100;

    /**
     * error shown to user
     */
    const E_PERMISSION = 101;
    const E_UNSUPPORTED = 102;

    /**
     * Exception is considered non-fatal. Used to determine
     * UserCommand->runAsUser() return status.
     */
    const E_NON_FATAL = 103;

}
webcachemgr/src/Panel/CustomPanelBase.php000066400000002130150545647710014413 0ustar00<?php

/** ******************************************
 * LiteSpeed Web Server Cache Manager
 *
 * @author LiteSpeed Technologies, Inc. (https://www.litespeedtech.com)
 * @copyright (c) 2020-2023
 * @since 1.10
 * ******************************************* */

namespace Lsc\Wp\Panel;

abstract class CustomPanelBase
extends ControlPanel
{
    /**
     * The following functions deal with apache configuration files and
     * server/virtual host cache roots and will never be called in the
     * CustomPanel context. They are included here to meet abstract function
     * requirements in parent class ControlPanel.
     *
     */
    protected function initConfPaths()
    {}
    protected function serverCacheRootSearch()
    {}
    protected function vhCacheRootSearch()
    {}
    protected function addVHCacheRootSection(
        array $file_contents,
              $vhCacheRoot = 'lscache' )
    {}
    public function verifyCacheSetup()
    {}
    public function createVHConfAndSetCacheRoot(
        $vhConf,
        $vhCacheRoot = 'lscache' )
    {}
    public function applyVHConfChanges()
    {}

}
webcachemgr/src/Panel/CPanel.php000066400000057704150545647710012551 0ustar00<?php

/** ******************************************
 * LiteSpeed Web Server Cache Manager
 *
 * @author    Michael Alegre
 * @copyright 2017-2023 LiteSpeed Technologies, Inc.
 * ******************************************* */

namespace Lsc\Wp\Panel;

use Lsc\Wp\Logger;
use Lsc\Wp\LSCMException;
use Lsc\Wp\Util;
use Lsc\Wp\WPInstall;

class CPanel extends ControlPanel
{

    /**
     * @var string
     */
    const USER_PLUGIN_INSTALL_SCRIPT = '/usr/local/cpanel/whostmgr/docroot/cgi/lsws/res/ls_web_cache_mgr/install.sh';

    /**
     * @deprecated 1.13.11  Split into paper_lantern and jupiter theme specific
     *     constants.
     * @since 1.13.2
     * @var string
     */
    const USER_PLUGIN_DIR = '/usr/local/cpanel/base/frontend/paper_lantern/ls_web_cache_manager';

    /**
     * @since 1.13.11
     * @var string
     */
    const THEME_JUPITER_USER_PLUGIN_DIR = '/usr/local/cpanel/base/frontend/jupiter/ls_web_cache_manager';

    /**
     * @since 1.13.11
     * @var string
     */
    const THEME_PAPER_LANTERN_USER_PLUGIN_DIR = '/usr/local/cpanel/base/frontend/paper_lantern/ls_web_cache_manager';

    /**
     * @deprecated 1.13.11  No longer used.
     * @var string
     */
    const USER_PLUGIN_UNINSTALL_SCRIPT = self::USER_PLUGIN_DIR . '/uninstall.sh';

    /**
     * @since 1.13.11
     * @var string
     */
    const USER_PLUGIN_RELATIVE_UNINSTALL_SCRIPT = 'uninstall.sh';

    /**
     * @since 1.13.2
     * @var string
     */
    const USER_PLUGIN_BACKUP_DIR = '/tmp/lscp-plugin-tmp';

    /**
     * @since 1.13.11
     * @var string
     */
    const USER_PLUGIN_RELATIVE_DATA_DIR = 'data';

    /**
     * @deprecated 1.13.11
     * @since 1.13.2
     * @var string  An old location for cPanel user-end plugin conf file.
     */
    const USER_PLUGIN_CONF_OLD = self::USER_PLUGIN_DIR . '/lswcm.conf';

    /**
     * @since 1.13.11
     * @var string
     */
    const USER_PLUGIN_RELATIVE_CONF_OLD = '/lswcm.conf';

    /**
     * @since 1.13.11
     * @var string
     */
    const USER_PLUGIN_RELATIVE_CONF_OLD_2 = self::USER_PLUGIN_RELATIVE_DATA_DIR . '/lswcm.conf';

    /**
     * @var string
     */
    const USER_PLUGIN_CONF = '/usr/local/cpanel/3rdparty/ls_webcache_mgr/lswcm.conf';

    /**
     * @var string
     */
    const CPANEL_AUTOINSTALL_DISABLE_FLAG = '/usr/local/cpanel/whostmgr/docroot/cgi/lsws/cpanel_autoinstall_off';

    /**
     * @var string
     */
    const USER_PLUGIN_SETTING_VHOST_CACHE_ROOT = 'vhost_cache_root';

    /**
     * @var string
     */
    const USER_PLUGIN_SETTING_LSWS_DIR = 'lsws_dir';

    /**
     * @deprecated 1.13.11  Never used.
     * @since 1.13.2
     * @var string
     */
    protected $cpanelPluginDataDir;

    /**
     * @deprecated 1.13.11  Never used.
     * @since 1.13.2
     * @var string
     */
    protected $cpanelPluginTplDir;

    /**
     * @deprecated 1.13.11  Never used.
     * @since 1.13.2
     * @var string
     */
    protected $cpanelPluginCustTransDir;

    /**
     * @deprecated 1.13.11  Never used.
     * @since 1.13.2
     * @var string
     */
    protected $tmpCpanelPluginDataDir;

    /**
     * @since 1.13.2
     * @var string
     */
    protected $tmpCpanelPluginTplDir;

    /**
     * @since 1.13.2
     * @var string
     */
    protected $tmpCpanelPluginCustTransDir;

    protected function __construct()
    {
        /** @noinspection PhpUnhandledExceptionInspection */
        parent::__construct();
    }

    /**
     *
     * @since 1.13.2
     */
    protected function init2()
    {
        $this->panelName                   = 'cPanel/WHM';
        $this->defaultSvrCacheRoot         = '/home/lscache/';
        $this->tmpCpanelPluginTplDir       =
            self::USER_PLUGIN_BACKUP_DIR . '/landing';
        $this->tmpCpanelPluginCustTransDir =
            self::USER_PLUGIN_BACKUP_DIR . '/cust';

        /** @noinspection PhpUnhandledExceptionInspection */
        parent::init2();
    }

    protected function initConfPaths()
    {
        $this->apacheConf   =
            '/etc/apache2/conf.d/includes/pre_main_global.conf';
        $this->apacheVHConf =
            '/etc/apache2/conf.d/userdata/lscache_vhosts.conf';
    }

    /**
     *
     * @return string
     */
    protected function serverCacheRootSearch()
    {
        if ( file_exists($this->apacheConf) ) {
            return $this->getCacheRootSetting($this->apacheConf);
        }

        return '';
    }

    /**
     *
     * @return string
     */
    protected function vhCacheRootSearch()
    {
        $apacheUserdataDir = dirname($this->apacheVHConf);

        if ( file_exists($apacheUserdataDir) ) {
            return $this->cacheRootSearch($apacheUserdataDir);
        }

        return '';
    }

    /**
     *
     * @param array  $file_contents
     * @param string $vhCacheRoot
     *
     * @return array
     */
    protected function addVHCacheRootSection(
        array $file_contents,
              $vhCacheRoot = 'lscache' )
    {
        array_unshift(
            $file_contents,
            "<IfModule LiteSpeed>\nCacheRoot $vhCacheRoot\n</IfModule>\n\n"
        );

        return $file_contents;
    }

    /**
     *
     * @param string $vhConf
     * @param string $vhCacheRoot
     *
     * @throws LSCMException  Thrown when virtual host conf directory cannot be
     *     created.
     * @throws LSCMException  Thrown when virtual host conf file cannot be
     *     created.
     * @throws LSCMException  Thrown indirectly by $this->log() call.
     * @throws LSCMException  Thrown indirectly by $this->log() call.
     */
    public function createVHConfAndSetCacheRoot(
        $vhConf,
        $vhCacheRoot = 'lscache' )
    {
        $vhConfDir = dirname($vhConf);

        if ( !file_exists($vhConfDir) ) {

            if ( !mkdir($vhConfDir, 0755) ) {
                throw new LSCMException(
                    "Failed to create directory $vhConfDir."
                );
            }

            $this->log("Created directory $vhConfDir", Logger::L_DEBUG);
        }

        $vhConfFileCreated = (
            file_put_contents(
                $vhConf,
                "<IfModule Litespeed>\nCacheRoot $vhCacheRoot\n</IfModule>"
            )
            !==
            false
        );

        if ( !$vhConfFileCreated ) {
            throw new LSCMException("Failed to create file $vhConf.");
        }

        $this->log("Created file $vhConf.", Logger::L_DEBUG);
    }

    /**
     *
     * @throws LSCMException  Thrown indirectly by
     *     self::UpdateCpanelPluginConf() call.
     */
    public function applyVHConfChanges()
    {
        exec('/scripts/ensure_vhost_includes --all-users');

        if ( file_exists(self::THEME_JUPITER_USER_PLUGIN_DIR)
                || file_exists(self::THEME_PAPER_LANTERN_USER_PLUGIN_DIR) ) {

            self::UpdateCpanelPluginConf(
                self::USER_PLUGIN_SETTING_VHOST_CACHE_ROOT,
                $this->vhCacheRoot
            );
        }
    }

    /**
     * Gets a list of found docroots and associated server names.
     * Only needed for scan logic.
     *
     * @throws LSCMException  Thrown when an error is encountered by
     *     preg_split() call on trimmed $line value.
     * @throws LSCMException  Thrown indirectly by Logger::debug() call.
     *
     * @noinspection SpellCheckingInspection
     */
    protected function prepareDocrootMap()
    {
        exec(
            'grep -hro '
                . '--exclude="cache" --exclude="main" --exclude="*.cache" '
                . '"documentroot.*\|serveralias.*\|servername.*" '
                . '/var/cpanel/userdata/*',
            $lines
        );

        /**
         * [0]=docroot, [1]=serveraliases, [2]=servername, [3]=docroot, etc.
         * Not unique & not sorted.
         *
         * Example:
         * documentroot: /home/user1/finches
         * serveralias: finches.com mail.finches.com www.finches.com www.finches.user1.com cpanel.finches.com autodiscover.finches.com whm.finches.com webmail.finches.com webdisk.finches.com
         * servername: finches.user1.com
         * documentroot: /home/user1/public_html/dookoo
         * serveralias: www.dookoo.user1.com
         * servername: dookoo.user1.com
         * documentroot: /home/user1/public_html/doo/doo2
         * serveralias: www.doo2.user1.com
         * servername: doo2.user1.com
         * documentroot: /home/user1/finches
         * serveralias: finches.com mail.finches.com www.finches.com www.finches.user1.com
         * servername: finches.user1.com
         */

        $cur = '';
        $docroots = array();

        foreach ( $lines as $line ) {

            if ( $cur == '' ) {

                if ( strpos($line, 'documentroot:') === 0 ) {
                    /**
                     * 13 is strlen('documentroot:')
                     */
                    $cur = trim(substr($line, 13));

                    if ( !isset($docroots[$cur]) ) {

                        if ( is_dir($cur) ) {
                            $docroots[$cur] = '';
                        }
                        else {
                            /**
                             * bad entry ignore
                             */
                            $cur = '';
                        }
                    }
                }
            }
            elseif ( strpos($line, 'serveralias:') === 0 ) {
                /**
                 * 12 is strlen('serveralias:')
                 */
                $docroots[$cur] .= substr($line, 12);
            }
            elseif ( strpos($line, 'servername:') === 0 ) {
                /**
                 * 11 is strlen('servername:')
                 */
                $docroots[$cur] .= substr($line, 11);

                /**
                 * looking for the next docroot
                 */
                $cur = '';
            }
            else {
                Logger::debug("Unused line when preparing docroot map: $line.");
            }
        }

        $roots = array();
        $servernames = array();
        $index = 0;

        foreach ( $docroots as $docroot => $line ) {
            $names = preg_split('/\s+/', trim($line), -1, PREG_SPLIT_NO_EMPTY);

            if ( $names === false ) {
                throw new LSCMException(
                    'prepareDocrootMap(): Error encountered when calling '
                        . 'preg_split() on trimmed $line.'
                );
            }

            $names = array_unique($names);
            $roots[$index] = $docroot;

            foreach ( $names as $n ) {
                $servernames[$n] = $index;
            }

            $index++;
        }

        $this->docRootMap =
            array( 'docroots' => $roots, 'names' => $servernames );
    }

    /**
     *
     * @param WPInstall $wpInstall
     *
     * @return string
     */
    public function getPhpBinary( WPInstall $wpInstall )
    {
        /**
         * cPanel php wrapper should accurately detect the correct binary in
         * EA4 when EA4 only directive '--ea-reference-dir' is provided.
         */
        return '/usr/local/bin/php '
            . "--ea-reference-dir={$wpInstall->getPath()}/wp-admin "
            . $this->phpOptions;
    }

    /**
     *
     * @return bool
     */
    public static function isCpanelPluginAutoInstallOn()
    {
        if ( file_exists(self::CPANEL_AUTOINSTALL_DISABLE_FLAG) ) {
            return false;
        }

        return true;
    }

    /**
     *
     * @return bool
     */
    public static function turnOnCpanelPluginAutoInstall()
    {
        if ( !file_exists(self::CPANEL_AUTOINSTALL_DISABLE_FLAG) ) {
            return true;
        }

        return unlink(self::CPANEL_AUTOINSTALL_DISABLE_FLAG);
    }

    /**
     *
     * @return bool
     */
    public static function turnOffCpanelPluginAutoInstall()
    {
        return touch(self::CPANEL_AUTOINSTALL_DISABLE_FLAG);
    }

    /**
     *
     * @return string
     *
     * @throws LSCMException  Thrown when unable to find cPanel user-end plugin
     *     installation script.
     * @throws LSCMException Thrown when failing to back up cPanel user-end
     *     plugin data files.
     * @throws LSCMException  Thrown indirectly by
     *     self::backupCpanelPluginDataFiles() call.
     * @throws LSCMException  Thrown indirectly by Logger::error() call.
     */
    public function installCpanelPlugin()
    {
        if ( !file_exists(self::USER_PLUGIN_INSTALL_SCRIPT) ) {
            throw new LSCMException(
                'Unable to find cPanel user-end plugin installation script.'
                    . ' Please ensure that the LiteSpeed WHM plugin is already '
                    . 'installed.'
            );
        }

        $existingInstall = (
            file_exists(self::THEME_JUPITER_USER_PLUGIN_DIR)
                || file_exists(self::THEME_PAPER_LANTERN_USER_PLUGIN_DIR)
        );

        if ( $existingInstall ) {

            if ( !self::backupCpanelPluginDataFiles() ) {
                throw new LSCMException(
                    'Failed to backup cPanel user-end plugin data files. '
                        . 'Aborting install/update operation.'
                );
            }

            exec(self::USER_PLUGIN_INSTALL_SCRIPT);

            if ( !self::restoreCpanelPluginDataFiles() ) {
                Logger::error(
                    'Failed to restore cPanel user-end plugin data files.'
                );
            }
        }
        else {
            exec(self::USER_PLUGIN_INSTALL_SCRIPT);
            self::turnOnCpanelPluginAutoInstall();
        }

        $this->updateCoreCpanelPluginConfSettings();

        return ($existingInstall) ? 'update' : 'new';
    }

    /**
     *
     * @since 1.13.2
     * @since 1.13.2.2  Made function static.
     * @since 1.13.5.2  Removed optional param $oldLogic.
     *
     * @return bool
     *
     * @throws LSCMException  Thrown when failing to create a temporary backup
     *     directory.
     */
    protected static function backupCpanelPluginDataFiles()
    {
        if ( file_exists(self::THEME_JUPITER_USER_PLUGIN_DIR) ) {
            $pluginDir = self::THEME_JUPITER_USER_PLUGIN_DIR;
        }
        elseif ( file_exists(self::THEME_PAPER_LANTERN_USER_PLUGIN_DIR) ) {
            $pluginDir = self::THEME_PAPER_LANTERN_USER_PLUGIN_DIR;
        }
        else {
            return false;
        }

        if ( file_exists(self::USER_PLUGIN_BACKUP_DIR) ) {
            Util::rrmdir(self::USER_PLUGIN_BACKUP_DIR);
        }

        if ( !mkdir(self::USER_PLUGIN_BACKUP_DIR, 0755) ) {
            throw new LSCMException(
                'Failed to make temporary directory '
                    . self::USER_PLUGIN_BACKUP_DIR
            );
        }

        /**
         * Move existing conf file (if needed), templates, and custom
         * translations to temp directory and remove default template dir to
         * prevent overwriting when moving back.
         */

        $activeConfFile =
            self::getInstalledCpanelPluginActiveConfFileLocation($pluginDir);

        if ( $activeConfFile == '' || !file_exists($activeConfFile) ) {
            return false;
        }

        $backupCmds = '';

        if ( $activeConfFile != self::USER_PLUGIN_CONF ) {
            $backupCmds .= "/bin/mv $activeConfFile "
                . self::USER_PLUGIN_BACKUP_DIR . '/;';
        }

        $tmpCpanelPluginCustTransDir = self::USER_PLUGIN_BACKUP_DIR . '/cust';

        $backupCmds .= '/bin/mv '
            . "$pluginDir/landing " . self::USER_PLUGIN_BACKUP_DIR . '/;'
            . "/bin/rm -rf "
            . self::USER_PLUGIN_BACKUP_DIR . '/landing/default;'
            . '/bin/mv '
            . "$pluginDir/lang/cust $tmpCpanelPluginCustTransDir;"
            . "/bin/rm -rf $tmpCpanelPluginCustTransDir/README";

        exec($backupCmds);

        return true;
    }

    /**
     *
     * @since 1.13.2
     * @since 1.13.2.2  Made function static.
     * @since 1.13.5.2  Removed optional param $oldLogic.
     *
     * @return bool
     */
    protected static function restoreCpanelPluginDataFiles()
    {
        $pluginInstalls = array();

        if ( file_exists(self::THEME_JUPITER_USER_PLUGIN_DIR) ) {
            $pluginInstalls[] = self::THEME_JUPITER_USER_PLUGIN_DIR;
        }

        if ( file_exists(self::THEME_PAPER_LANTERN_USER_PLUGIN_DIR) ) {
            $pluginInstalls[] = self::THEME_PAPER_LANTERN_USER_PLUGIN_DIR;
        }


        if ( !file_exists(self::USER_PLUGIN_BACKUP_DIR)
                || empty($pluginInstalls) ) {

            return false;
        }

        $tmpCpanelPluginConfFile = self::USER_PLUGIN_BACKUP_DIR . '/lswcm.conf';

        foreach ( $pluginInstalls as $pluginInstall ) {

            $cpanelPluginLangDir = "$pluginInstall/lang";

            if (!file_exists($cpanelPluginLangDir)) {
                mkdir($cpanelPluginLangDir, 0755);
            }

            if ( file_exists($tmpCpanelPluginConfFile) ) {
                $activeConfFile = self::getInstalledCpanelPluginActiveConfFileLocation(
                    $pluginInstall
                );

                if ($activeConfFile == '') {
                    return false;
                }

                copy($tmpCpanelPluginConfFile, $activeConfFile);
                chmod($activeConfFile, 0644);
            }

            /**
             * Replace cPanel plugin templates, custom translations.
             */
            exec(
                '/bin/cp -prf '
                    . self::USER_PLUGIN_BACKUP_DIR . "/landing $pluginInstall/;"
                    . '/bin/cp -prf '
                    . self::USER_PLUGIN_BACKUP_DIR
                    . "/cust $cpanelPluginLangDir/"
            );
        }

        exec('/bin/rm -rf ' . self::USER_PLUGIN_BACKUP_DIR);

        return true;
    }

    /**
     *
     * @since 1.13.2.2  Made function static.
     *
     * @throws LSCMException  Thrown when unable to find the uninstallation
     *     script.
     */
    public static function uninstallCpanelPlugin()
    {
        $jupiterUninstallFile = self::THEME_JUPITER_USER_PLUGIN_DIR . '/'
            . self::USER_PLUGIN_RELATIVE_UNINSTALL_SCRIPT;
        $paperLanternUninstallFile = self::THEME_PAPER_LANTERN_USER_PLUGIN_DIR
            . '/' . self::USER_PLUGIN_RELATIVE_UNINSTALL_SCRIPT;

        if ( file_exists($jupiterUninstallFile) ) {
            $uninstallFile = $jupiterUninstallFile;
        }
        elseif ( file_exists($paperLanternUninstallFile) ) {
            $uninstallFile = $paperLanternUninstallFile;
        }
        else {
            throw new LSCMException(
                'Unable to find cPanel user-end plugin uninstallation script. '
                    . 'Plugin may already be uninstalled.'
            );
        }

        exec($uninstallFile);

        self::turnOffCpanelPluginAutoInstall();
    }

    /**
     * Attempt to update core cPanel plugin settings used for basic plugin
     * operation to the currently discovered values.
     *
     * @since 1.13.2.2
     * @since 1.13.5  Changed function visibility to public.
     *
     * @throws LSCMException  Thrown indirectly by
     *     self::UpdateCpanelPluginConf() call.
     * @throws LSCMException  Thrown indirectly by $this->getVHCacheRoot() call.
     * @throws LSCMException  Thrown indirectly by
     *     self::UpdateCpanelPluginConf() call.
     */
    public function updateCoreCpanelPluginConfSettings()
    {
        self::UpdateCpanelPluginConf(
            self::USER_PLUGIN_SETTING_LSWS_DIR,
            realpath(__DIR__ . '/../../../..')
        );

        self::UpdateCpanelPluginConf(
            self::USER_PLUGIN_SETTING_VHOST_CACHE_ROOT,
            $this->getVHCacheRoot()
        );
    }

    /**
     *
     * @since 1.13.2.2  Made function static.
     *
     * @param string $setting
     * @param mixed  $value
     *
     * @throws LSCMException  Thrown when unable to determine active cPanel
     *     user-end plugin conf file location usually indicating that the
     *     cPanel user-end plugin is not currently installed.
     * @throws LSCMException  Thrown when unable to create cPanel user-end
     *     plugin "data" directory for older versions of the cPanel user-end
     *     plugin that require this directory.
     */
    public static function UpdateCpanelPluginConf( $setting, $value )
    {
        $pluginInstalls = array();

        if ( file_exists(self::THEME_JUPITER_USER_PLUGIN_DIR) ) {
            $pluginInstalls[] = self::THEME_JUPITER_USER_PLUGIN_DIR;
        }
        else {
            $pluginInstalls[] = self::THEME_PAPER_LANTERN_USER_PLUGIN_DIR;
        }

        foreach ( $pluginInstalls as $pluginInstall ) {
            $activeConfFile = self::getInstalledCpanelPluginActiveConfFileLocation(
                $pluginInstall
            );

            if ( $activeConfFile == '' ) {
                throw new LSCMException(
                    'Unable to determine active conf file location for cPanel '
                        . 'user-end plugin. cPanel user-end plugin is likely '
                        . 'not installed.'
                );
            }

            if ( !file_exists($activeConfFile) ) {
                $oldConf = '';

                if ( file_exists("$pluginInstall/" . self::USER_PLUGIN_RELATIVE_CONF_OLD_2) ) {
                    $oldConf = "$pluginInstall/" . self::USER_PLUGIN_RELATIVE_CONF_OLD_2;
                }
                elseif ( file_exists("$pluginInstall/" . self::USER_PLUGIN_RELATIVE_CONF_OLD) ) {
                    $oldConf = "$pluginInstall/" . self::USER_PLUGIN_RELATIVE_CONF_OLD;
                }

                if ( $oldConf != '' ) {
                    $dataDir =
                        "$pluginInstall/" . self::USER_PLUGIN_RELATIVE_DATA_DIR;

                    if ( $activeConfFile == "$pluginInstall/" . self::USER_PLUGIN_RELATIVE_CONF_OLD_2
                        && !file_exists($dataDir)
                        && !mkdir($dataDir) ) {

                        throw new LSCMException(
                            "Failed to create directory $dataDir."
                        );
                    }

                    copy($oldConf, $activeConfFile);
                }
            }

            if ( file_exists($activeConfFile) ) {
                chmod($activeConfFile, 0644);

                switch ( $setting ) {

                    case self::USER_PLUGIN_SETTING_LSWS_DIR:
                        $pattern = '/LSWS_HOME_DIR = ".*"/';
                        $replacement = "LSWS_HOME_DIR = \"$value\"";
                        break;

                    case self::USER_PLUGIN_SETTING_VHOST_CACHE_ROOT:
                        $pattern = '/VHOST_CACHE_ROOT = ".*"/';
                        $replacement = "VHOST_CACHE_ROOT = \"$value\"";
                        break;

                    default:
                        return;
                }

                $content = file_get_contents($activeConfFile);

                if ( preg_match($pattern, $content) ) {
                    file_put_contents(
                        $activeConfFile,
                        preg_replace($pattern, $replacement, $content)
                    );
                }
                else {
                    file_put_contents(
                        $activeConfFile,
                        $replacement,
                        FILE_APPEND
                    );
                }
            }
        }
    }

    /**
     *
     * @since 1.13.11
     *
     * @param string $pluginDir
     *
     * @return string
     */
    protected static function getInstalledCpanelPluginActiveConfFileLocation(
        $pluginDir )
    {
        $versionFile = "$pluginDir/VERSION";

        if ( file_exists($versionFile) ) {
            $verGreaterThan2_1_2_2 = Util::betterVersionCompare(
                file_get_contents($versionFile),
                '2.1.2.2',
                '>'
            );

            if ( $verGreaterThan2_1_2_2 ) {
                return self::USER_PLUGIN_CONF;
            }
        }

        if ( file_exists("$pluginDir/" . self::USER_PLUGIN_RELATIVE_DATA_DIR) ) {
            return "$pluginDir/" . self::USER_PLUGIN_RELATIVE_CONF_OLD_2;
        }

        if ( file_exists($pluginDir) ) {
            return "$pluginDir/" . self::USER_PLUGIN_RELATIVE_CONF_OLD;
        }

        return '';
    }

}
webcachemgr/src/Panel/Plesk.php000066400000030124150545647710012450 0ustar00<?php

/** ******************************************
 * LiteSpeed Web Server Cache Manager
 *
 * @author LiteSpeed Technologies, Inc. (https://www.litespeedtech.com)
 * @copyright (c) 2018-2023
 * ******************************************* */

namespace Lsc\Wp\Panel;

use Lsc\Wp\Logger;
use Lsc\Wp\LSCMException;
use Lsc\Wp\Util;
use Lsc\Wp\WPInstall;

class Plesk extends ControlPanel
{

    /**
     *
     * @throws LSCMException Thrown indirectly by parent::__construct() call.
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     *
     * @since 1.13.2
     *
     * @throws LSCMException  Thrown indirectly by parent::init2() call.
     */
    protected function init2()
    {
        $this->panelName = 'Plesk';
        $this->defaultSvrCacheRoot = '/var/www/vhosts/lscache/';
        parent::init2();
    }

    /**
     * More reliable than php_uname('s')
     *
     * @return string
     *
     * @throws LSCMException  Thrown when supported Plesk OS detection command
     *     fails.
     * @throws LSCMException  Thrown when supported OS is not detected.
     */
    public function getPleskOS()
    {
        $supportedOsList = array(
            'centos',
            'virtuozzo',
            'cloudlinux',
            'redhat',
            'rhel',
            'ubuntu',
            'debian',
            'almalinux',
            'rocky'
        );

        $cmds = array();

        if ( file_exists('/etc/debian_version') ) {
            return 'debian';
        }

        if ( is_readable('/etc/os-release') ) {
            $cmds[] = 'grep ^ID= /etc/os-release | cut -d "=" -f2 | xargs';
        }

        if ( is_readable('/etc/lsb-release') ) {
            $cmds[] =
                'grep ^DISTRIB_ID= /etc/lsb-release | cut -d "=" -f2 | xargs';
        }

        if ( is_readable('/etc/redhat-release') ) {
            $cmds[] = 'cat /etc/redhat-release | awk \'{print $1}\'';
        }

        foreach ( $cmds as $cmd ) {

            if ( !($output = shell_exec($cmd)) ) {
                throw new LSCMException(
                    'Supported Plesk OS detection command failed.',
                    LSCMException::E_UNSUPPORTED
                );
            }

            $OS = trim($output);

            foreach ( $supportedOsList as $supportedOs ) {

                if ( stripos($OS, $supportedOs) !== false ) {
                    return $supportedOs;
                }
            }
        }

        throw new LSCMException(
            'Plesk detected with unsupported OS. '
                . '(Not CentOS/Virtuozzo/Cloudlinux/RedHat/Ubuntu/Debian/'
                . 'AlmaLinux/Rocky)',
            LSCMException::E_UNSUPPORTED
        );
    }

    /**
     *
     * @since 1.13.3
     *
     * @return string
     */
    protected function getVhDir()
    {
        $vhDir = '/var/www/vhosts';

        $psaConfFile = '/etc/psa/psa.conf';

        if ( file_exists($psaConfFile) ) {
            $ret = preg_match(
                '/HTTPD_VHOSTS_D\s+(\S+)/',
                file_get_contents($psaConfFile),
                $m
            );

            if ( $ret == 1 ) {
                $vhDir = $m[1];
            }
        }

        return $vhDir;
    }

    /**
     *
     * @throws LSCMException  Thrown indirectly by $this->getPleskOS() call.
     */
    protected function initConfPaths()
    {
        $OS = $this->getPleskOS();

        switch ( $OS ) {

            case 'centos':
            case 'virtuozzo':
            case 'cloudlinux':
            case 'redhat':
            case 'rhel':
            case 'almalinux':
            case 'rocky':
                $this->apacheConf = '/etc/httpd/conf.d/lscache.conf';
                break;

            case 'ubuntu':
                $this->apacheConf = '/etc/apache2/conf-enabled/lscache.conf';
                break;

            case 'debian':

                if ( is_dir('/etc/apache2/conf-enabled') ) {
                    $this->apacheConf =
                        '/etc/apache2/conf-enabled/lscache.conf';
                }
                else {
                    /**
                     * Old location.
                     */
                    $this->apacheConf = '/etc/apache2/conf.d/lscache.conf';
                }

                break;

            //no default case
        }

        $this->apacheVHConf = '/usr/local/psa/admin/conf/templates'
            . '/custom/domain/domainVirtualHost.php';
    }

    /**
     *
     * @return string
     */
    protected function serverCacheRootSearch()
    {
        $apacheConfDir = dirname($this->apacheConf);

        if ( file_exists($apacheConfDir) ) {
            return $this->cacheRootSearch($apacheConfDir);
        }

        return '';
    }

    /**
     *
     * @return string
     */
    protected function vhCacheRootSearch()
    {
        if ( file_exists($this->apacheVHConf) ) {
            return $this->getCacheRootSetting($this->apacheVHConf);
        }

        return '';
    }

    /**
     *
     * @param array  $file_contents
     * @param string $vhCacheRoot
     *
     * @return array
     */
    protected function addVHCacheRootSection(
        array $file_contents,
              $vhCacheRoot = 'lscache' )
    {
        return preg_replace(
            '!^\s*</VirtualHost>!im',
            "<IfModule Litespeed>\nCacheRoot $vhCacheRoot\n</IfModule>\n"
                . '</VirtualHost>',
            $file_contents
        );
    }

    /**
     *
     * @param string $vhConf
     * @param string $vhCacheRoot
     *
     * @throws LSCMException  Thrown indirectly by $this->log() call.
     * @throws LSCMException  Thrown indirectly by $this->log() call.
     * @throws LSCMException  Thrown indirectly by $this->log() call.
     */
    public function createVHConfAndSetCacheRoot(
        $vhConf,
        $vhCacheRoot = 'lscache' )
    {
        $vhConfTmpl = '/usr/local/psa/admin/conf/templates/default/domain/'
            . 'domainVirtualHost.php';
        $vhConfDir = dirname($vhConf);

        if ( !file_exists($vhConfDir) ) {
            mkdir($vhConfDir, 0755, true);

            $this->log("Created directory $vhConfDir", Logger::L_DEBUG);
        }

        copy($vhConfTmpl, $vhConf);
        Util::matchPermissions($vhConfTmpl, $vhConf);

        $this->log(
            "Copied Virtual Host conf template file $vhConfTmpl to $vhConf",
            Logger::L_DEBUG
        );

        file_put_contents(
            $vhConf,
            preg_replace(
                '!^\s*</VirtualHost>!im',
                "<IfModule Litespeed>\nCacheRoot $vhCacheRoot\n</IfModule>"
                    . "\n</VirtualHost>",
                file($vhConf)
            )
        );

        $this->log(
            "Virtual Host cache root set to $vhCacheRoot",
            Logger::L_INFO
        );
    }

    public function applyVHConfChanges()
    {
        exec('/usr/local/psa/admin/bin/httpdmng --reconfigure-all');
    }

    /**
     * Gets a list of found docroots and associated server names.
     *
     * Note: This function is repeated in Plesk plugin files to avoid extra
     * serialize ops etc. This copy is for cli only.
     */
    protected function prepareDocrootMap()
    {
        exec(
            'grep -hro --exclude="stat_ttl.conf" --exclude="*.bak" '
                . '--exclude="last_httpd.conf" '
                . '"DocumentRoot.*\|ServerName.*\|ServerAlias.*" '
                . "{$this->getVhDir()}/system/*/conf/*",
            $lines
        );

        /**
         * [0]=servername, [1]=serveralias, [2]=serveralias, [3]=docroot, etc.
         * Not unique & not sorted.
         *
         * Example:
         * ServerName "pltest1.com:443"
         * ServerAlias "www.pltest1.com"
         * ServerAlias "ipv4.pltest1.com"
         * DocumentRoot "/var/www/vhosts/pltest1.com/httpdocs"
         * ServerName "pltest1.com:80"
         * ServerAlias "www.pltest1.com"
         * ServerAlias "ipv4.pltest1.com"
         * DocumentRoot "/var/www/vhosts/pltest1.com/httpdocs"
         * ServerName "pltest2.com:443"
         * ServerAlias "www.pltest2.com"
         * ServerAlias "ipv4.pltest2.com"
         * DocumentRoot "/var/www/vhosts/pltest2.com/httpdocs"
         * ServerName "pltest2.com:80"
         * ServerAlias "www.pltest2.com"
         * ServerAlias "ipv4.pltest2.com"
         * DocumentRoot "/var/www/vhosts/pltest2.com/httpdocs"
         *
         * @noinspection SpellCheckingInspection
         */

        $x = 0;
        $names = $tmpDocrootMap = array();

        $lineCount = count($lines);

        while ( $x <  $lineCount ) {
            $matchFound =
                preg_match('/ServerName\s+"([^"]+)"/', $lines[$x], $m1);

            if ( !$matchFound ) {
                /**
                 * Invalid start of group, skip.
                 */
                $x++;
                continue;
            }

            $UrlInfo = parse_url(
                (preg_match('#^https?://#', $m1[1])) ? $m1[1] : "http://$m1[1]"
            );

            $names[] = $UrlInfo['host'];
            $x++;

            $pattern = '/ServerAlias\s+"([^"]+)"/';

            while ( isset($lines[$x])
                    && preg_match($pattern, $lines[$x], $m2) ) {

                $names[] = $m2[1];
                $x++;
            }

            $pattern = '/DocumentRoot\s+"([^"]+)"/';

            if ( isset($lines[$x])
                    && preg_match($pattern, $lines[$x], $m3) == 1
                    && is_dir($m3[1]) ) {

                $docroot = $m3[1];

                if ( !isset($tmpDocrootMap[$docroot]) ) {
                    $tmpDocrootMap[$docroot] = $names;
                }
                else {
                    $tmpDocrootMap[$docroot] =
                        array_merge($tmpDocrootMap[$docroot], $names);
                }

                $x++;
            }

            $names = array();
        }

        $index = 0;
        $roots = $serverNames = array();

        foreach ( $tmpDocrootMap as $docroot => $names ) {
            $roots[$index] = $docroot;

            $names = array_unique($names);

            foreach ( $names as $n ) {
                $serverNames[$n] = $index;
            }

            $index++;
        }

        $this->docRootMap =
            array( 'docroots' => $roots, 'names' => $serverNames );
    }

    /**
     * Check for known Plesk PHP binaries and return the newest available
     * version among them.
     *
     * @since 1.9.6
     *
     * @return string
     */
    protected function getDefaultPhpBinary()
    {
        $binaryList = array (
            '/opt/plesk/php/8.2/bin/php',
            '/opt/plesk/php/8.1/bin/php',
            '/opt/plesk/php/8.0/bin/php',
            '/opt/plesk/php/7.4/bin/php',
            '/opt/plesk/php/7.3/bin/php',
            '/opt/plesk/php/7.2/bin/php',
            '/opt/plesk/php/7.1/bin/php',
            '/opt/plesk/php/7.0/bin/php',
            '/opt/plesk/php/5.6/bin/php',
        );

        foreach ( $binaryList as $binary ) {

            if ( file_exists($binary)) {
                return $binary;
            }
        }

        return '';
    }

    /**
     *
     * @param WPInstall $wpInstall
     *
     * @return string
     */
    public function getPhpBinary( WPInstall $wpInstall )
    {
        $serverName = $wpInstall->getData(WPInstall::FLD_SERVERNAME);

        if ( $serverName != null ) {
            $output = shell_exec(
                'plesk db -Ne "SELECT s.value '
                    . 'FROM ((domains d INNER JOIN hosting h ON h.dom_id=d.id) '
                    . 'INNER JOIN ServiceNodeEnvironment s '
                    . 'ON h.php_handler_id=s.name) '
                    . 'WHERE d.name=' . escapeshellarg($serverName)
                    . ' AND s.section=\'phphandlers\'" '
                    . '| sed -n \'s:.*<clipath>\(.*\)</clipath>.*:\1:p\''
            );

            if ( $output ) {
                $binPath = trim($output);
            }
        }

        if ( !empty($binPath) ) {
            $phpBin = $binPath;
        }
        elseif ( ($defaultBinary = $this->getDefaultPHPBinary()) != '' ) {
            $phpBin = $defaultBinary;
        }
        else {
            $phpBin = 'php';
        }

        return "$phpBin $this->phpOptions";
    }

}
webcachemgr/src/Panel/ControlPanel.php000066400000074633150545647710014007 0ustar00<?php

/** ******************************************
 * LiteSpeed Web Server Cache Manager
 *
 * @author    Michael Alegre
 * @copyright 2017-2024 LiteSpeed Technologies, Inc.
 * ******************************************* */

namespace Lsc\Wp\Panel;

use DirectoryIterator;
use Exception;
use Lsc\Wp\Logger;
use Lsc\Wp\LSCMException;
use Lsc\Wp\Util;
use Lsc\Wp\WPInstall;

abstract class ControlPanel
{

    /**
     * @deprecated
     *
     * @var string
     */
    const PANEL_CPANEL = 'whm';

    /**
     * @deprecated
     *
     * @var string
     */
    const PANEL_PLESK = 'plesk';

    /**
     * @var string
     */
    const PANEL_API_VERSION = '1.17.4.2';

    /**
     * @since 1.9
     * @var int
     */
    const PANEL_API_VERSION_SUPPORTED = 0;

    /**
     * @since 1.9
     * @var int
     */
    const PANEL_API_VERSION_TOO_LOW = 1;

    /**
     * @since 1.9
     * @var int
     */
    const PANEL_API_VERSION_TOO_HIGH = 2;

    /**
     * @since 1.9
     * @var int
     */
    const PANEL_API_VERSION_UNKNOWN = 3;

    /**
     * @var int
     */
    const PHP_TIMEOUT = 30;

    /**
     * @var string
     */
    const NOT_SET = '__LSC_NOTSET__';

    /**
     * @var string
     */
    protected $panelName = '';

    /**
     * @var string
     */
    protected $phpOptions;

    /**
     * @var null|string
     */
    protected $serverCacheRoot;

    /**
     * @var null|string
     */
    protected $vhCacheRoot;

    /**
     * @var string
     */
    protected $defaultSvrCacheRoot;

    /**
     * @var string
     */
    protected $apacheConf;

    /**
     * @var string
     */
    protected $apacheVHConf;

    /**
     * @var null|array[]  'docroots' => (index => docroots),
     *                    'names'    => (servername => index)
     */
    protected $docRootMap = null;

    /**
     * @since 1.9.7
     * @var string
     */
    protected static $minAPIFilePath = '';

    /**
     * @var null|ControlPanel  Object that extends ControlPanel abstract class.
     */
    protected static $instance;

    /**
     *
     * @throws LSCMException  Thrown indirectly by $this->init2() call.
     */
    protected function __construct()
    {
        $this->init2();
    }

    /**
     * Temporary function name until existing deprecated public static init()
     * function is removed.
     *
     * @since 1.13.2
     *
     * @throws LSCMException  Thrown indirectly by $this->initConfPaths() call.
     */
    protected function init2()
    {
        /**
         * output_handler value cleared to avoid compressed output through
         * 'ob_gzhandler' etc.
         */
        $this->phpOptions = '-d disable_functions=ini_set -d opcache.enable=0 '
            . '-d max_execution_time=' . static::PHP_TIMEOUT
            . ' -d memory_limit=512M -d register_argc_argv=1 '
            . '-d zlib.output_compression=0 -d output_handler= '
            . '-d safe_mode=0 -d open_basedir=';

        $this->initConfPaths();
    }

    /**
     * Deprecated 02/04/19 as this function will be made private.
     * Use getClassInstance() with a fully qualified class name as a parameter
     * instead.
     *
     * Sets static::$instance with a new $className instance if it has not been
     * set already. An exception will be thrown if static::$instance has already
     * been set to a different class name than the one provided.
     *
     * @deprecated
     *
     * @param string $className  A fully qualified control panel class name.
     *
     * @return ControlPanel|null  Object that extends ControlPanel abstract
     *     class.
     *
     * @throws LSCMException  Thrown when unable to include custom panel file.
     * @throws LSCMException  Thrown when class 'CustomPanel' does not extend
     *     class '\Lsc\Wp\Panel\CustomPanelBase'.
     * @throws LSCMException  Re-thrown when "new $className()" call throws an
     *     exception.
     * @throws LSCMException  Thrown when an instance of a different
     *     ControlPanel/CustomPanel extending class has already been created.
     */
    public static function initByClassName( $className )
    {
        if ( static::$instance == null ) {

            if ( $className == 'custom' ) {
                $lsws_home = realpath(__DIR__ . '/../../../../');
                $customPanelFile =
                    "$lsws_home/admin/lscdata/custom/CustomPanel.php";

                if ( ! file_exists($customPanelFile)
                        || ! include_once $customPanelFile ) {

                    throw new LSCMException(
                        "Unable to include file $customPanelFile"
                    );
                }

                $className = '\Lsc\Wp\Panel\CustomPanel';

                $isSubClass = is_subclass_of(
                    $className,
                    '\Lsc\Wp\Panel\CustomPanelBase'
                );

                if ( ! $isSubClass ) {
                    throw new LSCMException(
                        'Class CustomPanel must extend class '
                            . '\Lsc\Wp\Panel\CustomPanelBase'
                    );
                }
            }

            try{
                static::$instance = new $className();
            }
            catch ( Exception $e ){
                throw new LSCMException(
                    "Could not create object with class name $className. "
                        . "Error: {$e->getMessage()}"
                );
            }
        }
        else {
            $instanceClassName = '\\' . get_class(static::$instance);

            if ( $instanceClassName != $className ) {
                throw new LSCMException(
                    "Could not initialize $className instance as an instance "
                        . "of another class ($instanceClassName) has already "
                        . 'been created.'
                );
            }
        }

        return static::$instance;
    }

    /**
     * Deprecated 01/14/19. Use initByClassName() instead.
     *
     * @deprecated
     *
     * @param string $name
     *
     * @return ControlPanel  Object that extends ControlPanel abstract class.
     *
     * @throws LSCMException  Thrown when static::$instance is not null.
     * @throws LSCMException  Thrown when provided $name is not recognized.
     * @throws LSCMException  Thrown indirectly by static::initByClassName()
     *     call.
     */
    public static function init( $name )
    {
        if ( static::$instance != null ) {
            throw new LSCMException(
                'ControlPanel cannot be initialized twice.'
            );
        }

        switch ($name) {
            case static::PANEL_CPANEL:
                $className = 'CPanel';
                break;
            case static::PANEL_PLESK:
                $className = 'Plesk';
                break;
            default:
                throw new LSCMException(
                    "Control panel '$name' is not supported."
                );
        }

        return static::initByClassName("\Lsc\Wp\Panel\\$className");
    }

    /**
     * Returns current ControlPanel instance when no $className is given. When
     * $className is provided, an instance of $className will also be
     * initialized if it has not yet been initialized already.
     *
     * @param string $className  Fully qualified class name.
     *
     * @return ControlPanel  Object that extends ControlPanel abstract class.
     *
     * @throws LSCMException  Thrown when static::$instance is null.
     * @throws LSCMException  Thrown indirectly by static::initByClassName()
     *     call.
     */
    public static function getClassInstance( $className = '' )
    {
        if ( $className != '' ) {
            static::initByClassName($className);
        }
        elseif ( static::$instance == null ) {
            throw new LSCMException(
                'Could not get instance, ControlPanel not initialized. '
            );
        }

        return static::$instance;
    }

    /**
     * Deprecated on 02/06/19. Use getClassInstance() instead.
     *
     * @deprecated
     *
     * @return ControlPanel  Object that extends ControlPanel abstract class.
     *
     * @throws LSCMException  Thrown indirectly by static::getClassInstance()
     *     call.
     */
    public static function getInstance()
    {
        return static::getClassInstance();
    }

    /**
     *
     * @param string $serverName
     *
     * @return string|null
     *
     * @throws LSCMException  Thrown indirectly by $this->prepareDocrootMap()
     *     call.
     */
    public function mapDocRoot( $serverName )
    {
        if ( $this->docRootMap == null ) {
            $this->prepareDocrootMap();
        }

        if ( isset($this->docRootMap['names'][$serverName]) ) {
            $index = $this->docRootMap['names'][$serverName];

            return $this->docRootMap['docroots'][$index];
        }

        // error out
        return null;
    }

    /**
     *
     * @return bool
     *
     * @throws LSCMException  Thrown indirectly by $this->getServerCacheRoot()
     *     call.
     * @throws LSCMException  Thrown indirectly by $this->getVHCacheRoot() call.
     */
    public function areCacheRootsSet()
    {
        $ret = true;

         if ( static::NOT_SET == $this->getServerCacheRoot() ) {
            $ret = false;
        }

        if ( static::NOT_SET == $this->getVHCacheRoot() ) {
            $ret = false;
        }

        return $ret;
    }

    /**
     *
     * @throws LSCMException  Thrown when cache is not enabled for the current
     *     LiteSpeed license.
     * @throws LSCMException  Thrown indirectly by $this->getServerCacheRoot()
     *     call.
     * @throws LSCMException  Thrown indirectly by $this->setServerCacheRoot()
     *     call.
     * @throws LSCMException  Thrown indirectly by $this->getVHCacheRoot() call.
     * @throws LSCMException  Thrown indirectly by $this->setVHCacheRoot() call.
     */
    public function verifyCacheSetup()
    {
        if ( !$this->isCacheEnabled() ) {
            throw new LSCMException(
                'LSCache is not included in the current LiteSpeed license. '
                    . 'Please purchase the LSCache add-on or upgrade to a '
                    . 'license type that includes LSCache and try again.',
                LSCMException::E_PERMISSION
            );
        }

        $restartRequired = false;

        if ( static::NOT_SET == $this->getServerCacheRoot() ) {
            $this->setServerCacheRoot();
            $restartRequired = true;
        }

        if ( static::NOT_SET == $this->getVHCacheRoot() ) {
            $this->setVHCacheRoot();
            $restartRequired = true;
        }

        if ( $restartRequired ) {
            Util::restartLsws();
        }
    }

    /**
     *
     * @param string $vhCacheRoot
     *
     * @throws LSCMException  Thrown indirectly by $this->log() call.
     * @throws LSCMException  Thrown indirectly by $this->writeVHCacheRoot()
     *     call.
     * @throws LSCMException  Thrown indirectly by $this->log() call.
     * @throws LSCMException  Thrown indirectly by $this->applyVHConfChanges()
     *     call.
     */
    public function setVHCacheRoot( $vhCacheRoot = 'lscache' )
    {
        $this->log('Attempting to set VH cache root...', Logger::L_VERBOSE);

        if ( !file_exists($this->apacheVHConf) ) {
            $this->createVHConfAndSetCacheRoot(
                $this->apacheVHConf,
                $vhCacheRoot
            );
        }
        else {
            $this->writeVHCacheRoot($this->apacheVHConf, $vhCacheRoot);
        }

        $this->vhCacheRoot = $vhCacheRoot;

        $this->log(
            "Virtual Host cache root set to $vhCacheRoot",
            Logger::L_INFO
        );

        if ( $this->vhCacheRoot[0] == '/'
                && !file_exists($this->vhCacheRoot) ) {

            /**
             * 01/29/19: Temporarily create top virtual host cache root
             * directory to avoid LSWS setting incorrect owner/group and
             * permissions for the directory outside the cage.
             */

            mkdir(str_replace('/$vh_user', '', $vhCacheRoot), 0755, true);
        }

        $this->applyVHConfChanges();
    }

    /**
     *
     * @return bool
     *
     * @throws LSCMException  Thrown when status file is not found.
     * @throws LSCMException  Thrown when status file cannot be read.
     *
     */
    public function isCacheEnabled()
    {
        $statusFile = '/tmp/lshttpd/.status';

        if ( !file_exists($statusFile) ) {
            throw new LSCMException(
                'Cannot determine LSCache availability. Please start/switch to '
                    . 'LiteSpeed Web Server before trying again.',
                LSCMException::E_PERMISSION
            );
        }

        if ( ($f = fopen($statusFile, 'r')) === false ) {
            throw new LSCMException(
                'Cannot determine LSCache availability.',
                LSCMException::E_PERMISSION
            );
        }

        fseek($f, -128, SEEK_END);
        $line = fread($f, 128);
        fclose($f);

        if ( preg_match('/FEATURES: ([0-9.]+)/', $line, $m)
                && ($m[1] & 1) == 1 ) {

            return true;
        }

        return false;
    }

    /**
     * return array of docroots, can set index from and batch
     *
     * @param int      $offset
     * @param null|int $length
     *
     * @return string[]
     *
     * @throws LSCMException  Thrown indirectly by $this->prepareDocrootMap()
     *     call.
     */
    public function getDocRoots( $offset = 0, $length = null )
    {
        if ( $this->docRootMap == null ) {
            $this->prepareDocrootMap();
        }

        return array_slice($this->docRootMap['docroots'], $offset, $length);
    }

    /**
     * Used in PleskEscalate.
     *
     * @return array[]
     *
     * @noinspection PhpUnused
     * @noinspection PhpDocMissingThrowsInspection
     */
    public function getDocrootMap()
    {
        if ( $this->docRootMap == null ) {
            /**
             * LSCMException not thrown in Plesk implementation.
             * @noinspection PhpUnhandledExceptionInspection
             */
            $this->prepareDocrootMap();
        }

        return $this->docRootMap;
    }

    /**
     *
     * @return string
     */
    public function getDefaultSvrCacheRoot()
    {
        return $this->defaultSvrCacheRoot;
    }

    /**
     *
     * @return string
     *
     * @throws LSCMException  Thrown indirectly by $this->initCacheRoots() call.
     */
    public function getServerCacheRoot()
    {
        if ( $this->serverCacheRoot == null ) {
            $this->initCacheRoots();
        }

        return $this->serverCacheRoot;
    }

    /**
     *
     * @return string
     *
     * @throws LSCMException  Thrown indirectly by $this->initCacheRoots() call.
     */
    public function getVHCacheRoot()
    {
        if ( $this->vhCacheRoot == null ) {
            $this->initCacheRoots();
        }

        return $this->vhCacheRoot;
    }

    /**
     *
     * @return void
     *
     * @throws LSCMException  Thrown in some existing implementations.
     */
    abstract protected function initConfPaths();

    /**
     *
     * @throws LSCMException  Thrown in some existing implementations.
     */
    abstract protected function prepareDocrootMap();

    /**
     *
     * @param WPInstall $wpInstall
     *
     * @return string
     *
     * @throws LSCMException  Thrown in some existing implementations.
     */
    abstract public function getPhpBinary( WPInstall $wpInstall );

    /**
     * Searches the given directories '.conf' files for CacheRoot setting.
     *
     * Note: Visibility is public to better accommodate escalation functions.
     *
     * @param string $confDir  Directory to be searched.
     *
     * @return string
     */
    public function cacheRootSearch( $confDir )
    {
        $files = new DirectoryIterator($confDir);

        foreach ( $files as $file ) {
            $filename = $file->getFilename();

            if ( strlen($filename) > 5
                    && substr_compare($filename, '.conf', -5) === 0 ) {

                $cacheRoot = $this->getCacheRootSetting($file->getPathname());

                if ( $cacheRoot != '' ) {
                    return $cacheRoot;
                }
            }
        }

        return '';
    }

    /**
     * Note: Visibility is public to better accommodate escalation functions.
     *
     * @param string $file
     *
     * @return string
     */
    public function getCacheRootSetting( $file )
    {
        if ( file_exists($file) ) {
            $matchFound = preg_match(
                '/^\s*CacheRoot (.+)/im',
                file_get_contents($file),
                $matches
            );

            if ( $matchFound ) {
                return trim($matches[1]);
            }
        }

        return '';
    }

    /**
     * Note: Visibility is public to better accommodate escalation functions.
     *
     * @return string
     */
    public function getLSWSCacheRootSetting()
    {
        $serverConf = __DIR__ . '/../../../../conf/httpd_config.xml';

        if ( file_exists($serverConf) ) {
            $matchFound = preg_match(
                '!<cacheStorePath>(.+)</cacheStorePath>!i',
                file_get_contents($serverConf),
                $matches
            );

            if ( $matchFound ) {
                return trim($matches[1]);
            }
        }

        return '';
    }

    abstract protected function serverCacheRootSearch();

    abstract protected function vhCacheRootSearch();

    /**
     * Checks server and VH conf files for cacheroot settings and populates in
     * object if found.
     *
     * @throws LSCMException  Thrown indirectly by $this->log() call.
     * @throws LSCMException  Thrown indirectly by $this->log() call.
     * @throws LSCMException  Thrown indirectly by $this->log() call.
     * @throws LSCMException  Thrown indirectly by $this->log() call.
     */
    protected function initCacheRoots()
    {
        $svrCacheRoot = $this->serverCacheRootSearch();

        if ( $svrCacheRoot == '' ) {
            $svrCacheRoot = $this->getLSWSCacheRootSetting();
        }

        $vhCacheRoot = $this->vhCacheRootSearch();

        if ( $svrCacheRoot ) {
            $this->serverCacheRoot = $svrCacheRoot;
            $this->log(
                "Server level cache root is $svrCacheRoot.",
                Logger::L_DEBUG
            );
        }
        else {
            $this->serverCacheRoot = static::NOT_SET;
            $this->log('Server level cache root is not set.', Logger::L_NOTICE);
        }

        if ( $vhCacheRoot ) {
            $this->vhCacheRoot = $vhCacheRoot;
            $this->log(
                "Virtual Host level cache root is $vhCacheRoot.",
                Logger::L_DEBUG
            );
        }
        else {
            $this->vhCacheRoot = static::NOT_SET;
            $this->log(
                'Virtual Host level cache root is not set.',
                Logger::L_INFO
            );
        }
    }

    /**
     *
     * @param string $msg
     * @param int    $level
     *
     * @throws LSCMException  Thrown indirectly by Logger::error() call.
     * @throws LSCMException  Thrown indirectly by Logger::warn() call.
     * @throws LSCMException  Thrown indirectly by Logger::notice() call.
     * @throws LSCMException  Thrown indirectly by Logger::info() call.
     * @throws LSCMException  Thrown indirectly by Logger::verbose() call.
     * @throws LSCMException  Thrown indirectly by Logger::debug() call.
     */
    protected function log( $msg, $level )
    {
        $msg = "$this->panelName - $msg";

        switch ($level) {

            case Logger::L_ERROR:
                Logger::error($msg);
                break;

            case Logger::L_WARN:
                Logger::warn($msg);
                break;

            case Logger::L_NOTICE:
                Logger::notice($msg);
                break;

            case Logger::L_INFO:
                Logger::info($msg);
                break;

            case Logger::L_VERBOSE:
                Logger::verbose($msg);
                break;

            case Logger::L_DEBUG:
                Logger::debug($msg);
                break;

            //no default
        }
    }

    /**
     *
     * @param string $svrCacheRoot
     *
     * @throws LSCMException  Thrown directly and indirectly.
     */
    public function setServerCacheRoot( $svrCacheRoot = '' )
    {
        $this->log('Attempting to set server cache root...', Logger::L_VERBOSE);

        if ( $svrCacheRoot != '' ) {
            $cacheroot = $svrCacheRoot;
        }
        else {
            $cacheroot = $this->defaultSvrCacheRoot;
        }

        $cacheRootLine =
            "<IfModule LiteSpeed>\nCacheRoot $cacheroot\n</IfModule>\n\n";

        if ( !file_exists($this->apacheConf) ) {
            file_put_contents($this->apacheConf, $cacheRootLine);
            chmod($this->apacheConf, 0644);

            $this->log("Created file $this->apacheConf", Logger::L_VERBOSE);
        }
        else {

            if ( !is_writable($this->apacheConf) ) {
                throw new LSCMException(
                    'Apache Config is not writeable. No changes made.'
                );
            }

            if ( !Util::createBackup($this->apacheConf) ) {
                throw new LSCMException(
                    'Could not backup Apache config. No changes made.'
                );
            }
            else {
                $file_contents = file($this->apacheConf);

                $pattern = '/^\s*<IfModule +LiteSpeed *>/im';

                if ( preg_grep($pattern, $file_contents) ) {

                    if ( preg_grep('/^\s*CacheRoot +/im', $file_contents) ) {
                        $file_contents = preg_replace(
                            '/^\s*CacheRoot +.+/im',
                            "CacheRoot $cacheroot",
                            $file_contents
                        );
                    }
                    else {
                        $file_contents = preg_replace(
                            '/^\s*<IfModule +LiteSpeed *>/im',
                            "<IfModule LiteSpeed>\nCacheRoot $cacheroot",
                            $file_contents
                        );
                    }
                }
                else {
                    array_unshift($file_contents, $cacheRootLine);
                }

                file_put_contents($this->apacheConf, $file_contents);
            }
        }

        $this->serverCacheRoot = $cacheroot;

        $this->log("Server level cache root set to $cacheroot", Logger::L_INFO);

        if ( file_exists($cacheroot) ) {
            exec("/bin/rm -rf $cacheroot");

            $this->log(
                'Server level cache root directory removed for proper '
                    . 'permission.',
                Logger::L_DEBUG
            );
        }
    }

    /**
     *
     * @param array  $file_contents
     * @param string $vhCacheRoot
     *
     * @return array
     */
    abstract protected function addVHCacheRootSection(
        array $file_contents,
              $vhCacheRoot = 'lscache'
    );

    /**
     *
     * @param string $vhConf
     *
     * @throws LSCMException  Thrown when virtual host conf file is not
     *     writeable.
     * @throws LSCMException  Thrown when a backup of the virtual host conf file
     *     could not be made.
     * @throws LSCMException  Thrown when "write to virtual host conf file" call
     *     fails.
     * @throws LSCMException  Thrown indirectly by $this->log() call.
     */
    public function writeVHCacheRoot( $vhConf, $vhCacheRoot = 'lscache' )
    {
        if ( !is_writable($vhConf) ) {
            throw new LSCMException(
                "Could not write to VH config $vhConf. No changes made.",
                LSCMException::E_PERMISSION
            );
        }
        if ( !Util::createBackup($vhConf) ) {
            throw new LSCMException(
                "Could not backup Virtual Host config file $vhConf. No "
                    . 'changes made.',
                LSCMException::E_PERMISSION
            );
        }

        $file_contents = file($vhConf);

        if ( preg_grep('/^\s*<IfModule +LiteSpeed *>/im', $file_contents) ) {

            if ( preg_grep('/^\s*CacheRoot +/im', $file_contents) ) {
                $modified_contents = preg_replace(
                    '/^\s*CacheRoot +.+/im',
                    "CacheRoot $vhCacheRoot",
                    $file_contents
                );
            }
            else {
                $modified_contents = preg_replace(
                    '/^\s*<IfModule +LiteSpeed *>/im',
                    "<IfModule LiteSpeed>\nCacheRoot $vhCacheRoot",
                    $file_contents
                );
            }
        }
        else {
            $modified_contents =
                $this->addVHCacheRootSection($file_contents, $vhCacheRoot);
        }

        if ( file_put_contents($vhConf, $modified_contents) === false ) {
            throw new LSCMException(
                "Failed to write to file $vhConf.",
                LSCMException::E_PERMISSION
            );
        }

        $this->log("Updated file $vhConf.", Logger::L_DEBUG);
    }

    /**
     * Note: Visibility is public to better accommodate escalation functions.
     *
     * @param string $vhConf
     * @param string $vhCacheRoot
     */
    abstract public function createVHConfAndSetCacheRoot(
        $vhConf,
        $vhCacheRoot = 'lscache'
    );

    /**
     * Note: Visibility is public to better accommodate escalation functions.
     *
     * @throws LSCMException  Thrown by some implementations.
     */
    abstract public function applyVHConfChanges();

    /**
     *
     * @since 1.9.7
     */
    protected static function setMinAPIFilePath()
    {
        static::$minAPIFilePath = realpath(__DIR__ . '/../..') . '/MIN_VER';
    }

    /**
     *
     * @since 1.9.7
     *
     * @return string
     */
    protected static function getMinAPIFilePath()
    {
        if ( static::$minAPIFilePath == '' ) {
            static::setMinAPIFilePath();
        }

        return static::$minAPIFilePath;
    }

    /**
     *
     * @since 1.9.7
     * @since 1.12  Changed visibility from protected to public.
     */
    public static function populateMinAPIVerFile()
    {
        $minVerFile = static::getMinAPIFilePath();

        $content = Util::get_url_contents(
            'https://www.litespeed.sh/sub/shared/MIN_VER'
        );

        if ( !empty($content) ) {
            file_put_contents($minVerFile, $content);
        }
        else {
            touch($minVerFile);
        }
    }

    /**
     *
     * @since 1.9.7
     *
     * @return string
     */
    protected static function getMinAPIVer()
    {
        $minVerFile = static::getMinAPIFilePath();

        clearstatcache();

        if ( !file_exists($minVerFile)
                || (time() - filemtime($minVerFile)) > 86400 ) {

            static::populateMinAPIVerFile();
        }

        if ( ($content = file_get_contents($minVerFile)) !== false ) {
            return trim($content);
        }

        return '';
    }

    /**
     *
     * @since 1.9.7
     *
     * @return bool
     */
    public static function meetsMinAPIVerRequirement()
    {
        $minAPIVer = static::getMinAPIVer();

        if ( $minAPIVer == ''
                || Util::betterVersionCompare(static::PANEL_API_VERSION, $minAPIVer, '<') ) {

            return false;
        }

        return true;
    }

    /**
     *
     * @since 1.9
     *
     * @param string $panelAPIVer  Shared code API version used by the panel
     *     plugin.
     *
     * @return int
     */
    public static function checkPanelAPICompatibility( $panelAPIVer )
    {
        $supportedAPIVers = array(
            '1.17.4.2',
            '1.17.4.1',
            '1.17.4',
            '1.17.3',
            '1.17.2',
            '1.17.1.1',
            '1.17.1',
            '1.17.0.5',
            '1.17.0.4',
            '1.17.0.3',
            '1.17.0.2',
            '1.17.0.1',
            '1.17',
            '1.16.1',
            '1.16.0.2',
            '1.16.0.1',
            '1.16',
            '1.15.0.1',
            '1.15',
            '1.14.5',
            '1.14.4.1',
            '1.14.4',
            '1.14.3.2',
            '1.14.3.1',
            '1.14.3',
            '1.14.2',
            '1.14.1.2',
            '1.14.1.1',
            '1.14.1',
            '1.14.0.3',
            '1.14.0.2',
            '1.14.0.1',
            '1.14',
            '1.13.13.1',
            '1.13.13',
            '1.13.12',
            '1.13.11.1',
            '1.13.11',
            '1.13.10.2',
            '1.13.10.1',
            '1.13.10',
            '1.13.9',
            '1.13.8',
            '1.13.7.1',
            '1.13.7',
            '1.13.6',
            '1.13.5.2',
            '1.13.5.1',
            '1.13.5',
            '1.13.4.4',
            '1.13.4.3',
            '1.13.4.2',
            '1.13.4.1',
            '1.13.4',
            '1.13.3.1',
            '1.13.3',
            '1.13.2.2',
            '1.13.2.1',
            '1.13.2',
            '1.13.1',
            '1.13.0.3',
            '1.13.0.2',
            '1.13.0.1',
            '1.13',
            '1.12',
            '1.11',
            '1.10',
            '1.9.8',
            '1.9.7',
            '1.9.6.1',
            '1.9.6',
            '1.9.5',
            '1.9.4',
            '1.9.3',
            '1.9.2',
            '1.9.1',
            '1.9',
            '1.8',
            '1.7',
            '1.6.1',
            '1.6',
            '1.5',
            '1.4',
            '1.3',
            '1.2',
            '1.1',
            '1.0'
        );

        if ( Util::betterVersionCompare($panelAPIVer, $supportedAPIVers[0], '>') ) {
            return static::PANEL_API_VERSION_TOO_HIGH;
        }
        elseif ( Util::betterVersionCompare($panelAPIVer, end($supportedAPIVers), '<') ) {
            return static::PANEL_API_VERSION_TOO_LOW;
        }
        elseif ( ! in_array($panelAPIVer, $supportedAPIVers) ) {
            return static::PANEL_API_VERSION_UNKNOWN;
        }
        else {
            return static::PANEL_API_VERSION_SUPPORTED;
        }
    }

    /**
     *
     * @deprecated 1.9  Use checkPanelAPICompatibility() instead.
     *
     * @param string $panelAPIVer  Shared code API version used by the panel
     *     plugin.
     *
     * @return bool
     */
    public static function isPanelAPICompatible( $panelAPIVer )
    {
        $apiCompatStatus = static::checkPanelAPICompatibility($panelAPIVer);

        if ( $apiCompatStatus != static::PANEL_API_VERSION_SUPPORTED ) {
            return false;
        }

        return true;
    }

}
webcachemgr/src/Panel/CustomPanel.php000066400000004767150545647710013642 0ustar00<?php

/** ******************************************
 * LiteSpeed Web Server Cache Manager
 *
 * @author LiteSpeed Technologies, Inc. (https://www.litespeedtech.com)
 * @copyright (c) 2020
 * ******************************************* */

namespace Lsc\Wp\Panel;

use Lsc\Wp\WPInstall;

class CustomPanel
extends CustomPanelBase
{
    protected function __construct()
    {
        /**
         * Panel name can be set to whatever you'd like.
         */
        $this->panelName = 'customPanel';

        /** @noinspection PhpUnhandledExceptionInspection */
        parent::__construct();
    }

    /**
     *
     * @since 1.13.2
     */
    protected function init2()
    {
        $this->panelName = 'customPanel';

        /** @noinspection PhpUnhandledExceptionInspection */
        parent::init2();
    }

    /**
     * Gets a list of found docroots and associated server names.
     * Only needed for lscmctl 'scan' command.
     */
    protected function prepareDocrootMap()
    {
        /**
         * This function can be left as is if you do not intend to use
         * the lscmctl 'scan' command. In this case lscmctl command
         * 'addinstalls' can be used to add WordPress installations to the
         * custom data file instead.
         *
         * If you would like to add support for the lscmctl 'scan' command,
         * implement this function so that it searches for all document root,
         * server name, and server alias groups and uses this information to
         * populate $this->docRootMap as follows:
         *
         * array(
         *     'docroots' => array(index => docroot),
         *     'names' => array("server name/alias" => index)
         * );
         *
         * Where the value of each discovered servername/alias in the 'names'
         * array matches the index of the related document root in the
         * 'docroots' array.
         */
        $this->docRootMap = array('docroots' => array(), 'names' => array());
    }

    /**
     * This function returns the PHP binary to be used when performing
     * WordPress related actions for the WordPress installation associated with
     * the passed in WPInstall object.
     *
     * @param WPInstall  $wpInstall
     * @return string
     */
    public function getPhpBinary( WPInstall $wpInstall )
    {
        /**
         * If PHP binary $phpBin can be more accurately detected for the given
         * installation, do so here.
         */
        $phpBin = 'php';

        return "{$phpBin} {$this->phpOptions}";
    }

}
webcachemgr/src/Panel/DirectAdmin.php000066400000036237150545647710013570 0ustar00<?php

/** ******************************************
 * LiteSpeed Web Server Cache Manager
 *
 * @author    Michael Alegre
 * @copyright 2019-2024 LiteSpeed Technologies, Inc.
 * ******************************************* */

namespace Lsc\Wp\Panel;

use DirectoryIterator;
use Lsc\Wp\Logger;
use Lsc\Wp\LSCMException;
use Lsc\Wp\WPInstall;

class DirectAdmin extends ControlPanel
{

    protected function __construct()
    {
        /** @noinspection PhpUnhandledExceptionInspection */
        parent::__construct();
    }

    /**
     *
     * @since 1.13.2
     */
    protected function init2()
    {
        $this->panelName           = 'DirectAdmin';
        $this->defaultSvrCacheRoot = '/home/lscache/';

        /** @noinspection PhpUnhandledExceptionInspection */
        parent::init2();
    }

    protected function initConfPaths()
    {
        $this->apacheConf   = '/etc/httpd/conf/extra/httpd-includes.conf';
        $this->apacheVHConf = '/usr/local/directadmin/data/templates/custom/'
            . 'cust_httpd.CUSTOM.2.pre';
    }

    /**
     *
     * @return string
     */
    protected function serverCacheRootSearch()
    {
        if ( !file_exists($this->apacheConf) ) {
            return '';
        }

        return $this->getCacheRootSetting($this->apacheConf);
    }

    /**
     *
     * @return string
     */
    protected function vhCacheRootSearch()
    {
        $apacheUserdataDir = dirname($this->apacheVHConf);

        if ( !file_exists($apacheUserdataDir) ) {
            return '';
        }

        return $this->daVhCacheRootSearch($apacheUserdataDir);
    }

    /**
     * Searches the given directories '.pre' and '.post' files for CacheRoot
     * setting.
     *
     * @param string $confDir  Directory to be searched.
     *
     * @return string
     */
    public function daVhCacheRootSearch( $confDir )
    {
        if ( !is_dir($confDir) ) {
            return '';
        }

        $files = new DirectoryIterator($confDir);

        foreach ( $files as $file ) {
            $filename = $file->getFilename();

            $isPreOrPostFile = (
                strlen($filename) > 4
                &&
                (
                    substr_compare($filename, '.pre', -4) === 0
                    ||
                    substr_compare($filename, '.post', -5) === 0
                )
            );

            if ( $isPreOrPostFile ) {
                $cacheRoot = $this->getCacheRootSetting($file->getPathname());

                if ( $cacheRoot != '' ) {
                    return $cacheRoot;
                }
            }
        }

        return '';
    }

    /**
     *
     * @param array  $file_contents
     * @param string $vhCacheRoot
     *
     * @return array
     */
    protected function addVHCacheRootSection(
        array $file_contents,
              $vhCacheRoot = 'lscache' )
    {
        array_unshift(
            $file_contents,
            "<IfModule LiteSpeed>\nCacheRoot $vhCacheRoot\n</IfModule>\n\n"
        );

        return $file_contents;
    }

    /**
     *
     * @param string $vhConf
     * @param string $vhCacheRoot
     *
     * @throws LSCMException  Thrown when mkdir() call fails to create virtual
     *     host conf directory.
     * @throws LSCMException  Thrown when file_put_contents() call fails to
     *     create virtual host conf file.
     * @throws LSCMException  Thrown indirectly by $this->log() call.
     * @throws LSCMException  Thrown indirectly by $this->log() call.
     */
    public function createVHConfAndSetCacheRoot(
        $vhConf,
        $vhCacheRoot = 'lscache' )
    {
        $vhConfDir = dirname($vhConf);

        if ( !file_exists($vhConfDir) ) {

            if ( !mkdir($vhConfDir, 0755) ) {
                throw new LSCMException(
                    "Failed to create directory $vhConfDir."
                );
            }

            $this->log("Created directory $vhConfDir", Logger::L_DEBUG);
        }

        $bytesWrittenToFile = file_put_contents(
            $vhConf,
            "<IfModule Litespeed>\nCacheRoot $vhCacheRoot\n</IfModule>"
        );

        if ( false === $bytesWrittenToFile ) {
            throw new LSCMException("Failed to create file $vhConf.");
        }

        $this->log("Created file $vhConf.", Logger::L_DEBUG);
    }

    public function applyVHConfChanges()
    {
        exec('/usr/local/directadmin/custombuild/build rewrite_confs');
    }

    /**
     *
     * @since 1.13.7
     *
     * @return array[]
     *
     * @throws LSCMException  Thrown indirectly by Logger::debug() call.
     */
    private function getHttpdConfDocrootMapInfo()
    {
        exec(
            'grep -hros "DocumentRoot.*\|ServerAlias.*\|ServerName.*" '
                . '/usr/local/directadmin/data/users/*/httpd.conf',
            $lines
        );

        /**
         * [0]=servername, [1]=serveraliases, [2]=docroot, [3]=servername, etc.
         * Not unique & not sorted.
         *
         * Example:
         * ServerName www.daruby1.com
         * ServerAlias www.daruby1.com daruby1.com
         * DocumentRoot /home/daruby1/domains/daruby1.com/public_html
         * ServerName www.daruby1.com
         * ServerAlias www.daruby1.com daruby1.com
         * DocumentRoot /home/daruby1/domains/daruby1.com/private_html
         * ServerName www.dauser1.com
         * ServerAlias www.dauser1.com dauser1.com
         * DocumentRoot /home/dauser1/domains/dauser1.com/public_html
         * ServerName www.dauser1.com
         * ServerAlias www.dauser1.com dauser1.com
         * DocumentRoot /home/dauser1/domains/dauser1.com/private_html
         *
         * @noinspection SpellCheckingInspection
         */

        $docRoots      = array();
        $curServerName = $curServerAliases = '';

        foreach ( $lines as $line ) {

            if ( $curServerName == '' ) {

                if ( strpos($line, 'ServerName') === 0 ) {
                    /**
                     * 10 is strlen('ServerName')
                     */
                    $curServerName = trim(substr($line, 10));
                }
            }
            elseif ( strpos($line, 'ServerAlias') === 0 ) {
                /**
                 * 11 is strlen('ServerAlias')
                 */
                $curServerAliases = trim(substr($line, 11));
            }
            elseif ( strpos($line, 'DocumentRoot') === 0 ) {
                /**
                 * 12 is strlen('DocumentRoot')
                 */
                $curDocRoot = trim(substr($line, 12), " \n\r\t\v\x00\"");

                /**
                 * Avoid possible duplicate detections due to
                 * public_html/private_html symlinks.
                 */
                if ( !isset($docRoots[$curDocRoot])
                        && is_dir($curDocRoot)
                        && !is_link($curDocRoot) ) {

                    $docRoots[$curDocRoot]   = explode(' ', $curServerAliases);
                    $docRoots[$curDocRoot][] = $curServerName;
                }

                /**
                 * Looking for the next data set
                 */
                $curServerName = $curServerAliases = '';
            }
            else {
                Logger::debug("Unused line when preparing docroot map: $line.");
            }
        }

        return $docRoots;
    }

    /**
     *
     * @since 1.13.7
     *
     * @return array[]
     *
     * @throws LSCMException Thrown indirectly by Logger::debug() call.
     */
    private function getOpenlitespeedConfDocrootMapInfo()
    {
        exec(
            'grep -hros "docRoot.*\|vhDomain.*\|vhAliases.*" '
                . '/usr/local/directadmin/data/users/*/openlitespeed.conf',
            $lines
        );

        /**
         * [0]=docroot, [1]=servername, [2]=serveraliases, [3]=docroot, etc.
         * Not unique & not sorted.
         *
         * Example:
         * docRoot                   /home/test/domains/test.com/public_html
         * vhDomain                  test.com
         * vhAliases                 www.test.com
         * docRoot                   /home/test/domains/test.com/public_html
         * vhDomain                  testalias.com
         * vhAliases                 www.testalias.com
         * docRoot                   /home/test/domains/test.com/private_html
         * vhDomain                  test.com
         * vhAliases                 www.test.com
         * docRoot                   /home/test/domains/test.com/private_html
         * vhDomain                  testalias.com
         * vhAliases                 www.testalias.com
         * docRoot                   /home/test_2/domains/test2.com/public_html
         * vhDomain                  test2.com
         * vhAliases                 www.test2.com
         * docRoot                   /home/test_2/domains/test2.com/private_html
         * vhDomain                  test2.com
         * vhAliases                 www.test2.com
         *
         * @noinspection SpellCheckingInspection
         */

        $docRoots      = array();
        $curServerName = $curDocRoot = '';

        foreach ( $lines as $line ) {

            if ( $curDocRoot == '' ) {

                if ( strpos($line, 'docRoot') === 0 ) {
                    /**
                     * 7 is strlen('docRoot')
                     */
                    $curDocRoot = trim(substr($line, 7));
                }
            }
            elseif ( strpos($line, 'vhDomain') === 0 ) {
                /**
                 * 8 is strlen('vhDomain')
                 */
                $curServerName = trim(substr($line, 8));
            }
            elseif ( strpos($line, 'vhAliases') === 0 ) {
                /**
                 * 9 is strlen('vhAliases')
                 */
                $curServerAlias = trim(substr($line, 9));

                /**
                 * Avoid possible duplicate detections due to
                 * public_html/private_html symlinks.
                 */
                if ( is_dir($curDocRoot) && !is_link($curDocRoot) ) {

                    if ( !isset($docRoots[$curDocRoot]) ) {
                        $docRoots[$curDocRoot] =
                            array( $curServerName, $curServerAlias );
                    }
                    else {

                        if ( !in_array($curServerName, $docRoots[$curDocRoot]) ) {
                            $docRoots[$curDocRoot][] = $curServerName;
                        }

                        if ( !in_array($curServerAlias, $docRoots[$curDocRoot]) ) {
                            $docRoots[$curDocRoot][] = $curServerAlias;
                        }
                    }
                }

                /**
                 * Looking for the next data set
                 */
                $curDocRoot = $curServerName = '';

            }
            else {
                Logger::debug("Unused line when preparing docroot map: $line.");
            }
        }

        return $docRoots;
    }

    /**
     * Gets a list of found docroots and associated server names.
     * Only needed for scan operation.
     *
     * @throws LSCMException  Thrown indirectly by
     *     $this->getHttpdConfDocrootMapInfo() call.
     * @throws LSCMException  Thrown indirectly by
     *     $this->getOpenlitespeedConfDocrootMapInfo() call.
     */
    protected function prepareDocrootMap()
    {
        $docRootMapInfo                  = $this->getHttpdConfDocrootMapInfo();
        $openlitespeedConfDocrootMapInfo =
            $this->getOpenlitespeedConfDocrootMapInfo();

        foreach ( $openlitespeedConfDocrootMapInfo as $oDocRoot => $oDomains ) {

            if ( !isset($docRootMapInfo[$oDocRoot]) ) {
                $docRootMapInfo[$oDocRoot] = $oDomains;
            }
            else {

                foreach ( $oDomains as $oDomain ) {

                    if ( !in_array($oDomain, $docRootMapInfo[$oDocRoot]) ) {
                        $docRootMapInfo[$oDocRoot][] = $oDomain;
                    }
                }
            }
        }

        $roots       = array();
        $servernames = array();
        $index       = 0;

        foreach ( $docRootMapInfo as $docRoot => $domains ) {
            $domains       = array_unique($domains);
            $roots[$index] = $docRoot;

            foreach ( $domains as $domain ) {
                $servernames[$domain] = $index;
            }

            $index++;
        }

        $this->docRootMap =
            array( 'docroots' => $roots, 'names' => $servernames );
    }

    /**
     * Check the user's httpd.conf file for a VirtualHost entry containing a
     * given servername/docroot combination and return the PHP handler version
     * if set.
     *
     * @param WPInstall $wpInstall
     *
     * @return string
     *
     * @throws LSCMException  Thrown when a valid user data conf file could not
     *     be found.
     */
    protected function getCustomPhpHandlerVer( WPInstall $wpInstall )
    {
        if ( ($serverName = $wpInstall->getServerName()) == null
                || ($docroot = $wpInstall->getDocRoot()) == null ) {

            return '';
        }

        $escServerName = str_replace('.', '\.', $serverName);
        $escDocRoot    =
            str_replace(array('.', '/'), array('\.', '\/'), $docroot);

        $user = $wpInstall->getOwnerInfo('user_name');

        $httpdConfFile = "/usr/local/directadmin/data/users/$user/httpd.conf";
        $olsConfFile   =
            "/usr/local/directadmin/data/users/$user/openlitespeed.conf";

        if ( file_exists($httpdConfFile) ) {
            $confFile = $httpdConfFile;
            $pattern  = '/VirtualHost'
                . '(?:(?!<\/VirtualHost).)*'
                . "ServerName $escServerName"
                . '(?:(?!<\/VirtualHost).)*'
                . "DocumentRoot $escDocRoot"
                . '(?:(?!<\/VirtualHost).)*'
                . 'AddHandler.* \.php(\d\d)/sU';
        }
        elseif ( file_exists($olsConfFile) ) {
            $confFile = $olsConfFile;
            $pattern  = '/virtualHost\s'
                . '(?:(?!}\s*\n*virtualHost).)*?'
                . '{'
                . '(?:(?!}\s*\n*virtualHost).)*?'
                . "(?:\s|\n)docRoot\s+$escDocRoot(?:\s|\n)"
                . '(?:(?!}\s*\n*virtualHost).)*?'
                . "(?:\s|\n)vhDomain\s+$escServerName(?:\s|\n)"
                . '(?:(?!}\s*\n*virtualHost).)*?'
                . '(?:\s|\n)scripthandler(?:\s|\n)*{'
                . '(?:(?!}\s*\n*virtualHost).)*?'
                . '\sphp(\d\d)(?=\s|\n)/s';
        }
        else {
            throw new LSCMException('Could not find valid user data conf file');
        }

         if ( preg_match($pattern, file_get_contents($confFile), $m) ) {
            return $m[1];
         }

         return '';
    }

    /**
     *
     * @param WPInstall $wpInstall
     *
     * @return string
     *
     * @throws LSCMException  Thrown indirectly by
     *     $this->getCustomPhpHandlerVer() call.
     */
    public function getPhpBinary( WPInstall $wpInstall )
    {
        $phpBin = '/usr/local/bin/php';

        if ( ($ver = $this->getCustomPhpHandlerVer($wpInstall)) != '' ) {

            $customBin = "/usr/local/php$ver/bin/php";

            if ( file_exists($customBin) && is_executable($customBin) ) {
                $phpBin = $customBin;
            }
        }

        return "$phpBin $this->phpOptions";
    }

}
webcachemgr/src/AjaxResponse.php000066400000003453150545647710012742 0ustar00<?php

/** *********************************************
 * LiteSpeed Web Server Cache Manager
 *
 * @author    Michael Alegre
 * @copyright 2019-2025 LiteSpeed Technologies, Inc.
 * @since     1.9
 * *******************************************
 */

namespace Lsc\Wp;

/**
 * @since 1.9
 */
class AjaxResponse
{

    /**
     * @since 1.9
     * @var   AjaxResponse
     */
    protected static $instance;

    /**
     * @since 1.9
     * @var   string
     */
    protected $ajaxContent;

    /**
     * @since 1.9
     * @var   string
     */
    protected $headerContent;

    /**
     *
     * @since 1.9
     */
    private function __construct()
    {

    }

    /**
     *
     * @since 1.9
     *
     * @return AjaxResponse
     */
    private static function me()
    {
        if ( self::$instance == null ) {
            self::$instance = new self();
        }

        return self::$instance;
    }

    /**
     *
     * @since 1.9
     *
     * @throws LSCMException
     */
    public static function outputAndExit()
    {
        $output = '';

        if ( self::$instance == null ) {
            throw new LSCMException('AjaxResponse object never created!');
        }

        $m = self::me();

        if ( !empty($m->headerContent) ) {
            $output .= "{$m->headerContent}\n\n";
        }

        $output .= $m->ajaxContent;

        ob_clean();
        echo $output;
        exit;
    }

    /**
     *
     * @since 1.9
     *
     * @param string $ajaxContent
     */
    public static function setAjaxContent( $ajaxContent )
    {
        self::me()->ajaxContent = $ajaxContent;
    }

    /**
     *
     * @since 1.9
     *
     * @param string $headerContent
     */
    public static function setHeaderContent( $headerContent )
    {
        self::me()->headerContent = $headerContent;
    }

}
webcachemgr/src/PanelController.php000066400000160275150545647710013451 0ustar00<?php

/** *********************************************
 * LiteSpeed Web Server Cache Manager
 *
 * @author    Michael Alegre
 * @copyright 2018-2025 LiteSpeed Technologies, Inc.
 * ******************************************* */

namespace Lsc\Wp;

use Lsc\Wp\Context\Context;
use Lsc\Wp\Panel\ControlPanel;
use Lsc\Wp\View\AjaxView;
use Lsc\Wp\View\Model\Ajax as AjaxViewModel;

class PanelController
{

    /**
     * @var int
     */
    const MGR_STEP_NONE           = 0;

    /**
     * @var int
     */
    const MGR_STEP_SCAN           = 1;

    /**
     * @var int
     */
    const MGR_STEP_DISCOVER_NEW   = 2;

    /**
     * @var int
     */
    const MGR_STEP_REFRESH_STATUS = 3;

    /**
     * @var int
     */
    const MGR_STEP_MASS_UNFLAG    = 4;

    /**
     * @var int
     */
    const MGR_STEP_MASS_FLAG      = 5;

    /**
     * @var int
     */
    const DASH_STEP_NONE              = 0;

    /**
     * @var int
     */
    const DASH_STEP_MASS_DASH_NOTIFY  = 1;

    /**
     * @var int
     */
    const DASH_STEP_MASS_DASH_DISABLE = 2;

    /**
     * @var ControlPanel
     */
    protected $panelEnv;

    /**
     * @var WPInstallStorage
     */
    protected $wpInstallStorage;

    /**
     * @var int
     */
    protected $mgrStep;

    /**
     * @var int
     */
    protected $dashStep = self::DASH_STEP_NONE;

    /**
     *
     * @param ControlPanel     $panelEnv
     * @param WPInstallStorage $wpInstallStorage
     * @param int              $mgrStep
     */
    public function __construct(
        ControlPanel     $panelEnv,
        WPInstallStorage $wpInstallStorage,
                         $mgrStep = self::MGR_STEP_NONE
    )
    {
        $this->panelEnv         = $panelEnv;
        $this->wpInstallStorage = $wpInstallStorage;
        $this->mgrStep          = $mgrStep;
    }

    /**
     *
     * @param string $type
     *
     * @return void|string[]
     */
    protected function getCurrentAction( $type = 'cacheMgr' )
    {
        switch ( $type ) {

            case 'dashNotifier':
                $all_actions = [
                    'notify_single'  => UserCommand::CMD_DASH_NOTIFY,
                    'disable_single' => UserCommand::CMD_DASH_DISABLE,
                    'get_msg'        => WPDashMsgs::ACTION_GET_MSG,
                    'add_msg'        => WPDashMsgs::ACTION_ADD_MSG,
                    'delete_msg'     => WPDashMsgs::ACTION_DELETE_MSG
                ];

                break;

            case 'cacheMgr':
                $all_actions = [
                    'enable_single'         => UserCommand::CMD_ENABLE,
                    'disable_single'        => UserCommand::CMD_DISABLE,
                    'flag_single'           => WPInstallStorage::CMD_FLAG,
                    'unflag_single'         => WPInstallStorage::CMD_UNFLAG,
                    'refresh_status_single' => UserCommand::CMD_STATUS,
                    'enable_sel'            => UserCommand::CMD_ENABLE,
                    'disable_sel'           => UserCommand::CMD_DISABLE,
                    'flag_sel'              => WPInstallStorage::CMD_FLAG,
                    'unflag_sel'            => WPInstallStorage::CMD_UNFLAG
                ];
                break;

            default:
                return;
        }

        foreach ( $all_actions as $act => $doAct ) {

            if ( Util::get_request_var($act) !== null ) {
                return [ 'act_key' => $act, 'action' => $doAct ];
            }
        }
    }

    /**
     *
     * @deprecated
     *
     * @return int
     *
     * @throws LSCMException  Thrown indirectly by
     *     $this->manageCacheOperations() call.
     */
    public function manageOperationsSubController()
    {
        return $this->manageCacheOperations();
    }

    /**
     *
     * @deprecated 1.13.3  Use $this->manageCacheOperations2() instead.
     *
     * @return int
     *
     * @throws LSCMException  Thrown indirectly by $this->checkScanAction()
     *     call.
     * @throws LSCMException  Thrown indirectly by $this->checkRefreshAction()
     *     call.
     * @throws LSCMException  Thrown indirectly by $this->checkUnflagAction()
     *     call.
     * @throws LSCMException  Thrown indirectly by $this->doFormAction() call.
     * @throws LSCMException  Thrown indirectly by $this->doSingleAction() call.
     */
    public function manageCacheOperations()
    {
        if (
                $this->checkScanAction()
                ||
                $this->checkRefreshAction()
                ||
                $this->checkFlagActions()
                ||
                ($actionInfo = $this->getCurrentAction()) == NULL
        ) {
            return $this->mgrStep;
        }

        $actKey = $actionInfo['act_key'];
        $action = $actionInfo['action'];

        if ( strcmp(substr($actKey, -3), 'sel') == 0 ) {
            $this->doFormAction($action);
        }
        else {
            $this->doSingleAction($action, Util::get_request_var($actKey));
        }

        return $this->mgrStep;
    }

    /**
     *
     * @since 1.13.3
     *
     * @return int
     *
     * @throws LSCMException  Thrown indirectly by $this->checkScanAction2()
     *     call.
     * @throws LSCMException  Thrown indirectly by $this->checkRefreshAction()
     *     call.
     * @throws LSCMException  Thrown indirectly by $this->checkUnflagAction()
     *     call.
     * @throws LSCMException  Thrown indirectly by $this->doFormAction() call.
     * @throws LSCMException  Thrown indirectly by $this->doSingleAction() call.
     */
    public function manageCacheOperations2()
    {
        if (
                $this->checkScanAction2()
                ||
                $this->checkRefreshAction()
                ||
                $this->checkFlagActions()
                ||
                ($actionInfo = $this->getCurrentAction()) == NULL
        ) {
            return $this->mgrStep;
        }

        $actKey = $actionInfo['act_key'];
        $action = $actionInfo['action'];

        if ( strcmp(substr($actKey, -3), 'sel') == 0 ) {
            $this->doFormAction($action);
        }
        else {
            $path = Util::get_request_var($actKey);
            $this->doSingleAction($action, $path);
        }

        return $this->mgrStep;
    }

    /**
     *
     * @return string
     */
    protected function getDashMsgInfoJSON()
    {
        $msgInfo = [ 'msg' => '', 'plugin' => '', 'plugin_name' => '' ];

        if ( ($msg = Util::get_request_var('notify_msg')) !== NULL ) {
            $msgInfo['msg'] = trim($msg);
        }

        if ( ($slug = Util::get_request_var('notify_slug')) !== NULL ) {
            $msgInfo['plugin'] = trim($slug);
        }

        /**
         * plugin_name is not passed at this time.
         */

        return json_encode($msgInfo);
    }

    /**
     *
     * @param int        $dashStep
     * @param WPDashMsgs $wpDashMsgs
     *
     * @return int
     *
     * @throws LSCMException  Thrown indirectly by
     *     $this->checkDashMassNotifyAction() call.
     * @throws LSCMException  Thrown indirectly by
     *     $this->checkDashMassDisableAction() call.
     * @throws LSCMException  Thrown indirectly by $this->doWpDashMsgOperation()
     *     call.
     * @throws LSCMException  Thrown indirectly by $this->doSingleDashAction()
     *     call.
     */
    public function manageDashOperations( $dashStep, WPDashMsgs $wpDashMsgs )
    {
        $this->dashStep = $dashStep;

        if (
                $this->checkDashMassNotifyAction()
                ||
                $this->checkDashMassDisableAction()
                ||
                ($actionInfo = $this->getCurrentAction('dashNotifier')) == NULL
        ) {
            return $this->dashStep;
        }

        $actKey      = $actionInfo['act_key'];
        $action      = $actionInfo['action'];
        $msgInfoJSON = '';

        if ( substr($action, 0, 3) == 'msg' ) {
            $this->doWpDashMsgOperation($wpDashMsgs, $action);
        }

        if ( $actKey == UserCommand::CMD_DASH_NOTIFY ) {
            $msgInfoJSON = base64_encode($this->getDashMsgInfoJSON());
        }

        $this->doSingleDashAction(
            $action,
            Util::get_request_var($actKey),
            $msgInfoJSON
        );

        return $this->dashStep;
    }

    /**
     *
     * @param array $array
     *
     * @return int
     *
     * @throws LSCMException  Rethrown when Context::getOption() throws an
     *     LSCMException exception.
     * @throws LSCMException  Thrown indirectly by Logger::error() call.
     */
    protected function getBatchSize( array $array )
    {
        try {
            $batchSize = Context::getOption()->getBatchSize();
        }
        catch ( LSCMException $e ) {
            $msg = "{$e->getMessage()} Could not get batch size.";
            Logger::error($msg);

            throw new LSCMException($msg);
        }

        if ( $batchSize > ($arrSize = count($array)) ) {
            return $arrSize;
        }

        return $batchSize;
    }

    /**
     *
     * @param object $viewModel
     * @param string $tplID
     *
     * @return string
     *
     * @throws LSCMException  Thrown indirectly by Logger::error() call.
     */
    protected function getAjaxViewContent( $viewModel, $tplID = '' )
    {
        try {
            return (new AjaxView($viewModel))->getAjaxContent($tplID);
        }
        catch ( LSCMException $e ) {
            Logger::error($e->getMessage());
        }

        return '';
    }

    /**
     *
     * @deprecated 1.9 Moved to using AjaxResponse object for this.
     *
     * @param array $ajaxInfo
     */
    protected function ajaxReturn( array $ajaxInfo )
    {
        ob_clean();
        echo json_encode($ajaxInfo);
        exit;
    }

    /**
     *
     * @deprecated 1.13.3  Use $this->checkScanAction2() instead.
     *
     * @return bool|void  Function outputs ajax and exits without returning a
     *     value when $init is evaluated to be false.
     *
     * @throws LSCMException  Thrown indirectly by
     *     $this->panelEnv->getDocroots() call.
     * @throws LSCMException  Thrown indirectly by Logger::uiError() call.
     * @throws LSCMException  Thrown indirectly by $this->getBatchSize() call.
     * @throws LSCMException  Thrown indirectly by
     *     $this->wpInstallStorage->doAction() call.
     * @throws LSCMException  Thrown indirectly by Logger::getUiMsgs() call.
     * @throws LSCMException  Thrown indirectly by AjaxResponse::outputAndExit()
     *     call.
     */
    protected function checkScanAction()
    {
        $init   = false;
        $action = '';

        if ( $this->mgrStep == self::MGR_STEP_SCAN ) {
            $action = WPInstallStorage::CMD_SCAN;
        }
        elseif ( $this->mgrStep == self::MGR_STEP_DISCOVER_NEW ) {
            $action = WPInstallStorage::CMD_DISCOVER_NEW;
        }
        elseif ( Util::get_request_var('re-scan') ) {
            $this->mgrStep = self::MGR_STEP_SCAN;
            $init          = true;
        }
        elseif ( Util::get_request_var('scan_more') ) {
            $this->mgrStep = self::MGR_STEP_DISCOVER_NEW;
            $init          = true;
        }
        else {
            return false;
        }

        if ( session_status() !== PHP_SESSION_ACTIVE ) {
            session_start();
        }

        $info = &$_SESSION['scanInfo'];

        if ( $init ) {
            $info = [ 'homeDirs' => $this->panelEnv->getDocroots() ];
            return true;
        }

        $completedCount = -1;

        if ( !isset($info['homeDirs']) ) {
            Logger::uiError(
                'Expected session data missing! Stopping mass operation.'
            );
        }
        else {
            $batchSize = $this->getBatchSize($info['homeDirs']);
            $batch     = array_splice($info['homeDirs'], 0, $batchSize);

            $completedCount = count(
                $this->wpInstallStorage->doAction(
                    $action,
                    $batch
                )
            );

            if ( $completedCount != $batchSize ) {
                $info['homeDirs'] = array_merge(
                    array_slice($batch, $completedCount),
                    $info['homeDirs']
                );
            }
        }

        if ( empty($info['homeDirs']) ) {
            unset($_SESSION['scanInfo']);
        }

        $msgs = $this->wpInstallStorage->getAllCmdMsgs();

        AjaxResponse::setAjaxContent(
            json_encode(
                [
                    'completed' => $completedCount,
                    'errMsgs'   => array_merge(
                        $msgs['fail'],
                        $msgs['err'],
                        Logger::getUiMsgs(Logger::UI_ERR)
                    )
                ]
            )
        );
        AjaxResponse::outputAndExit();
    }

    /**
     *
     * @since 1.15
     *
     * @param string[] $docroots
     * @param string[] $wpPaths   Array of discovered WordPress installations
     *     (passed by address).
     *
     * @return int  Completed count.
     *
     * @throws LSCMException  Thrown indirectly by WPInstallStorage->scan2()
     *     call.
     */
    protected function runScan2Logic( array $docroots, array &$wpPaths )
    {
        foreach ( $docroots as $docroot ) {
            $wpPaths = array_merge(
                $wpPaths,
                WPInstallStorage::scan2($docroot)
            );
        }

        return count($docroots);
    }

    /**
     *
     * @since 1.13.3
     *
     * @return bool|void  Function outputs ajax and exits without returning a
     *     value when $init is evaluated to be false.
     *
     * @throws LSCMException  Thrown indirectly by
     *     $this->panelEnv->getDocroots() call.
     * @throws LSCMException  Thrown indirectly by Logger::uiError() call.
     * @throws LSCMException  Thrown indirectly by $this->getBatchSize() call.
     * @throws LSCMException  Thrown indirectly by $this->runScan2Logic() call.
     * @throws LSCMException  Thrown indirectly by $this->getBatchSize() call.
     * @throws LSCMException  Thrown indirectly by
     *     $this->wpInstallStorage->doAction() call.
     * @throws LSCMException  Thrown indirectly by Logger::getUiMsgs() call.
     * @throws LSCMException  Thrown indirectly by AjaxResponse::outputAndExit()
     *     call.
     */
    protected function checkScanAction2()
    {
        $init   = false;
        $action = '';

        if ( $this->mgrStep == self::MGR_STEP_SCAN ) {
            $action = WPInstallStorage::CMD_SCAN2;
        }
        elseif ( $this->mgrStep == self::MGR_STEP_DISCOVER_NEW ) {
            $action = WPInstallStorage::CMD_DISCOVER_NEW2;
        }
        elseif ( Util::get_request_var('re-scan') ) {
            $this->mgrStep = self::MGR_STEP_SCAN;
            $init          = true;
        }
        elseif ( Util::get_request_var('scan_more') ) {
            $this->mgrStep = self::MGR_STEP_DISCOVER_NEW;
            $init          = true;
        }
        else {
            return false;
        }

        if ( session_status() !== PHP_SESSION_ACTIVE ) {
            session_start();
        }

        if ( Util::get_request_var('go_to_next') == 1 ){
            return true;
        }

        $info = &$_SESSION['scanInfo'];

        if ( $init ) {
            $info = [
                'homeDirs' => $this->panelEnv->getDocroots(),
                'installs' => []
            ];
            return true;
        }

        $scanStep       = self::MGR_STEP_NONE;
        $errMsgs        = [];
        $completedCount = -1;

        if (
                !is_array($info)
                ||
                !array_key_exists('homeDirs', $info)
                ||
                !array_key_exists('installs', $info)
        ) {
            Logger::uiError(
                'Expected session data missing! Stopping mass operation.'
            );
        }
        else {

            if ( $info['homeDirs'] !== null ) {
                $scanStep  = self::MGR_STEP_SCAN;
                $batchSize = $this->getBatchSize($info['homeDirs']);
                $batch     = array_splice($info['homeDirs'], 0, $batchSize);

                $wpPaths        = [];
                $completedCount = $this->runScan2Logic($batch, $wpPaths);

                if ( $completedCount != $batchSize ) {
                    $info['homeDirs'] = array_merge(
                        array_slice($batch, $completedCount),
                        $info['homeDirs']
                    );
                }

                if ( $action == WPInstallStorage::CMD_DISCOVER_NEW2 ) {

                    foreach( $wpPaths as $wpPath ) {

                        if ( $this->wpInstallStorage->getWPInstall($wpPath) == null) {
                            $info['installs'][] = $wpPath;
                        }
                    }
                }
                else {
                    $info['installs'] =
                        array_merge($info['installs'], $wpPaths);
                }

                if ( empty($info['homeDirs']) ) {
                    $info['homeDirs'] = null;

                    if ( $action == WPInstallStorage::CMD_SCAN2 ) {
                        $flippedInstalls = array_flip($info['installs']);

                        $wpInstalls = $this->wpInstallStorage->getWPInstalls();

                        if ( $wpInstalls === null ) {
                            $wpInstalls = [];
                        }

                        foreach ( $wpInstalls as $wpInstall ) {
                            $wpInstallPath = $wpInstall->getPath();

                            if ( !isset($flippedInstalls[$wpInstallPath]) ) {
                                $info['installs'][] = $wpInstallPath;
                            }
                        }
                    }
                }
            }
            elseif ( $info['installs'] !== null ) {
                $scanStep  = self::MGR_STEP_DISCOVER_NEW;
                $batchSize = $this->getBatchSize($info['installs']);
                $batch     = array_splice($info['installs'], 0, $batchSize);

                $completedCount = count(
                    $this->wpInstallStorage->doAction(
                        WPInstallStorage::CMD_ADD_NEW_WPINSTALL,
                        $batch
                    )
                );

                if ( $completedCount != $batchSize ) {
                    $info['installs'] = array_merge(
                        array_slice($batch, $completedCount),
                        $info['installs']
                    );
                }

                $msgs    = $this->wpInstallStorage->getAllCmdMsgs();
                $errMsgs = array_merge($msgs['fail'], $msgs['err']);

                if ( empty($info['installs']) ) {
                    $info['installs'] = null;
                }
            }
        }

        if ( $info['homeDirs'] === null && $info['installs'] === null ) {
            unset($_SESSION['scanInfo']);
        }

        AjaxResponse::setAjaxContent(
            json_encode(
                [
                    'scanStep'  => $scanStep,
                    'completed' => $completedCount,
                    'errMsgs'   => array_merge(
                        $errMsgs,
                        Logger::getUiMsgs(Logger::UI_ERR)
                    )
                ]
            )
        );
        AjaxResponse::outputAndExit();
    }

    /**
     *
     * @return bool|void  Function outputs ajax and exits without returning a
     *     value when $init is evaluated to be false.
     *
     * @throws LSCMException  Thrown indirectly by Logger::uiError() call.
     * @throws LSCMException  Thrown indirectly by $this->getBatchSize() call.
     * @throws LSCMException  Thrown indirectly by
     *     $this->wpInstallStorage->doAction() call.
     * @throws LSCMException  Thrown indirectly by Logger::getUiMsgs() call.
     * @throws LSCMException  Thrown indirectly by AjaxResponse::outputAndExit()
     *     call.
     */
    protected function checkRefreshAction()
    {
        if ( $this->mgrStep == self::MGR_STEP_REFRESH_STATUS ) {
            $init = false;
        }
        elseif ( Util::get_request_var('refresh_status') ) {
            $init          = true;
            $this->mgrStep = self::MGR_STEP_REFRESH_STATUS;
        }
        else {
            return false;
        }

        if ( session_status() !== PHP_SESSION_ACTIVE ) {
            session_start();
        }

        $info = &$_SESSION['refreshInfo'];

        if ( $init ) {
            $info = [ 'installs' => $this->wpInstallStorage->getPaths() ];
            return true;
        }

        $completedCount = -1;

        if ( !isset($info['installs']) ) {
            Logger::uiError(
                'Expected session data missing! Stopping mass operation.'
            );
        }
        else {
            $batchSize = $this->getBatchSize($info['installs']);
            $batch     = array_splice($info['installs'], 0, $batchSize);

            $completedCount = count(
                $this->wpInstallStorage->doAction(
                    UserCommand::CMD_STATUS,
                    $batch
                )
            );

            if ( $completedCount != $batchSize ) {
                $info['installs'] = array_merge(
                    array_slice($batch, $completedCount),
                    $info['installs']
                );
            }
        }

        if ( empty($info['installs']) ) {
            unset($_SESSION['refreshInfo']);
        }

        $msgs = $this->wpInstallStorage->getAllCmdMsgs();

        AjaxResponse::setAjaxContent(
            json_encode(
                [
                    'completed' => $completedCount,
                    'errMsgs'   => array_merge(
                        $msgs['fail'],
                        $msgs['err'],
                        Logger::getUiMsgs(Logger::UI_ERR)
                    )
                ]
            )
        );
        AjaxResponse::outputAndExit();
    }

    /**
     *
     * @deprecated release_ver_placeholder
     *
     * @return bool|void  Function outputs ajax and exits without returning a
     *     value when $init is evaluated to be false.
     *
     * @throws LSCMException  Thrown indirectly by Logger::uiError() call.
     * @throws LSCMException  Thrown indirectly by $this->getBatchSize() call.
     * @throws LSCMException  Thrown indirectly by
     *     $this->wpInstallStorage->doAction() call.
     * @throws LSCMException  Thrown indirectly by Logger::getUiMsgs() call.
     * @throws LSCMException  Thrown indirectly by Logger::getUiMsgs() call.
     * @throws LSCMException  Thrown indirectly by AjaxResponse::outputAndExit()
     *     call.
     */
    protected function checkUnflagAction()
    {
        if ( $this->mgrStep == self::MGR_STEP_MASS_UNFLAG ) {
            $init = false;
        }
        elseif ( Util::get_request_var('mass_unflag') ) {
            $init          = true;
            $this->mgrStep = self::MGR_STEP_MASS_UNFLAG;
        }
        else {
            return false;
        }

        if ( session_status() !== PHP_SESSION_ACTIVE ) {
            session_start();
        }

        $info = &$_SESSION['unflagInfo'];

        if ( $init ) {
            $info = [ 'installs' => $this->wpInstallStorage->getPaths() ];
            return true;
        }

        $completedCount = -1;

        if ( !isset($info['installs']) ) {
            Logger::uiError(
                'Expected session data missing! Stopping mass operation.'
            );
        }
        else {
            $batchSize = $this->getBatchSize($info['installs']);
            $batch     = array_splice($info['installs'], 0, $batchSize);

            $completedCount = count(
                $this->wpInstallStorage->doAction(
                    WPInstallStorage::CMD_MASS_UNFLAG,
                    $batch
                )
            );

            if ( $completedCount != $batchSize ) {
                $info['installs'] = array_merge(
                    array_slice($batch, $completedCount),
                    $info['installs']
                );
            }
        }

        if ( empty($info['installs']) ) {
            unset($_SESSION['unflagInfo']);
        }

        $msgs = $this->wpInstallStorage->getAllCmdMsgs();

        AjaxResponse::setAjaxContent(
            json_encode(
                [
                    'completed' => $completedCount,
                    'errMsgs'   => array_merge(
                        $msgs['fail'],
                        $msgs['err'],
                        Logger::getUiMsgs(Logger::UI_ERR)
                    ),
                    'succMsgs'  => array_merge(
                        $msgs['succ'],
                        Logger::getUiMsgs(Logger::UI_SUCC)
                    )
                ]
            )
        );
        AjaxResponse::outputAndExit();
    }

    /**
     *
     * @return bool|void  Function outputs ajax and exits without returning a
     *     value when $init is evaluated to be false.
     *
     * @throws LSCMException  Thrown indirectly by Logger::uiError() call.
     * @throws LSCMException  Thrown indirectly by $this->getBatchSize() call.
     * @throws LSCMException  Thrown indirectly by
     *     $this->wpInstallStorage->doAction() call.
     * @throws LSCMException  Thrown indirectly by Logger::getUiMsgs() call.
     * @throws LSCMException  Thrown indirectly by Logger::getUiMsgs() call.
     * @throws LSCMException  Thrown indirectly by AjaxResponse::outputAndExit()
     *     call.
     */
    protected function checkFlagActions()
    {
        if ( $this->mgrStep == self::MGR_STEP_MASS_UNFLAG ) {
            $action = WPInstallStorage::CMD_MASS_UNFLAG;
            $init   = false;
        }
        elseif ( $this->mgrStep == self::MGR_STEP_MASS_FLAG ) {
            $action = WPInstallStorage::CMD_MASS_FLAG;
            $init   = false;
        }
        elseif ( Util::get_request_var('mass_unflag') ) {
            $action        = WPInstallStorage::CMD_MASS_UNFLAG;
            $init          = true;
            $this->mgrStep = self::MGR_STEP_MASS_UNFLAG;
        }
        elseif ( Util::get_request_var('mass_flag') ) {
            $action        = WPInstallStorage::CMD_MASS_FLAG;
            $init          = true;
            $this->mgrStep = self::MGR_STEP_MASS_FLAG;
        }
        else {
            return false;
        }

        if ( session_status() !== PHP_SESSION_ACTIVE ) {
            session_start();
        }

        $info = &$_SESSION["{$action}_info"];

        $doOld = false;

        if ( $action == WPInstallStorage::CMD_MASS_UNFLAG ) {
            /**
             * Set to maintain compatibility with old ViewModel + Tpl.
             *
             * @deprecated  release_ver_placeholder
             */
            $oldInfo = &$_SESSION['unflagInfo'];
            $doOld   = true;
        }


        if ( $init ) {
            $info = [ 'installs' => $this->wpInstallStorage->getPaths() ];

            if ( $doOld ) {
                $oldInfo = $info;
            }

            return true;
        }

        $completedCount = -1;

        if ( !isset($info['installs']) ) {
            Logger::uiError(
                'Expected session data missing! Stopping mass operation.'
            );
        }
        else {
            $batchSize = $this->getBatchSize($info['installs']);
            $batch     = array_splice($info['installs'], 0, $batchSize);

            $completedCount = count(
                $this->wpInstallStorage->doAction($action, $batch)
            );

            if ( $completedCount != $batchSize ) {
                $info['installs'] = array_merge(
                    array_slice($batch, $completedCount),
                    $info['installs']
                );
            }
        }

        if ( empty($info['installs']) ) {
            unset($_SESSION["{$action}_info"]);

            if ( $doOld ) {
                unset($_SESSION['unflagInfo']);
            }
        }
        elseif ( $doOld ) {
            $oldInfo = $info;
        }

        $msgs = $this->wpInstallStorage->getAllCmdMsgs();

        AjaxResponse::setAjaxContent(
            json_encode(
                [
                    'completed' => $completedCount,
                    'errMsgs'   => array_merge(
                        $msgs['fail'],
                        $msgs['err'],
                        Logger::getUiMsgs(Logger::UI_ERR)
                    ),
                    'succMsgs'  => array_merge(
                        $msgs['succ'],
                        Logger::getUiMsgs(Logger::UI_SUCC)
                    )
                ]
            )
        );
        AjaxResponse::outputAndExit();
    }

    /**
     *
     * @param string $action
     *
     * @return void
     *
     * @throws LSCMException  Rethrown when Context::getOption() throws an
     *     LSCMException exception.
     * @throws LSCMException  Thrown indirectly by Logger::uiError() call.
     * @throws LSCMException  Thrown indirectly by Logger::uiError() call.
     * @throws LSCMException  Thrown indirectly by Logger::error() call.
     * @throws LSCMException  Thrown indirectly by
     *     $this->wpInstallStorage->doAction() call.
     */
    protected function doFormAction( $action )
    {
        $list = Util::get_request_list('installations');

        /**
         * Empty list also checked earlier using JS.
         */
        if ( $list == NULL ) {
            Logger::uiError('Please select at least one checkbox.');
            return;
        }

        foreach ( $list as $wpPath ) {

            if ( $this->wpInstallStorage->getWPInstall($wpPath) === null ) {
                Logger::uiError(
                    'Invalid input value detected -  No Action Taken'
                );
                return;
            }
        }

        try {
            Context::getOption()->setBatchTimeout(0);
        }
        catch ( LSCMException $e ) {
            $msg = "{$e->getMessage()} Could not set batch timeout.";
            Logger::error($msg);

            throw new LSCMException($msg);
        }

        $this->wpInstallStorage->doAction($action, $list);
    }

    /**
     * Get simple string representations of current installation status.
     *
     * @param WPInstall $wpInstall
     *
     * @return string[]
     */
    protected function getStatusStrings( WPInstall $wpInstall )
    {
        $status = $wpInstall->getStatus();

        if ( $status & WPInstall::ST_ERR_REMOVE ) {
            $statusString = 'removed';
        }
        elseif ( $wpInstall->hasFatalError() ) {
            $statusString = 'error';
        }
        elseif ( ($status & WPInstall::ST_PLUGIN_INACTIVE ) ) {
            $statusString = 'disabled';
        }
        elseif ( !($status & WPInstall::ST_LSC_ADVCACHE_DEFINED) ) {
            $statusString = 'warning';
        }
        else {
            $statusString = 'enabled';
        }

        if ( $wpInstall->isFlagBitSet() ) {
            $flagString = 'flagged';
        }
        else {
            $flagString = 'unflagged';
        }

        return [ 'status' => $statusString, 'flag_status' => $flagString ];
    }

    /**
     *
     * @param string $action
     * @param string $path
     *
     * @return void
     *
     * @throws LSCMException  Thrown indirectly by Logger::uiError() call.
     * @throws LSCMException  Thrown indirectly by
     *     $this->wpInstallStorage->doAction() call.
     * @throws LSCMException  Thrown indirectly by $this->getAjaxViewContent()
     *     call.
     * @throws LSCMException  Thrown indirectly by $this->getAjaxViewContent()
     *     call.
     * @throws LSCMException  Thrown indirectly by $this->getAjaxViewContent()
     *     call.
     * @throws LSCMException  Thrown indirectly by Logger::getUiMsgs() call.
     * @throws LSCMException  Thrown indirectly by Logger::getUiMsgs() call.
     * @throws LSCMException  Thrown indirectly by AjaxResponse::outputAndExit()
     *     call.
     */
    protected function doSingleAction( $action, $path )
    {
        $wpInstall = $this->wpInstallStorage->getWPInstall($path);

        if ( $wpInstall === null ) {
            Logger::uiError('Invalid input value detected - No Action Taken');
            return;
        }

        $preStatusInfo = $this->getStatusStrings($wpInstall);

        $this->wpInstallStorage->doAction($action, [ $path ]);

        $postStatusInfo = $this->getStatusStrings($wpInstall);

        $badgesDown = $badgesUp = [];
        $removed = false;

        if ( $postStatusInfo['status'] == 'removed' ) {
            $removed = true;

            $badgesDown[] = $preStatusInfo['status'];
            $badgesDown[] = 'flag';
        }
        else {

            if ( $preStatusInfo['status'] != $postStatusInfo['status'] ) {
                $badgesDown[] = $preStatusInfo['status'];
                $badgesUp[]   = $postStatusInfo['status'];
            }

            if (
                    $preStatusInfo['flag_status']
                        !=
                        $postStatusInfo['flag_status']
            ) {

                if ( $postStatusInfo['flag_status'] == 'flagged' ) {
                    $badgesUp[] = 'flag';
                }
                else {
                    $badgesDown[] = 'flag';
                }
            }
        }

        $viewModel = new AjaxViewModel\CacheMgrRowViewModel($wpInstall);

        $statusSort = $viewModel->getsortVal('status');
        $flagSort   = $viewModel->getsortVal('flag');

        switch ( $flagSort ) {

            case 'removed':
                $flagSearch = $flagSort;
                break;

            case 'flagged':
                $flagSearch = 'f';
                break;

            default:
                $flagSearch = 'u';
        }

        $msgs = $this->wpInstallStorage->getAllCmdMsgs();

        AjaxResponse::setAjaxContent(
            json_encode(
                [
                    'displayData' => [
                        'actions_td'    =>
                            $this->getAjaxViewContent($viewModel, 'actions_td'),
                        'status_search' => $statusSort,
                        'status_sort'   => $statusSort,
                        'status_td'     =>
                            $this->getAjaxViewContent($viewModel, 'status_td'),
                        'flag_search'   => $flagSearch,
                        'flag_sort'     => $flagSort,
                        'flag_td'       =>
                            $this->getAjaxViewContent($viewModel, 'flag_td')
                    ],
                    'badgesDown'  => $badgesDown,
                    'badgesUp'    => $badgesUp,
                    'removed'     => $removed,
                    'errMsgs'     => array_merge(
                        $msgs['fail'],
                        $msgs['err'],
                        Logger::getUiMsgs(Logger::UI_ERR)
                    ),
                    'succMsgs'    => array_merge(
                        $msgs['succ'],
                        Logger::getUiMsgs(Logger::UI_SUCC)
                    )
                ]
            )
        );
        AjaxResponse::outputAndExit();
    }

    /**
     *
     * @param WPDashMsgs $wpDashMsgs
     * @param string     $action
     *
     * @throws LSCMException  Thrown when parameter $action value is
     *     unrecognized.
     * @throws LSCMException  Thrown indirectly by AjaxResponse::outputAndExit()
     *     call.
     */
    protected function doWpDashMsgOperation(
        WPDashMsgs $wpDashMsgs,
                   $action
    )
    {
        if ( ($type = Util::get_request_var('msg_type')) !== NULL ) {
            $type = trim($type);
        }

        if ( ($msgId = Util::get_request_var('msg_id')) !== NULL ) {
            $msgId = trim($msgId);
        }

        switch ( $action ) {

            case WPDashMsgs::ACTION_GET_MSG:
                $msgs    = $wpDashMsgs->getMsgData($type);
                $msgInfo = [];

                if (
                        $msgId !== ''
                        &&
                        $msgId !== NULL
                        &&
                        isset($msgs[$msgId])
                ) {
                    $msgInfo = $msgs[$msgId];
                }

                $ajaxReturn = [ 'msgInfo' => $msgInfo ];
                break;

            case WPDashMsgs::ACTION_ADD_MSG:

                if ( ($msg = Util::get_request_var('notify_msg')) !== NULL ) {
                    $msg = trim($msg);
                }

                if ( ($slug = Util::get_request_var('notify_slug')) !== NULL ) {
                    $slug = trim($slug);
                }

                $ret = 0;

                if ( $wpDashMsgs->addMsg($type, $msgId, $msg, $slug) ) {
                    $ret = 1;
                }

                $ajaxReturn = [ 'ret' => $ret ];

                break;

            case WPDashMsgs::ACTION_DELETE_MSG:
                $ajaxReturn = [
                    'ret' => ($wpDashMsgs->deleteMsg($type, $msgId)) ? 1 : 0
                ];

                break;

            default:
                throw new LSCMException(
                    'PanelController->doWpDashMsgOperation(): Unrecognized '
                        . '$action value.'
                );
        }

        AjaxResponse::setAjaxContent(json_encode($ajaxReturn));
        AjaxResponse::outputAndExit();
    }

    /**
     *
     * @param string $action
     * @param string $path
     * @param string $msgInfoJSON
     *
     * @throws LSCMException  Thrown indirectly by AjaxResponse::outputAndExit()
     *     call.
     * @throws LSCMException  Thrown indirectly by
     *     $this->wpInstallStorage->doAction() call.
     * @throws LSCMException  Thrown indirectly by Logger::getUiMsgs() call.
     * @throws LSCMException  Thrown indirectly by Logger::getUiMsgs() call.
     * @throws LSCMException  Thrown indirectly by AjaxResponse::outputAndExit()
     *     call.
     */
    protected function doSingleDashAction( $action, $path, $msgInfoJSON = '' )
    {
        if ( $this->wpInstallStorage->getWPInstall($path) === null ) {
            AjaxResponse::setAjaxContent(
                json_encode(
                    [
                        'errMsgs'  => [
                            'Invalid input value detected - Please use the '
                                . 'exact path displayed in the '
                                . '"Manage Cache Installations" list when '
                                . 'testing.'
                        ],
                        'succMsgs' => []
                    ]
                )
            );
            AjaxResponse::outputAndExit();
        }

        $this->wpInstallStorage->doAction($action, [ $path ], [ $msgInfoJSON ]);

        $msgs = $this->wpInstallStorage->getAllCmdMsgs();

        AjaxResponse::setAjaxContent(
            json_encode(
                [
                    'errMsgs'  => array_merge(
                        $msgs['fail'],
                        $msgs['err'],
                        Logger::getUiMsgs(Logger::UI_ERR)
                    ),
                    'succMsgs' => array_merge(
                        $msgs['succ'],
                        Logger::getUiMsgs(Logger::UI_SUCC)
                    )
                ]
            )
        );
        AjaxResponse::outputAndExit();
    }

    /**
     *
     * @param string $action
     * @param int    $step
     *
     * @throws LSCMException  Thrown indirectly by Logger::uiError() call.
     * @throws LSCMException  Thrown indirectly by $this->getBatchSize() call.
     * @throws LSCMException  Thrown indirectly by Logger::uiError() call.
     * @throws LSCMException  Thrown indirectly by Logger::getUiMsgs() call.
     * @throws LSCMException  Thrown indirectly by Logger::getUiMsgs() call.
     * @throws LSCMException  Thrown indirectly by AjaxResponse::outputAndExit()
     *     call.
     */
    public function massEnableDisable( $action, $step )
    {
        if ( session_status() !== PHP_SESSION_ACTIVE ) {
            session_start();
        }

        $actionUpper = ucfirst($action);
        $info        = &$_SESSION["mass{$actionUpper}Info"];

        switch ( $step ) {

            case 1:
                $info = [ 'installs' => $this->wpInstallStorage->getPaths() ];
                break;

            case 2:
                $completedCount                          = -1;
                $succCount = $failCount = $bypassedCount = 0;

                if ( !isset($info['installs']) ) {
                    Logger::uiError(
                        'Expected session data missing! Stopping mass '
                            . 'operation.'
                    );
                }
                else {
                    $batchSize = $this->getBatchSize($info['installs']);
                    $batch     = array_splice($info['installs'], 0, $batchSize);

                    try
                    {
                        $finishedList = $this->wpInstallStorage->doAction(
                            "mass_$action",
                            $batch
                        );

                        $completedCount = count($finishedList);

                        if ( $completedCount != $batchSize ) {
                            $info['installs'] = array_merge(
                                array_slice($batch, $completedCount),
                                $info['installs']
                            );
                        }
                    }
                    catch ( LSCMException $e )
                    {
                        Logger::uiError(
                            "{$e->getMessage()} Stopping mass operation."
                        );
                        $finishedList = $info['installs'] = [];
                    }

                    $workingQueue = $this->wpInstallStorage->getWorkingQueue();

                    foreach ( $finishedList as $path ) {
                        $wpInstall =
                            $this->wpInstallStorage->getWPInstall($path);

                        if ( isset($workingQueue[$path]) ) {
                            $cmdStatus = $workingQueue[$path]->getCmdStatus();
                        }
                        else {
                            $cmdStatus = $wpInstall->getCmdStatus();
                        }

                        if ( $cmdStatus & UserCommand::EXIT_INCR_SUCC ) {
                            $succCount++;
                        }
                        elseif ( $cmdStatus & UserCommand::EXIT_INCR_FAIL ) {
                            $failCount++;
                        }
                        elseif (
                                $cmdStatus & UserCommand::EXIT_INCR_BYPASS
                                ||
                                $wpInstall->isFlagBitSet()
                        ) {
                            $bypassedCount++;
                        }
                    }
                }

                if ( empty($info['installs']) ) {
                    unset($_SESSION["mass{$actionUpper}Info"]);
                }

                $msgs = $this->wpInstallStorage->getAllCmdMsgs();

                AjaxResponse::setAjaxContent(
                    json_encode(
                        [
                            'completed'     => $completedCount,
                            'bypassedCount' => $bypassedCount,
                            'failCount'     => $failCount,
                            'succCount'     => $succCount,
                            'errMsgs'       => array_merge(
                                $msgs['fail'],
                                $msgs['err'],
                                Logger::getUiMsgs(Logger::UI_ERR)
                            ),
                            'succMsgs'      => array_merge(
                                $msgs['succ'],
                                Logger::getUiMsgs(Logger::UI_SUCC)
                            )
                        ]
                    )
                );
                AjaxResponse::outputAndExit();
                break;

            // No default case
        }
    }

    /**
     * Force updates LiteSpeed Cache Plugins whose versions
     * match those in $verList and refreshes status as well. Flagged
     * installations are bypassed.
     *
     * @param int $step  Value of 2 will prep session info, 3 will begin
     *     changing installed LSCWP versions in batches.
     *
     * @return void
     *
     * @throws LSCMException  Thrown indirectly by Logger::uiError() call.
     * @throws LSCMException  Thrown indirectly by $this->getBatchSize() call.
     * @throws LSCMException  Thrown indirectly by Logger::uiError() call.
     * @throws LSCMException  Thrown indirectly by Logger::getUiMsgs() call.
     * @throws LSCMException  Thrown indirectly by AjaxResponse::outputAndExit()
     *     call.
     */
    public function prepVersionChange( $step )
    {
        if ( session_status() !== PHP_SESSION_ACTIVE ) {
            session_start();
        }

        $info = &$_SESSION['verInfo'];

        switch ( $step ) {

            case 2:
                /**
                 * init upgrade
                 */

                if (
                    empty(
                    ($verList = Util::get_request_list('selectedVers'))
                    )
                ) {
                    /**
                     * Version list should not be empty
                     */
                    return;
                }

                $info = [
                    'installs' => $this->wpInstallStorage->getPaths(),
                    'verNum'   => Util::get_request_var('version_num'),
                    'verList'  => $verList
                ];

                break;

            case 3:
                $completedCount = -1;

                if ( !isset($info['installs']) ) {
                    Logger::uiError(
                        'Expected session data missing! Stopping mass '
                            . 'operation.'
                    );
                }
                else {
                    $batchSize = $this->getBatchSize($info['installs']);
                    $batch     = array_splice($info['installs'], 0, $batchSize);

                    try {
                        $completedCount = count(
                            $this->wpInstallStorage->doAction(
                                UserCommand::CMD_MASS_UPGRADE,
                                $batch,
                                /**
                                 * 1 => "from versions" (comma seperated),
                                 * 2 => "to version"
                                 */
                                [
                                    implode(',', $info['verList']),
                                    $info['verNum']
                                ]
                            )
                        );

                        if ( $completedCount != $batchSize ) {
                            $info['installs'] = array_merge(
                                array_slice($batch, $completedCount),
                                $info['installs']
                            );
                        }
                    }
                    catch ( LSCMException $e ) {
                        Logger::uiError(
                            "{$e->getMessage()} Stopping mass operation."
                        );

                        $info['installs'] = [];
                    }
                }

                if ( empty($info['installs']) || $completedCount == -1 ) {
                    unset($_SESSION['verInfo']);
                }

                $msgs = $this->wpInstallStorage->getAllCmdMsgs();

                AjaxResponse::setAjaxContent(
                    json_encode(
                        [
                            'completed' => $completedCount,
                            'errMsgs'   => array_merge(
                                $msgs['fail'],
                                $msgs['err'],
                                Logger::getUiMsgs(Logger::UI_ERR)
                            )
                        ]
                    )
                );
                AjaxResponse::outputAndExit();
                break;
        }
    }

    /**
     *
     * @return bool|void  Function outputs ajax and exits without returning a
     *     value when $init is evaluated to be false.
     *
     * @throws LSCMException  Thrown indirectly by Logger::uiError() call.
     * @throws LSCMException  Thrown indirectly by $this->getBatchSize() call.
     * @throws LSCMException  Thrown indirectly by Logger::uiError() call.
     * @throws LSCMException  Thrown indirectly by Logger::getUiMsgs() call.
     * @throws LSCMException  Thrown indirectly by Logger::getUiMsgs() call.
     * @throws LSCMException  Thrown indirectly by AjaxResponse::outputAndExit()
     *     call.
     */
    protected function checkDashMassNotifyAction()
    {
        if ( $this->dashStep == self::DASH_STEP_MASS_DASH_NOTIFY ) {
            $init = false;
        }
        elseif ( Util::get_request_var('mass-notify') ) {
            $init           = true;
            $this->dashStep = self::DASH_STEP_MASS_DASH_NOTIFY;
        }
        else {
            return false;
        }

        if ( session_status() !== PHP_SESSION_ACTIVE ) {
            session_start();
        }

        $info = &$_SESSION['massDashNotifyInfo'];

        if ( $init ) {
            $info = [
                'installs' => $this->wpInstallStorage->getPaths(),
                'msgInfo'  => base64_encode($this->getDashMsgInfoJSON())
            ];

            return true;
        }

        $completedCount                          = -1;
        $succCount = $failCount = $bypassedCount = 0;

        if ( !isset($info['installs']) ) {
            Logger::uiError(
                'Expected session data missing! Stopping mass operation.'
            );
        }
        else {
            $batchSize = $this->getBatchSize($info['installs']);
            $batch     = array_splice($info['installs'], 0, $batchSize);

            try {
                $finishedList = $this->wpInstallStorage->doAction(
                    UserCommand::CMD_MASS_DASH_NOTIFY,
                    $batch,
                    [ $info['msgInfo'] ]
                );

                $completedCount = count($finishedList);

                if ( $completedCount != $batchSize ) {
                    $info['installs'] = array_merge(
                        array_slice($batch, $completedCount),
                        $info['installs']
                    );
                }
            }
            catch ( LSCMException $e ) {
                Logger::uiError("{$e->getMessage()} Stopping mass operation.");
                $finishedList = $info['installs'] = [];
            }

            $workingQueue = $this->wpInstallStorage->getWorkingQueue();

            foreach ( $finishedList as $path ) {
                $wpInstall = $this->wpInstallStorage->getWPInstall($path);

                if ( isset($workingQueue[$path]) ) {
                    $cmdStatus = $workingQueue[$path]->getCmdStatus();
                }
                else {
                    $cmdStatus = $wpInstall->getCmdStatus();
                }

                if ( $cmdStatus & UserCommand::EXIT_INCR_SUCC ) {
                    $succCount++;
                }
                elseif ( $cmdStatus & UserCommand::EXIT_INCR_FAIL ) {
                    $failCount++;
                }
                elseif (
                        $cmdStatus & UserCommand::EXIT_INCR_BYPASS
                        ||
                        $wpInstall->isFlagBitSet()
                ) {
                    $bypassedCount++;
                }
            }
        }

        if ( empty($info['installs']) ) {
            unset($_SESSION['massDashNotifyInfo']);
        }

        $msgs = $this->wpInstallStorage->getAllCmdMsgs();

        AjaxResponse::setAjaxContent(
            json_encode(
                [
                    'completed'     => $completedCount,
                    'bypassedCount' => $bypassedCount,
                    'failCount'     => $failCount,
                    'succCount'     => $succCount,
                    'errMsgs'       => array_merge(
                        $msgs['fail'],
                        $msgs['err'],
                        Logger::getUiMsgs(Logger::UI_ERR)
                    ),
                    'succMsgs'      => array_merge(
                        $msgs['succ'],
                        Logger::getUiMsgs(Logger::UI_SUCC)
                    )
                ]
            )
        );
        AjaxResponse::outputAndExit();
    }

    /**
     *
     * @return bool|void  Function outputs ajax and exits without returning a
     *     value when $init is evaluated to be false.
     *
     * @throws LSCMException  Thrown indirectly by Logger::uiError() call.
     * @throws LSCMException  Thrown indirectly by $this->getBatchSize() call.
     * @throws LSCMException  Thrown indirectly by Logger::uiError() call.
     * @throws LSCMException  Thrown indirectly by Logger::getUiMsgs() call.
     * @throws LSCMException  Thrown indirectly by Logger::getUiMsgs() call.
     * @throws LSCMException  Thrown indirectly by AjaxResponse::outputAndExit()
     *     call.
     */
    protected function checkDashMassDisableAction()
    {
        if ( $this->dashStep == self::DASH_STEP_MASS_DASH_DISABLE ) {
            $init = false;
        }
        elseif ( Util::get_request_var('mass-disable-dash-notifier') ) {
            $init           = true;
            $this->dashStep = self::DASH_STEP_MASS_DASH_DISABLE;
        }
        else {
            return false;
        }

        if ( session_status() !== PHP_SESSION_ACTIVE ) {
            session_start();
        }

        $info = &$_SESSION['massDashDisableInfo'];

        if ( $init ) {
            $info = [ 'installs' => $this->wpInstallStorage->getPaths() ];
            return true;
        }

        $completedCount                          = -1;
        $succCount = $failCount = $bypassedCount = 0;

        if ( !isset($info['installs']) ) {
            Logger::uiError(
                'Expected session data missing! Stopping mass operation.'
            );
        }
        else {
            $batchSize = $this->getBatchSize($info['installs']);
            $batch     = array_splice($info['installs'], 0, $batchSize);

            try {
                $finishedList = $this->wpInstallStorage->doAction(
                    UserCommand::CMD_MASS_DASH_DISABLE,
                    $batch
                );

                $completedCount = count($finishedList);

                if ( $completedCount != $batchSize ) {
                    $info['installs'] = array_merge(
                        array_slice($batch, $completedCount),
                        $info['installs']
                    );
                }
            }
            catch ( LSCMException $e ) {
                Logger::uiError("{$e->getMessage()} Stopping mass operation.");
                $finishedList = $info['installs'] = [];
            }

            $workingQueue = $this->wpInstallStorage->getWorkingQueue();

            foreach ( $finishedList as $path ) {
                $wpInstall = $this->wpInstallStorage->getWPInstall($path);

                if ( isset($workingQueue[$path]) ) {
                    $cmdStatus = $workingQueue[$path]->getCmdStatus();
                }
                else {
                    $cmdStatus = $wpInstall->getCmdStatus();
                }

                if ( $cmdStatus & UserCommand::EXIT_INCR_SUCC ) {
                    $succCount++;
                }
                elseif ( $cmdStatus & UserCommand::EXIT_INCR_FAIL ) {
                    $failCount++;
                }
                elseif (
                        $cmdStatus & UserCommand::EXIT_INCR_BYPASS
                        ||
                        $wpInstall->isFlagBitSet()
                ) {
                    $bypassedCount++;
                }
            }
        }

        if ( empty($info['installs']) ) {
            unset($_SESSION['massDashDisableInfo']);
        }

        $msgs = $this->wpInstallStorage->getAllCmdMsgs();

        AjaxResponse::setAjaxContent(
            json_encode(
                [
                    'completed'     => $completedCount,
                    'bypassedCount' => $bypassedCount,
                    'failCount'     => $failCount,
                    'succCount'     => $succCount,
                    'errMsgs'       => array_merge(
                        $msgs['fail'],
                        $msgs['err'],
                        Logger::getUiMsgs(Logger::UI_ERR)
                    ),
                    'succMsgs'      => array_merge(
                        $msgs['succ'],
                        Logger::getUiMsgs(Logger::UI_SUCC)
                    )
                ]
            )
        );
        AjaxResponse::outputAndExit();
    }

}
webcachemgr/src/RedefineGlobalFuncs.php000066400000001541150545647710014175 0ustar00<?php

/** *********************************************
 * LiteSpeed Web Server Cache Manager
 *
 * @author LiteSpeed Technologies, Inc. (https://www.litespeedtech.com)
 * @copyright (c) 2021
 * @since 1.13.10
 * *******************************************
 */

/**
 * As of PHP 8.x, functions disabled using ini directive 'disable_functions'
 * are no longer included in PHP's functions table and must be redefined to
 * avoid fatal error "Call to undefined function" when called.
 *
 * This file is used to redefine internal PHP functions intentionally disabled
 * before loading the WordPress environment.
 */

if ( !function_exists('ini_set') ) {

    /**
     *
     * @since 1.13.10
     *
     * @param string $option
     * @param string $value
     *
     * @return false
     */
    function ini_set( $option, $value)
    {
        return false;
    }
}
webcachemgr/src/UserCommand.php000066400000071343150545647710012560 0ustar00<?php

/** *********************************************
 * LiteSpeed Web Server Cache Manager
 *
 * @author Michael Alegre
 * @copyright (c) 2018-2023 LiteSpeed Technologies, Inc.
 * *******************************************
 */

namespace Lsc\Wp;

use Exception;
use Lsc\Wp\Context\Context;
use Lsc\Wp\Context\ContextOption;
use Lsc\Wp\Context\UserCLIContextOption;
use Lsc\Wp\Panel\ControlPanel;

/**
 * Running as user - suexec
 */
class UserCommand
{

    /**
     * @var int
     */
    const EXIT_ERROR = 1;

    /**
     * @var int
     */
    const EXIT_SUCC = 2;

    /**
     * @var int
     */
    const EXIT_FAIL = 4;

    /**
     * @var int
     */
    const EXIT_INCR_SUCC = 8;

    /**
     * @var int
     */
    const EXIT_INCR_FAIL = 16;

    /**
     * @var int
     */
    const EXIT_INCR_BYPASS = 32;

    /**
     * @var int
     */
    const RETURN_CODE_TIMEOUT = 124;

    /**
     * @var string
     */
    const CMD_STATUS = 'status';

    /**
     * @var string
     */
    const CMD_ENABLE = 'enable';

    /**
     * @var string
     */
    const CMD_DIRECT_ENABLE = 'direct_enable';

    /**
     * @var string
     */
    const CMD_MASS_ENABLE = 'mass_enable';

    /**
     * @var string
     */
    const CMD_DISABLE = 'disable';

    /**
     * @var string
     */
    const CMD_MASS_DISABLE = 'mass_disable';

    /**
     * @var string
     */
    const CMD_UPGRADE = 'upgrade';

    /**
     * @var string
     */
    const CMD_MASS_UPGRADE = 'mass_upgrade';

    /**
     * @var string
     */
    const CMD_UPDATE_TRANSLATION = 'update_translation';

    /**
     * @var string
     */
    const CMD_REMOVE_LSCWP_PLUGIN_FILES = 'remove_lscwp_plugin_files';

    /**
     * @var string
     */
    const CMD_DASH_NOTIFY = 'dash_notify';

    /**
     * @var string
     */
    const CMD_MASS_DASH_NOTIFY = 'mass_dash_notify';

    /**
     * @var string
     */
    const CMD_DASH_DISABLE = 'dash_disable';

    /**
     * @var string
     */
    const CMD_MASS_DASH_DISABLE = 'mass_dash_disable';

    /**
     * @var string
     */
    const CMD_DASH_GET_MSG = 'dash_get_msg';

    /**
     * @var string
     */
    const CMD_DASH_ADD_MSG = 'dash_add_msg';

    /**
     * @var string
     */
    const CMD_DASH_DELETE_MSG = 'dash_delete_msg';

    /**
     * @since 1.12
     * @var string
     */
    const CMD_GET_QUICCLOUD_API_KEY = 'getQuicCloudApiKey';

    /**
     * @var bool
     */
    private $asUser;

    /**
     * @var WPInstall
     */
    private $currInstall;

    /**
     * @var string
     */
    private $action;

    /**
     * @var string[]
     */
    private $extraArgs;

    /**
     *
     * @param bool $asUser
     *
     * @throws LSCMException  Thrown indirectly by Context::initialize() call.
     */
    private function __construct( $asUser = false )
    {
        if ( ($this->asUser = $asUser) ) {
            require_once __DIR__ . '/../autoloader.php';
            date_default_timezone_set('UTC');
            Context::initialize(new UserCLIContextOption('userCommand'));
        }
    }

    /**
     * Handles logging unexpected error output (or not if too long) and returns
     * a crafted message to be displayed instead.
     *
     * @param WPInstall $wpInstall  WordPress Installation object.
     * @param string    $err        Compiled error message.
     * @param int       $lines      Number of $output lines read into the error
     *     msg.
     *
     * @return string  Message to be displayed instead.
     *
     * @throws LSCMException  Thrown indirectly by Logger::error() call.
     * @throws LSCMException  Thrown indirectly by Logger::error() call.
     */
    private static function handleUnexpectedError(
        WPInstall $wpInstall,
                  $err,
                  $lines )
    {
        $msg = 'Unexpected Error Encountered!';
        $path = $wpInstall->getPath();

        /**
         * $lines > 500 are likely some custom code triggering a page render.
         * Throw out actual message in this case.
         */
        if ( $lines < 500 ) {
            $match = false;

            $commonErrs = array(
                WPInstall::ST_ERR_EXECMD_DB =>
                    'Error establishing a database connection'
            );

            foreach ( $commonErrs as $statusBit => $commonErr ) {

                if ( strpos($err, $commonErr) !== false ) {
                    $wpInstall->unsetStatusBit(WPInstall::ST_ERR_EXECMD);
                    $wpInstall->setStatusBit($statusBit);

                    $msg .= " $commonErr.";
                    $match = true;
                    break;
                }
            }

            if ( !$match ) {
                Logger::error("$path - $err");
                return "$msg See " . ContextOption::LOG_FILE_NAME
                    . " for more information.";
            }
        }

        Logger::error("$path - $msg");
        return $msg;
    }

    /**
     * Parse out locale and plugin version information from issue() result
     * output GET_TRANSLATION or BAD_TRANSLATION line.
     *
     * @since 1.14
     *
     * @param string $line
     *
     * @return string[]
     */
    private static function parseTranslationLocaleAndPluginVer( $line )
    {
        list($locale, $pluginVer) = explode(' ', $line);

        return array( 'locale' => $locale, 'pluginVer' => $pluginVer );
    }

    /**
     *
     * @since 1.9
     *
     * @param WPInstall $wpInstall
     * @param string    $output
     *
     * @throws LSCMException  Thrown indirectly by
     *     PluginVersion::retrieveTranslation() call.
     * @throws LSCMException  Thrown indirectly by self::subCommandIssue() call.
     * @throws LSCMException  Thrown indirectly by
     *     PluginVersion::removeTranslationZip() call.
     */
    private static function handleGetTranslationOutput(
        WPInstall $wpInstall,
                  $output )
    {
        $translationInfo = self::parseTranslationLocaleAndPluginVer($output);

        $translationRetrieved = PluginVersion::retrieveTranslation(
            $translationInfo['locale'],
            $translationInfo['pluginVer']
        );

        if ( $translationRetrieved ) {
            $subOutput =
                self::subCommandIssue(self::CMD_UPDATE_TRANSLATION, $wpInstall);

            foreach ( $subOutput as $subLine ) {

                if ( preg_match('/BAD_TRANSLATION=(.+)/', $subLine, $m) ) {
                    $badTranslationInfo =
                        self::parseTranslationLocaleAndPluginVer($m[1]);

                    PluginVersion::removeTranslationZip(
                        $badTranslationInfo['locale'],
                        $badTranslationInfo['pluginVer']
                    );
                }
            }
        }
    }

    /**
     *
     * @since 1.9
     *
     * @param WPInstall $wpInstall
     * @param string    $line
     * @param int       $retStatus
     * @param int       $cmdStatus
     * @param string    $err
     *
     * @return bool
     *
     * @throws LSCMException  Thrown indirectly by
     *     $wpInstall->populateDataFromUrl() call.
     * @throws LSCMException  Thrown indirectly by
     *     self::handleGetTranslationOutput() call.
     */
    private static function handleResultOutput(
        WPInstall $wpInstall,
                  $line,
                  &$retStatus,
                  &$cmdStatus,
                  &$err )
    {
        if ( preg_match('/SITEURL=(.+)/', $line, $m) ) {

            if ( !$wpInstall->populateDataFromUrl($m[1]) ) {
                /**
                 * Matching docroot could not be found, ignore other
                 * output. setCmdStatusAndMsg() etc already handled in
                 * setSiteUrl().
                 */
                return false;
            }
        }
        elseif ( preg_match('/STATUS=(.+)/', $line, $m) ) {
            $retStatus = (int)$m[1];
        }
        elseif ( preg_match('/MASS_INCR=(.+)/', $line, $m) ) {

            if ( $m[1] == 'SUCC' ) {
                $cmdStatus |= UserCommand::EXIT_INCR_SUCC;
            }
            elseif ( $m[1] == 'FAIL' ) {
                $cmdStatus |= UserCommand::EXIT_INCR_FAIL;
            }
            elseif( $m[1] = 'BYPASS' ) {
                $cmdStatus |= UserCommand::EXIT_INCR_BYPASS;
            }
        }
        elseif ( preg_match('/GET_TRANSLATION=(.+)/', $line, $m) ) {
            self::handleGetTranslationOutput($wpInstall, $m[1]);
        }
        else {
            $err .= "Unexpected result line: $line\n";
        }

        return true;
    }

    /**
     *
     * @since 1.9
     *
     * @param WPInstall $wpInstall
     *
     * @throws LSCMException  Thrown indirectly by self::subCommandIssue() call.
     */
    private static function removeLeftoverLscwpFiles( WPInstall $wpInstall )
    {
        self::subCommandIssue(self::CMD_REMOVE_LSCWP_PLUGIN_FILES, $wpInstall);

        $wpInstall->removeNewLscwpFlagFile();
    }

    /**
     *
     * @param string    $action
     * @param WPInstall $wpInstall
     * @param array     $extraArgs
     *
     * @return string
     *
     * @throws LSCMException  Thrown indirectly by $wpInstall->getPhpBinary()
     *     call.
     * @throws LSCMException  Thrown indirectly by Context::getOption() call.
     */
    protected static function getIssueCmd(
                  $action,
        WPInstall $wpInstall,
        array     $extraArgs = array() )
    {
        $su = $wpInstall->getSuCmd();
        $timeout = ControlPanel::PHP_TIMEOUT;
        $phpBin = $wpInstall->getPhpBinary();
        $path = $wpInstall->getPath();
        $serverName = $wpInstall->getData(WPInstall::FLD_SERVERNAME);
        $env = Context::getOption()->getInvokerName();

        if ( $serverName === null ) {
            $serverName = $docRoot = 'x';
        }
        else {
            $docRoot = $wpInstall->getData(WPInstall::FLD_DOCROOT);

            if ( $docRoot === null ) {
                $docRoot = 'x';
            }
        }

        $modifier = implode(' ', $extraArgs);
        $file = __FILE__;

        return "$su -c \"cd $path/wp-admin && timeout $timeout $phpBin $file "
            . "$action $path $docRoot $serverName $env"
            . (($modifier !== '') ? " $modifier\"" : '"');
    }

    /**
     *
     * @since 1.12
     *
     * @param string    $action
     * @param WPInstall $wpInstall
     * @param string[]  $extraArgs
     *
     * @return null|string
     *
     * @throws LSCMException  Thrown indirectly by self::preIssueValidation()
     *     call.
     * @throws LSCMException  Thrown indirectly by self::getIssueCmd() call.
     * @throws LSCMException  Thrown indirectly by Logger::debug() call.
     * @throws LSCMException  Thrown indirectly by Logger::debug() call.
     * @throws LSCMException  Thrown indirectly by Logger::logMsg() call.
     * @throws LSCMException  Thrown indirectly by Logger::logMsg() call.
     */
    public static function getValueFromWordPress(
                  $action,
        WPInstall $wpInstall,
        array     $extraArgs = array() )
    {
        if ( !self::preIssueValidation($action, $wpInstall, $extraArgs) ) {
            return null;
        }

        $cmd = self::getIssueCmd($action, $wpInstall, $extraArgs);

        exec($cmd, $output, $return_var);

        Logger::debug(
            "getValueFromWordPress command $action=$return_var $wpInstall\n$cmd"
        );
        Logger::debug('output = ' . var_export($output, true));

        $ret = null;
        $debug = $upgrade = $err = '';
        $curr = &$err;

        foreach ( $output as $line ) {

            /**
             * If this line is not present in output, did not return normally.
             * This line will appear after any [UPGRADE] output.
             */
            if ( strpos($line, 'LS UserCommand Output Start') !== false ) {
                continue;
            }
            elseif ( strpos($line, '[RESULT]') !== false ) {

                if ( preg_match('/API_KEY=(.+)/', $line, $m) ) {
                    $ret = $m[1];
                }
                else {
                    $err .= "Unexpected result line $line\n";
                }
            }
            elseif ( ($pos = strpos($line, '[DEBUG]')) !== false ) {
                $debug .= substr($line, $pos + 7) . "\n";
                $curr = &$debug;
            }
            elseif ( strpos($line, '[UPGRADE]') !== false ) {
                //Ignore this output
                $curr = &$upgrade;
            }
            else {
                $curr .= "$line\n";
            }
        }

        $path = $wpInstall->getPath();

        if ( $debug ) {
            Logger::logMsg("$path - $debug", Logger::L_DEBUG);
        }

        if ( $err ) {
            Logger::logMsg("$path - $err", Logger::L_ERROR);
        }

        return $ret;
    }

    /**
     *
     * @since 1.14
     *
     * @param string    $subAction
     * @param WPInstall $wpInstall
     *
     * @return string[]
     *
     * @throws LSCMException  Thrown indirectly by self::getIssueCmd() call.
     * @throws LSCMException  Thrown indirectly by Logger::debug() call.
     * @throws LSCMException  Thrown indirectly by Logger::debug() call.
     */
    private static function subCommandIssue(
        $subAction,
        WPInstall $wpInstall )
    {
        $subCmd = self::getIssueCmd($subAction, $wpInstall);

        exec($subCmd, $subOutput, $subReturn_var);

        Logger::debug(
            "Issue sub command $subAction=$subReturn_var $wpInstall\n$subCmd"
        );
        Logger::debug('sub output = ' . var_export($subOutput, true));

        return $subOutput;
    }

    /**
     *
     * @param string    $action
     * @param WPInstall $wpInstall
     * @param string[]  $extraArgs
     *
     * @return bool
     *
     * @throws LSCMException  Thrown indirectly by self::preIssueValidation()
     *     call.
     * @throws LSCMException  Thrown indirectly by self::getIssueCmd() call.
     * @throws LSCMException  Thrown indirectly by Logger::debug() call.
     * @throws LSCMException  Thrown indirectly by Logger::debug() call.
     * @throws LSCMException  Thrown indirectly by
     *     self::removeLeftoverLscwpFiles() call.
     * @throws LSCMException  Thrown indirectly by self::handleResultOutput()
     *     call.
     * @throws LSCMException  Thrown indirectly by Logger::logMsg() call.
     * @throws LSCMException  Thrown indirectly by Logger::logMsg() call.
     * @throws LSCMException  Thrown indirectly by $wpInstall->addUserFlagFile()
     *     call.
     * @throws LSCMException  Thrown indirectly by Logger::error() call.
     * @throws LSCMException  Thrown indirectly by self::handleUnexpectedError()
     *     call.
     */
    public static function issue(
                  $action,
        WPInstall $wpInstall,
        array     $extraArgs = array() )
    {
        if ( !self::preIssueValidation($action, $wpInstall, $extraArgs) ) {
            return false;
        }

        $cmd = self::getIssueCmd($action, $wpInstall, $extraArgs);

        exec($cmd, $output, $return_var);

        Logger::debug(
            "Issue command $action=$return_var $wpInstall\n$cmd"
        );
        Logger::debug('output = ' . var_export($output, true));

        if ( $wpInstall->hasNewLscwpFlagFile() ) {
            self::removeLeftoverLscwpFiles($wpInstall);
        }

        $errorStatus = $retStatus = $cmdStatus = 0;

        switch ( $return_var ) {

            case UserCommand::RETURN_CODE_TIMEOUT:
                $errorStatus |= WPInstall::ST_ERR_TIMEOUT;
                break;

            case UserCommand::EXIT_ERROR:
            case 255:
                $errorStatus |= WPInstall::ST_ERR_EXECMD;
                break;

            //no default
        }

        $isExpectedOutput = false;
        $unexpectedLines = 0;
        $succ = $upgrade = $err = $msg = $logMsg = '';
        $logLvl = -1;
        $curr = &$err;

        foreach ( $output as $line ) {

            /**
             * If this line is not present in output, did not return normally.
             * This line will appear after any [UPGRADE] output.
             */
            if ( strpos($line, 'LS UserCommand Output Start') !== false ) {
                $isExpectedOutput = true;
            }
            elseif ( strpos($line, '[RESULT]') !== false ) {

                $ret = self::handleResultOutput(
                    $wpInstall,
                    $line,
                    $retStatus,
                    $cmdStatus,
                    $err
                );

                if ( !$ret ) {

                    /**
                     * Problem handling RESULT output, ignore other output.
                     */
                    return false;
                }
            }
            elseif ( ($pos = strpos($line, '[SUCCESS]')) !== false ) {
                $succ .= substr($line, $pos + 9) . "\n";
                $curr = &$succ;
            }
            elseif ( ($pos = strpos($line, '[ERROR]')) !== false ) {
                $err .= substr($line, $pos + 7) . "\n";
                $curr = &$err;
            }
            elseif ( strpos($line, '[LOG]') !== false ) {

                if ( $logMsg != '' ) {
                    Logger::logMsg(trim($logMsg), $logLvl);
                    $logMsg = '';
                }

                if ( preg_match('/\[(\d+)] (.+)/', $line, $m) ) {
                    $logLvl = $m[1];
                    $logMsg = "{$wpInstall->getPath()} - $m[2]\n";
                }

                $curr = &$logMsg;
            }
            elseif ( strpos($line, '[UPGRADE]') !== false ) {
                /**
                 * Ignore this output
                 */
                $curr = &$upgrade;
            }
            else {

                if ( !$isExpectedOutput ) {
                    $line = htmlentities($line);
                    $unexpectedLines++;
                }

                $curr .= "$line\n";
            }
        }

        if ( $logMsg != '' ) {
            Logger::logMsg(trim($logMsg), $logLvl);
        }

        if ( !$isExpectedOutput && !$errorStatus ) {
            $errorStatus |= WPInstall::ST_ERR_EXECMD;
        }

        if ( $errorStatus ) {
            $wpInstall->addUserFlagFile(false);
            $errorStatus |= WPInstall::ST_FLAGGED;

            $cmdStatus |= UserCommand::EXIT_INCR_FAIL;
        }

        $newStatus = ($errorStatus | $retStatus);

        if ( $newStatus != 0 ) {
            $wpInstall->setStatus($newStatus);
        }

        if ( $succ ) {
            $cmdStatus |= UserCommand::EXIT_SUCC;
            $msg = $succ;
        }

        if ( $err ) {

            if ( $return_var == UserCommand::EXIT_FAIL ) {
                $cmdStatus |= UserCommand::EXIT_FAIL;
            }
            else {
                $cmdStatus |= UserCommand::EXIT_ERROR;
            }

            if ( $isExpectedOutput ) {
                $msg = $err;
                Logger::error("{$wpInstall->getPath()} - $err");
            }
            else {
                $msg = self::handleUnexpectedError(
                    $wpInstall,
                    $err,
                    $unexpectedLines
                );
            }
        }

        $wpInstall->setCmdStatusAndMsg($cmdStatus, $msg);

        return true;
    }

    /**
     *
     * @param string[] $args
     *
     * @return null|WPInstall
     */
    public static function newFromCmdArgs( array &$args )
    {
        if ( !($wpPath = array_shift($args))
                || !($docRoot = array_shift($args))
                || !($serverName = array_shift($args)) ) {

            return null;
        }

        if ( !is_dir($wpPath) ) {
            return null;
        }

        /**
         * LSCWP_REF used by LSCWP plugin.
         */
        Util::define_wrapper('LSCWP_REF', array_shift($args));

        $install = new WPInstall($wpPath);

        if ( $docRoot != 'x' ) {
            $install->setDocRoot($docRoot);
        }

        if ( $serverName != 'x' ) {
            $install->setServerName($serverName);
        }

        return $install;
    }

    /**
     *
     * @param string    $action
     * @param WPInstall $wpInstall
     * @param string[]  $extraArgs  Not used at the moment.
     *
     * @return bool
     *
     * @throws LSCMException  Thrown when $action value is unsupported.
     * @throws LSCMException  Thrown indirectly by $wpInstall->hasValidPath()
     *     call.
     * @throws LSCMException  Thrown indirectly by Logger::debug() call.
     * @throws LSCMException  Thrown indirectly by $wpInstall->refreshStatus()
     *     call.
     * @throws LSCMException  Thrown indirectly by $wpInstall->addUserFlagFile()
     *     call.
     * @throws LSCMException  Thrown indirectly by Logger::debug() call.
     * @throws LSCMException  Thrown indirectly by
     *     DashNotifier::prepLocalDashPluginFiles() call.
     *
     * @noinspection PhpUnusedParameterInspection
     */
    private static function preIssueValidation(
                  $action,
        WPInstall $wpInstall,
        array     $extraArgs )
    {
        if ( !self::isSupportedIssueCmd($action) ) {
            throw new LSCMException(
                "Illegal action $action.",
                LSCMException::E_PROGRAM
            );
        }

        if ( !$wpInstall->hasValidPath() ) {
            return false;
        }

        switch ( $action ) {

            case self::CMD_MASS_ENABLE:
            case self::CMD_MASS_DISABLE:
            case self::CMD_MASS_UPGRADE:

                if ( $wpInstall->hasFlagFile() ) {
                    Logger::debug(
                        "Bypass mass operation for flagged install $wpInstall"
                    );
                    return false;
                }

                //fallthrough
            case self::CMD_MASS_DASH_NOTIFY:
            case self::CMD_MASS_DASH_DISABLE:

                if ( $wpInstall->hasFatalError() ) {
                    $wpInstall->refreshStatus();

                    if ( $wpInstall->hasFatalError() ) {
                        $wpInstall->addUserFlagFile(false);

                        Logger::debug(
                            'Bypassed mass operation for error install and '
                                . "flagged $wpInstall"
                        );
                        return false;
                    }
                }

            //no default
        }

        if ( $action == self::CMD_DASH_NOTIFY
                || $action == self::CMD_MASS_DASH_NOTIFY ) {

            DashNotifier::prepLocalDashPluginFiles();
        }

        return true;
    }

    /**
     *
     * @since 1.9  Changed echoed output format to include "[LOG][$lvl] $msg".
     *     Stopped echoing "[DEBUG] $msg" output.
     *
     * @return int
     */
    private function runAsUser()
    {
        try
        {
            $ret = 0;

            if ( $this->action == self::CMD_REMOVE_LSCWP_PLUGIN_FILES ) {
                $proc = WPCaller::getInstance($this->currInstall, false);

                $proc->removeLscwpPluginFiles();
                $ret = self::EXIT_SUCC;
            }
            else {
                $proc = WPCaller::getInstance($this->currInstall);

                switch ( $this->action ) {

                    case self::CMD_STATUS:
                        $ret = $proc->updateStatus(true);
                        break;

                    case self::CMD_ENABLE:
                        $ret = $proc->enable($this->extraArgs);
                        $this->currInstall->removeNewLscwpFlagFile();
                        break;

                    case self::CMD_DIRECT_ENABLE:
                        $ret = $proc->directEnable();
                        $this->currInstall->removeNewLscwpFlagFile();
                        break;

                    case self::CMD_MASS_ENABLE:
                        $ret = $proc->massEnable($this->extraArgs);
                        $this->currInstall->removeNewLscwpFlagFile();
                        break;

                    case self::CMD_DISABLE:
                        $ret = $proc->disable($this->extraArgs);
                        break;

                    case self::CMD_MASS_DISABLE:
                        $ret = $proc->massDisable($this->extraArgs);
                        break;

                    case self::CMD_UPGRADE:
                        $ret = $proc->upgrade($this->extraArgs);
                        break;

                    case self::CMD_MASS_UPGRADE:
                        $ret = $proc->massUpgrade($this->extraArgs);
                        break;

                    case self::CMD_UPDATE_TRANSLATION:
                        $proc->updateTranslationFiles();
                        $ret = self::EXIT_SUCC;
                        break;

                    case self::CMD_DASH_NOTIFY:
                        $ret = $proc->dashNotify($this->extraArgs);
                        break;

                    case self::CMD_MASS_DASH_NOTIFY:
                        $ret = $proc->massDashNotify($this->extraArgs);
                        break;

                    case self::CMD_DASH_DISABLE:
                        $ret = $proc->dashDisable($this->extraArgs);
                        break;

                    case self::CMD_MASS_DASH_DISABLE:
                        $ret = $proc->massDashDisable($this->extraArgs);
                        break;

                    case self::CMD_GET_QUICCLOUD_API_KEY:
                        $proc->getQuicCloudAPIKey(true);
                        $ret = self::EXIT_SUCC;
                        break;

                    //no default
                }
            }

            echo "LS UserCommand Output Start\n";

            foreach ( $proc->getOutputResult() as $key => $value ) {
                echo "[RESULT] $key=$value\n";
            }

            foreach ( Logger::getUiMsgs(Logger::UI_SUCC) as $msg ) {
                echo "[SUCCESS] $msg\n";
            }

            foreach ( Logger::getUiMsgs(Logger::UI_ERR) as $msg ) {
                echo "[ERROR] $msg\n";
            }

            foreach ( Logger::getLogMsgQueue() as $logEntry ) {
                $lvl = $logEntry->getLvl();
                $msg = $logEntry->getMsg();

                echo "[LOG][$lvl] $msg\n";
            }
        }
        catch ( Exception $e )
        {
            $ret = UserCommand::EXIT_ERROR;

            if ( $e instanceof LSCMException
                    && $e->getCode() == LSCMException::E_NON_FATAL ) {

                $ret = UserCommand::EXIT_FAIL;
            }

            echo "LS UserCommand Output Start\n";
            echo "[ERROR] {$e->getMessage()}\n";
        }

        return $ret;
    }

    /**
     *
     * @param string $action
     *
     * @return bool
     */
    private static function isSupportedIssueCmd( $action )
    {
        $supported = array(
            self::CMD_STATUS,
            self::CMD_ENABLE,
            self::CMD_DIRECT_ENABLE,
            self::CMD_MASS_ENABLE,
            self::CMD_DISABLE,
            self::CMD_MASS_DISABLE,
            self::CMD_UPGRADE,
            self::CMD_MASS_UPGRADE,
            self::CMD_UPDATE_TRANSLATION,
            self::CMD_REMOVE_LSCWP_PLUGIN_FILES,
            self::CMD_DASH_NOTIFY,
            self::CMD_MASS_DASH_NOTIFY,
            self::CMD_DASH_DISABLE,
            self::CMD_MASS_DASH_DISABLE,
            self::CMD_GET_QUICCLOUD_API_KEY
        );

        return in_array($action, $supported);
    }

    /**
     *
     * @param string[] $args
     *
     * @return bool
     */
    private function initArgs( $args )
    {
        $action = array_shift($args);

        if ( self::isSupportedIssueCmd($action) ) {
            $this->action = $action;

            if ( $install = self::newFromCmdArgs($args) ) {
                $this->currInstall = $install;
                $this->extraArgs = $args;
                return true;
            }
        }

        return false;
    }

    /**
     *
     * @return UserCommand
     *
     * @throws LSCMException  Thrown indirectly by "new self()" call.
     *
     * @noinspection PhpDocRedundantThrowsInspection
     */
    private static function getUserCommand()
    {
        /**
         * Check if invoked from shell.
         */
        if ( empty($_SERVER['argv']) ) {
            return null;
        }

        $args = $_SERVER['argv'];

        if ( array_shift($args) != __FILE__ ) {
            return null;
        }

        $instance = new self(true);

        if ( !$instance->initArgs($args) ) {
            echo 'illegal input ' . implode(' ', $_SERVER['argv']);
            exit(self::EXIT_ERROR);
        }

        return $instance;
    }

    /**
     *
     * @throws LSCMException  Thrown indirectly by self::getUserCommand() call.
     */
    public static function run()
    {
        if ( $cmd = self::getUserCommand() ) {

            if ( !defined('LSCM_RUN_AS_USER') ) {
                Util::define_wrapper('LSCM_RUN_AS_USER', 1);
            }

            $ret = $cmd->runAsUser();
            exit($ret);
        }
    }

}

/**
 * This should only be invoked from command line.
 *
 * @noinspection PhpUnhandledExceptionInspection
 */
UserCommand::run();
webcachemgr/src/WPCaller.php000066400000153356150545647710012021 0ustar00<?php

/** *********************************************
 * LiteSpeed Web Server Cache Manager
 *
 * @author    Michael Alegre
 * @copyright 2018-2025 LiteSpeed Technologies, Inc.
 * *******************************************
 */

namespace Lsc\Wp;

use Lsc\Wp\Context\Context;
use Lsc\Wp\WpWrapper\PluginUpgrader;
use Lsc\Wp\WpWrapper\WpConstants;
use Lsc\Wp\WpWrapper\WpFuncs;
use Lsc\Wp\WpWrapper\Wpdb;
use Lsc\Wp\WpWrapper\WpQuery;
use Lsc\Wp\WpWrapper\WpTextdomainRegistry;

/**
 * Calls WP internal functions in SHORTINIT mode.
 */
class WPCaller
{

    /**
     * @var string
     */
    const LSCWP_PLUGIN = 'litespeed-cache/litespeed-cache.php';

    /**
     * @var string
     */
    const LSCWP_HTTP_HOST_TEST = 'litespeed_something_is_wrong';

    /**
     * @var null|WPCaller
     */
    private static $instance = null;

    /**
     * @var WPInstall
     */
    private $currInstall;

    /**
     * @since 1.13.4.4
     * @var string
     */
    private $advancedCacheFile;

    /**
     * @var bool
     */
    private $loadLscwp;

    /**
     * @var string
     */
    private $pluginEntry;

    /**
     * @since 1.13
     * @var null|string
     */
    private $installedLscwpVer = null;

    /**
     * @var string[]
     */
    private $outputResult = array();

    /**
     * @var string
     */
    private $massIncr = '';

    /**
     *
     * @param WPInstall $curInstall
     * @param bool      $loadLscwp
     *
     * @throws LSCMException  Thrown indirectly by $this->init() call.
     */
    private function __construct( WPInstall $curInstall, $loadLscwp )
    {
        $this->currInstall = $curInstall;
        $this->loadLscwp   = $loadLscwp;

        $this->init();
    }

    /**
     *
     * @since 1.13.4.4
     *
     * @throws LSCMException  Thrown indirectly by $this->initWp() call.
     */
    private function init()
    {
        $this->advancedCacheFile =
            "{$this->currInstall->getPath()}/wp-content/advanced-cache.php";

        $this->initWp();
    }

    /**
     *
     * @param WPInstall $currInstall
     * @param bool      $loadLscwp
     *
     * @return WPCaller
     *
     * @throws LSCMException  Thrown indirectly by "new self()" call.
     */
    public static function getInstance(
        WPInstall $currInstall,
                  $loadLscwp = true )
    {
        if ( self::$instance == null
                || self::$instance->currInstall !== $currInstall ) {

            self::$instance = new self($currInstall, $loadLscwp);
        }

        return self::$instance;
    }

    /**
     *
     * @param int    $errno   Not used at this time.
     * @param string $errstr
     *
     * @return bool
     *
     * @noinspection PhpUnusedParameterInspection
     */
    public static function warning_handler( $errno, $errstr )
    {
        $strs = array(
            'ini_set() has been disabled for security reasons',
            'Constant FS_METHOD already defined'
        );

        if ( in_array($errstr, $strs) ) {
            /**
             * Throw this warning out.
             */
            return true;
        }

        return false;
    }

    /**
     * Deprecated 03/12/19 as this function is no longer used.
     *
     * Prevents database table options not in the $allowedOptions list
     * from having their value updated by others during execution.
     *
     * Run when WP function apply_filters('pre_update_option', ...) is called
     * in WP function update_option().
     *
     * @deprecated
     *
     * @param mixed  $value      New option value.
     * @param string $option     Option name in db.
     * @param mixed  $old_value  Old option value.
     *
     * @return mixed
     */
    public static function lock_database( $value, $option, $old_value )
    {
        $allowedOptions = array(
            'litespeed-cache-conf',
            '_transient_lscwp_whm_install',
            'active_plugins',
            '_transient_doing_cron',
            '_site_transient_update_plugins',
            'uninstall_plugins'
        );

        if ( in_array($option, $allowedOptions) ) {
            return $value;
        }
        else {
            return $old_value;
        }
    }

    /**
     * Redefine disabled PHP global/core functions that no longer exist
     * (PHP 8+).
     *
     * @since 1.13.10
     */
    private static function redefineDisabledFunctions()
    {
        if ( Util::betterVersionCompare(phpversion(), '8.0', '>=') ) {
            include_once(__DIR__ . '/RedefineGlobalFuncs.php');
        }
    }

    /**
     *
     * @return string[]
     */
    public function getOutputResult()
    {
        return $this->outputResult;
    }

    /**
     * Adds key value pair to $this->outputResult to be grabbed later in
     * the $output variable of the UserCommand::issue() exec call.
     *
     * @param string $key
     * @param mixed  $value
     */
    private function outputResult( $key, $value )
    {
        $this->outputResult[$key] = $value;
    }

    /**
     *
     * @deprecated 1.9  Use Logger::getLogMsgQueue() to get these messages as
     *     LogEntry objects.
     *
     * @return string[]
     *
     * @throws LSCMException  Thrown indirectly by Logger::getLogMsgQueue()
     *     call.
     */
    public function getDebugMsgs()
    {
        $debugMsgs = array();

        $msgQueue = Logger::getLogMsgQueue();

        foreach ( $msgQueue as $logEntry ) {
            $label       = Logger::getLvlDescr($logEntry->getLvl());
            $debugMsgs[] = "[$label] {$logEntry->getMsg()}";
        }

        return $debugMsgs;
    }

    /**
     * @deprecated 1.9  Deprecated 07/30/19. Use
     *     Logger::getUiMsgs(Logger::UI_ERR) to get these messages.
     *
     * @return string[]
     *
     * @throws LSCMException  Thrown indirectly by Logger::getUiMsgs() call.
     */
    public function getErrMsgs()
    {
        return Logger::getUiMsgs(Logger::UI_ERR);
    }

    /**
     *
     * @deprecated 1.9  Deprecated 07/30/19. Use
     *     Logger::getUiMsgs(Logger::UI_SUCC) to get these messages.
     *
     * @return string[]
     *
     * @throws LSCMException  Thrown indirectly by Logger::getUiMsgs() call.
     */
    public function getSuccMsgs()
    {
        return Logger::getUiMsgs(Logger::UI_SUCC);
    }

    /**
     *
     * WP Variables $table_prefix
     *
     * @global string $table_prefix
     *
     * @return string
     */
    private function getSiteURL()
    {
        global $table_prefix;

        $siteURL = WpFuncs::getOption('siteurl');

        if ( !$siteURL ) {
            return '';
        }

        if ( strpos($siteURL, self::LSCWP_HTTP_HOST_TEST) !== false ) {
            /**
             * User is setting WP_SITEURL using fake $_SERVER['HTTP_HOST'].
             * Get siteurl value from DB directly.
             */
            return WpFuncs::getVar(
                "SELECT option_value FROM {$table_prefix}options "
                    . "WHERE option_name = 'siteurl'"
            );
        }

        return $siteURL;
    }

    /**
     *
     * @since 1.17.0.3
     *
     * @param string $advCacheFileContents
     *
     * @return bool
     */
    private static function advancedCacheFileBelongsToLscwp(
        $advCacheFileContents
    )
    {
        if ( self::advancedCacheFileHasLscacheDefine($advCacheFileContents) ) {
            return true;
        }

        if ( self::advancedCacheFileHasPlaceholderMsg($advCacheFileContents) ) {
            return true;
        }

        return false;
    }


    /**
     *
     * @since 1.13.4.3
     *
     * @return bool
     */
    private function generic3rdPartyAdvCachePluginExists()
    {
        if ( Util::betterVersionCompare($this->installedLscwpVer, '3.0.4', '>=') ) {

            if ( file_exists($this->advancedCacheFile) ) {

                $advCacheFileContents =
                    file_get_contents($this->advancedCacheFile);

                if ( $advCacheFileContents !== '' ) {
                    /**
                     * Old LSCWP advanced-cache.php file is no longer used in
                     * these versions but is also never cleaned up. As a result,
                     * any existing advanced-cache.php files need to have their
                     * contents checked to avoid detecting an old LSCWP
                     * advanced-cache.php file as a generic 3rd-party
                     * advanced-cache plugin.
                     */
                    return !self::advancedCacheFileBelongsToLscwp(
                        $advCacheFileContents
                    );
                }
            }
        }
        elseif ( !defined('LSCACHE_ADV_CACHE')
                || WpConstants::getWpConstant('LSCACHE_ADV_CACHE') !== true ) {

            return true;
        }

        return false;
    }

    /**
     *
     * @since 1.13.8  Added optional parameter $output.
     *
     * @param WPInstall $install
     * @param bool      $output
     *
     * @return int
     *
     * @throws LSCMException  Thrown indirectly by Logger::uiError() call.
     * @throws LSCMException  Thrown indirectly by $install->addUserFlagFile()
     *     call.
     * @throws LSCMException  Thrown indirectly by $install->addUserFlagFile()
     *     call.
     * @throws LSCMException  Thrown indirectly by Logger::notice() call.
     * @throws LSCMException  Thrown indirectly by Logger::notice() call.
     */
    private function checkStatus( WPInstall $install, $output = false )
    {
        if ( $output ) {

            if ( ($siteUrl = $this->getSiteURL()) === '' ) {
                Logger::uiError(
                    'Could not retrieve siteURL to match against known '
                        . 'docroots.'
                );
                $install->addUserFlagFile();

                return (WPInstall::ST_ERR_SITEURL | WPInstall::ST_FLAGGED);
            }

            $this->outputResult('SITEURL', $siteUrl);
        }

        $status = 0;

        /**
         * Check if plugin files exist first, as status in db could be stale if
         * LSCWP was removed manually.
         */
        if ( file_exists($this->pluginEntry)
                && WpFuncs::isPluginActive(self::LSCWP_PLUGIN) ) {

            $status |= WPInstall::ST_PLUGIN_ACTIVE;

            //TODO: Get rid of ST_LSC_ADVCACHE_DEFINED status or replace with
            //      new "is caching enabled" define check.

            if ( $this->generic3rdPartyAdvCachePluginExists() ) {
                $status |= WPInstall::ST_FLAGGED;
            }
            else {
                $status |= WPInstall::ST_LSC_ADVCACHE_DEFINED;
            }
        }
        else {
            $status |= WPInstall::ST_PLUGIN_INACTIVE;
        }

        if ( $install->hasFlagFile() ) {
            $status |= WPInstall::ST_FLAGGED;
        }

        if ( $status & WPInstall::ST_FLAGGED ) {

            if ( $install->addUserFlagFile() ) {
                Logger::notice('Install is flagged');
            }
            else {
                Logger::notice('Install is not flagged');
            }
        }

        return $status;
    }

    /**
     *
     * @param bool $output
     *
     * @return int
     *
     * @throws LSCMException  Thrown indirectly by $this->checkStatus() call.
     */
    public function updateStatus( $output = false )
    {
        $status = $this->checkStatus($this->currInstall, $output);
        $this->currInstall->setStatus($status);

        if ( $output ) {
            $this->outputResult('STATUS', $status);
        }

        if ( $status & WPInstall::ST_ERR_SITEURL ) {
            return UserCommand::EXIT_FAIL;
        }

        return UserCommand::EXIT_SUCC;
    }

    /**
     *
     * @return int
     *
     * @throws LSCMException  Thrown indirectly by $this->updateStatus() call.
     */
    private function getCurrStatus()
    {
        $this->updateStatus();

        return $this->currInstall->getStatus();
    }

    /**
     * Check if any known cache plugins that do not use an advanced-cache.php
     * file are active for this WordPress installation. If any of these plugins
     * are found, that plugin's slug is returned.
     *
     * @since 1.9.1
     *
     * @return string  Empty string or detected active cache plugin slug.
     */
    private function checkForKnownNonAdvCachePlugins()
    {
        $knownPlugins = array(
            'wp-fastest-cache' => 'wp-fastest-cache/wpFastestCache.php'
        );


        foreach ( $knownPlugins as $slug => $plugin ) {
            /**
             * Check if plugin files exist first, as status in db could be
             * stale if plugin files were removed manually.
             */
            $pluginExistsAndIsActive = (
                file_exists(
                    WpConstants::getWpConstant('WP_PLUGIN_DIR') . "/$plugin"
                )
                &&
                WpFuncs::isPluginActive($plugin)
            );

            if ( $pluginExistsAndIsActive) {
                return $slug;
            }
        }

        return '';
    }

    /**
     *
     * @param bool $isMassAction
     * @param bool $isNewInstall
     *
     * @return bool
     *
     * @throws LSCMException  Thrown indirectly by $this->getCurrStatus() call.
     * @throws LSCMException  Thrown indirectly by
     *     $this->currInstall->addUserFlagFile() call.
     * @throws LSCMException  Thrown indirectly by  Logger::uiSuccess() call.
     * @throws LSCMException  Thrown indirectly by Logger::notice() call.
     * @throws LSCMException  Thrown indirectly by
     *     $this->currInstall->addUserFlagFile() call.
     * @throws LSCMException  Thrown indirectly by Logger::uiError() call.
     * @throws LSCMException  Thrown indirectly by Logger::notice() call.
     * @throws LSCMException  Thrown indirectly by  Logger::uiSuccess() call.
     * @throws LSCMException  Thrown indirectly by Logger::notice() call.
     * @throws LSCMException  Thrown indirectly by
     *     $this->currInstall->addUserFlagFile() call.
     * @throws LSCMException  Thrown indirectly by Logger::uiError() call.
     * @throws LSCMException  Thrown indirectly by Logger::notice() call.
     */
    private function canEnable( $isMassAction, $isNewInstall )
    {
        $status = $this->getCurrStatus();

        if ( $status & WPInstall::ST_PLUGIN_INACTIVE ) {

            if ( !$isNewInstall && $isMassAction ) {
                $this->currInstall->addUserFlagFile();

                Logger::uiSuccess(
                    'LSCWP Detected As Manually Disabled - Flag Set'
                );
                Logger::notice(
                    'Ignore - Previously disabled, flag it from mass operation'
                );

                return false;
            }

            $thirdPartyCachePluginSlug =
                $this->checkForKnownNonAdvCachePlugins();

            if ( $thirdPartyCachePluginSlug != '' ) {
                $this->currInstall->addUserFlagFile();

                Logger::uiError(
                    'Cannot Enable LSCWP - Detected another active cache '
                        . "plugin \"$thirdPartyCachePluginSlug\". Flag set."
                );

                Logger::notice(
                    'Ignore - Detected another active cache plugin '
                        . "\"$thirdPartyCachePluginSlug\". Flagged."
                );

                return false;
            }
        }
        elseif ( !$isNewInstall ) {
            /**
             * already active
             */
            if ( $status & WPInstall::ST_LSC_ADVCACHE_DEFINED ) {
                Logger::uiSuccess('LSCWP Already Enabled - No Action Taken');
                Logger::notice('Ignore - Already enabled');
            }
            else {
                $this->currInstall->addUserFlagFile();

                Logger::uiError(
                    'LSCWP Already Enabled But Not Caching - Detected another '
                        . 'active cache plugin. Please visit the WordPress '
                        . 'Dashboard for further instructions.'
                );
                Logger::notice(
                    'Ignore - Existing install but advanced cache not set'
                );
            }

            return false;
        }

        return true;
    }

    /**
     *
     * @return int
     *
     * @throws LSCMException  Thrown indirectly by $this->canEnable() call.
     * @throws LSCMException  Thrown indirectly by $this->enable_lscwp() call.
     * @throws LSCMException  Thrown indirectly by
     *     $this->directEnableNewInstall() call.
     */
    public function directEnable()
    {
        $isNewInstall = !file_exists($this->pluginEntry);

        if ( !$this->canEnable(false, $isNewInstall) ) {
            $this->outputResult('STATUS', $this->currInstall->getStatus());
            return UserCommand::EXIT_FAIL;
        }

        if ( !$isNewInstall ) {
            $status = $this->enable_lscwp();
        }
        else {
            $status = $this->directEnableNewInstall();
        }

        $this->outputResult('STATUS', $status);
        return UserCommand::EXIT_SUCC;
    }

    /**
     *
     * @return int
     *
     * @throws LSCMException  Thrown when unable to extract downloaded LSCWP
     *     files.
     * @throws LSCMException  Thrown indirectly by $this->downloadLSCWPZip()
     *     call.
     * @throws LSCMException  Thrown indirectly by $this->enable_lscwp() call.
     * @throws LSCMException  Thrown indirectly by
     *     $this->removeLscwpPluginFiles() call.
     */
    private function directEnableNewInstall()
    {
        $pluginDir = WpConstants::getWpConstant('WP_PLUGIN_DIR');

        $lscwpZip = "$pluginDir/litespeed-cache.latest-stable.zip";

        $this->downloadLSCWPZip($lscwpZip);

        WpFuncs::WpFilesystem();

        $unzipRet = WpFuncs::unzipFile($lscwpZip, $pluginDir);
        unlink($lscwpZip);

        if ( $unzipRet !== true ) {
            throw new LSCMException(
                "Unable to extract downloaded LSCWP files.",
                LSCMException::E_NON_FATAL
            );
        }

        $this->currInstall->addNewLscwpFlagFile();

        $customIni = Context::LOCAL_PLUGIN_DIR . '/'
            . PluginVersion::LSCWP_DEFAULTS_INI_FILE_NAME;

        if ( file_exists($customIni) ) {
            copy(
                $customIni,
                "$pluginDir/litespeed-cache/data/"
                    . PluginVersion::LSCWP_DEFAULTS_INI_FILE_NAME
            );
        }

        $this->installedLscwpVer = $this->getPluginVersionFromFile();

        $status = $this->enable_lscwp();

        if ( $status & WPInstall::ST_PLUGIN_INACTIVE) {
            $this->removeLscwpPluginFiles();
        }
        else {
            $this->updateTranslationFiles();
        }

        return $status;
    }

    /**
     *
     * @param string $lscwpZip
     *
     * @return null
     *
     * @throws LSCMException  Thrown when LSCWP download operation fails.
     */
    private function downloadLscwpZip( $lscwpZip )
    {
        $pluginDir = WpConstants::getWpConstant('WP_PLUGIN_DIR');
        $url = 'https://downloads.wordpress.org/plugin/'
            . 'litespeed-cache.latest-stable.zip';

        exec(
            "wget -q --tries=1 --no-check-certificate $url -P $pluginDir",
            $output1,
            $return_var1
        );

        if ( $return_var1 === 0 && file_exists($lscwpZip) ) {
            return;
        }

        /**
         * Fall back to curl in case wget is disabled for user.
         */
        exec(
            "cd $pluginDir && curl -O -s --retry 1 --insecure $url",
            $output2,
            $return_var2
        );

        if ( $return_var2 === 0 && file_exists($lscwpZip) ) {
            return;
        }

        throw new LSCMException(
            "Failed to download LSCWP with wget exit status $return_var1 and "
                . "curl exit status $return_var2.",
            LSCMException::E_NON_FATAL
        );
    }

    /**
     *
     * @param array $extraArgs  Not used at this time.
     * @param bool  $massOp     True when called from massEnable().
     *
     * @return int
     *
     * @throws LSCMException  Thrown indirectly by PluginVersion::getInstance()
     *     call.
     * @throws LSCMException  Thrown indirectly by
     *     PluginVersion::getInstance()->prepareUserInstall() call.
     * @throws LSCMException  Thrown indirectly by $this->canEnable() call.
     * @throws LSCMException  Thrown indirectly by $this->enable_lscwp() call.
     * @throws LSCMException  Thrown indirectly by
     *     $this->removeLscwpPluginFiles() call.
     *
     * @noinspection PhpUnusedParameterInspection
     */
    public function enable( array $extraArgs, $massOp = false )
    {
        $isNewInstall = PluginVersion::getInstance()->prepareUserInstall(
            WpConstants::getWpConstant('WP_PLUGIN_DIR')
        );

        if ( $isNewInstall ) {
            $this->installedLscwpVer = $this->getPluginVersionFromFile();
            $this->currInstall->addNewLscwpFlagFile();
        }

        if ( !$this->canEnable($massOp, $isNewInstall) ) {
            $status = $this->currInstall->getStatus();
            $ret    = UserCommand::EXIT_FAIL;
        }
        else {
            $status = $this->enable_lscwp();
            $ret    = UserCommand::EXIT_SUCC;
        }

        if ( $isNewInstall ) {

            if ( $status & WPInstall::ST_PLUGIN_INACTIVE ) {
                $this->removeLscwpPluginFiles();
            }
            else {
                $this->updateTranslationFiles();
            }
        }

        $this->outputResult('STATUS', $this->currInstall->getStatus());
        return $ret;
    }

    /**
     *
     * @param string[] $extraArgs
     *
     * @return int
     *
     * @throws LSCMException  Thrown indirectly by $this->enable() call.
     */
    public function massEnable( array $extraArgs )
    {
        $ret = $this->enable($extraArgs, true);

        if ( $this->massIncr != '' ) {
            $this->outputResult('MASS_INCR', $this->massIncr);
        }

        return $ret;
    }

    /**
     *
     * @param bool $isMassAction
     *
     * @return bool
     *
     * @throws LSCMException  Thrown indirectly by $this->getCurrStatus() call.
     * @throws LSCMException  Thrown indirectly by Logger::notice() call.
     * @throws LSCMException  Thrown indirectly by Logger::uiSuccess() call.
     * @throws LSCMException  Thrown indirectly by
     *     $this->currInstall->addUserFlagFile() call.
     * @throws LSCMException  Thrown indirectly by Logger::uiSuccess() call.
     * @throws LSCMException  Thrown indirectly by Logger::notice() call.
     * @throws LSCMException  Thrown indirectly by
     *     $this->currInstall->addUserFlagFile() call.
     * @throws LSCMException  Thrown indirectly by Logger::uiSuccess() call.
     */
    private function canDisable( $isMassAction )
    {
        $status = $this->getCurrStatus();

        if ( $status & WPInstall::ST_PLUGIN_INACTIVE ) {
            Logger::notice('Ignore - Already disabled');
            Logger::uiSuccess(
                'LiteSpeed Cache Already Disabled - No Action Taken'
            );

            return false;
        }

        if ( $isMassAction ) {

            if ( !($status & WPInstall::ST_LSC_ADVCACHE_DEFINED) ) {
                $this->currInstall->addUserFlagFile();

                Logger::uiSuccess(
                    'LSCWP Detected As Manually Enabled But Not Caching - Flag '
                        . 'Set. If desired, this installation can be disabled '
                        . 'from the Manage Cache Installations screen.'
                );
                Logger::notice(
                    'Ignore for mass disable - Installed manually as advanced '
                        . 'cache not set.'
                );

                return false;
            }

            if ( WpFuncs::isPluginActiveForNetwork(self::LSCWP_PLUGIN) ) {
                $this->currInstall->addUserFlagFile();

                Logger::uiSuccess(
                    'LiteSpeed Cache Detected As Network Activated - Flag Set '
                        . '& No Action Taken'
                );

                return false;
            }
        }

        return true;
    }

    /**
     *
     * @param string[] $extraArgs  Not used at this time.
     * @param bool     $massOp     True when called from MassDisable().
     *
     * @return int
     *
     * @throws LSCMException  Thrown indirectly by $this->canDisable() call.
     * @throws LSCMException  Thrown indirectly by $this->performDisable() call.
     * @throws LSCMException  Thrown indirectly by Logger::uiSuccess() call.
     *
     * @noinspection PhpUnusedParameterInspection
     */
    public function disable( array $extraArgs, $massOp = false )
    {
        if ( !$this->canDisable($massOp) ) {
            $ret = UserCommand::EXIT_FAIL;
        }
        else {

            if ( $this->performDisable(true) & WPInstall::ST_PLUGIN_ACTIVE ) {
                $ret = UserCommand::EXIT_FAIL;
            }
            else {
                Logger::uiSuccess('LiteSpeed Cache Disabled');
                $this->massIncr = 'SUCC';
                $ret            = UserCommand::EXIT_SUCC;
            }
        }

        $this->outputResult('STATUS', $this->currInstall->getStatus());

        return $ret;
    }

    /**
     *
     * @param string[] $extraArgs
     *
     * @return int
     *
     * @throws LSCMException  Thrown indirectly by $this->disable() call.
     */
    public function massDisable( array $extraArgs )
    {
        $ret = $this->disable($extraArgs, true);

        if ( $this->massIncr != '' ) {
            $this->outputResult('MASS_INCR', $this->massIncr);
        }

        return $ret;
    }

    /**
     * Includes LSCWP files needed to properly disable the LSCWP plugin.
     *
     * @since 1.13  Removed param $lscwpVer.
     */
    private function includeDisableRequiredFiles()
    {
        $dir = WpConstants::getWpConstant('WP_PLUGIN_DIR') . '/litespeed-cache';

        if ( Util::betterVersionCompare($this->installedLscwpVer, '3.0', '>=') ) {
            require_once "$dir/src/admin.cls.php";
        }
        elseif ( Util::betterVersionCompare($this->installedLscwpVer, '1.1.2.2', '>') ) {
            require_once "$dir/admin/litespeed-cache-admin.class.php";
        }
        else {
            require_once "$dir/admin/class-litespeed-cache-admin.php";
        }

        if ( Util::betterVersionCompare($this->installedLscwpVer, '1.1.0', '<')
                && Util::betterVersionCompare($this->installedLscwpVer, '1.0.6', '>') ) {

            require_once "$dir/admin/class-litespeed-cache-admin-rules.php";
        }
    }

    /**
     *
     * @param bool $uninstall
     *
     * @return int
     *
     * @throws LSCMException  Thrown indirectly by $this->disable_lscwp() call.
     */
    private function performDisable( $uninstall )
    {
        $this->includeDisableRequiredFiles();
        return $this->disable_lscwp($uninstall);
    }

    /**
     *
     * @param string[] $fromVersions
     * @param string   $toVersion
     * @param bool     $massOp        Not used at this time.
     *
     * @return bool
     *
     * @noinspection PhpUnusedParameterInspection
     */
    private function canUpgrade( array $fromVersions, $toVersion, $massOp )
    {
        if ( !file_exists($this->pluginEntry) ) {
            return false;
        }

        if ( $toVersion == $this->installedLscwpVer ) {
            return false;
        }

        foreach ( $fromVersions as $fromVer ) {
            $fromVerParts      = explode('.', $fromVer);
            $installedVerParts = explode('.', $this->installedLscwpVer);

            $i = 0;

            while ( isset($fromVerParts[$i]) ) {
                $fromVerPart = $fromVerParts[$i];

                if ( $fromVerPart == 'x' ) {
                    return true;
                }

                if ( !isset($installedVerParts[$i])
                        || $installedVerParts[$i] != $fromVerPart ) {

                    continue 2;
                }

                $i++;
            }

            if ( !isset($installedVerParts[$i]) ) {
                return true;
            }
        }

        return false;
    }

    /**
     *
     * @param string[] $extraArgs
     * @param bool     $massOp
     *
     * @return int
     *
     * @throws LSCMException  Thrown indirectly by $this->updateStatus() call.
     * @throws LSCMException  Thrown indirectly by $this->upgrade_lscwp() call.
     */
    public function upgrade( array $extraArgs, $massOp = false )
    {
        $toVersion = $extraArgs[1];

        $canUpgrade = $this->canUpgrade(
            explode(',', $extraArgs[0]),
            $toVersion,
            $massOp
        );

        if ( !$canUpgrade ) {
            $this->updateStatus(true);
            return UserCommand::EXIT_FAIL;
        }
        else {
            $this->upgrade_lscwp($toVersion);
            return UserCommand::EXIT_SUCC;
        }
    }

    /**
     *
     * @param string[] $extraArgs
     *
     * @return int
     *
     * @throws LSCMException  Thrown indirectly by $this->upgrade() call.
     */
    public function massUpgrade( array $extraArgs )
    {
        $ret = $this->upgrade($extraArgs, true);

        if ( $this->massIncr != '' ) {
            $this->outputResult('MASS_INCR', $this->massIncr);
        }

        return $ret;
    }

    /**
     *
     * @param bool $uninstall
     */
    private function deactivate_lscwp( $uninstall )
    {
        WpFuncs::deactivatePlugins(self::LSCWP_PLUGIN);

        if ( $uninstall ) {
            //Todo: add some msg about having removed plugin files?
            WpFuncs::deletePlugins(array( self::LSCWP_PLUGIN ));
        }
    }

    /**
     *
     * @param bool $uninstall
     *
     * @return int
     *
     * @throws LSCMException  Thrown indirectly by $this->getCurrStatus() call.
     */
    private function disable_lscwp( $uninstall )
    {
        if ( WpConstants::getWpConstant('MULTISITE') ) {
            $blogs =
                Wpdb::getCol("SELECT blog_id FROM " . Wpdb::getBlogs() . ';');

            foreach ( $blogs as $id ) {
                WpFuncs::switchToBlog($id);

                $this->deactivate_lscwp($uninstall);

                WpFuncs::restoreCurrentBlog();
            }
        }
        else {
            $this->deactivate_lscwp($uninstall);
        }

        return $this->getCurrStatus();
    }

    /**
     *
     * @return int
     *
     * @throws LSCMException  Thrown indirectly by $this->getCurrStatus() call.
     * @throws LSCMException  Thrown indirectly by $this->performDisable() call.
     * @throws LSCMException  Thrown indirectly by Logger::uiError() call.
     * @throws LSCMException  Thrown indirectly by
     *     $this->currInstall->addUserFlagFile() call.
     * @throws LSCMException  Thrown indirectly by Logger::uiError() call.
     * @throws LSCMException  Thrown indirectly by Logger::uiSuccess() call.
     */
    private function enable_lscwp()
    {
        /**
         * Should not check directly, can error on success due to object cache.
         */
        WpFuncs::activatePlugin(self::LSCWP_PLUGIN);

        $status = $this->getCurrStatus();

        if ( !($status & WPInstall::ST_LSC_ADVCACHE_DEFINED) ) {
            $status = $this->performDisable(true);

            Logger::uiError(
                'Detected '
                    . "{$this->currInstall->getPath()}/wp-content/advanced-cache.php "
                    . 'as belonging to another cache plugin. Please deactivate '
                    . 'the related cache plugin and try again. You may also '
                    . 'try manually installing through the WordPress Dashboard '
                    . 'and following the instructions given.'
            );

            $this->massIncr = 'FAIL';
        }
        elseif ( $status & WPInstall::ST_PLUGIN_ACTIVE ) {

            if (
                    !is_writable($this->currInstall->getWpConfigFile())
                    &&
                    (
                        !defined('WP_CACHE')
                        ||
                        WpConstants::getWpConstant('WP_CACHE') !== true
                    )
            ) {

                /**
                 * LSCACHE_ADV_CACHE is incorrectly defined true at this point.
                 * Detected status must be manually corrected.
                 */
                $status &= ~WPInstall::ST_LSC_ADVCACHE_DEFINED;
                $this->currInstall->setStatus($status);

                $this->currInstall->addUserFlagFile();
                $status = $this->currInstall->getStatus();

                Logger::uiError(
                    'LSCWP Enabled But Not Caching - Please visit the '
                        . 'WordPress Dashboard for further instructions.'
                );
            }
            else {
                Logger::uiSuccess('LSCWP Enabled');
            }

            $this->massIncr = 'SUCC';
        }

        return $status;
    }

    /**
     *
     * @param string $ver
     * @param bool   $runHooks
     *
     * @throws LSCMException  Thrown when LSCWP plugin version upgrade fails.
     */
    private function upgrade_lscwp( $ver, $runHooks = true )
    {
        /**
         * Label the following $upgraderWrapper output (Cannot be buffered).
         */
        echo "[UPGRADE]\n";

        $upgraderWrapper = new PluginUpgrader;

        $upgraderWrapper->init();
        $upgraderWrapper->upgradeStrings();

        $lscwpPackageURL =
            "https://downloads.wordpress.org/plugin/litespeed-cache.$ver.zip";

        if ( $runHooks ) {
            WpFuncs::addFilter(
                'upgrader_pre_install',
                array(
                    $upgraderWrapper->getWpPluginUpgraderObject(),
                    'deactivate_plugin_before_upgrade'
                ),
                10,
                2
            );

            WpFuncs::addFilter(
                'upgrader_clear_destination',
                array(
                    $upgraderWrapper->getWpPluginUpgraderObject(),
                    'delete_old_plugin'
                ),
                10,
                4
            );
        }

        $upgraderWrapper->run(
            array(
                'package'           => $lscwpPackageURL,
                'destination'       =>
                    WpConstants::getWpConstant('WP_PLUGIN_DIR'),
                'clear_destination' => true,
                'clear_working'     => true,
                'hook_extra'        => array(
                    'plugin' => $this->pluginEntry,
                    'type'   => 'plugin',
                    'action' => 'update',
                )
            )
        );

        /**
         * Start new messages on a new line
         */
        echo "\n";

        if ( $runHooks ) {
            /**
             * Cleanup our hooks, in case something else does an upgrade on
             * this connection.
             */
            WpFuncs::removeFilter(
                'upgrader_pre_install',
                array(
                    $upgraderWrapper->getWpPluginUpgraderObject(),
                    'deactivate_plugin_before_upgrade'
                )
            );

            WpFuncs::removeFilter(
                'upgrader_clear_destination',
                array(
                    $upgraderWrapper->getWpPluginUpgraderObject(),
                    'delete_old_plugin'
                )
            );
        }

        if ( !$upgraderWrapper->getResult()
                || WpFuncs::isWpError($upgraderWrapper->getResult()) ) {

            throw new LSCMException(
                "Failed to upgrade to v$ver.",
                LSCMException::E_NON_FATAL
            );
        }

        $this->updateTranslationFiles();

        /**
         * Force refresh of plugin update information
         */
        WpFuncs::wpCleanPluginsCache();
    }

    /**
     * Gets LSCWP version from the litespeed-cache.php file.
     *
     * @return string
     */
    private function getPluginVersionFromFile()
    {
        $lscwp_data = WpFuncs::getPluginData($this->pluginEntry, false, false);

        return $lscwp_data['Version'];
    }

    /**
     * Checks for local plugin translation files and copies them to the plugin
     * languages directory if able. This function will also attempt to inform
     * the root user when a locale's translation should be retrieved or removed.
     */
    public function updateTranslationFiles()
    {
        $locale = WpFuncs::getLocale();

        if ( $locale == 'en_US' ) {
            return;
        }

        $localTranslationDir = Context::LOCAL_PLUGIN_DIR
            . "/$this->installedLscwpVer/translations";

        $moFileName = "litespeed-cache-$locale.mo";
        $poFileName = "litespeed-cache-$locale.po";
        $localMoFile = "$localTranslationDir/$moFileName";
        $localPoFile = "$localTranslationDir/$poFileName";
        $zipFile = "$localTranslationDir/$locale.zip";
        $translationFlag = "$localTranslationDir/"
            . PluginVersion::TRANSLATION_CHECK_FLAG_BASE . "_$locale";

        $langDir =
            $this->currInstall->getPath() . '/wp-content/languages/plugins';

        if ( !file_exists($langDir) ) {
            mkdir($langDir, 0755);
        }

        if ( file_exists($localMoFile) && file_exists($localPoFile) ) {
            copy($localMoFile, "$langDir/$moFileName");
            copy($localPoFile, "$langDir/$poFileName");
        }
        elseif ( file_exists($zipFile) ) {
            WpFuncs::WpFilesystem();

            if ( WpFuncs::unzipFile($zipFile, $langDir) !== true ) {
                $this->outputResult(
                    'BAD_TRANSLATION',
                    "$locale $this->installedLscwpVer"
                );
            }
        }
        elseif ( !file_exists($translationFlag)
                || (time() - filemtime($translationFlag)) > 86400  ) {

            $this->outputResult(
                'GET_TRANSLATION',
                "$locale $this->installedLscwpVer"
            );
        }
    }

    /**
     *
     * @since 1.13.4.4
     * @since 1.17.0.3  Added required parameter $advCacheFileContents.
     *
     * @param string $advCacheFileContents
     *
     * @return bool
     */
    private static function advancedCacheFileHasLscacheDefine(
        $advCacheFileContents
    )
    {
        $definePosition = strpos($advCacheFileContents, 'LSCACHE_ADV_CACHE');

        return ($definePosition !== false);
    }

    /**
     * Check if advanced-cache.php file contains LSCWP placeholder text. This
     * file with generic placeholder text was re-added by LSCWP for improved
     * compatibility with WordPress versions lower than v5.3.
     *
     * @since 1.17.0.3
     *
     * @param string $advCacheFileContent
     *
     * @return bool
     */
    private static function advancedCacheFileHasPlaceholderMsg(
        $advCacheFileContent
    )
    {
        $definePosition = strpos(
            $advCacheFileContent,
            'A compatibility placeholder for WordPress < v5.3'
        );

        return ($definePosition !== false);
    }

    private function includeLSCWPAdvancedCacheFile()
    {
        if ( file_exists($this->advancedCacheFile) ) {

            $advCacheFileContents =
                file_get_contents($this->advancedCacheFile);

            if (
                    $advCacheFileContents !== ''
                    &&
                    $this->advancedCacheFileHasLscacheDefine(
                        $advCacheFileContents
                    )
            ) {
                include_once $this->advancedCacheFile;
            }
        }
    }

    /**
     *
     * @throws LSCMException  Thrown indirectly by
     *     $this->currInstall->removePluginFiles() call.
     */
    public function removeLscwpPluginFiles()
    {
        $this->currInstall->removePluginFiles(dirname($this->pluginEntry));
    }

    /**
     *
     * @param string[] $extraArgs
     * @param bool     $massOp     Not used at this time.
     *
     * @return int
     *
     * @throws LSCMException  Thrown indirectly by
     *     DashNotifier::prepareUserInstall() call.
     * @throws LSCMException  Thrown indirectly by DashNotifier::doNotify()
     *     call.
     * @throws LSCMException  Thrown indirectly by Logger::uiSuccess() call.
     * @throws LSCMException  Thrown indirectly by Logger::uiError() call.
     *
     * @noinspection PhpUnusedParameterInspection
     */
    public function dashNotify( array $extraArgs, $massOp = false )
    {
        if ( DashNotifier::canNotify($this->currInstall->getPath()) ) {
            DashNotifier::prepareUserInstall();

            if ( DashNotifier::doNotify(base64_decode($extraArgs[0])) ) {
                Logger::uiSuccess('Notified Successfully');
                $this->massIncr = 'SUCC';

                return UserCommand::EXIT_SUCC;
            }

            Logger::uiError('Failed to Notify');
            $this->massIncr = 'FAIL';
        }
        else {
            $this->massIncr = 'BYPASS';
        }

        return UserCommand::EXIT_FAIL;
    }

    /**
     *
     * @param string[] $extraArgs
     *
     * @return int
     *
     * @throws LSCMException  Thrown indirectly by $this->dashNotify() call.
     */
    public function massDashNotify( array $extraArgs )
    {
        $ret = $this->dashNotify($extraArgs, true);

        if ( $this->massIncr != '' ) {
            $this->outputResult('MASS_INCR', $this->massIncr);
        }

        return $ret;
    }

    /**
     *
     * @param string[] $extraArgs  Unused for now.
     * @param bool     $massOp     Unused for now.
     *
     * @return int
     *
     * @throws LSCMException  Thrown indirectly by Logger::uiSuccess() call.
     *
     * @noinspection PhpUnusedParameterInspection
     */
    public function dashDisable( array $extraArgs, $massOp = false )
    {
        if ( WpConstants::getWpConstant('MULTISITE') ) {
            $blogs =
                Wpdb::getCol('SELECT blog_id FROM ' . Wpdb::getBlogs() . ';');

            foreach ( $blogs as $id ) {
                WpFuncs::switchToBlog($id);

                DashNotifier::deactivate(true);

                WpFuncs::restoreCurrentBlog();
            }
        }
        else {
            DashNotifier::deactivate(true);
        }

        if ( WpFuncs::isPluginActive(DashNotifier::DASH_PLUGIN) ) {
            $this->massIncr = 'FAIL';
            return UserCommand::EXIT_FAIL;
        }

        Logger::uiSuccess('Dash Notifier Disabled');
        $this->massIncr = 'SUCC';

        return UserCommand::EXIT_SUCC;
    }

    /**
     *
     * @param string[] $extraArgs
     *
     * @return int
     *
     * @throws LSCMException  Thrown indirectly by $this->dashDisable() call.
     */
    public function massDashDisable( array $extraArgs )
    {
        $ret = $this->dashDisable($extraArgs, true);

        if ( $this->massIncr != '' ) {
            $this->outputResult('MASS_INCR', $this->massIncr);
        }

        return $ret;
    }

    /**
     *
     * @since 1.12
     *
     * @param bool $setOutputResult
     *
     * @return string
     */
    public function getQuicCloudAPIKey( $setOutputResult = false )
    {
        $key = WpFuncs::applyFilters('litespeed_conf', 'api_key', null);

        if ( $key == 'api_key' || $key == null ) {
            $key = '';
        }

        if ( $setOutputResult ) {
            $this->outputResult('API_KEY', $key);
        }

        return $key;
    }

    /**
     * Set global server and environment variables.
     *
     * @since 1.9.8
     *
     * @param string $key
     * @param mixed  $val
     */
    private function setEnvVar( $key, $val )
    {
        $_SERVER[$key] = $val;
        putenv("$key=$val");
    }

    /**
     * Checks if the current WordPress installation is a multisite install and
     * does some preload setup if so.
     *
     * Patterns and multisite check logic based on WordPress function
     * is_multisite().
     *
     * @since 1.9.8
     *
     * @return bool
     *
     * @throws LSCMException  Thrown when DOMAIN_CURRENT_SITE is not found with
     *     MULTISITE defined.
     * @throws LSCMException  Thrown when PATH_CURRENT_SITE is not found with
     *     MULTISITE defined.
     */
    private function isMultisite()
    {
        $config_content =
            file_get_contents($this->currInstall->getWpConfigFile());

        $isMultiSite = (
            preg_match(
                '/define\(\s*[\'"]MULTISITE[\'"]\s*,[^;]*;/',
                $config_content,
                $m1
            )
            &&
            preg_match(
                '/define\(\s*[\'"]MULTISITE[\'"]\s*,\s*true\s*\)\s*;/',
                $m1[0]
            )
        )
        ||
        (
            preg_match(
                '/define\(\s*[\'"]SUBDOMAIN_INSTALL[\'"]\s*,[^;]*;/',
                $config_content
            )
            ||
            preg_match(
                '/define\(\s*[\'"]VHOST[\'"]\s*,[^;]*;/',
                $config_content
            )
            ||
            preg_match(
                '/define\(\s*[\'"]SUNRISE[\'"]\s*,[^;]*;/',
                $config_content
            )
        );

        if ( !$isMultiSite ) {
            return false;
        }

        $domainCurrentSiteFound = preg_match(
            '/define\(\s*[\'"]DOMAIN_CURRENT_SITE[\'"]\s*,'
                . '\s*[\'"](.+)[\'"]\s*\)\s*;/',
            $config_content,
            $m2
        );

        if ( !$domainCurrentSiteFound ) {
            throw new LSCMException(
                'Cannot find DOMAIN_CURRENT_SITE with MULTISITE defined.'
            );
        }

        $this->currInstall->setServerName($m2[1]);

        $pathCurrentSiteFound = preg_match(
            '/define\(\s*[\'"]PATH_CURRENT_SITE[\'"]\s*,'
                . '\s*[\'"](.+)[\'"]\s*\)\s*;/',
            $config_content,
            $m3
        );

        if ( !$pathCurrentSiteFound ) {
            throw new LSCMException(
                'Cannot find PATH_CURRENT_SITE with MULTISITE defined.'
            );
        }

        $this->setEnvVar('REQUEST_URI', $m3[1]);

        Util::define_wrapper('WP_NETWORK_ADMIN', true);

        return true;
    }

    /**
     *
     * WP Variables: $wpdb, $shortcode_tags
     *
     * @global \wpdb $wpdb
     * @global array $shortcode_tags
     *
     * @throws LSCMException  Thrown when detected WordPress version is lower
     *     then 4.0.
     * @throws LSCMException  Thrown when unable to find a required WordPress
     *     include file.
     * @throws LSCMException  Thrown indirectly by $this->isMultisite() call.
     *
     * @noinspection PhpUndefinedClassInspection
     */
    private function initWp()
    {
        /**
         * Declared global variables for use in included files.
         *
         * @noinspection PhpUnusedLocalVariableInspection
         */
        global $wpdb, $shortcode_tags;

        error_reporting(E_ALL);

        /**
         * Attempt to override any WordPress memory limits.
         */
        Util::define_wrapper('WP_MEMORY_LIMIT', '512M');
        Util::define_wrapper('WP_MAX_MEMORY_LIMIT', '512M');

        /**
         * Only load core WordPress functionality.
         */
        Util::define_wrapper('SHORTINIT', true);

        $wpPath = $this->currInstall->getPath();

        /**
         * Set WP version data global variables, including $wp_version.
         */
        include_once "$wpPath/wp-includes/version.php";

        /** @noinspection PhpUndefinedVariableInspection  $wp_version is defined
         *     and made available in previous version.php include
         */
        if ( Util::betterVersionCompare($wp_version, '4.0', '<') ) {
            throw new LSCMException(
                "Detected WordPress version as $wp_version. Version 4.0 '
                    . 'required at minimum."
            );
        }

        /**
         * Set needed server variables.
         */
        $_SERVER['SCRIPT_FILENAME'] = "$wpPath/wp-admin/plugins.php";

        if ( ! $this->isMultisite() ) {
            $this->setEnvVar('REQUEST_URI', '');
        }

        /**
         * Set for LSCWP v1.1.5.1+ plugin logic.
         */
        if ( $docRoot = $this->currInstall->getDocRoot() ) {

            /**
             * For enable/disable.
             */
            $this->setEnvVar('DOCUMENT_ROOT', $docRoot);
        }

        $serverName = $this->currInstall->getServerName();

        if ( empty($serverName) ) {
            $serverName = self::LSCWP_HTTP_HOST_TEST;
        }

        /**
         * For security plugins.
         */
        $this->setEnvVar('HTTP_HOST', $serverName);

        /**
         * Version specific includes may fail on RC releases.
         */

        $includeFiles = array(
            '/wp-load.php',
            '/wp-includes/default-constants.php',
            '/wp-includes/formatting.php',
            '/wp-includes/meta.php',
            '/wp-includes/l10n.php',
            '/wp-includes/class-wp-walker.php',
            '/wp-includes/capabilities.php'
        );

        if ( Util::betterVersionCompare($wp_version, '4.4.0', '>=') ) {
            $includeFiles[] = '/wp-includes/class-wp-roles.php';
            $includeFiles[] = '/wp-includes/class-wp-role.php';
            $includeFiles[] = '/wp-includes/class-wp-user.php';
            $includeFiles[] = '/wp-includes/rest-api.php';
            $includeFiles[] = '/wp-includes/class-wp-http-encoding.php';
            $includeFiles[] = '/wp-includes/class-wp-http-proxy.php';
            $includeFiles[] = '/wp-includes/class-wp-http-response.php';
            $includeFiles[] = '/wp-includes/class-wp-http-curl.php';
            $includeFiles[] = '/wp-includes/class-wp-http-cookie.php';
        }

        $includeFiles[] = '/wp-includes/query.php';
        $includeFiles[] = '/wp-includes/theme.php';
        $includeFiles[] = '/wp-includes/class-wp-theme.php';
        $includeFiles[] = '/wp-includes/user.php';
        $includeFiles[] = '/wp-includes/general-template.php';
        $includeFiles[] = '/wp-includes/link-template.php';
        $includeFiles[] = '/wp-includes/post.php';
        $includeFiles[] = '/wp-includes/kses.php';
        $includeFiles[] = '/wp-includes/cron.php';
        $includeFiles[] = '/wp-includes/update.php';
        $includeFiles[] = '/wp-includes/shortcodes.php';
        $includeFiles[] = '/wp-includes/http.php';

        if ( Util::betterVersionCompare($wp_version, '5.9.0', '>=') ) {
            $includeFiles[] = '/wp-includes/class-wp-http.php';
        }
        else {
            $includeFiles[] = '/wp-includes/class-http.php';
        }


        if ( Util::betterVersionCompare($wp_version, '4.6.0', '>=') ) {
            $includeFiles[] = '/wp-includes/class-wp-http-requests-response.php';
        }

        if ( Util::betterVersionCompare($wp_version, '4.7.0', '>=') ) {
            $includeFiles[] = '/wp-includes/class-wp-http-requests-hooks.php';

            /**
             * Content contained in /wp-includes/query.php for earlier versions.
             */
            $includeFiles[] = '/wp-includes/class-wp-query.php';
        }

        if ( Util::betterVersionCompare($wp_version, '5.0.0', '>=') ) {
            $includeFiles[] = '/wp-includes/blocks.php';
            $includeFiles[] = '/wp-includes/class-wp-block-parser.php';
        }

        if ( Util::betterVersionCompare($wp_version, '6.1.0', '>=') ) {
            $includeFiles[] = '/wp-includes/class-wp-textdomain-registry.php';
        }

        $includeFiles[] = '/wp-includes/ms-functions.php';
        $includeFiles[] = '/wp-includes/ms-deprecated.php';
        $includeFiles[] = '/wp-includes/pluggable.php';
        $includeFiles[] = '/wp-admin/includes/plugin.php';
        $includeFiles[] = '/wp-admin/includes/file.php';
        $includeFiles[] = '/wp-admin/includes/class-wp-upgrader.php';
        $includeFiles[] = '/wp-admin/includes/misc.php';
        $includeFiles[] = '/wp-admin/includes/template.php';

        if ( Util::betterVersionCompare($wp_version, '6.5.0', '>=') ) {
            $includeFiles[] = '/wp-includes/class-wp-plugin-dependencies.php';
        }

        set_error_handler('\Lsc\Wp\WPCaller::warning_handler');

        /**
         * Force WP to use PHP I/O file handling.
         */
        Util::define_wrapper('FS_METHOD', 'direct');

        /**
         * Trigger an early return from WP Rocket advanced-cache.php to prevent
         * WP Rocket from serving a cached copy and killing the process. This
         * occurs when calling an action from our control panel plugins and is
         * fixed by more closely matching the environment of a direct cli call.
         */
        unset($_SERVER['REQUEST_METHOD']);

        self::redefineDisabledFunctions();

        foreach ( $includeFiles as $file ) {
            $file = $wpPath . $file;

            if ( !file_exists($file) ) {
                throw new LSCMException(
                    "Could not include missing file $file."
                );
            }

            include_once $file;
        }

        restore_error_handler();

        /**
         * Needs to be defined after including files.
         */
        Util::define_wrapper('WP_ADMIN', true);

        /**
         * Define common WP constants and set 'wp_plugin_paths' array.
         */
        WpFuncs::wpPluginDirectoryConstants();

        /**
         * Do not load other plugins.
         */
        $GLOBALS['wp_plugin_paths'] = array();

        WpFuncs::wpCookieConstants();

        /**
         * Create global wp_query (WordPress) object entry. Needed during
         * LSCWP uninstall.
         */
        $wpQueryWrapper = new WpQuery();

        $GLOBALS['wp_the_query'] = $wpQueryWrapper->getWpWpQueryObject();
        $GLOBALS['wp_query']     = $GLOBALS['wp_the_query'];

        if ( Util::betterVersionCompare($wp_version, '6.1.0', '>=') ) {
            $wpTextdomainRegistryWrapper = new WpTextdomainRegistry();

            $GLOBALS['wp_textdomain_registry'] =
                $wpTextdomainRegistryWrapper->getWpWpTextdomainRegistryObject();
        }

        $this->pluginEntry = WpConstants::getWpConstant('WP_PLUGIN_DIR')
            . '/' . self::LSCWP_PLUGIN;

        if ( $this->loadLscwp && file_exists($this->pluginEntry) ) {
            include $this->pluginEntry;

            $this->installedLscwpVer = $this->getPluginVersionFromFile();

            if ( Util::betterVersionCompare($this->installedLscwpVer, '3.0.4', '<') ) {
                $this->includeLSCWPAdvancedCacheFile();
            }
        }
    }

}
webcachemgr/src/WPDashMsgs.php000066400000011401150545647710012310 0ustar00<?php

/** *********************************************
 * LiteSpeed Web Server WordPress Dash Notifier
 *
 * @author    Michael Alegre
 * @copyright 2019-2023 LiteSpeed Technologies, Inc.
 * *******************************************
 */

namespace Lsc\Wp;

class WPDashMsgs
{

    /**
     * @var string
     */
    const MSG_TYPE_RAP = 'rap';

    /**
     * @var string
     */
    const MSG_TYPE_BAM = 'bam';

    /**
     * @var string
     */
    const KEY_RAP_MSGS = 'rapMsgs';

    /**
     * @var string
     */
    const KEY_BAM_MSGS = 'bamMsgs';

    /**
     * Do not change the following constant values, substr 'msg' is used in
     * PanelController to determine action.
     */

    /**
     * @var string
     */
    const ACTION_GET_MSG = 'msgGet';

    /**
     * @var string
     */
    const ACTION_ADD_MSG = 'msgAdd';

    /**
     * @var string
     */
    const ACTION_DELETE_MSG = 'msgDelete';

    /**
     * @var string
     */
    protected $dataFile;

    /**
     * @var string[][]
     */
    protected $msgData = array();


    public function __construct( )
    {
        $this->dataFile =
            realpath(__DIR__ . '/../../..') . '/admin/lscdata/wpDashMsgs.data';

        $this->init();
    }

    protected function init()
    {
        if ( file_exists($this->dataFile) ) {
            $data = json_decode(file_get_contents($this->dataFile), true);

            if ( $data && is_array($data) ) {
                $this->msgData = $data;
            }
        }

        if ( !isset($this->msgData[self::KEY_RAP_MSGS]) ) {
            $this->msgData[self::KEY_RAP_MSGS] = array();
        }

        if ( !isset($this->msgData[self::KEY_BAM_MSGS]) ) {
            $this->msgData[self::KEY_BAM_MSGS] = array();
        }

        /**
         * Set default rap message and plugin slug.
         */
        $this->msgData[self::KEY_RAP_MSGS] = array_merge(
            array(
                'default' => array(
                    'msg'  => 'Greetings! This is your hosting company '
                        . 'encouraging you to click the button to install the '
                        . 'LiteSpeed Cache plugin. This plugin will speed up '
                        . 'your WordPress site dramatically. Please contact us '
                        . 'with any questions.',
                    'slug' => 'litespeed-cache'
                )
            ),
            $this->msgData[self::KEY_RAP_MSGS]
        );
    }

    /**
     *
     * @param string $type
     *
     * @return string[]|string[][]
     */
    public function getMsgData( $type = '' )
    {
        switch ($type) {

            case self::MSG_TYPE_RAP:
                return $this->msgData[self::KEY_RAP_MSGS];

            case self::MSG_TYPE_BAM:
                return $this->msgData[self::KEY_BAM_MSGS];

            default:
                return $this->msgData;
        }
    }

    /**
     *
     * @param string $type
     * @param string $msgId
     * @param string $msg
     * @param string $slug
     *
     * @return bool
     */
    public function addMsg( $type, $msgId, $msg, $slug = '' )
    {
        if ( $msgId === ''
                || $msgId === NULL
                || ($msgId == 'default' && $type == self::MSG_TYPE_RAP)
                || strlen($msgId) > 50
                || preg_match('/[^a-zA-Z0-9_-]/', $msgId) ) {

            return false;
        }

        switch ($type) {

            case self::MSG_TYPE_RAP:
                $this->msgData[self::KEY_RAP_MSGS][$msgId] =
                    array( 'msg' => $msg, 'slug' => $slug );
                break;

            case self::MSG_TYPE_BAM:
                $this->msgData[self::KEY_BAM_MSGS][$msgId] =
                    array( 'msg' => $msg );
                break;

            default:
                return false;
        }

        $this->saveDataFile();
        return true;
    }

    /**
     *
     * @param string $type
     * @param string $msgId
     *
     * @return bool
     */
    public function deleteMsg( $type, $msgId )
    {
        if ( $msgId === '' || $msgId === NULL ) {
            return false;
        }

        switch ($type) {

            case self::MSG_TYPE_RAP:

                if ( $msgId == 'default' ) {
                    return false;
                }

                $key = self::KEY_RAP_MSGS;
                break;

            case self::MSG_TYPE_BAM:
                $key = self::KEY_BAM_MSGS;
                break;

            default:
                return false;
        }

        if ( isset($this->msgData[$key][$msgId]) ) {
            unset($this->msgData[$key][$msgId]);

            $this->saveDataFile();
            return true;
        }

        return false;
    }

    protected function saveDataFile()
    {
        file_put_contents($this->dataFile, json_encode($this->msgData));
    }

}
webcachemgr/src/DashNotifier.php000066400000023621150545647710012716 0ustar00<?php

/** *********************************************
 * LiteSpeed Web Server WordPress Dash Notifier
 *
 * @author    Michael Alegre
 * @copyright 2019-2023 LiteSpeed Technologies, Inc.
 * *******************************************
 */

namespace Lsc\Wp;

use Lsc\Wp\Context\Context;
use Lsc\Wp\WpWrapper\WpConstants;
use Lsc\Wp\WpWrapper\WpFuncs;

class DashNotifier
{

    /**
     * @var string
     */
    const BYPASS_FLAG = '.dash_notifier_bypass';

    /**
     * @var string
     */
    const DASH_MD5 = 'dash_md5';

    /**
     * @var string
     */
    const DASH_PLUGIN = 'dash-notifier/dash-notifier.php';

    /**
     * @var string
     */
    const DEFAULT_PLUGIN_PATH = '/wp-content/plugins/dash-notifier';

    /**
     * @deprecated 1.9
     *
     * @var string
     */
    const DOWNLOAD_DIR = '/usr/src/litespeed-wp-plugin';

    /**
     * @var string
     */
    const PLUGIN_NAME = 'dash-notifier';

    /**
     * @var string
     */
    const VER_FILE = 'dash_ver';

    private function __construct()
    {

    }

    /**
     *
     * @since 1.9
     *
     * @return void
     *
     * @throws LSCMException  Thrown when read dash version file command fails.
     * @throws LSCMException  Thrown indirectly by self::getLatestVersion()
     *     call.
     * @throws LSCMException  Thrown indirectly by self::downloadVersion() call.
     * @throws LSCMException  Thrown indirectly by self::downloadVersion() call.
     * @throws LSCMException  Thrown indirectly by self::downloadVersion() call.
     * @throws LSCMException  Thrown indirectly by Logger::error() call.
     */
    public static function prepLocalDashPluginFiles()
    {
        $dashVerFile = Context::LOCAL_PLUGIN_DIR . '/' . self::VER_FILE;

        if ( ! file_exists($dashVerFile) ) {
            self::downloadVersion(self::getLatestVersion());
            return;
        }

        if ( ($content = file_get_contents($dashVerFile)) === false ) {
            throw new LSCMException(
                'prepLocalDashPluginFiles(): Failed to read file '
                    . self::VER_FILE . ' contents.'
            );
        }

        $localVer = trim($content);

        $pluginDir = Context::LOCAL_PLUGIN_DIR . '/' . self::PLUGIN_NAME;

        if ( ! file_exists($pluginDir) ) {
            self::downloadVersion($localVer);
            return;
        }

        $isStoredMd5Valid = (
            file_get_contents(Context::LOCAL_PLUGIN_DIR . '/' . self::DASH_MD5)
            ==
            Util::DirectoryMd5($pluginDir)
        );

        if ( !$isStoredMd5Valid ) {
            self::downloadVersion($localVer);
            return;
        }

        clearstatcache();

        if ( (time() - filemtime($dashVerFile)) > 86400 ) {

            try {
                $latestVer = self::getLatestVersion();

                if ( Util::betterVersionCompare($latestVer, $localVer, '<') ) {
                    self::downloadVersion($latestVer);
                }
            }
            catch ( LSCMException $e ) {
                Logger::error($e->getMessage());
            }

            touch($dashVerFile);
        }
    }

    /**
     *
     * @since 1.9
     *
     * @return string
     *
     * @throws LSCMException  Thrown when unable to retrieve latest Dash
     *     Notifier plugin version.
     */
    public static function getLatestVersion()
    {
        $content = Util::get_url_contents(
            'https://www.litespeedtech.com/packages/lswpcache/dash_latest'
        );

        if ( empty($content) ) {
            throw new LSCMException(
                'Could not retrieve latest Dash Notifier plugin version'
            );
        }

        return trim($content);
    }

    /**
     *
     * @since 1.9
     *
     * @param string $version
     *
     * @throws LSCMException  Thrown indirectly by self::wgetPlugin() call.
     */
    protected static function downloadVersion( $version )
    {
        $pluginDir = Context::LOCAL_PLUGIN_DIR . '/' . self::PLUGIN_NAME;

        if ( file_exists($pluginDir) ) {
            exec("/bin/rm -rf $pluginDir");
        }

        self::wgetPlugin($version, true);
    }

    /**
     *
     * @since 1.9
     *
     * @param string $version
     * @param bool   $saveMD5
     *
     * @throws LSCMException  Thrown when wget command fails to download
     *     requested Dash Notifier plugin version.
     * @throws LSCMException  Thrown when unable to unzip downloaded Dash
     *     Notifier plugin package.
     * @throws LSCMException  Thrown when downloaded Dash Notifier plugin
     *     package is missing an expected file.
     * @throws LSCMException  Thrown indirectly by Logger::info() call.
     * @throws LSCMException  Thrown indirectly by Util::unzipFile() call.
     */
    protected static function wgetPlugin( $version, $saveMD5 = false )
    {
        Logger::info("Downloading Dash Notifier v$version...");

        $zipFileName  = self::PLUGIN_NAME . ".$version.zip";

        exec(
            "wget -q --tries=1 --no-check-certificate "
                . "https://downloads.wordpress.org/plugin/$zipFileName -P "
                . Context::LOCAL_PLUGIN_DIR,
            $output,
            $return_var
        );

        if ( $return_var !== 0 ) {
            throw new LSCMException(
                "Failed to download Dash Notifier v$version with wget exit "
                    . "status $return_var.",
                LSCMException::E_NON_FATAL
            );
        }

        $localZipFile = Context::LOCAL_PLUGIN_DIR . "/$zipFileName";

        $extracted = Util::unzipFile($localZipFile, Context::LOCAL_PLUGIN_DIR);
        unlink($localZipFile);

        if ( ! $extracted ) {
            throw new LSCMException(
                "Unable to unzip $localZipFile",
                LSCMException::E_NON_FATAL
            );
        }

        $pluginDir    = Context::LOCAL_PLUGIN_DIR . '/' . self::PLUGIN_NAME;

        if ( ! file_exists("$pluginDir/" . self::PLUGIN_NAME . '.php') ) {
            throw new LSCMException(
                "Unable to download Dash Notifier v$version.",
                LSCMException::E_NON_FATAL
            );
        }

        if ( $saveMD5 ) {
            file_put_contents(
                Context::LOCAL_PLUGIN_DIR . '/' . self::DASH_MD5,
                Util::DirectoryMd5($pluginDir)
            );
        }

        file_put_contents(
            Context::LOCAL_PLUGIN_DIR . '/' . self::VER_FILE,
            $version
        );
    }

    /**
     * Check if WordPress installation should be notified using the Dash
     * Notifier plugin.
     *
     * @param string $wpPath  Root directory for WordPress installation.
     *
     * @return bool
     */
    public static function canNotify( $wpPath )
    {
        return !file_exists("$wpPath/" . self::BYPASS_FLAG);
    }

    /**
     * Checks the current installation for existing LSCWP plugin files and
     * copies them to the installation's plugins directory if not found.
     * This function should only be run as the user.
     *
     * @return bool  True when new Dash Notifier plugin files are used.
     *
     * @throws LSCMException  Thrown when unable to copy Dash Notifier plugin
     *     files to WordPress plugin directory.
     * @throws LSCMException  Thrown indirectly by Logger::debug() call.
     */
    public static function prepareUserInstall()
    {
        $pluginDir = WpConstants::getWpConstant('WP_PLUGIN_DIR');

        $dashNotifierPlugin = "$pluginDir/dash-notifier/dash-notifier.php";

        if ( file_exists($dashNotifierPlugin) ) {
            /**
             * Existing installation detected.
             */
            return false;
        }

        exec(
            '/bin/cp -rf ' . Context::LOCAL_PLUGIN_DIR . '/' . self::PLUGIN_NAME
            . " $pluginDir"
        );

        if ( !file_exists($dashNotifierPlugin) ) {
            throw new LSCMException(
                "Failed to copy Dash Notifier plugin files to $pluginDir.",
                LSCMException::E_NON_FATAL
            );
        }

        Logger::debug(
            'Copied Dash Notifier plugin files into plugins directory '
                . $pluginDir
        );

        return true;
    }

    /**
     * Activate Dash Notifier plugin if it is not already activated, and give
     * the plugin any notification data in the form of a JSON encoded array.
     *
     * @param string $jsonInfo  Dash Notifier plugin info.
     *
     * @return bool
     *
     * @throws LSCMException  Thrown when unable to find Dash Notifier plugin
     *     files.
     */
    public static function doNotify( $jsonInfo )
    {
        if (
            file_exists(
                WpConstants::getWpConstant('WP_PLUGIN_DIR')
                    . '/' . self::DASH_PLUGIN
            )
        ) {
            /**
             * Used to pass info to the Dash Notifier Plugin.
             */
            Util::define_wrapper( 'DASH_NOTIFIER_MSG', $jsonInfo);

            if ( !WpFuncs::isPluginActive(self::DASH_PLUGIN) ) {

                /**
                * Should not check directly, can error on success due to object
                * cache.
                */
               WpFuncs::activatePlugin(self::DASH_PLUGIN);

               if ( !WpFuncs::isPluginActive(self::DASH_PLUGIN) ) {
                   return false;
               }
            }
            else {
                include WpConstants::getWpConstant('WP_PLUGIN_DIR')
                    . '/' . self::DASH_PLUGIN;
            }
        }
        else {
            throw new LSCMException(
                'Dash Notifier plugin files are missing. Cannot notify.',
                LSCMException::E_NON_FATAL
            );
        }

        return true;
    }

    /**
     *
     * @param bool $uninstall
     */
    public static function deactivate( $uninstall )
    {
        WpFuncs::deactivatePlugins(self::DASH_PLUGIN);

        if ( $uninstall ) {
            //add some msg about having removed plugin files?
            WpFuncs::deletePlugins(array( self::DASH_PLUGIN ));
        }
    }

}
webcachemgr/src/WpWrapper/PluginUpgrader.php000066400000004657150545647710015226 0ustar00<?php

/** *********************************************
 * LiteSpeed Web Server Cache Manager
 *
 * @author    Michael Alegre
 * @copyright 2023-2025 LiteSpeed Technologies, Inc.
 * @since     1.17
 * *******************************************
 */

namespace Lsc\Wp\WpWrapper;

/**
 * https://developer.wordpress.org/reference/classes/plugin_upgrader/
 *
 * @since 1.17
 */
class PluginUpgrader
{

    /**
     * https://developer.wordpress.org/reference/classes/plugin_upgrader/
     *
     * @since 1.17
     * @var \Plugin_Upgrader
     *
     * @noinspection PhpUndefinedClassInspection
     */
    private $pluginUpgrader;

    /**
     * https://developer.wordpress.org/reference/classes/wp_upgrader/__construct/
     *
     * @since 1.17
     *
     * @param \WP_Upgrader_Skin|null $skin
     *
     * @noinspection PhpDeprecatedImplicitlyNullableParameterInspection
     * @noinspection PhpFullyQualifiedNameUsageInspection
     * @noinspection PhpUndefinedClassInspection
     * @noinspection RedundantSuppression
     */
    public function __construct( \WP_Upgrader_Skin $skin = null )
    {
        /** @noinspection PhpUndefinedClassInspection */
        $this->pluginUpgrader = new \Plugin_Upgrader($skin);
    }

    /**
     *
     * @since 1.17
     *
     * @return \Plugin_Upgrader
     *
     * @noinspection PhpUndefinedClassInspection
     */
    public function getWpPluginUpgraderObject()
    {
        return $this->pluginUpgrader;
    }

    /**
     *
     * @since 1.17
     *
     * @return array|WP_Error
     *
     * @noinspection PhpUndefinedClassInspection
     */
    public function getResult()
    {
        return $this->pluginUpgrader->result;
    }

    /**
     * https://developer.wordpress.org/reference/classes/wp_upgrader/init/
     *
     * @since 1.17
     */
    public function init()
    {
        $this->pluginUpgrader->init();
    }

    /**
     * https://developer.wordpress.org/reference/classes/plugin_upgrader/upgrade_strings/
     *
     * @since 1.17
     */
    public function upgradeStrings()
    {
        $this->pluginUpgrader->upgrade_strings();
    }

    /**
     * https://developer.wordpress.org/reference/classes/wp_upgrader/run/
     *
     * @since 1.17
     *
     * @param array $options
     *
     * @return array|false|WP_Error
     *
     * @noinspection PhpUndefinedClassInspection
     */
    public function run( array $options )
    {
        return $this->pluginUpgrader->run($options);
    }
}webcachemgr/src/WpWrapper/Wpdb.php000066400000002162150545647710013157 0ustar00<?php

/** *********************************************
 * LiteSpeed Web Server Cache Manager
 *
 * @author    Michael Alegre
 * @copyright 2023 LiteSpeed Technologies, Inc.
 * @since     1.7
 * *******************************************
 */

namespace Lsc\Wp\WpWrapper;

/**
 * https://developer.wordpress.org/reference/classes/wpdb/
 *
 * @since 1.17
 */
class Wpdb
{

    /**
     * https://developer.wordpress.org/reference/classes/wpdb/
     *
     * @since 1.17
     *
     * @global \wpdb $wpdb
     *
     * @return string
     *
     * @noinspection PhpUndefinedClassInspection
     */
    public static function getBlogs()
    {
        global $wpdb;

        return $wpdb->blogs;
    }

    /**
     * https://developer.wordpress.org/reference/classes/wpdb/get_col/
     *
     * @since 1.17
     *
     * @global \wpdb $wpdb
     *
     * @param string|null $query
     * @param int         $x
     *
     * @return array
     *
     * @noinspection PhpUndefinedClassInspection
     */
    public static function getCol( $query = null, $x = 0 )
    {
        global $wpdb;

        return $wpdb->get_col($query, $x);
    }
}webcachemgr/src/WpWrapper/WpConstants.php000066400000001202150545647710014540 0ustar00<?php

/** *********************************************
 * LiteSpeed Web Server Cache Manager
 *
 * @author    Michael Alegre
 * @copyright 2023 LiteSpeed Technologies, Inc.
 * @since     1.17
 * *******************************************
 */

namespace Lsc\Wp\WpWrapper;

/**
 * Wrapper class used to retrieve the value of WordPress core code specific
 * global constants.
 *
 * @since 1.17
 */
class WpConstants
{

    /**
     *
     * @since 1.17
     *
     * @param string $constantName
     *
     * @return mixed
     */
    public static function getWpConstant( $constantName )
    {
        return constant($constantName);
    }
}webcachemgr/src/WpWrapper/WpFuncs.php000066400000021070150545647710013647 0ustar00<?php

/** *********************************************
 * LiteSpeed Web Server Cache Manager
 *
 * @author    Michael Alegre
 * @copyright 2023 LiteSpeed Technologies, Inc.
 * @since     1.17
 * *******************************************
 */

namespace Lsc\Wp\WpWrapper;

/**
 * Wrapper class containing functions used to make WordPress core code specific
 * calls.
 *
 * @since 1.17
 */
class WpFuncs
{

    /**
     * https://developer.wordpress.org/reference/functions/switch_to_blog/
     *
     * @since 1.17
     *
     * @param int $id
     *
     * @return true
     */
    public static function switchToBlog( $id )
    {
        /** @noinspection PhpUndefinedFunctionInspection */
        return switch_to_blog($id);
    }

    /**
     * https://developer.wordpress.org/reference/functions/restore_current_blog/
     *
     * @since 1.17
     *
     * @return bool
     */
    public static function restoreCurrentBlog()
    {
        /** @noinspection PhpUndefinedFunctionInspection */
        return restore_current_blog();
    }

    /**
     * https://developer.wordpress.org/reference/functions/get_option/
     *
     * @since 1.17
     *
     * @param string $option
     * @param mixed  $defaultValue
     *
     * @return mixed
     */
    public static function getOption( $option, $defaultValue = false )
    {
        /** @noinspection PhpUndefinedFunctionInspection */
        return get_option($option, $defaultValue);
    }

    /**
     * https://developer.wordpress.org/reference/classes/wpdb/get_var/
     *
     * @since 1.17
     *
     * @param string|null $query
     * @param int         $x
     * @param int         $y
     *
     * @return string|null
     */
    public static function getVar( $query = null, $x = 0, $y = 0 )
    {
        global $wpdb;

        return $wpdb->get_var($query, $x, $y);
    }

    /**
     * https://developer.wordpress.org/reference/functions/is_plugin_active/
     *
     * @since 1.17
     *
     * @param string $plugin
     *
     * @return bool
     */
    public static function isPluginActive( $plugin )
    {
        /** @noinspection PhpUndefinedFunctionInspection */
        return is_plugin_active($plugin);
    }

    /**
     * https://developer.wordpress.org/reference/functions/is_plugin_active_for_network/
     *
     * @since 1.17
     *
     * @param string $plugin
     *
     * @return bool
     */
    public static function isPluginActiveForNetwork( $plugin )
    {
        /** @noinspection PhpUndefinedFunctionInspection */
        return is_plugin_active_for_network($plugin);
    }

    /**
     * https://developer.wordpress.org/reference/functions/wp_filesystem/
     *
     * @since 1.17
     *
     * @param array|false  $args
     * @param string|false $context
     * @param bool         $allow_relaxed_file_ownership
     *
     * @return bool|null
     */
    public static function WpFilesystem(
        $args = false,
        $context = false,
        $allow_relaxed_file_ownership = false )
    {
        /** @noinspection PhpUndefinedFunctionInspection */
        return WP_Filesystem($args, $context, $allow_relaxed_file_ownership);
    }

    /**
     * https://developer.wordpress.org/reference/functions/unzip_file/
     *
     * @since 1.17
     *
     * @param string $file
     * @param string $to
     *
     * @return true|WP_Error
     *
     * @noinspection PhpUndefinedClassInspection
     *
     */
    public static function unzipFile( $file, $to )
    {
        /** @noinspection PhpUndefinedFunctionInspection */
        return unzip_file($file, $to);
    }

    /**
     * https://developer.wordpress.org/reference/functions/deactivate_plugins/
     *
     * @since 1.17
     *
     * @param string|string[] $plugins
     * @param bool            $silent
     * @param bool|null       $network_wide
     */
    public static function deactivatePlugins(
        $plugins,
        $silent = false,
        $network_wide = null )
    {
        /** @noinspection PhpUndefinedFunctionInspection */
        deactivate_plugins($plugins, $silent, $network_wide);
    }

    /**
     * https://developer.wordpress.org/reference/functions/delete_plugins/
     *
     * @since 1.17
     *
     * @param string[] $plugins
     *
     * @return bool|null|WP_Error
     *
     * @noinspection PhpUndefinedClassInspection
     */
    public static function deletePlugins( array $plugins )
    {
        /** @noinspection PhpUndefinedFunctionInspection */
        return delete_plugins($plugins);
    }

    /**
     * https://developer.wordpress.org/reference/functions/activate_plugin/
     *
     * @since 1.17
     *
     * @param string $plugin
     * @param string $redirect
     * @param bool   $network_wide
     * @param bool   $silent
     *
     * @return null|WP_Error
     *
     * @noinspection PhpUndefinedClassInspection
     */
    public static function activatePlugin(
        $plugin,
        $redirect = '',
        $network_wide = false,
        $silent = false )
    {
        /** @noinspection PhpUndefinedFunctionInspection */
        return activate_plugin($plugin, $redirect, $network_wide, $silent);
    }

    /**
     * https://developer.wordpress.org/reference/functions/add_filter/
     *
     * @since 1.17
     *
     * @param string   $hook_name
     * @param callable $callback
     * @param int      $priority
     * @param int      $accepted_args
     *
     * @return true
     */
    public static function addFilter(
                 $hook_name,
        callable $callback,
                 $priority = 10,
                 $accepted_args = 1 )
    {
        /** @noinspection PhpUndefinedFunctionInspection */
        return add_filter($hook_name, $callback, $priority, $accepted_args);
    }

    /**
     * https://developer.wordpress.org/reference/functions/remove_filter/
     *
     * @since 1.17
     *
     * @param string                $hook_name
     * @param callable|string|array $callback
     * @param int                   $priority
     *
     * @return bool
     */
    public static function removeFilter( $hook_name, $callback, $priority = 10 )
    {
        /** @noinspection PhpUndefinedFunctionInspection */
        return remove_filter($hook_name, $callback, $priority);
    }

    /**
     * https://developer.wordpress.org/reference/functions/is_wp_error/
     *
     * @since 1.17
     *
     * @param mixed $thing
     *
     * @return bool
     */
    public static function isWpError( $thing )
    {
        /** @noinspection PhpUndefinedFunctionInspection */
        return is_wp_error($thing);
    }

    /**
     * https://developer.wordpress.org/reference/functions/wp_clean_plugins_cache/
     *
     * @since 1.17
     *
     * @param bool $clear_update_cache
     */
    public static function wpCleanPluginsCache( $clear_update_cache = true )
    {
        /** @noinspection PhpUndefinedFunctionInspection */
        wp_clean_plugins_cache($clear_update_cache);
    }

    /**
     * https://developer.wordpress.org/reference/functions/get_plugin_data/
     *
     * @since 1.17
     *
     * @param string $plugin_file
     * @param bool   $markup
     * @param bool   $translate
     *
     * @return array
     */
    public static function getPluginData(
        $plugin_file,
        $markup = true,
        $translate = true )
    {
        /** @noinspection PhpUndefinedFunctionInspection */
        return get_plugin_data($plugin_file, $markup, $translate);
    }

    /**
     * https://developer.wordpress.org/reference/functions/get_locale/
     *
     * @since 1.17
     *
     * @return string
     */
    public static function getLocale()
    {
        /** @noinspection PhpUndefinedFunctionInspection */
        return get_locale();
    }

    /**
     * https://developer.wordpress.org/reference/functions/apply_filters/
     *
     * @since 1.17
     *
     * @param string $hook_name
     * @param mixed  $value
     * @param mixed  $args
     *
     * @return mixed
     */
    public static function applyFilters( $hook_name, $value, $args )
    {
        /** @noinspection PhpUndefinedFunctionInspection */
        return apply_filters($hook_name, $value, $args);
    }

    /**
     * https://developer.wordpress.org/reference/functions/wp_plugin_directory_constants/
     *
     * @since 1.17
     */
    public static function wpPluginDirectoryConstants()
    {
        /** @noinspection PhpUndefinedFunctionInspection */
        wp_plugin_directory_constants();
    }

    /**
     * https://developer.wordpress.org/reference/functions/wp_cookie_constants/
     *
     * @since 1.17
     */
    public static function wpCookieConstants()
    {
        /** @noinspection PhpUndefinedFunctionInspection */
        wp_cookie_constants();
    }
}webcachemgr/src/WpWrapper/WpQuery.php000066400000002043150545647710013675 0ustar00<?php

/** *********************************************
 * LiteSpeed Web Server Cache Manager
 *
 * @author    Michael Alegre
 * @copyright 2023 LiteSpeed Technologies, Inc.
 * @since     1.17
 * *******************************************
 */

namespace Lsc\Wp\WpWrapper;

/**
 * https://developer.wordpress.org/reference/classes/wp_query/
 *
 * @since 1.17
 */
class WpQuery
{

    /**
     * @since 1.17
     * @var \WP_Query
     *
     * @noinspection PhpUndefinedClassInspection
     */
    private $wpQuery;

    /**
     * https://developer.wordpress.org/reference/classes/wp_query/__construct/
     *
     * @since 1.17
     *
     * @param string|array $query
     */
    public function __construct( $query = '' )
    {
        /** @noinspection PhpUndefinedClassInspection */
        $this->wpQuery = new \WP_Query($query);
    }

    /**
     *
     * @since 1.17
     *
     * @return \WP_Query
     *
     * @noinspection PhpUndefinedClassInspection
     */
    public function getWpWpQueryObject()
    {
        return $this->wpQuery;
    }
}webcachemgr/src/WpWrapper/WpTextdomainRegistry.php000066400000002021150545647710016431 0ustar00<?php

/** *********************************************
 * LiteSpeed Web Server Cache Manager
 *
 * @author    Michael Alegre
 * @copyright 2023 LiteSpeed Technologies, Inc.
 * @since     1.17
 * *******************************************
 */

namespace Lsc\Wp\WpWrapper;

/**
 * https://developer.wordpress.org/reference/classes/wp_textdomain_registry/
 *
 * @since 1.17
 */
class WpTextdomainRegistry
{

    /**
     * @since 1.17
     * @var \WP_Textdomain_Registry
     *
     * @noinspection PhpUndefinedClassInspection
     */
    private $wpTextdomainRegistry;

    /**
     *
     * @since 1.17
     */
    public function __construct()
    {
        /** @noinspection PhpUndefinedClassInspection */
        $this->wpTextdomainRegistry = new \WP_Textdomain_Registry();
    }

    /**
     *
     * @since 1.17
     *
     * @return \WP_Textdomain_Registry
     *
     * @noinspection PhpUndefinedClassInspection
     */
    public function getWpWpTextdomainRegistryObject()
    {
        return $this->wpTextdomainRegistry;
    }
}webcachemgr/src/WPInstall.php000066400000041500150545647710012210 0ustar00<?php

/** *********************************************
 * LiteSpeed Web Server Cache Manager
 *
 * @author LiteSpeed Technologies, Inc. (https://www.litespeedtech.com)
 * @copyright (c) 2018-2025
 * *******************************************
 */

namespace Lsc\Wp;

use Lsc\Wp\Panel\ControlPanel;
use Lsc\Wp\Context\Context;

class WPInstall
{

    /**
     * @var int
     */
    const ST_PLUGIN_ACTIVE = 1;

    /**
     * @var int
     */
    const ST_PLUGIN_INACTIVE = 2;

    /**
     * @var int
     */
    const ST_LSC_ADVCACHE_DEFINED = 4;

    /**
     * @var int
     */
    const ST_FLAGGED = 8;

    /**
     * @var int
     */
    const ST_ERR_SITEURL = 16;

    /**
     * @var int
     */
    const ST_ERR_DOCROOT = 32;

    /**
     * @var int
     */
    const ST_ERR_EXECMD = 64;

    /**
     * @var int
     */
    const ST_ERR_TIMEOUT = 128;

    /**
     * @var int
     */
    const ST_ERR_EXECMD_DB = 256;

    /**
     * @var int
     */
    const ST_ERR_WPCONFIG = 1024;

    /**
     * @var int
     */
    const ST_ERR_REMOVE = 2048;

    /**
     * @var string
     */
    const FLD_STATUS = 'status';

    /**
     * @var string
     */
    const FLD_DOCROOT = 'docroot';

    /**
     * @var string
     */
    const FLD_SERVERNAME = 'server_name';

    /**
     * @var string
     */
    const FLD_SITEURL = 'site_url';

    /**
     * @var string
     */
    const FLAG_FILE = '.litespeed_flag';

    /**
     * @var string
     */
    const FLAG_NEW_LSCWP = '.lscm_new_lscwp';

    /**
     * @var string
     */
    protected $path;

    /**
     * @var array
     */
    protected $data;

    /**
     * @var null|string
     */
    protected $phpBinary = null;

    /**
     * @var null|string
     */
    protected $suCmd = null;

    /**
     * @var null|array  Keys are 'user_id', 'user_name', 'group_id'
     */
    protected $ownerInfo = null;

    /**
     * @var bool
     */
    protected $changed = false;

    /**
     * @var bool
     */
    protected $refreshed = false;

    /**
     * @var null|string
     */
    protected $wpConfigFile = '';

    /**
     * @var int
     */
    protected $cmdStatus = 0;

    /**
     * @var string
     */
    protected $cmdMsg = '';

    /**
     *
     * @param string $path
     */
    public function __construct( $path )
    {
        $this->init($path);
    }

    /**
     *
     * @param string $path
     */
    protected function init( $path )
    {
        if ( ($realPath = realpath($path)) === false ) {
            $this->path = $path;
        }
        else {
            $this->path = $realPath;
        }

        $this->data = array(
            self::FLD_STATUS     => 0,
            self::FLD_DOCROOT    => null,
            self::FLD_SERVERNAME => null,
            self::FLD_SITEURL    => null
        );
    }

    /**
     *
     * @return string
     */
    public function __toString()
    {
        if ( $this->data[self::FLD_SITEURL] ) {
            $siteUrl = Util::tryIdnToUtf8($this->data[self::FLD_SITEURL]);
        }
        else {
            $siteUrl = '';
        }

        return sprintf(
            "%s (status=%d docroot=%s siteurl=%s)",
            $this->path,
            $this->data[self::FLD_STATUS],
            $this->data[self::FLD_DOCROOT],
            $siteUrl
        );
    }

    /**
     *
     * @return string|null
     */
    public function getDocRoot()
    {
        return $this->getData(self::FLD_DOCROOT);
    }

    /**
     *
     * @param string $docRoot
     *
     * @return bool
     */
    public function setDocRoot( $docRoot )
    {
        return $this->setData(self::FLD_DOCROOT, $docRoot);
    }

    /**
     *
     * @return string|null
     */
    public function getServerName()
    {
        return $this->getData(self::FLD_SERVERNAME);
    }

    /**
     *
     * @param string $serverName
     *
     * @return bool
     */
    public function setServerName( $serverName )
    {
        return $this->setData(
            self::FLD_SERVERNAME,
            Util::tryIdnToAscii((string)$serverName)
        );
    }

    /**
     * Note: Temporary function name until existing deprecated setSiteUrl()
     * function is removed.
     *
     * @param string $siteUrl
     *
     * @return bool
     */
    public function setSiteUrlDirect( $siteUrl )
    {
        return $this->setData(
            self::FLD_SITEURL,
            Util::tryIdnToAscii((string)$siteUrl)
        );
    }

    /**
     *
     * @param int $status
     *
     * @return bool
     */
    public function setStatus( $status )
    {
        return $this->setData(self::FLD_STATUS, $status);
    }

    /**
     *
     * @return int
     */
    public function getStatus()
    {
        return $this->getData(self::FLD_STATUS);
    }

    /**
     *
     * @param string $field
     *
     * @return mixed|null
     */
    public function getData( $field = '' )
    {
        if ( !$field ) {
            return $this->data;
        }

        if ( isset($this->data[$field]) ) {
            return $this->data[$field];
        }

        /**
         * Error out
         */
        return null;
    }

    /**
     *
     * @param string $field
     * @param mixed  $value
     *
     * @return bool
     */
    protected function setData( $field, $value )
    {
        if ( $this->data[$field] !== $value ) {
            $this->changed = true;
            $this->data[$field] = $value;

            return true;
        }

        return false;
    }

    /**
     * Calling from unserialized data.
     *
     * @param array $data
     */
    public function initData( array $data )
    {
        $this->data = $data;
    }

    /**
     *
     * @return string
     */
    public function getPath()
    {
        return $this->path;
    }

    /**
     *
     * @return bool
     */
    public function shouldRemove()
    {
        return (bool)(($this->getStatus() & self::ST_ERR_REMOVE));
    }

    /**
     *
     * @return bool
     */
    public function hasFlagFile()
    {
        return file_exists("$this->path/" . self::FLAG_FILE);
    }

    /**
     *
     * @return bool
     */
    public function hasNewLscwpFlagFile()
    {
        return file_exists("$this->path/" . self::FLAG_NEW_LSCWP);
    }

    /**
     *
     * @return bool
     *
     * @throws LSCMException  Thrown indirectly by Logger::uiError() call.
     * @throws LSCMException  Thrown indirectly by Logger::notice() call.
     * @throws LSCMException  Thrown indirectly by $this->addUserFlagFile()
     *     call.
     * @throws LSCMException  Thrown indirectly by Logger::uiError() call.
     * @throws LSCMException  Thrown indirectly by Logger::error() call.
     */
    public function hasValidPath()
    {
        if ( !is_dir($this->path) || !is_dir("$this->path/wp-admin") ) {
            $this->setStatusBit(self::ST_ERR_REMOVE);

            $msg = "$this->path - Could not be found and has been removed from "
                . 'Cache Manager list.';
            Logger::uiError($msg);
            Logger::notice($msg);

            return false;
        }

        if ( $this->getWpConfigFile() == null ) {
            $this->setStatusBit(self::ST_ERR_WPCONFIG);
            $this->addUserFlagFile(false);

            $msg = "$this->path - Could not find a valid wp-config.php file. "
                . 'Install has been flagged.';
            Logger::uiError($msg);
            Logger::error($msg);

            return false;
        }

        return true;
    }

    /**
     * Set the provided status bit.
     *
     * @param int $bit
     */
    public function setStatusBit( $bit )
    {
        $this->setStatus(($this->getStatus() | $bit));
    }

    /**
     * Unset the provided status bit.
     *
     * @param int $bit
     */
    public function unsetStatusBit( $bit )
    {
        $this->setStatus(($this->getStatus() & ~$bit ));
    }

    /**
     *
     * @deprecated 1.9.5  Deprecated to avoid confusion with $this->cmdStatus
     *     and $this->cmdMsg related functions. Use $this->setStatus() instead.
     *
     * @param int $newStatus
     */
    public function updateCommandStatus( $newStatus )
    {
        $this->setData(self::FLD_STATUS, $newStatus);
    }

    /**
     *
     * @return null|string
     */
    public function getWpConfigFile()
    {
        if ( $this->wpConfigFile === '' ) {
            $file = "$this->path/wp-config.php";

            if ( !file_exists($file) ) {
                /**
                 *  check parent dir
                 */
                $parentDir = dirname($this->path);
                $file = "$parentDir/wp-config.php";

                if ( !file_exists($file)
                        || file_exists("$parentDir/wp-settings.php") ) {

                    /**
                     * If wp-config moved up, in same dir should NOT have
                     * wp-settings
                     */
                    $file = null;
                }
            }

            $this->wpConfigFile = $file;
        }

        return $this->wpConfigFile;
    }

    /**
     * Takes a WordPress site URL and uses it to populate serverName, siteUrl,
     * and docRoot data. If a matching docRoot cannot be found using the
     * serverName, the installation will be flagged and an ST_ERR_DOCROOT status
     * set.
     *
     * @param string $url
     *
     * @return bool
     *
     * @throws LSCMException  Thrown indirectly by
     *     ControlPanel::getClassInstance() call.
     * @throws LSCMException  Thrown indirectly by
     *     ControlPanel::getClassInstance()->mapDocRoot() call.
     * @throws LSCMException  Thrown indirectly by $this->addUserFlagFile()
     *     call.
     * @throws LSCMException  Thrown indirectly by Logger::error() call.
     */
    public function populateDataFromUrl( $url )
    {
        /** @noinspection HttpUrlsUsage */
        $parseSafeUrl =
            (preg_match('#^https?://#', $url)) ? $url : "http://$url";

        $info = parse_url($parseSafeUrl);

        $serverName = Util::tryIdnToAscii((string)$info['host']);

        $this->setData(self::FLD_SERVERNAME, $serverName);

        $siteUrlTrim = $serverName;

        if ( isset($info['path']) ) {
            $siteUrlTrim .= $info['path'];
        }

        $this->setData(self::FLD_SITEURL, $siteUrlTrim);

        $docRoot = ControlPanel::getClassInstance()->mapDocRoot($serverName);
        $this->setData(self::FLD_DOCROOT, $docRoot);

        if ( $docRoot === null ) {
            $this->setStatus(self::ST_ERR_DOCROOT);
            $this->addUserFlagFile(false);

            $msg = "$this->path - Could not find matching document root for "
                . "WP siteurl/servername $serverName.";

            $this->setCmdStatusAndMsg(UserCommand::EXIT_ERROR, $msg);
            Logger::error($msg);
            return false;
        }

        return true;
    }

    /**
     * Deprecated 06/18/19. Renamed to populateDataFromUrl().
     *
     * @deprecated
     *
     * @param string $siteUrl
     *
     * @return bool
     *
     * @throws LSCMException  Thrown indirectly by $this->populateDataFromUrl()
     *     call.
     */
    public function setSiteUrl( $siteUrl )
    {
        return $this->populateDataFromUrl($siteUrl);
    }

    /**
     * Adds the flag file to an installation.
     *
     * @param bool $runningAsUser
     *
     * @return bool  True when install has a flag file created/already.
     *
     * @throws LSCMException  Thrown when unlink() call on preexisting flag file
     *     fails.
     * @throws LSCMException  Thrown indirectly by Context::getFlagFileContent()
     *     call.
     */
    public function addUserFlagFile( $runningAsUser = true )
    {
        $flagFile = "$this->path/" . self::FLAG_FILE;

        if ( file_exists($flagFile) ) {
            /** Do not trust existing flag file */
            if ( !unlink($flagFile) ) {
                throw new LSCMException(
                    'Failed to remove preexisting untrusted flag file.'
                );
            }
        }

        if ( !file_put_contents($flagFile, Context::getFlagFileContent()) ) {
            return false;
        }

        if ( !$runningAsUser ) {
            $ownerInfo = $this->getOwnerInfo();

            chown($flagFile, $ownerInfo['user_id']);
            chgrp($flagFile, $ownerInfo['group_id']);
        }

        $this->setStatusBit(self::ST_FLAGGED);
        return true;
    }

    /**
     *
     * @return bool
     */
    public function removeFlagFile()
    {
        $flagFile = "$this->path/" . self::FLAG_FILE;

        if ( file_exists($flagFile) ) {

            if ( !unlink($flagFile) ) {
                return false;
            }
        }

        $this->unsetStatusBit(self::ST_FLAGGED);
        return true;
    }

    /**
     * Add a flag file to indicate that a new LSCWP plugin was added to this
     * installation.
     *
     * This function should only be called by the installation owner to avoid
     * permission problems involving this file.
     *
     * @return bool
     */
    public function addNewLscwpFlagFile()
    {
        $file = "$this->path/" . self::FLAG_NEW_LSCWP;

        if ( !file_exists($file) ) {

            if ( !file_put_contents($file, '') ) {
                return false;
            }
        }

        return true;
    }

    /**
     * Remove "In Progress" flag file to indicate that a WPInstall action has
     * been completed.
     *
     * @return bool
     */
    public function removeNewLscwpFlagFile()
    {
        $file = "$this->path/" . self::FLAG_NEW_LSCWP;

        if ( file_exists($file) ) {

            if ( !unlink($file) ) {
                return false;
            }
        }

        return true;
    }

    /**
     *
     * @param bool $forced
     *
     * @return int
     *
     * @throws LSCMException  Thrown indirectly by UserCommand::issue() call.
     */
    public function refreshStatus( $forced = false )
    {
        if ( !$this->refreshed || $forced ) {
            UserCommand::issue(UserCommand::CMD_STATUS, $this);
            $this->refreshed = true;
        }

        return $this->getData(self::FLD_STATUS);
    }

    /**
     *
     * @param string $pluginDir
     *
     * @throws LSCMException  Thrown indirectly by Logger::debug() call.
     */
    public function removePluginFiles( $pluginDir )
    {
        if ( file_exists(dirname($pluginDir)) && file_exists($pluginDir) ) {
            exec("rm -rf $pluginDir");

            Logger::debug(
                "$this->path - Removed LSCache for WordPress plugin files from "
                    . 'plugins directory'
            );
        }
    }

    /**
     *
     * @return bool
     */
    public function isFlagBitSet()
    {
        if ( ($this->getStatus() & self::ST_FLAGGED) ) {
            return true;
        }

        return false;
    }

    /**
     *
     * @param null|int $status
     *
     * @return bool
     */
    public function hasFatalError( $status = null )
    {
        if ( $status === null ) {
            $status = $this->getData(self::FLD_STATUS);
        }

        $errMask = (
            self::ST_ERR_EXECMD
                | self::ST_ERR_EXECMD_DB
                | self::ST_ERR_TIMEOUT
                | self::ST_ERR_SITEURL
                | self::ST_ERR_DOCROOT
                | self::ST_ERR_WPCONFIG
        );

        return (($status & $errMask) > 0);
    }

    /**
     *
     * @return string
     *
     * @throws LSCMException  Thrown indirectly by
     *     ControlPanel::getClassInstance() call.
     * @throws LSCMException  Thrown indirectly by
     *     ControlPanel::getClassInstance()->getPhpBinary() call.
     */
    public function getPhpBinary()
    {
        if ( $this->phpBinary == null ) {
            $this->phpBinary =
                ControlPanel::getClassInstance()->getPhpBinary($this);
        }

        return $this->phpBinary;
    }

    /**
     * Returns requested owner info.
     *
     * @param string $field  Key ('user_id', 'user_name', or 'group_id') in the
     *     $ownerInfo array.
     *
     * @return array|int|string|null
     */
    public function getOwnerInfo( $field = '' )
    {
        if ( $this->ownerInfo == null ) {
            $this->ownerInfo = Util::populateOwnerInfo($this->path);
        }

        if ( $field == '' ) {
            return $this->ownerInfo;
        }
        elseif ( isset($this->ownerInfo[$field]) ) {
            return $this->ownerInfo[$field];
        }

        return null;
    }

    /**
     *
     * @return string
     */
    public function getSuCmd()
    {
        if ( $this->suCmd == null ) {
            $this->suCmd = "su {$this->getOwnerInfo('user_name')} -s /bin/bash";
        }

        return $this->suCmd;
    }

    /**
     *
     * @return int
     */
    public function getCmdStatus()
    {
        return $this->cmdStatus;
    }

    /**
     *
     * @return string
     */
    public function getCmdMsg()
    {
        return $this->cmdMsg;
    }

    public function setCmdStatusAndMsg( $status, $msg )
    {
        $this->cmdStatus = $status;
        $this->cmdMsg    = $msg;
    }

}
webcachemgr/src/View/Tpl/VersionChange.tpl000066400000002556150545647710014557 0ustar00<?php

use \Lsc\Wp\View\Model\VersionChangeViewModel as ViewModel;

$icon = $this->viewModel->getTplData(ViewModel::FLD_ICON);
$installsCount = $this->viewModel->getTplData(ViewModel::FLD_INSTALLS_COUNT);
$verNum = $this->viewModel->getTplData(ViewModel::FLD_VER_NUM);

$d = array(
    'title' => 'Updating LiteSpeed Cache Plugins...',
    'icon' => $icon
);
$this->loadTplBlock('Title.tpl', $d);

?>

<div id="progress-box" class="msg-box">
  Attempting to upgrade <span id="currIndex">0</span> out of
  <span id="totalCount"><?php echo $installsCount; ?></span> ...
</div>

<div>
  Currently upgrading all known LiteSpeed Cache plugin installations to
  version <b><?php echo htmlspecialchars($verNum); ?></b>.
  Please be patient.
</div>
<br />

<?php

$d = array(
    'back' => 'Back',
    'backDo' => 'lscwpVersionManager',
    'visibility' => 'hidden'
);
$this->loadTplBlock('ButtonPanelBackNext.tpl', $d);

?>

<button class="accordion accordion-error" type="button" style="display: none">
  Error Messages <span id ="errMsgCnt" class="badge errMsg-badge">0</span>
</button>
<div class="panel panel-error">

  <?php

  $d = array(
      'id' => 'errMsgs',
      'class' => 'scrollable',
  );
  $this->loadTplBlock('DivMsgBox.tpl', $d);

  ?>

</div>

<script type="text/javascript">lswsInitDropdownBoxes();</script>
<script type="text/javascript">lscwpVersionChangeUpdate();</script>webcachemgr/src/View/Tpl/DashNotifier.tpl000066400000056377150545647710014415 0ustar00<?php

use Lsc\Wp\View\Model\DashNotifierViewModel as ViewModel;

$iconDir = $this->viewModel->getTplData(ViewModel::FLD_ICON_DIR);
$discoveredCnt = $this->viewModel->getTplData(ViewModel::FLD_DISCOVERED_COUNT);
$rapMsgIds = $this->viewModel->getTplData(ViewModel::FLD_RAP_MSG_IDS);
$bamMsgIds = $this->viewModel->getTplData(ViewModel::FLD_BAM_MSG_IDS);

/**
 * Close usual "lswsform" to allow the following page to have multiple forms
 * based on selected tab.
 */
echo '</form>';

?>



<div id="heading">
  <h1 class="uk-margin-top-remove">

    <?php if ( $iconDir != '' ) : ?>

    <span>
      <img src="<?php echo $iconDir; ?>/wpNotifier.svg" alt="wp_dash_notifier_icon" />
    </span>

    <?php endif; ?>

    WordPress Dashboard Notification
  </h1>
  <p class="uk-width-medium-2-3 uk-width-small-1-1 uk-text-dark"
     style="font-size: 15px; margin-left: 0;">
    This tool deploys and activates the
    <a href="https://wordpress.org/plugins/dash-notifier/" target='_blank'>WP Dash Notifier</a>
    WordPress plugin on all of the server's WordPress installations.
  </p>
</div>

<div id="display-msgs">
  <button class="accordion accordion-error" type="button" style="display: none">
    Error Messages
    <span id ="errMsgCnt" class="badge errMsg-badge">0</span>
  </button>
  <div class="panel panel-error">

    <?php

    $d = array(
        'id' => 'errMsgs',
        'class' => 'scrollable',
    );
    $this->loadTplBlock('DivMsgBox.tpl', $d);

    ?>

  </div>

  <button class="accordion accordion-success" type="button" style="display: none">
    Success Messages
    <span id="succMsgCnt" class="badge succMsg-badge">0</span>
  </button>

  <div class="panel panel-success">

    <?php

    $d = array(
        'id' => 'succMsgs',
        'class' => 'scrollable',
    );
    $this->loadTplBlock('DivMsgBox.tpl', $d);

    ?>

  </div>
</div>

<ul class="uk-tab uk-tab-grid" data-uk-tab="{connect:'#notify'}">
  <li>
    <a href="#">
      <i class="fa fa-puzzle-piece fa-1x uk-margin-small-right"></i>Recommend A
      Plugin
    </a>
  </li>
  <li>
    <a href="#">
      <i class="fa fa-paper-plane fa-1x uk-margin-small-right"></i>Broadcast A
      Message
    </a>
  </li>
</ul>

<ul id="notify" class="uk-switcher uk-margin">
  <li>
    <form name="rap-form" accept-charset="utf-8">
      <input type="hidden" name="step" value="1"/>
      <input type="hidden" name="do" value="dash_notifier"/>
      <div class="uk-block uk-block-default uk-panel-space
             uk-padding-top-remove uk-padding-bottom-remove">
        <div>
          <div class="uk-margin-bottom uk-margin-top uk-text-dark">
            Broadcast a notification message recommending a particular plugin,
            complete with an install/activate button for that plugin.
          </div>
        </div>

        <button class="accordion uk-margin-bottom button-primary" type="button">
            <i class="fa fa-info-circle fa-1x uk-margin-small-right
                 uk-text-primary"></i>
            Recommending A Plugin
        </button>
          <div class="panel uk-accordion-content-background">
            <div class="uk-margin uk-margin-top">
              <p>
                On this page, a plugin can be recommended to all
                <a href="?do=lscwp_manage">discovered WordPress installations</a>
                by providing both the plugin's slug and a dashboard message.
                The following illustrates possible dashboard messages shown to
                WordPress users when recommending a plugin with plugin slug
                'litespeed-cache' with a simple plain text message.
              </p>
              <ol>
                <li class="uk-margin-top">
                  <span>
                    User does not have the 'litespeed-cache' plugin installed
                  </span>
                  <figure class="uk-margin-small uk-margin-small-top">
                    <img src="<?php echo $iconDir; ?>/../images/dash-notify-install.png"
                         alt="recommend_new_plugin_img" class="uk-border-rounded"/>
                  </figure>
                </li>
                <li class="uk-margin-top">
                  <span>
                    User has 'litespeed-cache' plugin installed, but
                    deactivated
                  </span>
                  <figure class="uk-margin-small uk-margin-small-top">
                    <img src="<?php echo $iconDir; ?>/../images/dash-notify-activate.png"
                         alt="recommend_disabled_plugin_img"
                         class="uk-border-rounded" />
                  </figure>
                </li>
                <li class="uk-margin-top">
                  <span>
                    User has 'litespeed-cache' plugin installed and active
                    <br />
                    * No message will be displayed
                  </span>
                </li>
              </ol>
              <h3>Other Info</h3>
              <ul class="uk-list-space">
                <li>
                  WordPress users who click the "Dismiss" button will not be
                  re-notified if the provided dashboard message and plugin slug
                  match those of the dismissed message.
                </li>
                <li>
                  WordPress users who click the "Never Notify Me Again" button
                 will have the Dash Notifier plugin uninstalled and a
                 '.dash_notifier_bypass' file created in their installation's
                 root directory. These users will not be notified of any
                 further messages while this file exists.
                </li>
              </ul>
            </div>
          </div>

        <ul class="uk-grid uk-grid-width-large-1-2 uk-grid-width-medium-1-1
              uk-grid-small">
          <li class="uk-panel uk-panel-space">
            <div class="">
              <span>Plugin Slug</span>
              <span class="far fa-question-circle uk-margin-small-right
                      uk-text-muted"
                    style="font-size: 14px;"
                    title="A plugin's unique identifier. This can be found by finding the plugin's page on wordpress.org/plugins and taking the last part of the URL. For example, the URL for the LiteSpeed Cache plugin for WordPress is wordpress.org/plugins/litespeed-cache, making the plugin slug 'litespeed-cache'."
                    data-uk-tooltip></span>
              <input id="pluginSlug" class="uk-margin-right" type="text"
                     name="notify_slug" size="30" value=""/>
              <button class="nowrap lsws-muted-btn" type="button" name="verify_slug"
                      value="Verify Plugin Slug" title="Verify provided WordPress plugin slug"
                      onclick="javascript:dashVerifySlug(
                                  document.getElementById('pluginSlug').value);">
                Verify
              </button>
              <br />
              <span id="verify-output" class="uk-text-small"></span>
            </div>

            <div>
              <div>
                <span>WordPress Dashboard Message</span>
                <span class="far fa-question-circle uk-text-muted"
                  style="font-size: 14px;"
                  title="Message to be displayed as a Dash Notifier message. Both plain text and HTML are allowed. Newlines will be ignored in plain text."
                  data-uk-tooltip></span>

                <button type="button" class="uk-margin-left uk-button-link"
                        name="clear_msg" value="Clear Current Message"
                        title="Clear current WordPress Dashboard Message"
                        onclick="javascript:clearDashMsg('rap');" data-uk-tooltip>
                  <i class="fa fa-times"
                     style="color: #FF5C85; font-size: 18px;"></i>
                </button>
              </div>
              <div>
                <textarea id="rap-dashMsg" class="uk-margin-small-top" rows="10"
                          name="notify_msg"
                          style="width: 90%; resize: vertical;"></textarea>
              </div>
            </div>
          </li>

          <li class="uk-panel uk-panel-space">
            <div class="uk-margin-bottom">
              <div class="uk-margin-small-right">
              <span>Stored Messages</span>
              <span class="far fa-question-circle uk-text-muted"
                    style="font-size: 14px;"
                    title="Load or delete previously saved dashboard message + plugin slug combinations"
                    data-uk-tooltip></span>
              </div>
              <div>
                <select id="rap-msgIds"
                        style="min-width: 200px;border-color: #bbb;
                          border-radius: 5px;">

                  <?php

                  foreach ( $rapMsgIds as $id ):
                      $safeId = htmlspecialchars($id);

                  ?>

                  <option value ="<?php echo $safeId; ?>">
                    <?php echo $safeId; ?>
                  </option>

                  <?php endforeach; ?>

                </select>
                <span id="savedMsgsBtnsRap">
                  <button type="button" class="nowrap lsws-muted-btn"
                          title="Load the selected version"
                          onclick="javascript:loadSavedDashMsg('rap');">
                    Load
                  </button>
                  <button type="button" class="nowrap lsws-muted-btn"
                          title="Delete the selected version"
                          onclick="javascript:deleteSavedDashMsg('rap');">
                    Delete
                  </button>
                </span>
              </div>
            </div>

            <div class="uk-margin-large-bottom">
                <div class="uk-margin-small-right">
                  <span>Save As</span>
                  <span class="far fa-question-circle uk-text-muted"
                        style="font-size: 14px;"
                        title="Save the entered Dashbaord Message and Plugin Slug combination. Maximum of 50 characters (a-zA-Z0-9_-)."
                        data-uk-tooltip></span>
                </div>
                <div>
                  <input id="rap-saveKey" type="text"
                         name="save_key" value=""/>
                  <button class="nowrap lsws-muted-btn" type="button" name="save_msg"
                          value="Save Message As"
                          title="Save current message with the provided ID"
                          onclick="javascript:saveDashMsg(
                                      document.getElementById('rap-saveKey').value,
                                      'rap');">
                    Save
                  </button>
                </div>
            </div>
          </li>
        </ul>

        <button class="accordion uk-margin-bottom button-primary" type="button">
          <span class="uk-margin-small-left">Testing / Preview</span>
        </button>
        <div class="panel uk-padding-top uk-accordion-content-background"
             style="border-radius: 0 0 5px 5px;">
          <div class="uk-margin uk-margin-top">
            <span>
              Use this option to test enabling/disabling notifications on a
              single WordPress installation by providing it's path.
            </span>
            <br /><br />
            <span class="uk-margin-small-right">
              Specify a WordPress installation path
            </span>
            <input class="uk-margin-right" id="rap-wpPath" type="text" name="wpPath"
                   size="40" value=""/>
            <span id="rap-notifySingleBtn">
              <button class="lsws-primary-btn" type="button" name="notify_single"
                      value="Notify Installation" title="Notify provided WordPress installation"
                      onclick="javascript:dashNotifySingle(
                                  document.getElementById('rap-wpPath').value,
                                  document.getElementById('rap-dashMsg').value
                                  .replace(/^\s+|\s+$/g, ''), 'rap');">
                Deploy / Notify
              </button>
            </span>
            <span id="rap-disableSingleBtn">
              <button class="lsws-primary-btn" type="button" name="disable_single"
                      value="Disable for Installation"
                      title="Disable Dash Notifier for provided WordPress installation"
                      onclick="javascript:dashDisableSingle(
                                  document.getElementById('rap-wpPath').value,
                                  'rap');">
                Remove
              </button>
            </span>
            <br />
          </div>
        </div>

        <div class="uk-block uk-margin-top uk-padding-top uk-padding-bottom">
          <span>
            Discovered WordPress installations
            <a href="?do=lscwp_manage">
              (<b><?php echo $discoveredCnt; ?></b> Discovered
            )</a>
          </span>
          <br /><br />
          <button type="button" name="mass-notify" value="Deploy / Notify All"
                  class="lsws-primary-btn"
                  title="Notify all WordPress installations discovered in 'Manage Cache Installations' using the Dashboard Notifier plugin."
                  onclick="javascript:dashMassActionSubmit(this.name,
                      this.value, 'rap');"
          >
            Mass Deploy / Notify
          </button>

          <button type="button" name="mass-disable-dash-notifier" value="Remove All"
                  class="lsws-primary-btn"
                  title="Disable and remove Dashboard Notifier Wordpress plugin from all WordPress installations discovered in 'Manage Cache Installations'."
                  onclick="javascript:dashMassActionSubmit(this.name,
                      this.value, 'rap');"
          >
            Mass Remove
          </button>
        </div>
      </div>
    </form>
    <hr />
  </li>

  <li>
    <form name="bam-form" accept-charset="utf-8">
      <input type="hidden" name="step" value="1"/>
      <input type="hidden" name="do" value="dash_notifier"/>
      <div class="uk-block uk-block-default uk-panel-space
             uk-padding-top-remove uk-padding-bottom-remove">
        <div>
          <div class="uk-margin-bottom uk-margin-top uk-text-dark">
            Broadcast simple informational messages.
          </div>
        </div>

        <button class="accordion uk-margin-bottom button-primary" type="button">
            <i class="fa fa-info-circle fa-1x uk-margin-small-right
                 uk-text-primary"></i>
              Broadcasting A Message
        </button>
        <div class="panel uk-accordion-content-background">
          <div class="uk-margin uk-margin-top">
            <p>
              On this page, a message can be sent to all
              <a href="?do=lscwp_manage">discovered WordPress installations</a>
              by providing a dashboard message. The following illustrates
              the dashboard messages shown to WordPress users when sending a
              simple plain text message.
            </p>
            <ol>
              <li class="uk-margin-top">
               <figure class="uk-margin-small uk-margin-small-top">
                <img src="<?php echo $iconDir; ?>/../images/dash-notify-simple.png"
                     alt="send_a_message_img" class="uk-border-rounded"/>
               </figure>
              </li>
            </ol>

            <h3>Other Info</h3>
            <ul class="uk-list-space">
              <li>
                WordPress users who click the "Dismiss" button will not be
                re-notified if the provided dashboard message matches that
                of the last dismissed message.
              </li>
              <li>
               WordPress users who click the "Never Notify Me Again" button
               will have the Dash Notifier plugin uninstalled and a
               '.dash_notifier_bypass' file created in their installation's
               root directory. These users will not be notified of any
               further messages while this file exists.
              </li>
            </ul>
          </div>
        </div>

        <ul class="uk-grid uk-grid-width-large-1-2 uk-grid-width-medium-1-1
              uk-grid-small">
          <li class="uk-panel uk-panel-space">
            <div>
              <div>
                <span>WordPress Dashboard Message</span>
                <span class="far fa-question-circle uk-text-muted"
                      style="font-size: 14px;"
                      title="Message to be displayed as a Dash Notifier message. Both plain text and HTML are allowed. Newlines will be ignored in plain text."
                      data-uk-tooltip></span>
                <button class="uk-margin-left uk-button-link" type="button"
                        name="clear_msg" value="Clear Current Message"
                        title="Clear current WordPress Dashboard Message"
                        onclick="javascript:clearDashMsg('bam');" data-uk-tooltip>
                  <i class="fa fa-times"
                     style="color: #FF5C85; font-size: 18px;"></i>
                </button>
              </div>
              <div>
                <textarea id="bam-dashMsg" class="uk-margin-small-top" rows="10"
                          name="notify_msg"
                          style="width: 90%; resize: vertical;"></textarea>
              </div>
            </div>
          </li>

          <li class="uk-panel uk-panel-space">
            <div class="uk-margin-bottom">
              <div class="uk-margin-small-right">
                <span>Stored Messages</span>
                <span class="far fa-question-circle uk-text-muted"
                      style="font-size: 14px;"
                      title="Load or delete previously saved dashboard message + plugin slug combinations"
                      data-uk-tooltip></span>
              </div>
              <div>
                <select id="bam-msgIds"
                        style="min-width: 200px; border-color: #bbb;
                          border-radius: 5px;">

                  <?php

                  foreach ( $bamMsgIds as $id ):
                      $safeId = htmlspecialchars($id);

                  ?>

                  <option value ="<?php echo $safeId; ?>">
                    <?php echo $safeId; ?>
                  </option>

                  <?php endforeach; ?>

                </select>
                <span id="savedMsgsBtnsBam">
                  <button type="button" class="nowrap lsws-muted-btn"
                          title="Load the selected version"
                          onclick="javascript:loadSavedDashMsg('bam');">
                    Load
                  </button>
                  <button type="button" class="nowrap lsws-muted-btn"
                          title="Delete the selected version"
                          onclick="javascript:deleteSavedDashMsg('bam');">
                    Delete
                  </button>
                </span>
              </div>
            </div>

            <div>
              <div class="uk-margin-small-right">
                <span>Save As</span>
                <span class="far fa-question-circle uk-text-muted"
                      style="font-size: 14px;"
                      title="Save the entered Dashbaord Message and Plugin Slug combination. Maximum of 50 characters (a-zA-Z0-9_-)."
                      data-uk-tooltip></span>
              </div>
              <div>
                <input id="bam-saveKey" type="text" name="save_key" value=""/>
                <button class="nowrap lsws-muted-btn" type="button" name="save_msg"
                        value="Save Message As"
                        title="Save current message with the provided ID"
                        onclick="javascript:saveDashMsg(
                                    document.getElementById('bam-saveKey').value,
                                    'bam');">
                  Save
                </button>
              </div>
            </div>
          </li>
        </ul>

        <button class="accordion uk-margin-bottom button-primary" type="button">
          <span class="uk-margin-small-left">Testing / Preview</span>
        </button>
        <div class="panel uk-padding-top uk-accordion-content-background"
             style="border-radius: 0 0 5px 5px;">
          <div class="uk-margin uk-margin-top">
            <span>
              Use this option to test enabling/disabling notifications on a
              single WordPress installation by providing it's path.
            </span>
            <br /><br />
            <span class="uk-margin-small-right">
              Specify a WordPress installation path
            </span>
            <input class="uk-margin-right" id="bam-wpPath" type="text" name="wpPath"
                   size="40" value=""/>
            <span id="bam-notifySingleBtn">
              <button class="lsws-primary-btn" type="button" name="notify_single"
                      value="Notify Installation" title="Notify provided WordPress installation"
                      onclick="javascript:dashNotifySingle(
                                  document.getElementById('bam-wpPath').value,
                                  document.getElementById('bam-dashMsg').value
                                  .replace(/^\s+|\s+$/g, ''), 'bam');">
                Deploy / Notify
              </button>
            </span>
            <span id="bam-disableSingleBtn">
              <button class="lsws-primary-btn" type="button" name="disable_single"
                      value="Disable for Installation"
                      title="Disable Dash Notifier for provided WordPress installation"
                      onclick="javascript:dashDisableSingle(
                                  document.getElementById('bam-wpPath').value,
                                  'bam');">
                Remove
              </button>
            </span>
            <br />
          </div>
        </div>

        <div class="uk-block uk-margin-top uk-padding-top uk-padding-bottom">
          <span>
            Discovered WordPress installations
            <a href="?do=lscwp_manage">
              (<b><?php echo $discoveredCnt; ?></b> Discovered)
            </a>
          </span>
          <br /><br />
          <button type="button" name="mass-notify" value="Deploy / Notify All"
                  class="lsws-primary-btn"
                  title="Notify all WordPress installations discovered in 'Manage Cache Installations' using the Dashboard Notifier plugin."
                  onclick="javascript:dashMassActionSubmit(this.name,
                      this.value, 'bam');"
          >
            Mass Deploy / Notify
          </button>

          <button type="button" name="mass-disable-dash-notifier" value="Remove All"
                  class="lsws-primary-btn"
                  title="Disable and remove Dashboard Notifier Wordpress plugin from all WordPress installations discovered in 'Manage Cache Installations'."
                  onclick="javascript:dashMassActionSubmit(this.name,
                      this.value, 'bam');"
          >
            Mass Remove
          </button>
          <br />
        </div>
      </div>
    </form>
    <hr />
  </li>
</ul>

<?php

$d = array(
    'back' => 'Back'
);
$this->loadTplBlock('ButtonPanelBackNext.tpl', $d);

?>

<script type="text/javascript">lswsInitDropdownBoxes();</script>
webcachemgr/src/View/Tpl/MassDashDisableProgress.tpl000066400000004215150545647710016532 0ustar00<?php

use \Lsc\Wp\View\Model\MassDashDisableProgressViewModel as ViewModel;

$icon = $this->viewModel->getTplData(ViewModel::FLD_ICON);
$installsCount = $this->viewModel->getTplData(ViewModel::FLD_INSTALLS_COUNT);

$d = array(
    'title' => 'Mass Notifying All Discovered WordPress Installations...',
    'icon' => $icon
);
$this->loadTplBlock('Title.tpl', $d);

?>

<div id="progress-box" class="msg-box">
  Attempting to disable Dash Notifier for <span id="currIndex">0</span> out of
  <span id="totalCount"><?php echo $installsCount; ?></span> ...
</div>

<div>
  Currently attempting to disable Dash Notifier for all discovered WordPress
  installations. Installations detected with "Error" status will be bypassed.

  Please be patient.
</div>

<?php

$msgs = array(
    "<span id=\"bypassedCount\"><b>0</b></span> WordPress installation(s) bypassed.",
    "Dash Notifier disabled for <span id=\"succCount\"><b>0</b></span> WordPress installation(s).",
    "Dash Notifier failed to disable for <span id=\"failCount\" class=\"red\"><b>0</b></span> WordPress "
            . "installation(s)."
);

$d = array(
    'msgs' => $msgs,
    'class' => 'msg-info',
);
$this->loadTplBlock('DivMsgBox.tpl', $d);

$d = array(
    'back' => 'OK',
    'backDo' => 'dash_notifier',
    'visibility' => 'hidden'
);
$this->loadTplBlock('ButtonPanelBackNext.tpl', $d);

?>

<button class="accordion accordion-error" type="button" style="display: none">
  Error Messages <span id ="errMsgCnt" class="badge errMsg-badge">0</span>
</button>
<div class="panel panel-error">

<?php

$d = array(
    'id' => 'errMsgs',
    'class' => 'scrollable',
);
$this->loadTplBlock('DivMsgBox.tpl', $d);

?>

</div>

<button class="accordion accordion-success" type="button" style="display: none">
  Success Messages <span id="succMsgCnt" class="badge succMsg-badge">0</span>
</button>
<div class="panel panel-success">

<?php

$d = array(
    'id' => 'succMsgs',
    'class' => 'scrollable',
    'title' => 'Success Messages:',
);
$this->loadTplBlock('DivMsgBox.tpl', $d);

?>

</div>

<script type="text/javascript">lswsInitDropdownBoxes();</script>
<script type="text/javascript">dashMassDisableUpdate();</script>
webcachemgr/src/View/Tpl/RefreshStatusProgress.tpl000066400000002177150545647710016352 0ustar00<?php

use \Lsc\Wp\View\Model\RefreshStatusProgressViewModel as ViewModel;

$icon = $this->viewModel->getTplData(ViewModel::FLD_ICON);
$installCount = $this->viewModel->getTplData(ViewModel::FLD_INSTALLS_COUNT);

$d = array(
    'title' => 'Refreshing Status of WordPress Installations...',
    'icon' => $icon
);
$this->loadTplBlock('Title.tpl', $d);

?>

<div id="progress-box" class="msg-box">
  Refreshing Status for <span id ="currIndex">0</span> out of
  <span id="totalCount"><?php echo $installCount; ?></span> ...
</div>

<?php

$d = array(
    'back' => 'Back',
    'backDo' => 'lscwp_manage',
    'visibility' => 'hidden'
);
$this->loadTplBlock('ButtonPanelBackNext.tpl', $d);

?>

<button class="accordion accordion-error" type="button" style="display: none">
  Error Messages <span id ="errMsgCnt" class="badge errMsg-badge">0</span>
</button>
<div class="panel panel-error">

<?php

$d = array(
    'id' => 'errMsgs',
    'class' => 'scrollable',
);
$this->loadTplBlock('DivMsgBox.tpl', $d);

?>

</div>

<script type="text/javascript">lswsInitDropdownBoxes();</script>
<script type="text/javascript">lscwpRefreshStatusUpdate();</script>webcachemgr/src/View/Tpl/DataFileMsg.tpl000066400000001164150545647710014136 0ustar00<?php

use \Lsc\Wp\View\Model\DataFileMsgViewModel as ViewModel;

$title = $this->viewModel->getTplData(ViewModel::FLD_TITLE);
$discover = $this->viewModel->getTplData(ViewModel::FLD_DISCOVER);

$d = array(
    'title' => $title
);
$this->loadTplBlock('Title.tpl', $d);

?>

<div>
  <p>
    Please go to
    <a href="?do=lscwp_manage" title="Go to Manage Cache Installations">
      Manage Cache Installations
    </a>
    and Scan to <?php echo $discover; ?> all active WordPress installations
    before continuing.
  </p>
</div>

<?php

$d = array(
    'back' => 'Back'
);
$this->loadTplBlock('ButtonPanelBackNext.tpl', $d);
webcachemgr/src/View/Tpl/FlagUnflagAllProgress.tpl000066400000003122150545647710016176 0ustar00<?php

use Lsc\Wp\View\Model\FlagUnflagAllProgressViewModel as ViewModel;

$action       = $this->viewModel->getTplData(ViewModel::FLD_ACTION);
$icon         = $this->viewModel->getTplData(ViewModel::FLD_ICON);
$installCount = $this->viewModel->getTplData(ViewModel::FLD_INSTALLS_COUNT);

$ucAction = ucfirst($action);

/** @noinspection SpellCheckingInspection */
$this->loadTplBlock(
  'Title.tpl',
  [
    'title' => "{$ucAction}ging WordPress Installations...",
    'icon'  => $icon
  ]
);

?>

<div id="progress-box" class="msg-box">
  <?php echo $ucAction; ?>ging <span id ="currIndex">0</span> out of
  <span id="totalCount"><?php echo $installCount; ?></span> ...
</div>

<?php

$this->loadTplBlock(
  'ButtonPanelBackNext.tpl',
  [ 'back' => 'Back', 'backDo' => 'lscwp_manage', 'visibility' => 'hidden' ]
);

?>

<button class="accordion accordion-error" type="button" style="display: none">
  Error Messages <span id ="errMsgCnt" class="badge errMsg-badge">0</span>
</button>
<div class="panel panel-error">

  <?php

  $this->loadTplBlock(
    'DivMsgBox.tpl',
    [ 'id' => 'errMsgs', 'class' => 'scrollable' ]
  );

  ?>

</div>

<button class="accordion accordion-success" type="button" style="display: none">
  Success Messages <span id="succMsgCnt" class="badge succMsg-badge">0</span>
</button>
<div class="panel panel-success">

  <?php

  $this->loadTplBlock(
    'DivMsgBox.tpl',
    [ 'id' => 'succMsgs', 'class' => 'scrollable' ]
  );

  ?>

</div>

<script type="text/javascript">
  lswsInitDropdownBoxes();
  lscwpFlagUnflagAllUpdate(<?php echo ($action == 'unflag') ? '4' : '5'; ?>);
</script>webcachemgr/src/View/Tpl/Blocks/InputSubmitBtn.tpl000066400000001752150545647710016165 0ustar00<?php

/**
 * Expects: $d['name'], $d['value']
 * Optional: $d['class'], $d['title'], $d['confirm'], $d['onclick'],
 *           $d['attributes'], $d['state'], and $d['text']
 */

?>

<button type="submit" name="<?php echo $d['name']; ?>"
        value="<?php echo $d['value']; ?>"

        <?php if ( isset($d['class']) ) : ?>

        class="<?php echo $d['class']; ?>"

        <?php

        endif;

        if ( isset($d['title']) ):

        ?>

        title="<?php echo $d['title']; ?>"

        <?php

        endif;

        if ( isset($d['confirm']) ) :

        ?>

        onclick="return confirm('<?php echo $d['confirm']; ?>')"

        <?php elseif ( isset($d['onclick']) ): ?>

        onclick="return <?php echo $d['onclick']; ?>"

        <?php

        endif;

        echo (isset($d['attributes'])) ? " {$d['attributes']}" : '';

        echo (isset($d['state'])) ? " {$d['state']}" : '';

        ?>
    >
  <?php echo (isset($d['text'])) ? $d['text'] : $d['value']; ?>
</button>
webcachemgr/src/View/Tpl/VersionManage.tpl000066400000014600150545647710014553 0ustar00<input type="hidden" name="act" />
<input type="hidden" name="version_num" />

<?php

use Lsc\Wp\View\Model\VersionManageViewModel as ViewModel;

/** @noinspection DuplicatedCode */
$icon = $this->viewModel->getTplData(ViewModel::FLD_ICON);
$activeVer = $this->viewModel->getTplData(ViewModel::FLD_ACTIVE_VER);
$verList = $this->viewModel->getTplData(ViewModel::FLD_VERSION_LIST);
$allowedList = $this->viewModel->getTplData(ViewModel::FLD_ALLOWED_VER_LIST);
$state = $this->viewModel->getTplData(ViewModel::FLD_STATE);
$errMsgs = $this->viewModel->getTplData(ViewModel::FLD_ERR_MSGS);

$d = array(
    'title' => 'LiteSpeed Cache Plugin Version Manager',
    'icon' => $icon
);
$this->loadTplBlock('Title.tpl', $d);

if ( !empty($errMsgs) ) {
    $d = array(
        'msgs' => $errMsgs,
        'class' => 'msg-error scrollable',
    );
    $this->loadTplBlock('DivMsgBox.tpl', $d);
}

$d = array(
    'title' => '<b>Set Active Version</b>'
);
$this->loadTplBlock('SectionTitle.tpl', $d);

?>

<?php if ( empty($allowedList) ): ?>

<div>
  <p>
    [Feature Disabled] Unable to find/retrieve valid LSCWP version list.
  </p>
</div>

<?php else: ?>

<div>
  <span class="hint">
    Sets the LiteSpeed Cache plugin version to be used in all future "Enable"
    operations. (To ensure stability, there may be a delay before new LiteSpeed
    Cache plugin versions appear in this list)
  </span>
</div>
<br />
<table class="vermgr">
  <tbody>
    <tr>
      <td style="padding-top: 2px;">
        Current Active Version:
        <span style="color: #0066CC;">
          <?php echo ($activeVer) ? htmlspecialchars($activeVer) : 'Not Selected'; ?>
        </span>
      </td>
      <td>
        <label
            for="lscwpActiveSelector"
            style="font-weight: normal; margin-bottom: unset;"
        >
          New Active Version
        </label>
        <select id="lscwpActiveSelector">

          <?php

          foreach ( $allowedList as $ver ):
              $safeVer = htmlspecialchars($ver);

          ?>

          <option value ="<?php echo $safeVer; ?>">
            <?php echo $safeVer; ?>
          </option>

          <?php endforeach; ?>

        </select>
      </td>
      <td id="switchVerBtn">
        <button
            type="button"
            class="nowrap lsws-primary-btn"
            title="Switch LiteSpeed Cache plugin to the version selected"
            onclick="lscwpVermgr('switchTo');"
        >
          Switch Version
        </button>
      </td>
    </tr>
  </tbody>
</table>

<?php endif; ?>

<br />

<?php

$d = array(
    'title' => '<b>Force Version Change For All Existing Installations</b>'
);
$this->loadTplBlock('SectionTitle.tpl', $d);

if ( $state == ViewModel::ST_SCAN_NEEDED ):

?>

<div>
  <p>
    Cache Management list could not be read. Please go to
    <a href="?do=lscwp_manage" title="Go to Manage Cache Installations">
      Manage Cache Installations
    </a>
    and Scan/Re-scan to discover active WordPress installations.
  </p>
</div>

<?php elseif ( $state == ViewModel::ST_NO_NON_ERROR_INSTALLS_DISCOVERED): ?>

<div>
  <p>
    No WordPress installations with a non-error status discovered in the
    previous scan (Installations with a Cache Status of "Error" are not
    counted). If you have any newly installed WordPress installations, please go
    to
    <a href="?do=lscwp_manage" title="Go to Manage Cache Installations">
      Manage Cache Installations
    </a>
    and Re-scan/Discover New.
  </p>
</div>

<?php elseif ( empty($verList) ): ?>

<div>
  <p>
    [Feature Disabled] Unable to find/retrieve valid LSCWP version list.
  </p>
</div>

<?php else: ?>

<div>
  <span class="hint">
    Upgrades active LiteSpeed Cache plugins matching the selection in the
    "From Version" list to the version chosen under "Upgrade To".
    <br />
    Flagged installations will be skipped. (To ensure stability, there may be a
    delay before new LiteSpeed Cache plugin versions appear in this list)
  </span>
</div>

<br /><br />

<table id="lscwp-upgrade-mgr">
  <tbody>
    <tr>
      <td style="margin-top: 9px; vertical-align: top;">From Version(s):</td>
      <td style="text-align: left;">
        <table class="datatable nowrap">
          <thead>
            <tr>
              <th>
                <input
                    type="checkbox"
                    id="fromSelectAll"
                    onClick="selectAll(this)"
                />
                <label
                    for="fromSelectAll"
                    style="font-weight: normal; margin-bottom: unset;"
                >
                  Select All
                </label>
              </th>
            </tr>
          </thead>
          <tbody>

            <?php

            foreach ( $verList as $ver ):
                $safeVer = htmlspecialchars($ver);

            ?>

            <tr>
              <td>
                <span style="width: 20px; display: inline-block;"></span>
                <input
                    type="checkbox"
                    id="from_<?php echo $safeVer; ?>"
                    name="selectedVers[]"
                    value="<?php echo $safeVer; ?>"
                />
                <label
                    for="from_<?php echo $safeVer; ?>"
                    style="font-weight: normal; margin-bottom: unset;"
                >
                  <?php echo $safeVer; ?>
                </label>
              </td>
            </tr>

            <?php endforeach; ?>

          </tbody>
        </table>
      </td>
      <td style="vertical-align: top;">
        <label
            for="lscwpUpgradeSelector"
            style="font-weight: normal; margin-bottom: unset;"
        >
          Upgrade To:
        </label>
        <select id="lscwpUpgradeSelector">

          <?php

          foreach ( $allowedList as $ver ):
              $safeVer = htmlspecialchars($ver);
          ?>

          <option value ="<?php echo $safeVer; ?>">
            <?php echo $safeVer; ?>
          </option>

          <?php endforeach; ?>

        </select>
      </td>
      <td style="vertical-align: top; text-align: center;">
        <button
            type="button" title="Force version change for all matching selections"
            onclick="lscwpVermgr('upgradeTo');"
            class="upgrade-btn lsws-primary-btn"
        >
          Upgrade
        </button>
      </td>
    </tr>
  </tbody>
</table>

<?php

endif;

$d = array(
    'back' => 'Back',
);
$this->loadTplBlock('ButtonPanelBackNext.tpl', $d);
webcachemgr/src/View/Tpl/ScanProgressStep2.tpl000066400000003255150545647710015350 0ustar00<?php

/**
 * @since 1.13.3
 */

use \Lsc\Wp\View\Model\ScanProgressStepViewModel as ViewModel;

$title = $this->viewModel->getTplData(ViewModel::FLD_TITLE);
$icon = $this->viewModel->getTplData(ViewModel::FLD_ICON);
$totalCount = $this->viewModel->getTplData(ViewModel::FLD_TOTAL_COUNT);
$mgrStep = $this->viewModel->getTplData(ViewModel::FLD_MGR_STEP);

$d = array(
    'title' => $title,
    'icon' => $icon
);
$this->loadTplBlock('Title.tpl', $d);

?>

<div id="progress-box" class="msg-box">
    Scanning <span id="currIndex">0</span> out of
    <span id="totalCount"><?php echo $totalCount; ?></span> ...
</div>

<div>
    Currently attempting to refresh status for all WordPress installations found
    in the previous discovery step.
    <br />
    If performing a <b>Scan/Re-scan</b>, all installations will be found and
    added to the Cache Manager list.
    <br />
    If <b>Discovering New</b>, only installations belonging to users not already
    in the Cache Manager list will be discovered.
</div>
<br />

<?php

$d = array(
    'back' => 'Back',
    'backDo' => 'lscwp_manage',
    'visibility' => 'hidden'
);
$this->loadTplBlock('ButtonPanelBackNext.tpl', $d);

?>

<button class="accordion accordion-error" type="button" style="display: none">
    Error Messages <span id ="errMsgCnt" class="badge errMsg-badge">0</span>
</button>
<div class="panel panel-error">

    <?php

    $d = array(
        'id' => 'errMsgs',
        'class' => 'scrollable',
    );
    $this->loadTplBlock('DivMsgBox.tpl', $d);

    ?>

</div>

<script type="text/javascript">lswsInitDropdownBoxes();</script>
<script type="text/javascript">
    lscwpScanProgressStep1Update('<?php echo $mgrStep; ?>');
</script>webcachemgr/src/View/Tpl/ScanProgress.tpl000066400000003475150545647710014436 0ustar00<?php

/**
 * @deprecated 1.13.3  This template file has been deprecated and will be
 *                     removed in a future update. Please use new templates
 *                     ScanProgressStep1.tpl and ScanProgressStep2.tpl instead.
 */

use \Lsc\Wp\View\Model\ScanProgressViewModel as ViewModel;

$title = $this->viewModel->getTplData(ViewModel::FLD_TITLE);
$icon = $this->viewModel->getTplData(ViewModel::FLD_ICON);
$homeDirCount = $this->viewModel->getTplData(ViewModel::FLD_HOME_DIR_COUNT);
$mgrStep = $this->viewModel->getTplData(ViewModel::FLD_MGR_STEP);

$d = array(
    'title' => $title,
    'icon' => $icon
);
$this->loadTplBlock('Title.tpl', $d);

?>

<div id="progress-box" class="msg-box">
  Scanning <span id="currIndex">0</span> out of
  <span id="totalCount"><?php echo $homeDirCount; ?></span> ...
</div>

<div>
  Currently scanning for all WordPress Installations located under a
  /public_html/ directory.
  <br />
  If performing a <b>Scan/Re-scan</b>, all installations will be found and
  added to the Cache Manager list.
  <br />
  If <b>Discovering New</b>, only installations belonging to users not already
  in the Cache Manager list will be discovered.
</div>
<br />

<?php

$d = array(
    'back' => 'Back',
    'backDo' => 'lscwp_manage',
    'visibility' => 'hidden'
);
$this->loadTplBlock('ButtonPanelBackNext.tpl', $d);

?>

<button class="accordion accordion-error" type="button" style="display: none">
  Error Messages <span id ="errMsgCnt" class="badge errMsg-badge">0</span>
</button>
<div class="panel panel-error">

<?php

$d = array(
    'id' => 'errMsgs',
    'class' => 'scrollable',
);
$this->loadTplBlock('DivMsgBox.tpl', $d);

?>

</div>

<script type="text/javascript">lswsInitDropdownBoxes();</script>
<script type="text/javascript">
    lscwpScanProgressUpdate('<?php echo $mgrStep; ?>');
</script>webcachemgr/src/View/Tpl/MassEnableDisableProgress.tpl000066400000005252150545647710017043 0ustar00<?php

use \Lsc\Wp\View\Model\MassEnableDisableProgressViewModel as ViewModel;

$icon = $this->viewModel->getTplData(ViewModel::FLD_ICON);
$action = $this->viewModel->getTplData(ViewModel::FLD_ACTION);
$installsCount = $this->viewModel->getTplData(ViewModel::FLD_INSTALLS_COUNT);
$activeVer = $this->viewModel->getTplData(ViewModel::FLD_ACTIVE_VER);

$actionUpper = ucfirst($action);

$d = array(
    'title' => 'Mass ' . substr($actionUpper, 0, -1) . 'ing All LiteSpeed Cache Plugins...',
    'icon' => $icon
);
$this->loadTplBlock('Title.tpl', $d);

if ( $action == 'enable' && $activeVer == false ):

?>

<div>
  No active LSCWP version set! Mass Enable aborted.
</div>

<?php

$d = array(
    'back' => 'OK'
);
$this->loadTplBlock('ButtonPanelBackNext.tpl', $d);

else:

?>

<div id="progress-box" class="msg-box">
  Attempting to <?php echo $action; ?> <span id="currIndex">0</span> out of
  <span id="totalCount"><?php echo $installsCount; ?></span> ...
</div>

<div>
  Currently attempting to <?php echo $action; ?> all LiteSpeed Cache
  plugin installations.

  <?php if ( $action == 'enable' ) : ?>

  If the LiteSpeed Cache Plugin is not installed, version
  <b><?php echo htmlspecialchars($activeVer); ?></b> will be used.

  <?php endif; ?>

  Please be patient.
</div>

<?php

$msgs = array(
    "<span id=\"bypassedCount\"><b>0</b></span> flagged/error WordPress installation(s) bypassed.",
    "LSCWP newly {$action}d for <span id=\"succCount\"><b>0</b></span> WordPress installation(s).",
    "LSCWP {$action} failed for <span id=\"failCount\" class=\"red\"><b>0</b></span> WordPress "
    . "installation(s)."
);

$d = array(
    'msgs' => $msgs,
    'class' => 'msg-info',
);
$this->loadTplBlock('DivMsgBox.tpl', $d);

$d = array(
    'back' => 'OK',
    'visibility' => 'hidden'
);
$this->loadTplBlock('ButtonPanelBackNext.tpl', $d);

?>

<button class="accordion accordion-error" type="button" style="display: none">
  Error Messages <span id ="errMsgCnt" class="badge errMsg-badge">0</span>
</button>
<div class="panel panel-error">

<?php

$d = array(
    'id' => 'errMsgs',
    'class' => 'scrollable',
);
$this->loadTplBlock('DivMsgBox.tpl', $d);

?>

</div>

<button class="accordion accordion-success" type="button" style="display: none">
  Success Messages <span id="succMsgCnt" class="badge succMsg-badge">0</span>
</button>
<div class="panel panel-success">

<?php

$d = array(
    'id' => 'succMsgs',
    'class' => 'scrollable',
    'title' => 'Success Messages:',
);
$this->loadTplBlock('DivMsgBox.tpl', $d);

?>
  
</div>

<script type="text/javascript">lswsInitDropdownBoxes();</script>
<script type="text/javascript">
  lscwpEnableDisableUpdate('<?php echo $action; ?>');
</script>

<?php endif;webcachemgr/src/View/Tpl/MissingTpl.tpl000066400000000261150545647710014104 0ustar00<?php

use \Lsc\Wp\View\Model\MissingTplViewModel as ViewModel;

$msg = $this->viewModel->getTplData(ViewModel::FLD_MSG);

?>

<div>
  <p>
    <?php echo $msg; ?>
  </p>
</div>
webcachemgr/src/View/Tpl/CacheRootNotSet.tpl000066400000000633150545647710015022 0ustar00<?php

$d = array(
    'title' => 'Cache Root Not Set',
);
$this->loadTplBlock('Title.tpl', $d);

?>

<div>
  <p>
    Server and/or Virtual Host cache root has not yet been set. Please go to
    <a href="?do=cacheRootSetup" title="Go to Cache Root Setup">Cache Root Setup</a>
    and set these first.
  </p>
</div>

<?php

$d = array(
    'back' => 'Back'
);
$this->loadTplBlock('ButtonPanelBackNext.tpl', $d);
webcachemgr/src/View/Tpl/Ajax/CacheMgrFlagCol.tpl000066400000001314150545647710015577 0ustar00<?php

use Lsc\Wp\View\Model\Ajax\CacheMgrRowViewModel as ViewModel;

$listData = $this->viewModel->getTplData(ViewModel::FLD_LIST_DATA);

$classes = 'icon-btn';

foreach ( $listData as $path => $info ):
    $flagData = $info['flagData'];

?>

<td align="center"
    data-search="<?php echo ($flagData['sort'] == 'flagged') ? 'f' : 'u'; ?>"
    data-sort="<?php echo $flagData['sort']; ?>">
  <button type="button" value="<?php echo $path; ?>"
          class="<?php echo $classes; ?>"
          title="<?php echo $flagData['btn_title']; ?>"
          <?php echo $flagData['onclick']?>
          <?php echo $flagData['btn_attributes']; ?>
  >
    <?php echo $flagData['icon']; ?>
  </button>
</td>

<?php endforeach;webcachemgr/src/View/Tpl/Ajax/CacheMgrActionsCol.tpl000066400000002433150545647710016331 0ustar00<?php

use Lsc\Wp\View\Model\Ajax\CacheMgrRowViewModel as ViewModel;

$listData = $this->viewModel->getTplData(ViewModel::FLD_LIST_DATA);

$classes = 'icon-btn';

foreach ( $listData as $path => $info ):
    $statusData = $info['statusData'];

?>

<td align="center">
  <span class="action-btns">
    <button type="button" value="<?php echo $path; ?>"
            class="<?php echo $classes; ?>"
            title="<?php echo $statusData['btn_title']; ?>"
            <?php echo ($statusData['onclick']) ? $statusData['onclick'] : ''; ?>
            <?php echo $statusData['btn_attributes']; ?>
            <?php echo $statusData['btn_state']; ?>
    >
      <?php echo $statusData['btn_content']; ?>
    </button>

    <?php if ( $statusData['sort'] == 'removed' ) : ?>

    <button type="button" value="<?php echo $path; ?>"
            class="<?php echo $classes; ?>"
    >
      <span class="inactive-refresh-btn"></span>
    </button>

    <?php else: ?>

    <button type="button" value="<?php echo $path; ?>"
            class="<?php echo $classes; ?>"
            title="Click to refresh status"
            onclick="javascript:lscwpRefreshSingle(this);"
            data-uk-tooltip
    >
      <span class="refresh_btn"></span>
    </button>

    <?php endif; ?>

  </span>
</td>

<?php endforeach;webcachemgr/src/View/Tpl/Ajax/CacheMgrStatusCol.tpl000066400000000776150545647710016224 0ustar00<?php

use Lsc\Wp\View\Model\Ajax\CacheMgrRowViewModel as ViewModel;

$listData = $this->viewModel->getTplData(ViewModel::FLD_LIST_DATA);

foreach ( $listData as $path => $info ):
    $statusData = $info['statusData'];

?>

<td align="center" data-search="<?php echo $statusData['sort']; ?>"
    data-sort="<?php echo $statusData['sort']; ?>">
  <?php echo $statusData['state']; ?>
  <a class="msg-alert" href="#display-msgs" data-uk-tooltip
    title="Click to go to messages">
  </a>
</td>

<?php endforeach;webcachemgr/src/View/Tpl/Manage.tpl000066400000033254150545647710013213 0ustar00<?php

use Lsc\Wp\View\Model\ManageViewModel as ViewModel;

$iconDir     = $this->viewModel->getTplData(ViewModel::FLD_ICON_DIR);
$scanBtnName = $this->viewModel->getTplData(ViewModel::FLD_SCAN_BTN_NAME);
$btnState    = $this->viewModel->getTplData(ViewModel::FLD_BTN_STATE);
$activeVer   = $this->viewModel->getTplData(ViewModel::FLD_ACTIVE_VER);
$listData    = $this->viewModel->getTplData(ViewModel::FLD_LIST_DATA);
$countData   = $this->viewModel->getTplData(ViewModel::FLD_COUNT_DATA);
$showList    = $this->viewModel->getTplData(ViewModel::FLD_SHOW_LIST);
$warnMsgs    = $this->viewModel->getTplData(ViewModel::FLD_WARN_MSGS);
$infoMsgs    = $this->viewModel->getTplData(ViewModel::FLD_INFO_MSGS);
$errMsgs     = $this->viewModel->getTplData(ViewModel::FLD_ERR_MSGS);
$succMsgs    = $this->viewModel->getTplData(ViewModel::FLD_SUCC_MSGS);

?>

<div id="manager">

  <?php

  $this->loadTplBlock(
    'Title.tpl',
    [
      'title' => 'Manage All LiteSpeed Cache for WordPress Installations',
      'icon'  => "$iconDir/manageCacheInstallations.svg"
    ]
  );

  ?>

  <div id="display-msgs">

    <?php

    if ( !empty($warnMsgs) ) {
      $this->loadTplBlock(
        'DivMsgBox.tpl',
        [ 'msgs' => $warnMsgs, 'class' => 'msg-warn' ]
      );
    }

    if ( !empty($infoMsgs) ) {
      $this->loadTplBlock(
        'DivMsgBox.tpl',
        [ 'msgs' => $infoMsgs, 'class' => 'msg-info' ]
      );
    }

    $errMsgCnt  = count($errMsgs);
    $succMsgCnt = count($succMsgs);

    ?>

    <button
        class="accordion accordion-error"
        type="button"
        style="display: <?php echo ($errMsgCnt > 0) ? 'initial' : 'none'; ?>"
    >
      Error Messages
      <span id ="errMsgCnt" class="badge errMsg-badge">
        <?php echo $errMsgCnt; ?>
      </span>
    </button>
    <div class="panel panel-error">

      <?php

      $this->loadTplBlock(
        'DivMsgBox.tpl',
        [ 'id' => 'errMsgs', 'msgs' => $errMsgs, 'class' => 'scrollable' ]
      );

      ?>

    </div>

    <button
        class="accordion accordion-success"
        type="button"
        style="display: <?php echo ($succMsgCnt > 0) ? 'initial' : 'none'; ?>"
    >
      Success Messages
      <span id="succMsgCnt" class="badge succMsg-badge">
        <?php echo $succMsgCnt; ?>
      </span>
    </button>
    <div class="panel panel-success">

      <?php

      $this->loadTplBlock(
        'DivMsgBox.tpl',
        [ 'id' => 'succMsgs', 'msgs' => $succMsgs, 'class' => 'scrollable' ]
      );

      ?>

    </div>
  </div>

  <div align="left" >

    <?php

    $classes  = '';
    $addClass = 'lsws-primary-btn';

    $this->loadTplBlock(
      'InputSubmitBtn.tpl',
      [
        'name'    => 're-scan',
        'value'   => $scanBtnName,
        'title'   => 'Scan filesystem for WordPress installations',
        'confirm' => "$scanBtnName will scan your filesystem for WordPress "
          . 'installations. This may take up to a few minutes to complete. '
          . "$scanBtnName now?",
        'class'   => "$classes $addClass"
      ],
      true
    );

    if ( $btnState == 'disabled' ) {
      $addClass = 'disabled-btn';
    }

    $this->loadTplBlock(
      'InputSubmitBtn.tpl',
      [
        'name'    => 'scan_more',
        'value'   => 'Discover New',
        'title'   => 'Discover new WordPress installations since the last scan',
        'confirm' => 'Discover new  WordPress installations since the last '
          . 'scan. This will not update information for existing '
          . 'installations. This may take up to a few minutes to complete. '
          . 'Continue?',
        'state'   => $btnState,
        'class'   => "$classes $addClass",
      ],
      true
    );

    $this->loadTplBlock(
      'InputSubmitBtn.tpl',
      [
        'name'    => 'refresh_status',
        'value'   => 'Refresh Status',
        'title'   => 'Check the cache status for all WordPress installations '
          . 'currently listed',
        'confirm' => 'Refresh Status will check the cache status for all '
          . 'WordPress installations currently listed. If you have many '
          . 'installations, this may take up to a few minutes to complete. '
          . 'Refresh Status now?',
        'state'   => $btnState,
        'class'   => "$classes $addClass",
      ],
      true
    );

    $this->loadTplBlock(
      'InputSubmitBtn.tpl',
      [
        'name'    => 'mass_flag',
        'value'   => 'Flag All',
        'title'   => 'Flag all currently discovered installations',
        'confirm' => 'Flag all currently discovered installations?',
        'state'   => $btnState,
        'class'   => "$classes $addClass",
      ],
      true
    );

    $this->loadTplBlock(
      'InputSubmitBtn.tpl',
      [
        'name'    => 'mass_unflag',
        'value'   => 'Unflag All',
        'title'   => 'Unflag all currently discovered installations',
        'confirm' => 'Unflag all currently discovered installations?',
        'state'   => $btnState,
        'class'   => "$classes $addClass",
      ],
      true
    );

    ?>

  </div>

  <div align="left" class="pad-bottom-small">

    <?php

    $classes = 'lsws-secondary-btn';

    if ( !$activeVer ) {
      $dTitle = '[Feature Disabled] No active LSCWP version set!';
      $dState = 'disabled';
    }
    else {
      $dTitle = 'Enable cache for all selected WordPress installations (Ignores Flag)';
      $dState = $btnState;
    }

    if ( $btnState == 'disabled' ) {
      $classes  = 'disabled-btn';
      $dClasses = $classes;
    }
    else {
      $dClasses = ($dState != 'disabled') ? $classes : 'disabled-btn';
    }

    ob_start();

    ?>

    With Selected:
    <button
        type="button"
        name="enable_sel"
        value="Enable Selected"
        class="<?php echo $dClasses; ?>"
        title="<?php echo $dTitle; ?>"
        onclick="lscwpValidateSelectFormSubmit(this.name, this.value);"
        <?php echo $dState; ?>
    >
      Enable
    </button>
    <button
        type="button"
        name="disable_sel"
        value="Disable Selected"
        class="<?php echo $classes; ?>"
        title="Disable cache for all selected WordPress installations (Ignores Flag)"
        onclick="lscwpValidateSelectFormSubmit(this.name, this.value);"
        <?php echo $btnState; ?>
    >
      Disable
    </button>
    <button
        type="button"
        name="flag_sel"
        value="Flag Selected"
        class="<?php echo $classes; ?>"
        title="Flag all selected WordPress installations"
        onclick="lscwpValidateSelectFormSubmit(this.name, this.value);"
        <?php echo $btnState; ?>
    >
      Flag
    </button>
    <button
        type="button"
        name="unflag_sel"
        value="Unflag Selected"
        class="<?php echo $classes; ?>"
        title="Unflag all selected WordPress installations"
        onclick="lscwpValidateSelectFormSubmit(this.name, this.value);"
        <?php echo $btnState; ?>
    >
      Unflag
    </button>

    <?php

    $btn_row = ob_get_clean();

    echo $btn_row;

    ?>

  </div>

  <table class="plugin-ver">
    <tbody>
      <tr>
        <td align="right">
          LiteSpeed Cache Plugin Version:
          <a href="?do=lscwpVersionManager" title="Go to Version Manager">
            <?php echo ($activeVer) ? htmlspecialchars($activeVer) : 'Not Set'; ?>
          </a>
        </td>
      </tr>
    </tbody>
  </table>
  <br/>
  <div id="mask-container">
    <div id="hover-mask">
      <svg
          version="1.1"
          id="L9"
          xmlns="http://www.w3.org/2000/svg"
          xmlns:xlink="http://www.w3.org/1999/xlink"
          x="0px"
          y="0px"
          viewBox="0 0 100 100"
          enable-background="new 0 0 0 0"
          xml:space="preserve"
      >
        <path
            fill="#fff"
            d="M73,50c0-12.7-10.3-23-23-23S27,37.3,27,50
              M30.9,50c0-10.5,8.5-19.1,19.1-19.1S69.1,39.5,69.1,50"
        >
          <animateTransform
              attributeName="transform"
              attributeType="XML"
              type="rotate"
              dur="1s"
              from="0 50 50"
              to="360 50 50"
              repeatCount="indefinite"
          />
        </path>
      </svg>
    </div>

    <table id="lsws-data-table" class="datatable cachemgr hover">
      <thead>
        <tr>

          <?php

          $discoveredCnt = $countData[ViewModel::COUNT_DATA_INSTALLS];
          $enabledCnt    = $countData[ViewModel::COUNT_DATA_ENABLED];
          $warnCnt       = $countData[ViewModel::COUNT_DATA_WARN];
          $errCnt        = $countData[ViewModel::COUNT_DATA_ERROR];
          $flagCnt       = $countData[ViewModel::COUNT_DATA_FLAGGED];

          ?>

          <th width="20px"></th>
          <th>
            Discovered WordPress Installations
            <span
                id="total-badge"
                class="badge primary-badge"
                data-uk-tooltip
                title="<?php echo $discoveredCnt; ?> installations discovered"
            >
              <?php echo $countData[ViewModel::COUNT_DATA_INSTALLS]; ?>
            </span>
            |
            <span
                id="enabled-badge"
                class="badge"
                data-uk-tooltip
                title="LSCWP is enabled for <?php echo $enabledCnt; ?> installations"
            >
              <?php echo $countData[ViewModel::COUNT_DATA_ENABLED]; ?>
            </span>
            <span
                id="warning-badge"
                class="badge"
                data-uk-tooltip
                title="LSCWP partially enabled for <?php echo $warnCnt; ?> installations"
            >
              <?php echo $countData[ViewModel::COUNT_DATA_WARN]; ?>
            </span>
            <span
                id="error-badge"
                class="badge"
                data-uk-tooltip
                title="<?php echo $errCnt; ?> installations encountered a fatal error"
            >
              <?php echo $countData[ViewModel::COUNT_DATA_ERROR]; ?>
            </span>
          </th>
          <th class="action-th">Actions</th>
          <th>
            Cache Status
          </th>
          <th>
            Flag
            <span
                id="flagged-badge"
                class="badge"
                data-uk-tooltip
                title="<?php echo $flagCnt; ?> installations flagged (excluded from mass operations)"
            >
              <?php echo $countData[ViewModel::COUNT_DATA_FLAGGED]; ?>
            </span>
          </th>
        </tr>
      </thead>
      <tfoot>
        <tr>
          <th></th>
          <th></th>
          <th></th>
          <th></th>
          <th></th>
        </tr>
      </tfoot>
      <tbody>

        <?php

        if ( $showList ) :
          $classes = 'icon-btn';

          foreach ( $listData as $path => $info ):
            $statusData = $info['statusData'];
            $flagData   = $info['flagData'];
            $siteUrl    = $info['siteUrl'];
            $safePath   = htmlspecialchars($path);

        ?>

        <tr>
          <td>
            <input
                type="checkbox"
                name="installations[]"
                value="<?php echo $path; ?>"
                onclick="lscwpManageCheckboxSelect(this);"
            />
          </td>
          <td class="path-box">
            <?php echo htmlspecialchars($siteUrl); ?>
            <br />
            <small class="install-path"><?php echo $safePath; ?></small>
          </td>
          <td align="center">
            <span class="action-btns">
              <button
                  type="button"
                  value="<?php echo $path; ?>"
                  class="<?php echo $classes; ?>"
                  title="<?php echo $statusData['btn_title']; ?>"
                  <?php echo ($statusData['onclick']) ?: ''; ?>
                  <?php echo $statusData['btn_attributes']; ?>
                  <?php echo $statusData['btn_state']; ?>
              >
                <?php echo $statusData['btn_content']; ?>
              </button>
              <button
                  type="button"
                  value="<?php echo $path; ?>"
                  class="<?php echo $classes; ?>"
                  title="Click to refresh status"
                  onclick="lscwpRefreshSingle(this);"
                  data-uk-tooltip
              >
                <span class="refresh_btn"></span>
              </button>
            </span>
          </td>
          <td
              align="center"
              data-search="<?php echo $statusData['sort']; ?>"
              data-sort="<?php echo $statusData['sort']; ?>"
          >
            <?php echo $statusData['state']; ?>
            <a
                class="msg-alert"
                href="#display-msgs"
                data-uk-tooltip
                title="Click to go to messages"
            >
            </a>
          </td>
          <td
              align="center"
              data-search="<?php echo ($flagData['sort'] == 'flagged') ? 'f' : 'u'; ?>"
              data-sort="<?php echo $flagData['sort']; ?>"
          >
            <button
                type="button"
                value="<?php echo $path; ?>"
                class="<?php echo $classes; ?>"
                title="<?php echo $flagData['btn_title']; ?>"
                <?php echo $flagData['onclick']?>
                <?php echo $flagData['btn_attributes']; ?>
            >
              <?php echo $flagData['icon']; ?>
            </button>
          </td>
        </tr>

        <?php

          endforeach;
        endif;

        ?>

      </tbody>
    </table>
  </div>

  <?php echo $btn_row; ?>

  <br /><br />
  <div>
    <small>
      *Flagging an installation will cause it to be excluded from
      Mass Enable/Disable operations.
    </small>
  </div>
  <br />
</div>
<script type="text/javascript">
  lswsInitDropdownBoxes();
  lswsInitDataTable();
</script>webcachemgr/src/View/Tpl/MassDashNotifyProgress.tpl000066400000004202150545647710016433 0ustar00<?php

use \Lsc\Wp\View\Model\MassDashNotifyProgressViewModel as ViewModel;

$icon = $this->viewModel->getTplData(ViewModel::FLD_ICON);
$installsCount = $this->viewModel->getTplData(ViewModel::FLD_INSTALLS_COUNT);

$d = array(
    'title' => 'Mass Notifying All Discovered WordPress Installations...',
    'icon' => $icon
);
$this->loadTplBlock('Title.tpl', $d);

?>

<div id="progress-box" class="msg-box">
  Attempting to notify <span id="currIndex">0</span> out of
  <span id="totalCount"><?php echo $installsCount; ?></span> ...
</div>

<div>
  Currently attempting to notify all discovered WordPress installations.
  Installations detected with "Error" status or containing a
  '.dash_notifier_bypass' file will be bypassed.

  Please be patient.
</div>

<?php

$msgs = array(
    "<span id=\"bypassedCount\"><b>0</b></span> WordPress installation(s) bypassed.",
    "Dash Notifier notified <span id=\"succCount\"><b>0</b></span> WordPress installation(s).",
    "Dash Notifier failed to notify <span id=\"failCount\" class=\"red\"><b>0</b></span> WordPress "
    . "installation(s)."
);

$d = array(
    'msgs' => $msgs,
    'class' => 'msg-info',
);
$this->loadTplBlock('DivMsgBox.tpl', $d);

$d = array(
    'back' => 'OK',
    'backDo' => 'dash_notifier',
    'visibility' => 'hidden'
);
$this->loadTplBlock('ButtonPanelBackNext.tpl', $d);

?>

<button class="accordion accordion-error" type="button" style="display: none">
  Error Messages <span id ="errMsgCnt" class="badge errMsg-badge">0</span>
</button>
<div class="panel panel-error">

<?php

$d = array(
    'id' => 'errMsgs',
    'class' => 'scrollable',
);
$this->loadTplBlock('DivMsgBox.tpl', $d);

?>

</div>

<button class="accordion accordion-success" type="button" style="display: none">
  Success Messages <span id="succMsgCnt" class="badge succMsg-badge">0</span>
</button>
<div class="panel panel-success">

<?php

$d = array(
    'id' => 'succMsgs',
    'class' => 'scrollable',
    'title' => 'Success Messages:',
);
$this->loadTplBlock('DivMsgBox.tpl', $d);

?>

</div>

<script type="text/javascript">lswsInitDropdownBoxes();</script>
<script type="text/javascript">dashMassNotifyUpdate();</script>webcachemgr/src/View/Tpl/ScanProgressStep1.tpl000066400000003205150545647710015342 0ustar00<?php

/**
 * @since 1.13.3
 */

use \Lsc\Wp\View\Model\ScanProgressStepViewModel as ViewModel;

$title = $this->viewModel->getTplData(ViewModel::FLD_TITLE);
$icon = $this->viewModel->getTplData(ViewModel::FLD_ICON);
$totalCount = $this->viewModel->getTplData(ViewModel::FLD_TOTAL_COUNT);
$mgrStep = $this->viewModel->getTplData(ViewModel::FLD_MGR_STEP);

$d = array(
    'title' => $title,
    'icon' => $icon
);
$this->loadTplBlock('Title.tpl', $d);

?>

<div id="progress-box" class="msg-box">
    Scanning <span id="currIndex">0</span> out of
    <span id="totalCount"><?php echo $totalCount; ?></span> ...
</div>

<div>
    Currently scanning known document roots for all WordPress Installations.
    <br />
    If performing a <b>Scan/Re-scan</b>, all installations will be found and
    added to the Cache Manager list.
    <br />
    If <b>Discovering New</b>, only installations belonging to users not already
    in the Cache Manager list will be discovered.
</div>
<br />

<?php

$d = array(
    'back' => 'Back',
    'backDo' => 'lscwp_manage',
    'visibility' => 'hidden'
);
$this->loadTplBlock('ButtonPanelBackNext.tpl', $d);

?>

<button class="accordion accordion-error" type="button" style="display: none">
    Error Messages <span id ="errMsgCnt" class="badge errMsg-badge">0</span>
</button>
<div class="panel panel-error">

    <?php

    $d = array(
        'id' => 'errMsgs',
        'class' => 'scrollable',
    );
    $this->loadTplBlock('DivMsgBox.tpl', $d);

    ?>

</div>

<script type="text/javascript">lswsInitDropdownBoxes();</script>
<script type="text/javascript">
    lscwpScanProgressStep1Update('<?php echo $mgrStep; ?>');
</script>webcachemgr/src/View/Tpl/UnflagAllProgress.tpl000066400000002660150545647710015412 0ustar00<?php

use \Lsc\Wp\View\Model\UnflagAllProgressViewModel as ViewModel;

$icon = $this->viewModel->getTplData(ViewModel::FLD_ICON);
$installCount = $this->viewModel->getTplData(ViewModel::FLD_INSTALLS_COUNT);

$d = array(
    'title' => 'Unflagging WordPress Installations...',
    'icon' => $icon
);
$this->loadTplBlock('Title.tpl', $d);

?>

<div id="progress-box" class="msg-box">
  Unflagging <span id ="currIndex">0</span> out of
  <span id="totalCount"><?php echo $installCount; ?></span> ...
</div>

<?php

$d = array(
    'back' => 'Back',
    'backDo' => 'lscwp_manage',
    'visibility' => 'hidden'
);
$this->loadTplBlock('ButtonPanelBackNext.tpl', $d);

?>

<button class="accordion accordion-error" type="button" style="display: none">
  Error Messages <span id ="errMsgCnt" class="badge errMsg-badge">0</span>
</button>
<div class="panel panel-error">

<?php

$d = array(
    'id' => 'errMsgs',
    'class' => 'scrollable',
);
$this->loadTplBlock('DivMsgBox.tpl', $d);

?>

</div>

<button class="accordion accordion-success" type="button" style="display: none">
  Success Messages <span id="succMsgCnt" class="badge succMsg-badge">0</span>
</button>
<div class="panel panel-success">

<?php

$d = array(
    'id' => 'succMsgs',
    'class' => 'scrollable',
);
$this->loadTplBlock('DivMsgBox.tpl', $d);

?>

</div>

<script type="text/javascript">lswsInitDropdownBoxes();</script>
<script type="text/javascript">lscwpUnflagAllUpdate();</script>webcachemgr/src/View/Tpl/MassEnableDisable.tpl000066400000005566150545647710015326 0ustar00<input type="hidden" name="act" />

<?php

use \Lsc\Wp\View\Model\MassEnableDisableViewModel as ViewModel;

$icon = $this->viewModel->getTplData(ViewModel::FLD_ICON);
$activeVer = $this->viewModel->getTplData(ViewModel::FLD_ACTIVE_VER);
$state = $this->viewModel->getTplData(ViewModel::FLD_STATE);

$d = array(
    'title' => 'Mass Enable/Disable LiteSpeed Cache',
    'icon' => $icon
);
$this->loadTplBlock('Title.tpl', $d);

if ( $state == ViewModel::ST_INSTALLS_DISCOVERED ):

?>

<p>
  The following operations will affect all WordPress installations not currently
  flagged.
</p>

<p>
  To exclude a WordPress installation from mass operations, flag it in
  <a href="?do=lscwp_manage" title="Go to Manage Cache Installations">
    Manage Cache Installations
  </a>
  .
</p>

<br />

<fieldset class="mass-box">
  <legend><b>Mass Enable</b></legend>

  <?php if ( $activeVer == false ): ?>

  <div>
    [Feature Disabled] No active LSCWP version set! Cannot Mass Enable.

    <br /><br />

  </div>

  <?php else: ?>

  <div>
    LiteSpeed Cache will be enabled for all WordPress installations not
    currently flagged. For WordPress installations that do not already have
    the plugin,
    <b>
      LiteSpeed Cache for WordPress <?php echo htmlspecialchars($activeVer); ?>
      will be installed.
    </b>
    This can be changed anytime in the
    <a href="?do=lscwpVersionManager" title="Go to Version Manager">Version Manager</a>.

    <br /><br />

    <button class="lsws-primary-btn" type="button"
            title="Mass Enable LiteSpeed Cache for all unflagged installations."
            onclick="javascript:actionset('enable');">
      Start
    </button>
  </div>

  <?php endif; ?>

</fieldset>

<br /><br />

<fieldset class="mass-box">
  <legend><b>Mass Disable</b></legend>
  <div>
    LiteSpeed Cache will be disabled for all WordPress installations not
    currently flagged.

    <br /><br />

    <button class="lsws-primary-btn" type="button"
            title="Mass Disable LiteSpeed Cache for all unflagged installations."
            onclick="javascript:actionset('disable');">
      Start
    </button>
  </div>
</fieldset>

<?php elseif ( $state == ViewModel::ST_NO_INSTALLS_DISCOVERED ): ?>

<div>
  <p>
    No WordPress installations discovered in the previous scan. If you have
    any newly installed WordPress installations, please go to
    <a href="?do=lscwp_manage" title="Go to Manage Cache Installations">
      Manage Cache Installations
    </a>
    and Re-scan/Discover New.
  </p>
</div>

<?php else: ?>

<div>
  <p>
    Please go to
    <a href="?do=lscwp_manage" title="Go to Manage Cache Installations">
      Manage Cache Installations
    </a>
    and click Scan to discover all active WordPress installations before
    attempting to Mass Enable/Disable Cache.
  </p>
</div>

<?php

endif;

$d = array(
    'back' => 'Back'
);
$this->loadTplBlock('ButtonPanelBackNext.tpl', $d);
webcachemgr/src/View/AjaxView.php000066400000003036150545647710012765 0ustar00<?php

/** ******************************************
 * LiteSpeed Web Server Cache Manager
 *
 * @author  LiteSpeed Technologies, Inc. (https://www.litespeedtech.com)
 * @copyright  (c) 2018-2020
 * ******************************************* */

namespace Lsc\Wp\View;

use \Lsc\Wp\LSCMException;

class AjaxView
{

    /**
     * @var object
     */
    private $viewModel;

    /**
     * @var string
     */
    private $sharedTplDir = __DIR__;

    /**
     *
     * @param object  $viewModel
     */
    public function __construct( $viewModel )
    {
        $this->viewModel = $viewModel;
    }

    /**
     *
     * @param string  $tplID
     * @return string
     * @throws LSCMException  Thrown directly and indirectly.
     */
    public function getAjaxContent( $tplID = '' )
    {
        ob_start();
        try
        {
            $this->loadAjaxTpl($this->viewModel->getTpl($tplID));
        }
        catch ( LSCMException $e )
        {
            ob_clean();
            throw $e;
        }

        return ob_get_clean();
    }

    /**
     *
     * @param string  $tplPath
     * @throws LSCMException
     */
    private function loadAjaxTpl( $tplPath )
    {
        $tplFile = basename($tplPath);
        $custTpl = "{$this->sharedTplDir}/Cust/{$tplFile}";

        if ( file_exists($custTpl) ) {
            include $custTpl;
        }
        elseif ( file_exists($tplPath) ) {
            include $tplPath;
        }
        else {
            throw new LSCMException("Could not load ajax template {$tplPath}.");
        }
    }

}
webcachemgr/src/View/Model/DashNotifierViewModel.php000066400000005105150545647710016501 0ustar00<?php

/* * ******************************************
 * LiteSpeed Web Server Cache Manager
 * @author: LiteSpeed Technologies, Inc. (https://www.litespeedtech.com)
 * @copyright: (c) 2019
 * ******************************************* */

namespace Lsc\Wp\View\Model;

use \Lsc\Wp\Context\Context;
use \Lsc\Wp\Logger;
use \Lsc\Wp\LSCMException;
use \Lsc\Wp\WPDashMsgs;
use \Lsc\Wp\WPInstallStorage;

class DashNotifierViewModel
{

    const STEP_CONFIRM = 0;
    const STEP_DO_ACTION = 1;
    const FLD_ICON_DIR = 'iconDir';
    const FLD_DISCOVERED_COUNT = 'discoveredCount';
    const FLD_RAP_MSG_IDS = 'rapMsgIds';
    const FLD_BAM_MSG_IDS = 'bamMsgIds';

    /**
     * @var WPInstallStorage
     */
    protected $wpInstallStorage;

    /**
     * @var WPDashMsgs
     */
    protected $wpDashMsgs;

    /**
     * @var mixed[]
     */
    protected $tplData = array();

    /**
     *
     * @param WPInstallStorage  $wpInstallStorage
     * @param WPDashMsgs        $wpDashMsgs
     */
    public function __construct( WPInstallStorage $wpInstallStorage,
            WPDashMsgs $wpDashMsgs )
    {
        $this->wpInstallStorage = $wpInstallStorage;
        $this->wpDashMsgs = $wpDashMsgs;

        $this->init();
    }

    protected function init()
    {
        $this->setIconDir();
        $this->setStoredMsgIds();
        $this->setDiscoveredCount();
    }

    /**
     *
     * @param string  $field
     * @return null|string
     */
    public function getTplData( $field )
    {
        if ( !isset($this->tplData[$field]) ) {
            return null;
        }

        return $this->tplData[$field];
    }

    protected function setIconDir()
    {
        $iconDir = '';

        try
        {
            $iconDir = Context::getOption()->getIconDir();
        }
        catch ( LSCMException $e )
        {
            Logger::debug($e->getMessage() . ' Could not get icon directory.');
        }

        $this->tplData[self::FLD_ICON_DIR] = $iconDir;
    }

    protected function setStoredMsgIds()
    {
        $msgs = $this->wpDashMsgs->getMsgData();

        $this->tplData[self::FLD_RAP_MSG_IDS] =
                array_keys($msgs[WPDashMsgs::KEY_RAP_MSGS]);
        $this->tplData[self::FLD_BAM_MSG_IDS] =
                array_keys($msgs[WPDashMsgs::KEY_BAM_MSGS]);
    }

    protected function setDiscoveredCount()
    {
        $this->tplData[self::FLD_DISCOVERED_COUNT] =
                $this->wpInstallStorage->getCount();
    }

    /**
     *
     * @return string
     */
    public function getTpl()
    {
        return realpath(__DIR__ . '/../Tpl') . '/DashNotifier.tpl';
    }

}
webcachemgr/src/View/Model/MissingTplViewModel.php000066400000002010150545647710016203 0ustar00<?php

/* * ******************************************
 * LiteSpeed Web Server Cache Manager
 * @author: LiteSpeed Technologies, Inc. (https://www.litespeedtech.com)
 * @copyright: (c) 2018-2019
 * ******************************************* */

namespace Lsc\Wp\View\Model;

use \Lsc\Wp\Context\Context;

class MissingTplViewModel
{

    const FLD_MSG = 'msg';

    /**
     * @var string[]
     */
    private $tplData = array();

    /**
     *
     * @param string  $msg
     */
    public function __construct( $msg )
    {
        $this->init($msg);
    }

    private function init( $msg )
    {
        $this->tplData[self::FLD_MSG] = $msg;
    }

    /**
     *
     * @param string  $field
     * @return null|string
     */
    public function getTplData( $field )
    {
        if ( !isset($this->tplData[$field]) ) {
            return null;
        }

        return $this->tplData[$field];
    }

    public function getTpl()
    {
        return Context::getOption()->getSharedTplDir() . '/MissingTpl.tpl';
    }

}
webcachemgr/src/View/Model/DataFileMsgViewModel.php000066400000004065150545647710016246 0ustar00<?php

/** ******************************************
 * LiteSpeed Web Server Cache Manager
 *
 * @author    Michael Alegre
 * @copyright 2018-2025 LiteSpeed Technologies, Inc.
 * ******************************************* */

namespace Lsc\Wp\View\Model;

use Lsc\Wp\Context\Context;
use Lsc\Wp\LSCMException;
use Lsc\Wp\WPInstallStorage;

class DataFileMsgViewModel
{

    const FLD_TITLE    = 'title';
    const FLD_DISCOVER = 'discover';

    /**
     * @var WPInstallStorage
     */
    private $wpInstallStorage;

    /**
     * @var string[]
     */
    private $tplData = array();

    /**
     *
     * @param WPInstallStorage  $wpInstallStorage
     */
    public function __construct( WPInstallStorage $wpInstallStorage )
    {
        $this->wpInstallStorage = $wpInstallStorage;

        $this->init();
    }

    private function init()
    {
        $this->setTitleAndDiscover();
    }

    /**
     *
     * @param string  $field
     * @return null|string
     */
    public function getTplData( $field )
    {
        if ( !isset($this->tplData[$field]) ) {
            return null;
        }

        return $this->tplData[$field];
    }

    private function setTitleAndDiscover()
    {
        switch ( $this->wpInstallStorage->getError() ) {

            case WPInstallStorage::ERR_NOT_EXIST:
                $title    = 'No Scan Data Found';
                $discover = 'discover';
                break;

            case WPInstallStorage::ERR_CORRUPTED:
                $title    = 'Scan Data Corrupted';
                $discover = 're-discover';
                break;

            default:
                $title    = 'Scan Data Needs To Be Updated';
                $discover = 're-discover';
        }

        $this->tplData[self::FLD_TITLE]    = $title;
        $this->tplData[self::FLD_DISCOVER] = $discover;
    }

    /**
     *
     * @return string
     *
     * @throws LSCMException  Thrown indirectly by Context::getOption() call.
     */
    public function getTpl()
    {
        return Context::getOption()->getSharedTplDir() . '/DataFileMsg.tpl';
    }

}
webcachemgr/src/View/Model/ScanProgressViewModel.php000066400000005275150545647710016543 0ustar00<?php

/** ******************************************
 * LiteSpeed Web Server Cache Manager
 *
 * @author LiteSpeed Technologies, Inc. (https://www.litespeedtech.com)
 * @copyright (c) 2018-2020
 * @deprecated 1.13.3  This file will be removed in a future release.
 * ******************************************* */

namespace Lsc\Wp\View\Model;

use \Lsc\Wp\Context\Context;
use \Lsc\Wp\LSCMException;
use \Lsc\Wp\Logger;

/**
 *
 * @deprecated 1.13.3
 */
class ScanProgressViewModel
{

    const FLD_TITLE = 'title';
    const FLD_ICON = 'icon';
    const FLD_MGR_STEP = 'mgrStep';
    const FLD_HOME_DIR_COUNT = 'homeDirCount';
    const OP_SCAN = 1;
    const OP_DISCOVER_NEW = 2;

    /**
     * @var int
     */
    protected $mgrStep;

    /**
     * @var (int|string)[]
     */
    protected $tplData = array();

    /**
     *
     * @param int  $mgrStep
     * @throws LSCMException  Thrown indirectly.
     */
    public function __construct( $mgrStep )
    {
        $this->mgrStep = $this->tplData[self::FLD_MGR_STEP] = $mgrStep;

        $this->init();
    }

    /**
     *
     * @throws LSCMException  Thrown indirectly.
     */
    protected function init()
    {
        $this->setTitle();
        $this->setIconPath();
        $this->grabSessionData();
    }

    /**
     *
     * @param string  $field
     * @return null|int|string
     */
    public function getTplData( $field )
    {
        if ( !isset($this->tplData[$field]) ) {
            return null;
        }

        return $this->tplData[$field];
    }

    protected function setTitle()
    {

        if ( $this->mgrStep == self::OP_SCAN ) {
            $title = 'Scanning/Re-scanning For All WordPress Installations...';
        }
        else {
            $title = 'Discovering New WordPress Installations...';
        }

        $this->tplData[self::FLD_TITLE] = $title;
    }

    /**
     *
     * @throws LSCMException  Thrown indirectly.
     */
    protected function setIconPath()
    {
        $iconPath = '';

        try
        {
            $iconDir = Context::getOption()->getIconDir();
            $iconPath = "{$iconDir}/manageCacheInstallations.svg";
        }
        catch ( LSCMException $e )
        {
            Logger::debug($e->getMessage() . ' Could not get icon directory.');
        }

        $this->tplData[self::FLD_ICON] = $iconPath;
    }

    protected function grabSessionData()
    {
        $info = $_SESSION['scanInfo'];

        $this->tplData[self::FLD_HOME_DIR_COUNT] = count($info['homeDirs']);
    }

    /**
     *
     * @return string
     * @throws LSCMException  Thrown indirectly.
     */
    public function getTpl()
    {
        return Context::getOption()->getSharedTplDir() . '/ScanProgress.tpl';
    }

}
webcachemgr/src/View/Model/ScanProgressStepViewModel.php000066400000007173150545647710017376 0ustar00<?php

/** ******************************************
 * LiteSpeed Web Server Cache Manager
 * @author: LiteSpeed Technologies, Inc. (https://www.litespeedtech.com)
 * @copyright: (c) 2020
 * @since 1.13.3
 * ******************************************* */

namespace Lsc\Wp\View\Model;

use \Lsc\Wp\Context\Context;
use \Lsc\Wp\LSCMException;
use \Lsc\Wp\Logger;

/**
 *
 * @since 1.13.3
 */
class ScanProgressStepViewModel
{

    /**
     * @since 1.13.3
     * @var string
     */
    const FLD_TITLE = 'title';

    /**
     * @since 1.13.3
     * @var string
     */
    const FLD_ICON = 'icon';

    /**
     * @since 1.13.3
     * @var string
     */
    const FLD_MGR_STEP = 'mgrStep';

    /**
     * @since 1.13.3
     * @var string
     */
    const FLD_TOTAL_COUNT = 'totalCount';

    /**
     * @since 1.13.3
     * @var string
     */
    const FLD_INSTALLS_COUNT = 'installsCount';

    /**
     * @since 1.13.3
     * @var int
     */
    const OP_SCAN = 1;

    /**
     * @since 1.13.3
     * @var int
     */
    protected $mgrStep;

    /**
     * @since 1.13.3
     * @var (int|string)[]
     */
    protected $tplData = array();

    /**
     *
     * @since 1.13.3
     *
     * @param int  $mgrStep
     * @throws LSCMException  Thrown indirectly.
     */
    public function __construct( $mgrStep )
    {
        $this->mgrStep = $this->tplData[self::FLD_MGR_STEP] = $mgrStep;

        $this->init();
    }

    /**
     *
     * @since 1.13.3
     *
     * @throws LSCMException  Thrown indirectly.
     */
    protected function init()
    {
        $this->setTitle();
        $this->setIconPath();
        $this->grabSessionData();
    }

    /**
     *
     * @since 1.13.3
     *
     * @param string  $field
     * @return null|int|string
     */
    public function getTplData( $field )
    {
        if ( !isset($this->tplData[$field]) ) {
            return null;
        }

        return $this->tplData[$field];
    }

    /**
     *
     * @since 1.13.3
     */
    protected function setTitle()
    {

        if ( $this->mgrStep == self::OP_SCAN ) {
            $title = 'Scanning/Re-scanning For All WordPress Installations...';
        }
        else {
            $title = 'Discovering New WordPress Installations...';
        }

        $this->tplData[self::FLD_TITLE] = $title;
    }

    /**
     *
     * @since 1.13.3
     *
     * @throws LSCMException  Thrown indirectly.
     */
    protected function setIconPath()
    {
        $iconPath = '';

        try
        {
            $iconDir = Context::getOption()->getIconDir();
            $iconPath = "{$iconDir}/manageCacheInstallations.svg";
        }
        catch ( LSCMException $e )
        {
            Logger::debug($e->getMessage() . ' Could not get icon directory.');
        }

        $this->tplData[self::FLD_ICON] = $iconPath;
    }

    /**
     *
     * @since 1.13.3
     */
    protected function grabSessionData()
    {
        $info = $_SESSION['scanInfo'];

        if ( !empty($info['homeDirs']) ) {
            $total = count($info['homeDirs']);
        }
        else {
            $total = count($info['installs']);
        }

        $this->tplData[self::FLD_TOTAL_COUNT] = $total;
    }

    /**
     *
     * @since 1.13.3
     *
     * @return string
     * @throws LSCMException  Thrown indirectly.
     */
    public function getTpl()
    {
        $info = $_SESSION['scanInfo'];

        if ( !empty($info['homeDirs']) ) {
            return Context::getOption()->getSharedTplDir()
                . '/ScanProgressStep1.tpl';
        }
        else {
            return Context::getOption()->getSharedTplDir()
                . '/ScanProgressStep2.tpl';
        }
    }

}
webcachemgr/src/View/Model/CacheRootNotSetViewModel.php000066400000001272150545647710017127 0ustar00<?php

/** ******************************************
 * LiteSpeed Web Server Cache Manager
 *
 * @author    Michael Alegre
 * @copyright 2018-2025 LiteSpeed Technologies, Inc.
 * ******************************************* */

namespace Lsc\Wp\View\Model;

use Lsc\Wp\Context\Context;
use Lsc\Wp\LSCMException;

class CacheRootNotSetViewModel
{

    public function __construct()
    {
        /**
         * Nothing to do
         */
    }

    /**
     *
     * @return string
     *
     * @throws LSCMException  Thrown indirectly by Context::getOption() call.
     */
    public function getTpl()
    {
        return Context::getOption()->getSharedTplDir() . '/CacheRootNotSet.tpl';
    }

}
webcachemgr/src/View/Model/RefreshStatusProgressViewModel.php000066400000003260150545647710020451 0ustar00<?php

/* * ******************************************
 * LiteSpeed Web Server Cache Manager
 * @author: LiteSpeed Technologies, Inc. (https://www.litespeedtech.com)
 * @copyright: (c) 2018-2019
 * ******************************************* */

namespace Lsc\Wp\View\Model;

use \Lsc\Wp\Context\Context;
use \Lsc\Wp\Logger;
use \Lsc\Wp\LSCMException;

class RefreshStatusProgressViewModel
{

    const FLD_ICON = 'icon';
    const FLD_INSTALLS_COUNT = 'installsCount';

    /**
     * @var (string|int)[]
     */
    protected $tplData = array();

    public function __construct()
    {
        $this->init();
    }

    protected function init()
    {
        $this->setIconPath();
        $this->grabSessionData();
    }

    /**
     *
     * @param string  $field
     * @return null|int|string
     */
    public function getTplData( $field )
    {
        if ( !isset($this->tplData[$field]) ) {
            return null;
        }

        return $this->tplData[$field];
    }

    protected function setIconPath()
    {
        $iconPath = '';

        try
        {
            $iconDir = Context::getOption()->getIconDir();
            $iconPath = "{$iconDir}/manageCacheInstallations.svg";
        }
        catch ( LSCMException $e )
        {
            Logger::debug($e->getMessage() . ' Could not get icon directory.');
        }

        $this->tplData[self::FLD_ICON] = $iconPath;
    }

    protected function grabSessionData()
    {
        $info = $_SESSION['refreshInfo'];

        $this->tplData[self::FLD_INSTALLS_COUNT] = count($info['installs']);
    }

    public function getTpl()
    {
        return Context::getOption()->getSharedTplDir() . '/RefreshStatusProgress.tpl';
    }

}
webcachemgr/src/View/Model/VersionManageViewModel.php000066400000012450150545647710016661 0ustar00<?php

/** ******************************************
 * LiteSpeed Web Server Cache Manager
 *
 * @author Michael Alegre
 * @copyright (c) 2018-2022 LiteSpeed Technologies, Inc.
 * ******************************************* */

namespace Lsc\Wp\View\Model;

use Lsc\Wp\WPInstallStorage;
use Lsc\Wp\Context\Context;
use Lsc\Wp\PluginVersion;
use Lsc\Wp\Logger;
use Lsc\Wp\LSCMException;

class VersionManageViewModel
{

    /**
     * @var string
     */
    const FLD_ICON = 'icon';

    /**
     * @var string
     */
    const FLD_VERSION_LIST = 'versionList';

    /**
     * @var string
     */
    const FLD_ALLOWED_VER_LIST = 'allowedList';

    /**
     * @var string
     */
    const FLD_ACTIVE_VER = 'activeVer';

    /**
     * @var string
     */
    const FLD_ERR_MSGS = 'errMsgs';

    /**
     * @var string
     */
    const FLD_STATE = 'state';

    /**
     * @var int
     */
    const ST_INSTALLS_DISCOVERED = 2;

    /**
     * @deprecated 1.13.4.1  Added back as a deprecated constant after
     *     accidental removal in v1.13.4. Use
     *     self::ST_NO_NON_ERROR_INSTALLS_DISCOVERED instead.
     *
     * @var int
     */
    const ST_NO_INSTALLS_DISCOVERED = 1;

    /**
     * @var int
     */
    const ST_NO_NON_ERROR_INSTALLS_DISCOVERED = 1;

    /**
     * @var int
     */
    const ST_SCAN_NEEDED = 0;

    /**
     * @var WPInstallStorage
     */
    protected $wpInstallStorage;

    /**
     * @var (boolean|string|string[])[]
     */
    protected $tplData = array();

    /**
     *
     * @param WPInstallStorage $wpInstallStorage
     *
     * @throws LSCMException  Thrown indirectly by $this->init() call.
     */
    public function __construct( WPInstallStorage $wpInstallStorage )
    {
        $this->wpInstallStorage = $wpInstallStorage;

        $this->init();
    }

    /**
     *
     * @throws LSCMException  Thrown indirectly by $this->setIconPath() call.
     * @throws LSCMException  Thrown indirectly by $this->setActiveVerData()
     *     call.
     * @throws LSCMException  Thrown indirectly by $this->setVerListData() call.
     * @throws LSCMException  Thrown indirectly by $this->setMsgData() call.
     */
    protected function init()
    {
        $this->setIconPath();
        $this->setActiveVerData();
        $this->setVerListData();
        $this->setStateData();
        $this->setMsgData();
    }

    /**
     *
     * @param string $field
     *
     * @return null|boolean|string|string[]
     */
    public function getTplData( $field )
    {
        if ( !isset($this->tplData[$field]) ) {
            return null;
        }

        return $this->tplData[$field];

    }

    /**
     *
     * @throws LSCMException  Thrown indirectly by Logger::debug() call.
     */
    protected function setIconPath()
    {
        $iconPath = '';

        try {
            $iconDir = Context::getOption()->getIconDir();
            $iconPath = "$iconDir/lscwpCurrentVersion.svg";
        }
        catch ( LSCMException $e ) {
            Logger::debug($e->getMessage() . ' Could not get icon directory.');
        }

        $this->tplData[self::FLD_ICON] = $iconPath;
    }

    /**
     *
     * @throws LSCMException  Thrown indirectly by Logger::debug() call.
     */
    protected function setActiveVerData()
    {
        try {
            $currVer = PluginVersion::getCurrentVersion();
        }
        catch ( LSCMException $e ) {
            Logger::debug(
                $e->getMessage() . ' Could not get active LSCWP version.'
            );

            $currVer = false;
        }

        $this->tplData[self::FLD_ACTIVE_VER] = $currVer;
    }

    protected function setStateData()
    {
        if ( $this->wpInstallStorage->getError() == 0 ) {

            if ( $this->wpInstallStorage->getCount(true) > 0 ) {
                $this->tplData[self::FLD_STATE] = self::ST_INSTALLS_DISCOVERED;
            }
            else {
                $this->tplData[self::FLD_STATE] =
                    self::ST_NO_NON_ERROR_INSTALLS_DISCOVERED;
            }
        }
        else {
            $this->tplData[self::FLD_STATE] = self::ST_SCAN_NEEDED;
        }
    }

    /**
     *
     * @throws LSCMException  Thrown indirectly by PluginVersion::getInstance()
     *     call.
     * @throws LSCMException  Thrown indirectly by Logger::debug() call.
     */
    protected function setVerListData()
    {
        $vermgr = PluginVersion::getInstance();

        try
        {
            $verList = $vermgr->getShortVersions();
            $allowedList = $vermgr->getAllowedVersions();
        }
        catch ( LSCMException $e )
        {
            Logger::debug(
                $e->getMessage() . ' Could not retrieve version list.'
            );

            $verList = $allowedList = array();
        }

        $this->tplData[self::FLD_VERSION_LIST] = $verList;
        $this->tplData[self::FLD_ALLOWED_VER_LIST] = $allowedList;
    }

    /**
     *
     * @throws LSCMException  Thrown indirectly by Logger::getUiMsgs() call.
     */
    protected function setMsgData()
    {
        $this->tplData[self::FLD_ERR_MSGS] = Logger::getUiMsgs(Logger::UI_ERR);
    }

    /**
     *
     * @return string
     *
     * @throws LSCMException  Thrown indirectly by Context::getOption() call.
     */
    public function getTpl()
    {
        return Context::getOption()->getSharedTplDir() . '/VersionManage.tpl';
    }

}
webcachemgr/src/View/Model/ManageViewModel.php000066400000034314150545647710015316 0ustar00<?php

/** ******************************************
 * LiteSpeed Web Server Cache Manager
 *
 * @author    Michael Alegre
 * @copyright 2018-2025 LiteSpeed Technologies, Inc.
 * ******************************************* */

namespace Lsc\Wp\View\Model;

use Lsc\Wp\Context\Context;
use Lsc\Wp\Util;
use Lsc\Wp\WPInstallStorage;
use Lsc\Wp\WPInstall;
use Lsc\Wp\PluginVersion;
use Lsc\Wp\Logger;
use Lsc\Wp\LSCMException;

class ManageViewModel
{

    /**
     * @var string
     */
    const FLD_ICON_DIR      = 'iconDir';

    /**
     * @var string
     */
    const FLD_SCAN_BTN_NAME = 'scanBtnName';

    /**
     * @var string
     */
    const FLD_BTN_STATE     = 'btnState';

    /**
     * @var string
     */
    const FLD_ACTIVE_VER    = 'activeVer';

    /**
     * @var string
     */
    const FLD_SHOW_LIST     = 'showList';

    /**
     * @var string
     */
    const FLD_LIST_DATA     = 'listData';

    /**
     * @var string
     */
    const FLD_COUNT_DATA    = 'countData';

    /**
     * @var string
     */
    const FLD_INFO_MSGS     = 'infoMsgs';

    /**
     * @var string
     */
    const FLD_SUCC_MSGS     = 'succMsgs';

    /**
     * @var string
     */
    const FLD_ERR_MSGS      = 'errMsgs';

    /**
     * @var string
     */
    const FLD_WARN_MSGS     = 'warnMsgs';

    /**
     * @var string
     */
    const COUNT_DATA_INSTALLS  = 'installs';

    /**
     * @var string
     */
    const COUNT_DATA_ENABLED   = 'enabled';

    /**
     * @var string
     */
    const COUNT_DATA_DISABLED  = 'disabled';

    /**
     * @var string
     */
    const COUNT_DATA_WARN      = 'warn';

    /**
     * @var string
     */
    const COUNT_DATA_ERROR     = 'err';

    /**
     * @var string
     */
    const COUNT_DATA_FLAGGED   = 'flagged';

    /**
     * @var string
     */
    const COUNT_DATA_UNFLAGGED = 'unflagged';

    /**
     * @var WPInstallStorage
     */
    protected $wpInstallStorage;

    /**
     * @var array
     */
    protected $tplData = [];

    /**
     * @var string
     */
    protected $iconDir = '';

    /**
     * @since 1.13.3
     * @var string[][]
     */
    protected $statusInfo = [
        'disabled'               => [
            'sort'           => 'disabled',
            'state'          => '<span '
                . 'class="glyphicon glyphicon-flash status-disabled" '
                . 'data-uk-tooltip title="LSCWP is disabled."></span>',
            'btn_content'    => '<span class="enable_btn"></span>',
            'btn_title'      => 'Click to enable LSCache',
            'onclick'        => 'onclick="javascript:lscwpEnableSingle(this);"',
            'btn_attributes' => 'data-uk-tooltip',
            'btn_state'      => ''
        ],
        'enabled'                => [
            'sort'           => 'enabled',
            'state'          => '<span '
                . 'class="glyphicon glyphicon-flash status-enabled" '
                . 'data-uk-tooltip title="LSCWP is enabled."></span>',
            'btn_content'    => '<span class="disable_btn"></span>',
            'btn_title'      => 'Click to disable LSCache',
            'onclick'        =>
                'onclick="javascript:lscwpDisableSingle(this);"',
            'btn_attributes' => 'data-uk-tooltip',
            'btn_state'      => ''
        ],
        'adv_cache'              => [
            'sort'           => 'warning',
            'state'          => '<span class="status-warning" data-uk-tooltip '
                . 'title="LSCache is enabled but not caching. Please visit the '
                . 'WordPress Dashboard for more information."></span>',
            'btn_content'    => '<span class="disable_btn"></span>',
            'btn_title'      => 'Click to disable LSCache',
            'onclick'        =>
                'onclick="javascript:lscwpDisableSingle(this);"',
            'btn_attributes' => 'data-uk-tooltip',
            'btn_state'      => ''
        ],
        'disabled_no_active_ver' => [
            'sort'           => 'disabled',
            'state'          => '<span '
                . 'class="glyphicon glyphicon-flash status-disabled" '
                . 'data-uk-tooltip title="LSCWP is disabled."></span>',
            'btn_content'    => '<span class="inactive-action-btn" '
                . 'data-uk-tooltip '
                . 'title="No active LSCWP version set! Cannot enable LSCache.">'
                . '</span>',
            'btn_title'      => '',
            'onclick'        => '',
            'btn_attributes' => '',
            'btn_state'      => 'disabled',
        ],
        'error'                  => [
            'sort'           => 'error',
            /**
             * 'state' added individually later.
             */
            'btn_title'      => '',
            'btn_content'    => '<span class="inactive-action-btn"></span>',
            'onclick'        => '',
            'btn_attributes' => '',
            'btn_state'      => 'disabled'
        ]
    ];

    /**
     * @since 1.13.3
     * @var string[][]
     */
    protected $flagInfo = [
        'unflagged' => [
            'sort'           => 'unflagged',
            'icon'           => '<span '
                . 'class="glyphicon glyphicon-flag ls-flag ls-flag-unset">'
                . '</span>',
            'btn_title'      => 'Click to set flag',
            'onclick'        => 'onclick="javascript:lscwpFlagSingle(this);"',
            'btn_attributes' => 'data-uk-tooltip'
        ],
        'flagged'   => [
            'sort'           => 'flagged',
            'icon'           => '<span '
                . 'class="glyphicon glyphicon-flag ls-flag ls-flag-set">'
                . '</span>',
            'btn_title'      => 'Click to unset flag',
            'onclick'        => 'onclick="javascript:lscwpUnflagSingle(this);"',
            'btn_attributes' => 'data-uk-tooltip'
        ],
    ];

    /**
     *
     * @param WPInstallStorage $wpInstallStorage
     *
     * @throws LSCMException  Thrown indirectly by $this->init() call.
     */
    public function __construct( WPInstallStorage $wpInstallStorage )
    {
        $this->wpInstallStorage = $wpInstallStorage;

        $this->init();
    }

    /**
     *
     * @throws LSCMException  thrown indirectly by $this->setIconDir() call.
     * @throws LSCMException  thrown indirectly by $this->setActiveVerData()
     *     call.
     * @throws LSCMException  thrown indirectly by $this->setMsgData() call.
     */
    protected function init()
    {
        $this->setIconDir();
        $this->setBtnDataAndListVisibility();
        $this->setActiveVerData();
        $this->setListAndCountData();
        $this->setMsgData();
    }

    /**
     *
     * @param string $field
     *
     * @return null|mixed
     */
    public function getTplData( $field )
    {
        if ( !isset($this->tplData[$field]) ) {
            return null;
        }

        return $this->tplData[$field];
    }

    /**
     *
     * @throws LSCMException  Thrown indirectly by Logger::debug() call.
     */
    protected function setIconDir()
    {
        $iconDir = '';

        try
        {
            $iconDir = Context::getOption()->getIconDir();
        }
        catch ( LSCMException $e )
        {
            Logger::debug("{$e->getMessage()}. Could not get icon directory.");
        }

        $this->tplData[self::FLD_ICON_DIR] = $iconDir;
    }

    /**
     *
     * @throws LSCMException  Thrown indirectly by Logger::uiInfo() call.
     */
    protected function setBtnDataAndListVisibility()
    {
        $scanBtnName = 'Re-scan';
        $btnState    = 'disabled';

        if ( ($errStatus = $this->wpInstallStorage->getError()) !== 0 ) {
            $this->tplData[self::FLD_SHOW_LIST] = false;

            if ( $errStatus == WPInstallStorage::ERR_NOT_EXIST ) {
                $scanBtnName = 'Scan';
                $msg         = 'Start by clicking Scan. This will discover all '
                    . 'active WordPress installations and add them to a list '
                    . 'below.';
            }
            elseif ( $errStatus == WPInstallStorage::ERR_VERSION_LOW ) {
                $scanBtnName = 'Scan';
                $msg         = 'To further improve Cache Management features '
                    . 'in this version, current installations must be '
                    . 're-discovered. Please perform a Scan now.';
            }
            else {
                $msg = 'Scan data could not be read. Please perform a Re-scan.';
            }

            Logger::uiInfo($msg);
        }
        else {
            $this->tplData[self::FLD_SHOW_LIST] = true;

            if ( $this->wpInstallStorage->getCount() > 0 ) {
                $btnState = '';
            }
        }

        $this->tplData[self::FLD_SCAN_BTN_NAME] = $scanBtnName;
        $this->tplData[self::FLD_BTN_STATE]     = $btnState;
    }

    protected function setListAndCountData()
    {
        $listData = [];

        $countData = [
            self::COUNT_DATA_INSTALLS  => 0,
            self::COUNT_DATA_ENABLED   => 0,
            self::COUNT_DATA_DISABLED  => 0,
            self::COUNT_DATA_WARN      => 0,
            self::COUNT_DATA_ERROR     => 0,
            self::COUNT_DATA_FLAGGED   => 0,
            self::COUNT_DATA_UNFLAGGED => 0
        ];

        $wpInstalls = $this->wpInstallStorage->getAllWPInstalls();

        if ( $wpInstalls !== null ) {
            $countData[self::COUNT_DATA_INSTALLS] = count($wpInstalls);

            foreach ( $wpInstalls as $wpInstall ) {
                $listData[$wpInstall->getPath()] = [
                    'statusData' =>
                        $this->getStatusDisplayData($wpInstall, $countData),
                    'flagData'   =>
                        $this->getFlagDisplayData($wpInstall, $countData),
                    'siteUrl'    => Util::tryIdnToUtf8(
                        (string)$wpInstall->getData(WPInstall::FLD_SITEURL)
                    )
                ];

            }
        }

        $this->tplData[self::FLD_LIST_DATA]  = $listData;
        $this->tplData[self::FLD_COUNT_DATA] = $countData;
    }

    /**
     *
     * @param WPInstall $wpInstall
     * @param int[]     $countData
     *
     * @return string[]
     */
    protected function getStatusDisplayData(
        WPInstall $wpInstall,
        array     &$countData
    )
    {
        $wpStatus = $wpInstall->getStatus();

        if ( $wpInstall->hasFatalError($wpStatus) ) {
            $countData[self::COUNT_DATA_ERROR]++;

            $fatalErrStateInfo =
                Util::getFatalErrorStateMessageAndLink($wpStatus);

            $currStatusData          = $this->statusInfo['error'];
            $currStatusData['state'] = '<a '
                . "href=\"{$fatalErrStateInfo['link']}\" "
                . 'target="_blank" rel="noopener" data-uk-tooltip '
                . "title =\"{$fatalErrStateInfo['stateMsg']}\" "
                . 'class="status-error"></a>';
        }
        elseif ( ($wpStatus & WPInstall::ST_PLUGIN_INACTIVE ) ) {
            $countData[self::COUNT_DATA_DISABLED]++;

            if ( !$this->getTplData(self::FLD_ACTIVE_VER) ) {
                $currStatusData = $this->statusInfo['disabled_no_active_ver'];
            }
            else {
                $currStatusData = $this->statusInfo['disabled'];
            }
        }
        elseif ( !($wpStatus & WPInstall::ST_LSC_ADVCACHE_DEFINED) ) {
            $countData[self::COUNT_DATA_WARN]++;
            $currStatusData = $this->statusInfo['adv_cache'];
        }
        else {
            $countData[self::COUNT_DATA_ENABLED]++;
            $currStatusData = $this->statusInfo['enabled'];
        }

        return $currStatusData;
    }

    /**
     *
     * @param WPInstall $wpInstall
     * @param int[]     $countData
     *
     * @return string[]
     */
    protected function getFlagDisplayData(
        WPInstall $wpInstall,
        array     &$countData
    )
    {
        if ( ($wpInstall->getStatus() & WPInstall::ST_FLAGGED ) ) {
            $countData[self::COUNT_DATA_FLAGGED]++;
            $currFlagData = $this->flagInfo['flagged'];
        }
        else {
            $countData[self::COUNT_DATA_UNFLAGGED]++;
            $currFlagData = $this->flagInfo['unflagged'];
        }

        return $currFlagData;
    }

    /**
     *
     * @throws LSCMException  Thrown indirectly by Logger::debug() call.
     * @throws LSCMException  Thrown indirectly by Logger::uiWarning() call.
     */
    protected function setActiveVerData()
    {
        try
        {
            $currVer = PluginVersion::getCurrentVersion();
        }
        catch ( LSCMException $e )
        {
            Logger::debug(
                "{$e->getMessage()} Could not get active LSCWP version."
            );

            Logger::uiWarning(
                'Active LiteSpeed Cache Plugin version is not set. Enable '
                    . 'operations cannot be performed. Please go to '
                    . '<a href="?do=lscwpVersionManager" '
                    . 'title="Go to Version Manager">Version Manager</a> to '
                    . 'select a version.'
                );

            $currVer = false;
        }

        $this->tplData[self::FLD_ACTIVE_VER] = $currVer;
    }

    /**
     *
     * @throws LSCMException  Thrown indirectly by Logger::getUiMsgs() call.
     * @throws LSCMException  Thrown indirectly by Logger::getUiMsgs() call.
     * @throws LSCMException  Thrown indirectly by Logger::getUiMsgs() call.
     * @throws LSCMException  Thrown indirectly by Logger::getUiMsgs() call.
     */
    protected function setMsgData()
    {
        $this->tplData[self::FLD_INFO_MSGS] =
            Logger::getUiMsgs(Logger::UI_INFO);

        $this->tplData[self::FLD_WARN_MSGS] =
            Logger::getUiMsgs(Logger::UI_WARN);

        $msgs = $this->wpInstallStorage->getAllCmdMsgs();

        $this->tplData[self::FLD_SUCC_MSGS] = array_merge(
            $msgs['succ'],
            Logger::getUiMsgs(Logger::UI_SUCC)
        );

        $this->tplData[self::FLD_ERR_MSGS] = array_merge(
            $msgs['fail'],
            $msgs['err'],
            Logger::getUiMsgs(Logger::UI_ERR)
        );
    }

    /**
     *
     * @return string
     *
     * @throws LSCMException  Thrown indirectly by Context::getOption() call.
     */
    public function getTpl()
    {
        return Context::getOption()->getSharedTplDir() . '/Manage.tpl';
    }

}
webcachemgr/src/View/Model/MassEnableDisableViewModel.php000066400000005442150545647720017425 0ustar00<?php

/* * ******************************************
 * LiteSpeed Web Server Cache Manager
 * @author: LiteSpeed Technologies, Inc. (https://www.litespeedtech.com)
 * @copyright: (c) 2018-2019
 * ******************************************* */

namespace Lsc\Wp\View\Model;

use \Lsc\Wp\Context\Context;
use \Lsc\Wp\Logger;
use \Lsc\Wp\LSCMException;
use \Lsc\Wp\PluginVersion;
use \Lsc\Wp\WPInstallStorage;

class MassEnableDisableViewModel
{

    const FLD_ICON = 'icon';
    const FLD_ACTIVE_VER = 'activeVer';
    const FLD_STATE = 'allowCacheOp';
    const ST_INSTALLS_DISCOVERED = 2;
    const ST_NO_INSTALLS_DISCOVERED = 1;
    const ST_SCAN_NEEDED = 0;

    /**
     * @var WPInstallStorage
     */
    protected $wpInstallStorage;

    /**
     * @var mixed[]
     */
    protected $tplData = array();

    /**
     *
     * @param WPInstallStorage  $wpInstallStorage
     */
    public function __construct( WPInstallStorage $wpInstallStorage )
    {
        $this->wpInstallStorage = $wpInstallStorage;

        $this->init();
    }

    protected function init()
    {
        $this->setIconPath();
        $this->setActiveVerData();
        $this->setStateData();
    }

    /**
     *
     * @param string  $field
     * @return null|mixed
     */
    public function getTplData( $field )
    {
        if ( !isset($this->tplData[$field]) ) {
            return null;
        }

        return $this->tplData[$field];
    }

    protected function setIconPath()
    {
        $iconPath = '';

        try
        {
            $iconDir = Context::getOption()->getIconDir();
            $iconPath = "{$iconDir}/massEnableDisableCache.svg";
        }
        catch ( LSCMException $e )
        {
            Logger::debug($e->getMessage() . ' Could not get icon directory.');
        }

        $this->tplData[self::FLD_ICON] = $iconPath;
    }

    protected function setActiveVerData()
    {
        try
        {
            $currVer = PluginVersion::getCurrentVersion();
        }
        catch ( LSCMException $e )
        {
            Logger::debug($e->getMessage() . ' Could not get active LSCWP version.');

            $currVer = false;
        }

        $this->tplData[self::FLD_ACTIVE_VER] = $currVer;
    }

    protected function setStateData()
    {
        if ( $this->wpInstallStorage->getError() == 0 ) {

            if ( $this->wpInstallStorage->getCount(true) > 0 ) {
                $this->tplData[self::FLD_STATE] = self::ST_INSTALLS_DISCOVERED;
            }
            else {
                $this->tplData[self::FLD_STATE] = self::ST_NO_INSTALLS_DISCOVERED;
            }
        }
        else {
            $this->tplData[self::FLD_STATE] = self::ST_SCAN_NEEDED;
        }
    }

    public function getTpl()
    {
        return Context::getOption()->getSharedTplDir() . '/MassEnableDisable.tpl';
    }

}
webcachemgr/src/View/Model/FlagUnflagAllProgressViewModel.php000066400000005512150545647720020311 0ustar00<?php

/** ******************************************
 * LiteSpeed Web Server Cache Manager
 *
 * @author    Michael Alegre
 * @copyright 2025 LiteSpeed Technologies, Inc.
 * ******************************************* */

namespace Lsc\Wp\View\Model;

use Lsc\Wp\Context\Context;
use Lsc\Wp\Logger;
use Lsc\Wp\LSCMException;

class FlagUnflagAllProgressViewModel
{

    const FLD_ACTION         = 'action';
    const FLD_ICON           = 'icon';
    const FLD_INSTALLS_COUNT = 'installsCount';

    /**
     * @var string  Should be either 'flag' or 'unflag'.
     */
    protected $action = '';

    /**
     * @var (int|string)[]
     */
    protected $tplData = [];

    /**
     *
     * @param string $action  Should be 'flag' or 'unflag'.
     *
     * @throws LSCMException  Thrown when $action value is unrecognized.
     * @throws LSCMException  Thrown indirectly by $this->init() call.
     */
    public function __construct( $action )
    {
        switch ( $action ) {

            case 'flag':
            case 'unflag':
                $this->action = $action;
                break;

            default:
                throw new LSCMException(
                    'Unrecognized $action value passed to FlagUnflagAllProgressViewModel constructor.'
                );
        }

        $this->init();
    }

    /**
     *
     * @throws LSCMException  Thrown indirectly by $this->setIconPath() call.
     */
    protected function init()
    {
        $this->setIconPath();
        $this->setAction();
        $this->grabSessionData();
    }

    /**
     *
     * @param string $field
     *
     * @return null|int|string
     */
    public function getTplData( $field )
    {
        if ( !isset($this->tplData[$field]) ) {
            return null;
        }

        return $this->tplData[$field];
    }

    /**
     *
     * @throws LSCMException  Thrown indirectly by Logger::debug() call.
     */
    protected function setIconPath()
    {
        $iconPath = '';

        try
        {
            $iconPath = Context::getOption()->getIconDir()
                . '/manageCacheInstallations.svg';
        }
        catch ( LSCMException $e )
        {
            Logger::debug("{$e->getMessage()}. Could not get icon directory.");
        }

        $this->tplData[self::FLD_ICON] = $iconPath;
    }

    protected function setAction()
    {
        $this->tplData[self::FLD_ACTION] = $this->action;
    }

    protected function grabSessionData()
    {
        $this->tplData[self::FLD_INSTALLS_COUNT] =
            count($_SESSION['mass_' . $this->action . '_info']['installs']);
    }

    /**
     *
     * @return string
     *
     * @throws LSCMException  Thrown indirectly by Context::getOption() call.
     */
    public function getTpl()
    {
        return Context::getOption()->getSharedTplDir()
            . '/FlagUnflagAllProgress.tpl';
    }

}
webcachemgr/src/View/Model/Ajax/CacheMgrRowViewModel.php000066400000022475150545647720017160 0ustar00<?php

/** ******************************************
 * LiteSpeed Web Server Cache Manager
 *
 * @author    Michael Alegre
 * @copyright 2018-2025 LiteSpeed Technologies, Inc.
 * ******************************************* */

namespace Lsc\Wp\View\Model\Ajax;

use Lsc\Wp\Context\Context;
use Lsc\Wp\LSCMException;
use Lsc\Wp\PluginVersion;
use Lsc\Wp\Util;
use Lsc\Wp\WPInstall;

class CacheMgrRowViewModel
{

    const FLD_LIST_DATA = 'listData';

    /**
     * @var WPInstall
     */
    protected $wpInstall;

    /**
     * @var array
     */
    protected $tplData = array();

    /**
     *
     * @param WPInstall $wpInstall
     */
    public function __construct( WPInstall $wpInstall )
    {
        $this->wpInstall = $wpInstall;

        $this->init();
    }

    protected function init()
    {
        $this->getActiveVerData();
        $this->setListRowData();
    }

    /**
     *
     * @param string $field
     *
     * @return null|mixed
     */
    public function getTplData( $field )
    {
        if ( !isset($this->tplData[$field]) ) {
            return null;
        }

        return $this->tplData[$field];
    }

    /**
     *
     * @param string $type
     *
     * @return string
     */
    public function getSortVal( $type )
    {
        $listData = $this->getTplData(self::FLD_LIST_DATA);

        return $listData[$this->wpInstall->getPath()]["{$type}Data"]['sort'];
    }

    protected function setListRowData()
    {
        $this->tplData[self::FLD_LIST_DATA] = [
            $this->wpInstall->getPath() => [
                'statusData' => $this->getStatusDisplayData(),
                'flagData'   => $this->getFlagDisplayData(),
                'siteUrl'    => Util::tryIdnToUtf8(
                    (string)$this->wpInstall->getData(WPInstall::FLD_SITEURL)
                )
            ]
        ];
    }

    /**
     *
     * @return string[]
     */
    protected function getStatusDisplayData()
    {
        $statusInfo = [
            'disabled'               => [
                'sort'           => 'disabled',
                'state'          => '<span '
                    . 'class="glyphicon glyphicon-flash status-disabled" '
                    . 'data-uk-tooltip title="LSCWP is disabled."></span>',
                'btn_content'    => '<span class="enable_btn"></span>',
                'btn_title'      => 'Click to enable LSCache',
                'onclick'        =>
                    'onclick="javascript:lscwpEnableSingle(this);"',
                'btn_attributes' => 'data-uk-tooltip',
                'btn_state'      => ''
            ],
            'enabled'                => [
                'sort'           => 'enabled',
                'state'          => '<span '
                    . 'class="glyphicon glyphicon-flash status-enabled" '
                    . 'data-uk-tooltip title="LSCWP is enabled."></span>',
                'btn_content'    => '<span class="disable_btn"></span>',
                'btn_title'      => 'Click to disable LSCache',
                'onclick'        =>
                    'onclick="javascript:lscwpDisableSingle(this);"',
                'btn_attributes' => 'data-uk-tooltip',
                'btn_state'      => ''
            ],
            'adv_cache'              => [
                'sort'           => 'warning',
                'state'          => '<span class="status-warning" '
                    . 'data-uk-tooltip '
                    . 'title="LSCache is enabled but not caching. Please visit '
                    . 'the WordPress Dashboard for more information."></span>',
                'btn_content'    => '<span class="disable_btn"></span>',
                'btn_title'      => 'Click to disable LSCache',
                'onclick'        =>
                    'onclick="javascript:lscwpDisableSingle(this);"',
                'btn_attributes' => 'data-uk-tooltip',
                'btn_state'      => ''
            ],
            'disabled_no_active_ver' => [
                'sort'           => 'disabled',
                'state'          => '<span '
                    . 'class="glyphicon glyphicon-flash status-disabled" '
                    . 'data-uk-tooltip title="LSCWP is disabled."></span>',
                'btn_content'    => '<span class="inactive-action-btn" '
                    . 'data-uk-tooltip '
                    . 'title="No active LSCWP version set! Cannot enable '
                    . 'LSCache."></span>',
                'onclick'        => '',
                'btn_attributes' => '',
                'btn_state'      => 'disabled'
            ],
            'error'                  => [
                'sort'           => 'error',
                /**
                 * 'state' added individually later.
                 */
                'btn_title'      => '',
                'btn_content'    => '<span class="inactive-action-btn"></span>',
                'onclick'        => '',
                'btn_attributes' => '',
                'btn_state'      => 'disabled'
            ],
            'removed'                => [
                'sort'           => 'removed',
                'state'          => '<span class="status-removed" '
                    . 'data-uk-tooltip '
                    . 'title="Installation could not be found and has been '
                    . 'removed."></span>',
                'btn_content'    => '<span class="inactive-action-btn"></span>',
                'onclick'        => '',
                'btn_attributes' => '',
                'btn_state'      => 'disabled'
            ]
        ];

        $wpStatus = $this->wpInstall->getStatus();

        if ( $wpStatus & WPInstall::ST_ERR_REMOVE ) {
            $currStatusData = $statusInfo['removed'];
        }
        elseif ( $this->wpInstall->hasFatalError($wpStatus) ) {
            $fatalErrStateInfo =
                Util::getFatalErrorStateMessageAndLink($wpStatus);

            $currStatusData          = $statusInfo['error'];
            $currStatusData['state'] = '<a '
                . "href=\"{$fatalErrStateInfo['link']}\" "
                . 'target="_blank" rel="noopener" data-uk-tooltip '
                . "title =\"{$fatalErrStateInfo['stateMsg']}\" "
                . 'class="status-error"></a>';
        }
        elseif ( ($wpStatus & WPInstall::ST_PLUGIN_INACTIVE ) ) {

            if ( !$this->getActiveVerData() ) {
                $currStatusData = $statusInfo['disabled_no_active_ver'];
            }
            else {
                $currStatusData = $statusInfo['disabled'];
            }
        }
        elseif ( !($wpStatus & WPInstall::ST_LSC_ADVCACHE_DEFINED) ) {
            $currStatusData = $statusInfo['adv_cache'];
        }
        else {
            $currStatusData = $statusInfo['enabled'];
        }

        return $currStatusData;
    }

    /**
     *
     * @return string[]
     */
    protected function getFlagDisplayData()
    {
        $flagInfo = [
            0 => [
                'sort' => 'unflagged',
                'icon'           => '<span '
                    . 'class="glyphicon glyphicon-flag ls-flag ls-flag-unset"'
                    . '></span>',
                'btn_title'      => 'Click to set flag',
                'onclick'        => 'onclick="lscwpFlagSingle(this);"',
                'btn_attributes' => 'data-uk-tooltip'
            ],
            1 => [
                'sort'           => 'flagged',
                'icon'           => '<span '
                    . 'class="glyphicon glyphicon-flag ls-flag ls-flag-set"'
                    . '></span>',
                'btn_title'      => 'Click to unset flag',
                'onclick'        => 'onclick="lscwpUnflagSingle(this);"',
                'btn_attributes' => 'data-uk-tooltip'
            ],
            2 => [
                'sort'           => 'removed',
                'icon'           => '<span '
                    . 'class="glyphicon glyphicon-flag ls-flag ls-flag-removed"'
                    . '></span>',
                'btn_title'      => '',
                'onclick'        => '',
                'btn_attributes' => ''
            ]
        ];

        $wpStatus = $this->wpInstall->getStatus();

        if ( $wpStatus & WPInstall::ST_ERR_REMOVE ) {
            $currFlagData = $flagInfo[2];
        }
        elseif ( ($wpStatus & WPInstall::ST_FLAGGED ) ) {
            $currFlagData = $flagInfo[1];
        }
        else {
            $currFlagData = $flagInfo[0];
        }

        return $currFlagData;
    }

    /**
     *
     * @return bool|string
     */
    protected function getActiveVerData()
    {
        try {
            return PluginVersion::getCurrentVersion();
        }
        catch ( LSCMException $e ) {
            //don't care about the exception in ajax load.
            return false;
        }

    }

    /**
     *
     * @param string $tplID
     *
     * @return null|string
     *
     * @throws LSCMException  Thrown indirectly by Context::getOption() call.
     */
    public function getTpl( $tplID )
    {
        $sharedTplDir = Context::getOption()->getSharedTplDir();

        switch ( $tplID ) {

            case 'actions_td':
                return "$sharedTplDir/Ajax/CacheMgrActionsCol.tpl";

            case 'status_td':
                return "$sharedTplDir/Ajax/CacheMgrStatusCol.tpl";

            case 'flag_td':
                return "$sharedTplDir/Ajax/CacheMgrFlagCol.tpl";

            //no default
        }
    }

}
webcachemgr/src/View/Model/MassEnableDisableProgressViewModel.php000066400000006473150545647720021157 0ustar00<?php

/** ******************************************
 * LiteSpeed Web Server Cache Manager
 *
 * @author    Michael Alegre
 * @copyright 2018-2025 LiteSpeed Technologies, Inc.
 * ******************************************* */

namespace Lsc\Wp\View\Model;

use Lsc\Wp\Context\Context;
use Lsc\Wp\PluginVersion;
use Lsc\Wp\LSCMException;
use Lsc\Wp\Logger;

class MassEnableDisableProgressViewModel
{

    const FLD_ICON           = 'icon';
    const FLD_ACTION         = 'action';
    const FLD_INSTALLS_COUNT = 'installsCount';
    const FLD_ACTIVE_VER     = 'activeVer';

    /**
     * @var string
     */
    protected $action;

    /**
     * @var string
     */
    protected $sessionKey;

    /**
     * @var array
     */
    protected $tplData = array();

    /**
     *
     * @param string $action
     *
     * @throws LSCMException  Thrown indirectly by $this->init() call.
     */
    public function __construct( $action )
    {
        $this->action     = $action;
        $this->sessionKey = 'mass' . ucfirst($this->action) . 'Info';

        $this->init();
    }

    /**
     *
     * @throws LSCMException  Thrown indirectly by $this->setIconPath().
     * @throws LSCMException  Thrown indirectly by $this->setActiveVerData()
     *     call.
     */
    protected function init()
    {
        $this->setIconPath();

        $this->tplData[self::FLD_ACTION] = $this->action;

        $this->grabSessionData();
        $this->setActiveVerData();
    }

    /**
     *
     * @param string $field
     *
     * @return null|mixed
     */
    public function getTplData( $field )
    {
        if ( !isset($this->tplData[$field]) ) {
            return null;
        }

        return $this->tplData[$field];
    }

    /**
     *
     * @throws LSCMException  Thrown indirectly by Logger::debug() call.
     */
    protected function setIconPath()
    {
        $iconPath = '';

        try
        {
            $iconPath = Context::getOption()->getIconDir()
                . '/massEnableDisableCache.svg';
        }
        catch ( LSCMException $e )
        {
            Logger::debug("{$e->getMessage()} Could not get icon directory.");
        }

        $this->tplData[self::FLD_ICON] = $iconPath;
    }

    protected function grabSessionData()
    {
        $info = $_SESSION[$this->sessionKey];

        $this->tplData[self::FLD_INSTALLS_COUNT] = count($info['installs']);
    }

    /**
     *
     * @throws LSCMException  Thrown indirectly by Logger::debug() call.
     */
    protected function setActiveVerData()
    {
        try {
            $activeVer = PluginVersion::getCurrentVersion();
        }
        catch ( LSCMException $e ) {
            Logger::debug(
                "{$e->getMessage()} Could not get active LSCWP version."
            );

            $activeVer = false;

            /**
             * Unset session data early.
             */
            if ( $this->tplData[self::FLD_ACTION] == 'enable' ) {
                unset($_SESSION[$this->sessionKey]);
            }
        }

        $this->tplData[self::FLD_ACTIVE_VER] = $activeVer;
    }

    /**
     *
     * @return string
     *
     * @throws LSCMException  Thrown indirectly by Context::getOption() call.
     */
    public function getTpl()
    {
        return Context::getOption()->getSharedTplDir()
            . '/MassEnableDisableProgress.tpl';
    }

}
webcachemgr/src/View/Model/UnflagAllProgressViewModel.php000066400000004062150545647720017516 0ustar00<?php

/** ******************************************
 * LiteSpeed Web Server Cache Manager
 *
 * @author    Michael Alegre
 * @copyright 2018-2025 LiteSpeed Technologies, Inc.
 * ******************************************* */

namespace Lsc\Wp\View\Model;

use Lsc\Wp\Context\Context;
use Lsc\Wp\Logger;
use Lsc\Wp\LSCMException;

class UnflagAllProgressViewModel
{

    const FLD_ICON           = 'icon';
    const FLD_INSTALLS_COUNT = 'installsCount';

    /**
     * @var (int|string)[]
     */
    protected $tplData = [];

    /**
     *
     * @throws LSCMException  Thrown indirectly by $this->init() call.
     */
    public function __construct()
    {
        $this->init();
    }

    /**
     *
     * @throws LSCMException  Thrown indirectly by $this->setIconPath() call.
     */
    protected function init()
    {
        $this->setIconPath();
        $this->grabSessionData();
    }

    /**
     *
     * @param string $field
     *
     * @return null|int|string
     */
    public function getTplData( $field )
    {
        if ( !isset($this->tplData[$field]) ) {
            return null;
        }

        return $this->tplData[$field];
    }

    /**
     *
     * @throws LSCMException  Thrown indirectly by Logger::debug() call.
     */
    protected function setIconPath()
    {
        $iconPath = '';

        try
        {
            $iconPath = Context::getOption()->getIconDir()
                . '/manageCacheInstallations.svg';
        }
        catch ( LSCMException $e )
        {
            Logger::debug("{$e->getMessage()}. Could not get icon directory.");
        }

        $this->tplData[self::FLD_ICON] = $iconPath;
    }

    protected function grabSessionData()
    {
        $this->tplData[self::FLD_INSTALLS_COUNT] =
            count($_SESSION['unflagInfo']['installs']);
    }

    /**
     *
     * @return string
     *
     * @throws LSCMException  Thrown indirectly by Context::getOption() call.
     */
    public function getTpl()
    {
        return Context::getOption()->getSharedTplDir()
            . '/UnflagAllProgress.tpl';
    }

}
webcachemgr/src/View/Model/MassDashDisableProgressViewModel.php000066400000004176150545647720020646 0ustar00<?php

/** ******************************************
 * LiteSpeed Web Server Cache Manager
 *
 * @author    Michael Alegre
 * @copyright 2019-2025 LiteSpeed Technologies, Inc.
 * ******************************************* */

namespace Lsc\Wp\View\Model;

use Lsc\Wp\Context\Context;
use Lsc\Wp\LSCMException;
use Lsc\Wp\Logger;

class MassDashDisableProgressViewModel
{

    const FLD_ICON           = 'icon';
    const FLD_INSTALLS_COUNT = 'installsCount';

    /**
     * @var string
     */
    protected $sessionKey = 'massDashDisableInfo';

    /**
     * @var array
     */
    protected $tplData = array();

    /**
     *
     * @throws LSCMException  Thrown indirectly by $this->init() call.
     */
    public function __construct()
    {
        $this->init();
    }

    /**
     *
     * @throws LSCMException  Thrown indirectly by $this->setIconPath() call.
     */
    protected function init()
    {
        $this->setIconPath();
        $this->grabSessionData();
    }

    /**
     *
     * @param string $field
     *
     * @return null|mixed
     */
    public function getTplData( $field )
    {
        if ( !isset($this->tplData[$field]) ) {
            return null;
        }

        return $this->tplData[$field];
    }

    /**
     *
     * @throws LSCMException  Thrown indirectly by Logger::debug() call.
     */
    protected function setIconPath()
    {
        $iconPath = '';

        try
        {
            $iconPath = Context::getOption()->getIconDir() . '/wpNotifier.svg';
        }
        catch ( LSCMException $e )
        {
            Logger::debug("{$e->getMessage()} Could not get icon directory.");
        }

        $this->tplData[self::FLD_ICON] = $iconPath;
    }

    protected function grabSessionData()
    {
        $info = $_SESSION[$this->sessionKey];

        $this->tplData[self::FLD_INSTALLS_COUNT] = count($info['installs']);
    }

    /**
     *
     * @return string
     *
     * @throws LSCMException  Thrown indirectly by Context::getOption() call.
     */
    public function getTpl()
    {
        return Context::getOption()->getSharedTplDir()
            . '/MassDashDisableProgress.tpl';
    }

}
webcachemgr/src/View/Model/VersionChangeViewModel.php000066400000003366150545647720016665 0ustar00<?php

/* * ******************************************
 * LiteSpeed Web Server Cache Manager
 * @author: LiteSpeed Technologies, Inc. (https://www.litespeedtech.com)
 * @copyright: (c) 2018-2019
 * ******************************************* */

namespace Lsc\Wp\View\Model;

use \Lsc\Wp\Context\Context;
use \Lsc\Wp\LSCMException;
use \Lsc\Wp\Logger;

class VersionChangeViewModel
{

    const FLD_ICON = 'icon';
    const FLD_INSTALLS_COUNT = 'installsCount';
    const FLD_VER_NUM = 'verNum';

    /**
     * @var (int|string)[]
     */
    protected $tplData = array();

    public function __construct()
    {
        $this->init();
    }

    protected function init()
    {
        $this->setIconPath();
        $this->grabSessionData();
    }

    /**
     *
     * @param string  $field
     * @return null|int|string
     */
    public function getTplData( $field )
    {
        if ( !isset($this->tplData[$field]) ) {
            return null;
        }

        return $this->tplData[$field];
    }

    protected function setIconPath()
    {
        $iconPath = '';

        try
        {
            $iconDir = Context::getOption()->getIconDir();
            $iconPath = "{$iconDir}/lscwpCurrentVersion.svg";
        }
        catch ( LSCMException $e )
        {
            Logger::debug($e->getMessage() . ' Could not get icon directory.');
        }

        $this->tplData[self::FLD_ICON] = $iconPath;
    }

    protected function grabSessionData()
    {
        $info = $_SESSION['verInfo'];

        $this->tplData[self::FLD_INSTALLS_COUNT] = count($info['installs']);
        $this->tplData[self::FLD_VER_NUM] = $info['verNum'];
    }

    public function getTpl()
    {
        return Context::getOption()->getSharedTplDir() . '/VersionChange.tpl';
    }

}
webcachemgr/src/View/Model/MassDashNotifyProgressViewModel.php000066400000004247150545647720020552 0ustar00<?php

/** ******************************************
 * LiteSpeed Web Server Cache Manager
 *
 * @author    Michael Alegre
 * @copyright 2019-2025 LiteSpeed Technologies, Inc.
 * ******************************************* */

namespace Lsc\Wp\View\Model;

use Lsc\Wp\Context\Context;
use Lsc\Wp\LSCMException;
use Lsc\Wp\Logger;

class MassDashNotifyProgressViewModel
{

    const FLD_ICON           = 'icon';
    const FLD_INSTALLS_COUNT = 'installsCount';
    const FLD_ACTIVE_VER     = 'activeVer';

    /**
     * @var string
     */
    protected $sessionKey = 'massDashNotifyInfo';

    /**
     * @var array
     */
    protected $tplData = array();

    /**
     *
     * @throws LSCMException  Thrown indirectly by $this->init() call.
     */
    public function __construct()
    {
        $this->init();
    }

    /**
     *
     * @throws LSCMException  Thrown indirectly by $this->setIconPath() call.
     */
    protected function init()
    {
        $this->setIconPath();
        $this->grabSessionData();
    }

    /**
     *
     * @param string $field
     *
     * @return null|mixed
     */
    public function getTplData( $field )
    {
        if ( !isset($this->tplData[$field]) ) {
            return null;
        }

        return $this->tplData[$field];
    }

    /**
     *
     * @throws LSCMException  Thrown indirectly by Logger::debug() call.
     */
    protected function setIconPath()
    {
        $iconPath = '';

        try
        {
            $iconPath = Context::getOption()->getIconDir() . '/wpNotifier.svg';
        }
        catch ( LSCMException $e )
        {
            Logger::debug("{$e->getMessage()} Could not get icon directory.");
        }

        $this->tplData[self::FLD_ICON] = $iconPath;
    }

    protected function grabSessionData()
    {
        $info = $_SESSION[$this->sessionKey];

        $this->tplData[self::FLD_INSTALLS_COUNT] = count($info['installs']);
    }

    /**
     *
     * @return string
     *
     * @throws LSCMException  Thrown indirectly by Context::getOption() call.
     */
    public function getTpl()
    {
        return Context::getOption()->getSharedTplDir()
            . '/MassDashNotifyProgress.tpl';
    }

}
webcachemgr/src/WPInstallStorage.php000066400000102362150545647720013542 0ustar00<?php

/** *********************************************
 * LiteSpeed Web Server Cache Manager
 *
 * @author    Michael Alegre
 * @copyright 2018-2025 LiteSpeed Technologies, Inc.
 * *******************************************
 */

namespace Lsc\Wp;

use Lsc\Wp\Context\Context;
use Lsc\Wp\Panel\ControlPanel;
use Lsc\Wp\ThirdParty\Polyfill\Utf8;

/**
 * map to data file
 */
class WPInstallStorage
{

    /**
     * @var string
     */
    const CMD_ADD_CUST_WPINSTALLS     = 'addCustWPInstalls';

    /**
     * @since 1.13.3
     * @var string
     */
    const CMD_ADD_NEW_WPINSTALL       = 'addNewWPInstall';

    /**
     * @deprecated 1.13.3  Use CMD_DISCOVER_NEW2 instead.
     * @var string
     */
    const CMD_DISCOVER_NEW            = 'discoverNew';

    /**
     * @since 1.14
     * @var string
     */
    const CMD_DISCOVER_NEW_AND_ENABLE = 'discoverNewAndEnable';

    /**
     * @since 1.13.3
     * @var string
     */
    const CMD_DISCOVER_NEW2           = 'discoverNew2';

    /**
     * @var string
     */
    const CMD_FLAG                    = 'flag';

    /**
     * @var string
     */
    const CMD_MASS_FLAG               = 'mass_flag';

    /**
     * @var string
     */
    const CMD_MASS_UNFLAG             = 'mass_unflag';

    /**
     * @deprecated 1.13.3  Use CMD_SCAN2 instead for now.
     * @var string
     */
    const CMD_SCAN                    = 'scan';

    /**
     * @since 1.13.3
     * @var string
     */
    const CMD_SCAN2                   = 'scan2';

    /**
     * @var string
     */
    const CMD_UNFLAG                  = 'unflag';

    /**
     * @var string
     */
    const DATA_VERSION = '1.5';

    /**
     * @var int
     */
    const ERR_NOT_EXIST    = 1;

    /**
     * @var int
     */
    const ERR_CORRUPTED    = 2;

    /**
     * @var int
     */
    const ERR_VERSION_HIGH = 3;

    /**
     * @var int
     */
    const ERR_VERSION_LOW  = 4;

    /**
     * @var string
     */
    protected $dataFile;

    /**
     * @var string
     */
    protected $customDataFile;

    /**
     * @var null|WPInstall[]  Key is the path to a WordPress installation.
     */
    protected $wpInstalls = null;

    /**
     * @var null|WPInstall[]  Key is the path to a WordPress installation.
     */
    protected $custWpInstalls = null;

    /**
     * @var int
     */
    protected $error;

    /**
     * @var WPInstall[]
     */
    protected $workingQueue = [];

    /**
     *
     * @param string $dataFile
     * @param string $custDataFile
     *
     * @throws LSCMException  Thrown indirectly by $this->init() call.
     */
    public function __construct( $dataFile, $custDataFile = '' )
    {
        $this->dataFile       = $dataFile;
        $this->customDataFile = $custDataFile;
        $this->error          = $this->init();
    }

    /**
     *
     * @return int
     *
     * @throws LSCMException  Thrown indirectly by Logger::debug() call.
     */
    protected function init()
    {
        $dataExists = false;

        try {

            if ( file_exists($this->dataFile) ) {
                $dataExists       = true;
                $this->wpInstalls = $this->getDataFileData($this->dataFile);
            }

            if (
                    $this->customDataFile != ''
                    &&
                    file_exists($this->customDataFile)
            ) {
                $dataExists           = true;
                $this->custWpInstalls =
                    $this->getDataFileData($this->customDataFile);
            }
        }
        catch ( LSCMException $e ) {
            Logger::debug($e->getMessage());
            return $e->getCode();
        }

        if ( !$dataExists ) {
            return self::ERR_NOT_EXIST;
        }

        return 0;
    }

    /**
     *
     * @since 1.15
     *
     * @param string $dataFile
     *
     * @return false|string
     */
    protected static function getDataFileContents( $dataFile )
    {
        return file_get_contents($dataFile);
    }

    /**
     *
     * @param string $dataFile
     *
     * @return WPInstall[]
     *
     * @throws LSCMException  Thrown when data file is corrupt.
     * @throws LSCMException  Thrown when there is a data file version issue.
     * @throws LSCMException  Thrown indirectly by $this->verifyDataFileVer()
     *     call.
     */
    protected function getDataFileData( $dataFile )
    {
        $content = static::getDataFileContents($dataFile);

        if ( ($data = json_decode($content, true)) === null ) {
            /**
             * Data file may be in old serialized format. Try unserializing.
             */
             $data = unserialize($content);
        }

        if ( $data === false || !is_array($data) || !isset($data['__VER__']) ) {
            throw new LSCMException(
                "$dataFile - Data is corrupt.",
                self::ERR_CORRUPTED
            );
        }

        if ( ($err = $this->verifyDataFileVer($dataFile, $data['__VER__'])) ) {
            throw new LSCMException(
                "$dataFile - Data file version issue.",
                $err
            );
        }

        unset($data['__VER__']);

        $wpInstalls = [];

        foreach ( $data as $utf8Path => $idata ) {
            $path = Utf8::decode($utf8Path);
            $i    = new WPInstall($path);

            $idata[WPInstall::FLD_SITEURL]    =
                urldecode((string)$idata[WPInstall::FLD_SITEURL]);
            $idata[WPInstall::FLD_SERVERNAME] =
                urldecode((string)$idata[WPInstall::FLD_SERVERNAME]);

            $i->initData($idata);
            $wpInstalls[$path] = $i;
        }

        return $wpInstalls;
    }

    /**
     *
     * @return int
     */
    public function getError()
    {
        return $this->error;
    }

    /**
     *
     * @param bool $nonFatalOnly
     *
     * @return int
     */
    public function getCount( $nonFatalOnly = false )
    {
        $count = 0;

        if ( $this->wpInstalls != null ) {

            if ( $nonFatalOnly ) {

                foreach ( $this->wpInstalls as $install ) {

                    if ( !$install->hasFatalError() ) {
                        $count++;
                    }
                }
            }
            else {
                $count += count($this->wpInstalls);
            }
        }

        if ( $this->custWpInstalls != null ) {

            if ( $nonFatalOnly ) {

                foreach ( $this->custWpInstalls as $custInstall ) {

                    if ( !$custInstall->hasFatalError() ) {
                        $count++;
                    }
                }
            }
            else {
                $count += count($this->custWpInstalls);
            }
        }

        return $count;
    }

    /**
     *
     * @return null|WPInstall[]
     *
     * @noinspection PhpUnused
     */
    public function getWPInstalls()
    {
        return $this->wpInstalls;
    }

    /**
     *
     * @return null|WPInstall[]
     *
     * @noinspection PhpUnused
     */
    public function getCustWPInstalls()
    {
        return $this->custWpInstalls;
    }

    /**
     *
     * @return null|WPInstall[]
     */
    public function getAllWPInstalls()
    {
        if ( $this->wpInstalls != null ) {

            if ( $this->custWpInstalls != null ) {
                return array_merge($this->wpInstalls, $this->custWpInstalls);
            }
            else {
                return $this->wpInstalls;
            }
        }
        elseif ( $this->custWpInstalls != null ) {
            return $this->custWpInstalls;
        }
        else {
            return null;
        }
    }

    /**
     * Get all known WPInstall paths.
     *
     * @return string[]
     */
    public function getPaths()
    {
        $paths = [];

        if ( $this->wpInstalls != null ) {
            $paths = array_keys($this->wpInstalls);
        }

        if ( $this->custWpInstalls != null ) {
            $paths = array_merge($paths, array_keys($this->custWpInstalls));
        }

        return $paths;
    }

    /**
     *
     * @param string $path
     *
     * @return WPInstall|null
     */
    public function getWPInstall( $path )
    {
        if ( ($realPath = realpath($path)) === false ) {
            $index = $path;
        }
        else {
            $index = $realPath;
        }

        if ( isset($this->wpInstalls[$index]) ) {
            return $this->wpInstalls[$index];
        }
        elseif ( isset($this->custWpInstalls[$index]) ) {
            return $this->custWpInstalls[$index];
        }

        return null;
    }

    /**
     *
     * @return WPInstall[]
     */
    public function getWorkingQueue()
    {
        return $this->workingQueue;
    }

    /**
     *
     * @param WPInstall $wpInstall
     */
    public function addWPInstall( WPInstall $wpInstall )
    {
        $this->wpInstalls[$wpInstall->getPath()] = $wpInstall;
    }

    /**
     *
     * @throws LSCMException  Thrown indirectly by $this->saveDataFile() call.
     * @throws LSCMException  Thrown indirectly by $this->saveDataFile() call.
     */
    public function syncToDisk()
    {
        $this->saveDataFile($this->dataFile, $this->wpInstalls);

        if ( $this->customDataFile != '' ) {
            $this->saveDataFile($this->customDataFile, $this->custWpInstalls);
        }
    }

    /**
     *
     * @param string           $dataFile
     * @param WPInstall[]|null $wpInstalls
     *
     * @throws LSCMException  Thrown indirectly by $this->log() call.
     */
    protected function saveDataFile( $dataFile, $wpInstalls )
    {
        $data = [ '__VER__' => self::DATA_VERSION ];

        if ( !empty($wpInstalls) ) {

            foreach ( $wpInstalls as $path => $install ) {

                if ( !$install->shouldRemove() ) {
                    $utf8Path = Utf8::encode($path);

                    $data[$utf8Path] = $install->getData();

                    $siteUrl = &$data[$utf8Path][WPInstall::FLD_SITEURL];

                    if ( $siteUrl != null ) {
                        $siteUrl = urlencode($siteUrl);
                    }

                    $serverName = &$data[$utf8Path][WPInstall::FLD_SERVERNAME];

                    if ( $serverName != null ) {
                        $serverName = urlencode($serverName);
                    }
                }
            }

            ksort($data);
        }

        file_put_contents($dataFile, json_encode($data), LOCK_EX);
        chmod($dataFile, 0600);

        $this->log("Data file saved $dataFile", Logger::L_DEBUG);
    }

    /**
     *
     * @param string $dataFile
     * @param string $dataFileVer
     *
     * @return int
     *
     * @throws LSCMException  Thrown indirectly by Logger::info() call.
     * @throws LSCMException  Thrown indirectly by $this->updateDataFile() call.
     */
    protected function verifyDataFileVer( $dataFile, $dataFileVer )
    {
        $res = Util::betterVersionCompare($dataFileVer, self::DATA_VERSION);

        if ( $res == 1 ) {
            Logger::info(
                'Data file version is higher than expected and cannot be used.'
            );

            return self::ERR_VERSION_HIGH;
        }

        if ( $res == -1 && !$this->updateDataFile($dataFile, $dataFileVer) ) {
            return self::ERR_VERSION_LOW;
        }

        return 0;
    }

    /**
     *
     * @param string $dataFile
     * @param string $dataFileVer
     *
     * @return bool
     *
     * @throws LSCMException  Thrown indirectly by Logger::info() call.
     * @throws LSCMException  Thrown indirectly by Util::createBackup() call.
     * @throws LSCMException  Thrown indirectly by Logger::error() call.
     */
    public static function updateDataFile( $dataFile, $dataFileVer )
    {
        Logger::info(
            "$dataFile - Old data file version detected. Attempting to "
                . 'update...'
        );

        /**
         * Currently no versions are upgradeable to 1.5
         */
        $updatableVersions = [];

        if (
                !in_array($dataFileVer, $updatableVersions)
                ||
                ! Util::createBackup($dataFile)
        ) {
            Logger::error(
                "$dataFile - Data file could not be updated to version "
                    . self::DATA_VERSION
            );

            return false;
        }

        /**
         * Upgrade funcs will be called here.
         */

        return true;
    }

    /**
     *
     * @param string $action
     *
     * @return string[]
     *
     * @throws LSCMException  Thrown when "get docroots" command fails.
     * @throws LSCMException  Thrown when $action value is unsupported.
     */
    protected function prepareActionItems( $action )
    {
        switch ( $action ) {

            case self::CMD_SCAN:
            case self::CMD_SCAN2:
            case self::CMD_DISCOVER_NEW:
            case self::CMD_DISCOVER_NEW2:

                try
                {
                    return ControlPanel::getClassInstance()->getDocRoots();
                }
                catch ( LSCMException $e )
                {
                    throw new LSCMException(
                        $e->getMessage()
                            . " Could not prepare $action action items."
                    );
                }

            case UserCommand::CMD_MASS_ENABLE:
            case UserCommand::CMD_MASS_DISABLE:
            case UserCommand::CMD_MASS_UPGRADE:
            case UserCommand::CMD_MASS_DASH_NOTIFY:
            case UserCommand::CMD_MASS_DASH_DISABLE:
            case self::CMD_MASS_UNFLAG:
                return $this->getPaths();

            default:
                throw new LSCMException('Missing parameter(s).');
        }
    }

    /**
     *
     * @param string   $action
     * @param string   $path
     * @param string[] $extraArgs
     *
     * @throws LSCMException  Thrown when an invalid LSCWP version is selected
     *     in action UserCommand::CMD_MASS_UPGRADE.
     * @throws LSCMException  Thrown when LSCWP version fails to download in
     *     action UserCommand::CMD_MASS_UPGRADE.
     * @throws LSCMException  Thrown when LSCWP source package is not available
     *     in action UserCommand::CMD_MASS_UPGRADE.
     * @throws LSCMException  Thrown indirectly by $wpInstall->hasValidPath()
     *     call.
     * @throws LSCMException  Thrown indirectly by $wpInstall->addUserFlagFile()
     *     call.
     * @throws LSCMException  Thrown indirectly by $wpInstall->hasValidPath()
     *     call.
     * @throws LSCMException  Thrown indirectly by $wpInstall->refreshStatus()
     *     call.
     * @throws LSCMException  Thrown indirectly by $wpInstall->addUserFlagFile()
     *     call.
     * @throws LSCMException  Thrown indirectly by PluginVersion::getInstance()
     *     call.
     * @throws LSCMException  Thrown indirectly by
     *     PluginVersion::getInstance()->getAllowedVersions() call.
     * @throws LSCMException  Thrown indirectly by UserCommand::issue() call.
     * @throws LSCMException  Thrown indirectly by $this->syncToDisk() call.
     * @throws LSCMException  Thrown indirectly by $this->syncToDisk() call.
     */
    protected function doWPInstallAction( $action, $path, array $extraArgs )
    {
        if ( ($wpInstall = $this->getWPInstall($path)) == null ) {
            $wpInstall = new WPInstall($path);
            $this->addWPInstall($wpInstall);
        }

        switch ( $action ) {

            case self::CMD_FLAG:
            case self::CMD_MASS_FLAG:

                if ( !$wpInstall->hasValidPath() ) {
                    return;
                }

                if ( $wpInstall->addUserFlagFile(false) ) {
                    $wpInstall->setCmdStatusAndMsg(
                        UserCommand::EXIT_SUCC,
                        'Flag file set'
                    );
                }
                else {
                    $wpInstall->setCmdStatusAndMsg(
                        UserCommand::EXIT_FAIL,
                        'Could not create flag file'
                    );
                }

                $this->workingQueue[$path] = $wpInstall;
                return;

            case self::CMD_UNFLAG:
            case self::CMD_MASS_UNFLAG:

                if ( !$wpInstall->hasValidPath() ) {
                    return;
                }

                $wpInstall->removeFlagFile();

                $wpInstall->setCmdStatusAndMsg(
                    UserCommand::EXIT_SUCC,
                    'Flag file unset'
                );

                $this->workingQueue[$path] = $wpInstall;
                return;

            case UserCommand::CMD_ENABLE:
            case UserCommand::CMD_DISABLE:
            case UserCommand::CMD_DASH_NOTIFY:
            case UserCommand::CMD_DASH_DISABLE:

                if ( $wpInstall->hasFatalError() ) {
                    $wpInstall->refreshStatus();

                    if ( $wpInstall->hasFatalError() ) {
                        $wpInstall->addUserFlagFile(false);

                        $wpInstall->setCmdStatusAndMsg(
                            UserCommand::EXIT_FAIL,
                            'Install skipped and flagged due to Error status.'
                        );

                        $this->workingQueue[$path] = $wpInstall;
                        return;
                    }
                }

                break;

            case UserCommand::CMD_MASS_UPGRADE:
                $lscwpVer     = $extraArgs[1];
                $isAllowedVer = in_array(
                    $lscwpVer,
                    PluginVersion::getInstance()->getAllowedVersions()
                );

                if ( !$isAllowedVer ) {
                    throw new LSCMException(
                        'Selected LSCWP version ('
                            . htmlspecialchars($lscwpVer)
                            . ') is invalid.'
                    );
                }
                break;

            //no default
        }

        if ( UserCommand::issue($action, $wpInstall, $extraArgs) ) {

            if (
                    $action == UserCommand::CMD_MASS_UPGRADE
                    &&
                    ($wpInstall->getCmdStatus() & UserCommand::EXIT_FAIL)
                    &&
                    preg_match(
                        '/Download failed. Not Found/',
                        $wpInstall->getCmdMsg()
                    )
            ) {
                $this->syncToDisk();

                throw new LSCMException(
                    'Could not download version '
                        . htmlspecialchars($extraArgs[1])
                        . '.'
                );
            }

            if (
                    $action == UserCommand::CMD_MASS_ENABLE
                    &&
                    ($wpInstall->getCmdStatus() & UserCommand::EXIT_FAIL)
                    &&
                    preg_match(
                        '/Source Package not available/',
                        $wpInstall->getCmdMsg()
                    )
            ) {
                $this->syncToDisk();

                throw new LSCMException($wpInstall->getCmdMsg());
            }

            $this->workingQueue[$path] = $wpInstall;
        }
    }

    /**
     *
     * @param string              $action
     * @param null|string[]       $list
     * @param string[]|string[][] $extraArgs
     *
     * @return string[]
     *
     * @throws LSCMException  Thrown indirectly by $this->prepareActionItems()
     *     call.
     * @throws LSCMException  Thrown indirectly by $this->log() call.
     * @throws LSCMException  Thrown indirectly by Context::getActionTimeout()
     *     call.
     * @throws LSCMException  Thrown indirectly by $this->scan() call.
     * @throws LSCMException  Thrown indirectly by $this->addNewWPInstall()
     *     call.
     * @throws LSCMException  Thrown indirectly by
     *     $this->addCustomInstallations() call.
     * @throws LSCMException  Thrown indirectly by
     *     PluginVersion::getCurrentVersion() call.
     * @throws LSCMException  Thrown indirectly by PluginVersion::getInstance()
     *     call.
     * @throws LSCMException  Thrown indirectly by
     *     PluginVersion::getInstance()->setActiveVersion() call.
     * @throws LSCMException  Thrown indirectly by $this->doWPInstallAction()
     *     call.
     * @throws LSCMException  Thrown indirectly by $this->syncToDisk() call.
     */
    public function doAction( $action, $list, array $extraArgs = [] )
    {
        if ( $list === null ) {
            $list = $this->prepareActionItems($action);
        }

        $count = count($list);
        $this->log("doAction $action for $count items", Logger::L_VERBOSE);

        $endTime      = ($count > 1) ? Context::getActionTimeout() : 0;
        $finishedList = [];

        switch ( $action ) {

            case self::CMD_SCAN:
            case self::CMD_DISCOVER_NEW:

                foreach ( $list as $path ) {
                    $this->scan($path, ($action == self::CMD_SCAN));

                    $finishedList[] = $path;

                    if ( $endTime && time() >= $endTime ) {
                        break;
                    }
                }

                break;

            case self::CMD_ADD_NEW_WPINSTALL:

                foreach ( $list as $path) {
                    $this->addNewWPInstall($path);

                    $finishedList[] = $path;

                    if ( $endTime && time() >= $endTime ) {
                        break;
                    }
                }

                break;

            case self::CMD_ADD_CUST_WPINSTALLS:
                $this->addCustomInstallations($extraArgs[0]);
                break;

            default:

                if (
                        $action == UserCommand::CMD_ENABLE
                        ||
                        $action == UserCommand::CMD_MASS_ENABLE
                ) {
                    /**
                     * Ensure that the current version is locally downloaded.
                     */
                    PluginVersion::getInstance()
                    ->setActiveVersion(PluginVersion::getCurrentVersion())
                    ;
                }

                foreach ( $list as $path ) {
                    $this->doWPInstallAction($action, $path, $extraArgs);

                    $finishedList[] = $path;

                    if ( $endTime && time() >= $endTime ) {
                        break;
                    }
                }
        }

        $this->syncToDisk();

        if ( $action == self::CMD_SCAN || $action == self::CMD_SCAN2 ) {
            /**
             * Explicitly clear any data file errors after scanning in case of
             * multiple actions performed in the same process (cli).
             */
            $this->error = 0;
        }

        return $finishedList;
    }

    /**
     *
     * @deprecated 1.13.3  Use $this->scan2() instead.
     *
     * @param string $docroot
     * @param bool   $forceRefresh
     *
     * @return void
     *
     * @throws LSCMException  Thrown indirectly by Context::getScanDepth() call.
     * @throws LSCMException  Thrown indirectly by $this->log() call.
     * @throws LSCMException  Thrown indirectly by $this->log() call.
     * @throws LSCMException  Thrown indirectly by $this->log() call.
     * @throws LSCMException  Thrown indirectly by
     *     $this->wpInstalls[$wp_path]->refreshStatus() call.
     */
    protected function scan( $docroot, $forceRefresh = false )
    {
        $directories = shell_exec(
            "find -L $docroot -maxdepth "
                . Context::getScanDepth()
                . ' -name wp-admin -print'
        );

        $hasMatches = false;

        if ( $directories ) {

            /**
             * Example:
             * /home/user/public_html/wordpress/wp-admin
             * /home/user/public_html/blog/wp-admin
             * /home/user/public_html/wp/wp-admin
             */
            $hasMatches = preg_match_all(
                "|$docroot(.*)(?=/wp-admin)|",
                $directories,
                $matches
            );
        }

        if ( ! $hasMatches ) {
            /**
             *  Nothing found.
             */
            return;
        }

        /** @noinspection PhpUndefinedVariableInspection */
        foreach ( $matches[1] as $path ) {
            $wp_path = realpath($docroot . $path);
            $refresh = $forceRefresh;

            if ( !isset($this->wpInstalls[$wp_path]) ) {
                $this->wpInstalls[$wp_path] = new WPInstall($wp_path);
                $refresh                    = true;
                $this->log(
                    "New installation found: $wp_path",
                    Logger::L_INFO
                );

                if (
                        $this->custWpInstalls != null
                        &&
                        isset($this->custWpInstalls[$wp_path])
                ) {
                    unset($this->custWpInstalls[$wp_path]);

                    $this->log(
                        "Installation removed from custom data file: $wp_path",
                        Logger::L_INFO
                    );
                }
            }
            else {
                $this->log(
                    "Installation already found: $wp_path",
                    Logger::L_DEBUG
                );
            }

            if ( $refresh ) {
                $this->wpInstalls[$wp_path]->refreshStatus();
                $this->workingQueue[$wp_path] = $this->wpInstalls[$wp_path];
            }
        }
    }

    /**
     *
     * @since 1.13.3
     * @since 1.15    Changed function visibility from 'public' to
     *     'public static'.
     *
     * @param string $docroot
     *
     * @return string[]
     *
     * @throws LSCMException  Thrown indirectly by Context::getScanDepth() call.
     */
    public static function scan2( $docroot )
    {
        $directories = shell_exec(
            "find -L $docroot -maxdepth "
                . Context::getScanDepth()
                .' -name wp-admin -print'
        );

        $hasMatches = false;

        if ( $directories ) {
            /**
             * Example:
             * /home/user/public_html/wordpress/wp-admin
             * /home/user/public_html/blog/wp-admin
             * /home/user/public_html/wp/wp-admin
             */
            $hasMatches = preg_match_all(
                "|$docroot(.*)(?=/wp-admin)|",
                $directories,
                $matches
            );
        }

        if ( ! $hasMatches ) {
            /**
             *  Nothing found.
             */
            return [];
        }

        $wpPaths = [];

        /** @noinspection PhpUndefinedVariableInspection */
        foreach ( $matches[1] as $path ) {
            $wpPaths[] = realpath($docroot . $path);
        }

        return $wpPaths;
    }

    /**
     * Add a new WPInstall object to WPInstallStorage's $wpInstalls[] given a
     * path to a WordPress installation and refresh its status. If a WPInstall
     * object already exists for the given path, refresh its status.
     *
     * @since 1.13.3
     *
     * @param string $wpPath
     *
     * @throws LSCMException  Thrown indirectly by $this->log() call.
     * @throws LSCMException  Thrown indirectly by $this->log() call.
     * @throws LSCMException  Thrown indirectly by $this->log() call.
     * @throws LSCMException  Thrown indirectly by
     *     $this->wpInstalls[$wpPath]->refreshStatus() call.
     */
    protected function addNewWPInstall( $wpPath )
    {
        if ( ($realPath = realpath($wpPath)) !== false ) {
            $wpPath = $realPath;
        }

        if ( !isset($this->wpInstalls[$wpPath]) ) {
            $this->wpInstalls[$wpPath] = new WPInstall($wpPath);
            $this->log("New installation found: $wpPath", Logger::L_INFO);

            if (
                    $this->custWpInstalls != null
                    &&
                    isset($this->custWpInstalls[$wpPath])
            ) {
                unset($this->custWpInstalls[$wpPath]);

                $this->log(
                    "Installation removed from custom data file: $wpPath",
                    Logger::L_INFO
                );
            }
        }
        else {
            $this->log(
                "Installation already found: $wpPath",
                Logger::L_DEBUG
            );
        }

        $this->wpInstalls[$wpPath]->refreshStatus();
        $this->workingQueue[$wpPath] = $this->wpInstalls[$wpPath];
    }

    /**
     *
     * @param string[] $wpInstallsInfo
     *
     * @return void
     *
     * @throws LSCMException  Thrown indirectly by $this->log() call.
     * @throws LSCMException  Thrown indirectly by $this->log() call.
     * @throws LSCMException  Thrown indirectly by $this->log() call.
     * @throws LSCMException  Thrown indirectly by $this->log() call.
     * @throws LSCMException  Thrown indirectly by
     *     $this->custWpInstalls[$wpPath]->refreshStatus() call.
     * @throws LSCMException  Thrown indirectly by $this->log() call.
     * @throws LSCMException  Thrown indirectly by $this->log() call.
     */
    protected function addCustomInstallations( array $wpInstallsInfo )
    {
        if ( $this->customDataFile == '' ) {
            $this->log(
                'No custom data file set, could not add custom Installation.',
                Logger::L_INFO
            );

            return;
        }

        if ( $this->custWpInstalls == null ) {
            $this->custWpInstalls = [];
        }

        for ( $i = 0; $i < count($wpInstallsInfo); $i++ ) {
            $info = preg_split('/\s+/', trim($wpInstallsInfo[$i]));

            $line = $i + 1;

            if ( count($info) != 4 ) {
                $this->log(
                    'Incorrect number of values for custom installation input '
                        . "string on line $line. Skipping.",
                    Logger::L_INFO
                );

                continue;
            }

            $wpPath = $info[0];

            if ( !file_exists("$wpPath/wp-admin") ) {
                $this->log(
                    "No 'wp-admin' directory found for $wpPath on line "
                        . "$line. Skipping.",
                    Logger::L_INFO
                );

                continue;
            }

            $docroot = $info[1];

            if ( !(substr($wpPath, 0, strlen($docroot)) === $docroot) ) {
                $this->log(
                    "docroot not contained in $wpPath on line $line. "
                        . 'Skipping.',
                    Logger::L_INFO
                );

                continue;
            }

            if ( !isset($this->wpInstalls[$wpPath]) ) {
                $this->custWpInstalls[$wpPath] = new WPInstall($wpPath);
                $this->custWpInstalls[$wpPath]->setDocRoot($docroot);
                $this->custWpInstalls[$wpPath]->setServerName($info[2]);
                $this->custWpInstalls[$wpPath]->setSiteUrlDirect($info[3]);
                $this->custWpInstalls[$wpPath]->refreshStatus();

                $this->log(
                    "New installation added to custom data file: $wpPath",
                    Logger::L_INFO
                );
            }
            else {
                $this->log(
                    "Installation already found during scan: $wpPath. "
                        . 'Skipping.',
                    Logger::L_INFO
                );
            }
        }
    }

    /**
     * Get all WPInstall command messages as a key=>value array.
     *
     * @return string[][]
     */
    public function getAllCmdMsgs()
    {
        $succ = $fail = $err = [];

        foreach ( $this->workingQueue as $wpInstall ) {

            if ( ($msg = $wpInstall->getCmdMsg()) ) {
                $cmdStatus = $wpInstall->getCmdStatus();

                switch( true ) {

                    case $cmdStatus & UserCommand::EXIT_SUCC:
                        $msgType = &$succ;
                        break;

                    case $cmdStatus & UserCommand::EXIT_FAIL:
                        $msgType = &$fail;
                        break;

                    case $cmdStatus & UserCommand::EXIT_ERROR:
                        $msgType = &$err;
                        break;

                    default:
                        continue 2;
                }

                $msgType[] = "{$wpInstall->getPath()} - $msg";
            }
        }

        return [ 'succ' => $succ, 'fail' => $fail, 'err' => $err ];
    }

    /**
     *
     * @param string $msg
     * @param int    $level
     *
     * @throws LSCMException  Thrown indirectly by Logger::error() call.
     * @throws LSCMException  Thrown indirectly by Logger::warn() call.
     * @throws LSCMException  Thrown indirectly by Logger::notice() call.
     * @throws LSCMException  Thrown indirectly by Logger::info() call.
     * @throws LSCMException  Thrown indirectly by Logger::verbose() call.
     * @throws LSCMException  Thrown indirectly by Logger::debug() call.
     */
    protected function log( $msg, $level )
    {
        $msg = "WPInstallStorage - $msg";

        switch ( $level ) {

            case Logger::L_ERROR:
                Logger::error($msg);
                break;

            case Logger::L_WARN:
                Logger::warn($msg);
                break;

            case Logger::L_NOTICE:
                Logger::notice($msg);
                break;

            case Logger::L_INFO:
                Logger::info($msg);
                break;

            case Logger::L_VERBOSE:
                Logger::verbose($msg);
                break;

            case Logger::L_DEBUG:
                Logger::debug($msg);
                break;

            //no default
        }
    }

}
webcachemgr/MIN_VER000064400000000007150545647720010111 0ustar001.17.3
webcachemgr/bootstrap_cli.php000066400000001023150545647720012405 0ustar00<?php

/** *********************************************
 * LiteSpeed Web Server Cache Manager
 *
 * @author Michael Alegre
 * @copyright (c) 2018-2022 LiteSpeed Technologies, Inc.
 * *******************************************
 */

use Lsc\Wp\Context\Context;
use Lsc\Wp\Context\RootCLIContextOption;
use Lsc\Wp\CliController;

require_once __DIR__ . '/autoloader.php';

date_default_timezone_set('UTC');

/** @noinspection PhpUnhandledExceptionInspection */
Context::initialize(new RootCLIContextOption());
CliController::run();
webcachemgr/VERSION000066400000000010150545647720010073 0ustar001.17.4.2webcachemgr/bootstrap.php000066400000001001150545647720011552 0ustar00<?php

/** *********************************************
 * LiteSpeed Web Server Cache Manager
 *
 * @author    Michael Alegre
 * @copyright 2018-2025 LiteSpeed Technologies, Inc.
 * *******************************************
 */

use Lsc\Wp\Context\Context;
use Lsc\Wp\Context\RootPanelContextOption;

require_once __DIR__ . '/autoloader.php';

/**
 * @noinspection PhpUnhandledExceptionInspection
 * @noinspection PhpUndefinedVariableInspection
 */
Context::initialize(new RootPanelContextOption($panelName));
webcachemgr/autoloader.php000066400000001565150545647720011713 0ustar00<?php

/* * *********************************************
 * LiteSpeed Web Server Cache Manager
 * @Author: LiteSpeed Technologies, Inc. (https://www.litespeedtech.com)
 * @Copyright: (c) 2018
 * *******************************************
 */

spl_autoload_register(function($class) {
    /**
     * project-specific namespace prefix
     */
    $prefix = 'Lsc\\Wp\\';

    /**
     * base directory for the namespace prefix
     */
    $base_dir = __DIR__ . '/src/';

    $len = strlen($prefix);

    if ( strncmp($prefix, $class, $len) !== 0 ) {
        /**
         * Class use the namespace prefix,
         * move to the next registered autoloader.
         */
        return;
    }

    $relative_class_name = substr($class, $len);

    $file = $base_dir . str_replace('\\', '/', $relative_class_name) . '.php';

    if ( file_exists($file) ) {
        require $file;
    }
});
plesk/httpd_config.xml000064400000014621150545647720011077 0ustar00<?xml version="1.0" encoding="UTF-8"?>
<httpServerConfig>
  <serverName>$HOSTNAME</serverName>
  <user>apache</user>
  <group>apache</group>
  <priority>0</priority>
  <chrootPath>/</chrootPath>
  <enableChroot>0</enableChroot>
  <inMemBufSize>60M</inMemBufSize>
  <swappingDir>/tmp/lshttpd/swap</swappingDir>
  <autoRestart>1</autoRestart>
  <autoFix503>0</autoFix503>
  <loadApacheConf>1</loadApacheConf>
  <autoReloadApacheConf>2</autoReloadApacheConf>
  <apacheBinPath>/usr/sbin/httpd</apacheBinPath>
  <apacheConfFile>/etc/httpd/conf/httpd.conf</apacheConfFile>
  <apachePortOffset>%AP_PORT_OFFSET%</apachePortOffset>
  <apacheIpOffset>0</apacheIpOffset>
  <apacheIgnoredModules>mod_php4,mod_php5,mod_php7,sapi_apache2,python</apacheIgnoredModules>
  <phpSuExec>%PHP_SUEXEC%</phpSuExec>
  <phpSuExecMaxConn>10</phpSuExecMaxConn>
  <mime>$SERVER_ROOT/conf/mime.properties</mime>
  <disableInitLogRotation>1</disableInitLogRotation>
  <showVersionNumber>0</showVersionNumber>
  <enableIpGeo></enableIpGeo>
  <useIpInProxyHeader>2</useIpInProxyHeader>
  <autoUpdateInterval>86400</autoUpdateInterval>
  <autoUpdateDownloadPkg>1</autoUpdateDownloadPkg>
  <adminEmails>%ADMIN_EMAIL%</adminEmails>
  <adminRoot>$SERVER_ROOT/admin/</adminRoot>
  <logging>
    <log>
      <fileName>/var/log/httpd/error_log</fileName>
      <logLevel>DEBUG</logLevel>
      <debugLevel>0</debugLevel>
      <rollingSize>2000M</rollingSize>
      <enableStderrLog>1</enableStderrLog>
      <enableAioLog>1</enableAioLog>
    </log>
    <accessLog>
      <fileName>$SERVER_ROOT/logs/access.log</fileName>
      <rollingSize>10M</rollingSize>
      <keepDays>30</keepDays>
      <compressArchive>0</compressArchive>
    </accessLog>
  </logging>
  <indexFiles>index.html, index.php, index.htm</indexFiles>
  <autoIndex></autoIndex>
  <autoIndexURI></autoIndexURI>
  <htAccess>
    <allowOverride>31</allowOverride>
    <accessFileName>.htaccess</accessFileName>
  </htAccess>
  <expires>
    <enableExpires>1</enableExpires>
    <expiresByType>image/*=A604800, text/css=A604800, application/x-javascript=A604800, application/javascript=A604800,font/*=A604800,application/x-font-ttf=A604800</expiresByType>
  </expires>
  <tuning>
    <maxConnections>10000</maxConnections>
    <maxSSLConnections>10000</maxSSLConnections>
    <connTimeout>120</connTimeout>
    <maxKeepAliveReq>10000</maxKeepAliveReq>
    <smartKeepAlive>0</smartKeepAlive>
    <keepAliveTimeout>10</keepAliveTimeout>
    <sndBufSize>0</sndBufSize>
    <rcvBufSize>0</rcvBufSize>
    <eventDispatcher>best</eventDispatcher>
    <maxCachedFileSize>4096</maxCachedFileSize>
    <totalInMemCacheSize>20M</totalInMemCacheSize>
    <maxMMapFileSize>256K</maxMMapFileSize>
    <totalMMapCacheSize>40M</totalMMapCacheSize>
    <useSendfile>1</useSendfile>
    <useAIO>1</useAIO>
    <AIOBlockSize>4</AIOBlockSize>
    <etagNoInode>1</etagNoInode>
    <SSLCryptoDevice>null</SSLCryptoDevice>
    <maxReqURLLen>8192</maxReqURLLen>
    <maxReqHeaderSize>16380</maxReqHeaderSize>
    <maxReqBodySize>500M</maxReqBodySize>
    <maxDynRespHeaderSize>8K</maxDynRespHeaderSize>
    <maxDynRespSize>500M</maxDynRespSize>
    <enableGzipCompress>1</enableGzipCompress>
    <enableDynGzipCompress>1</enableDynGzipCompress>
    <compressibleTypes>default</compressibleTypes>
    <gzipAutoUpdateStatic>1</gzipAutoUpdateStatic>
    <gzipCacheDir></gzipCacheDir>
  </tuning>
  <security>
    <fileAccessControl>
      <followSymbolLink>1</followSymbolLink>
      <checkSymbolLink>0</checkSymbolLink>
      <forceStrictOwnership>1</forceStrictOwnership>
      <requiredPermissionMask>000</requiredPermissionMask>
      <restrictedPermissionMask>000</restrictedPermissionMask>
      <restrictedScriptPermissionMask>000</restrictedScriptPermissionMask>
      <restrictedDirPermissionMask>000</restrictedDirPermissionMask>
    </fileAccessControl>
    <perClientConnLimit>
      <staticReqPerSec>0</staticReqPerSec>
      <dynReqPerSec>0</dynReqPerSec>
      <outBandwidth>0</outBandwidth>
      <inBandwidth>0</inBandwidth>
      <softLimit>10000</softLimit>
      <hardLimit>10000</hardLimit>
      <gracePeriod>15</gracePeriod>
      <banPeriod>300</banPeriod>
    </perClientConnLimit>
    <CGIRLimit>
      <maxCGIInstances>200</maxCGIInstances>
      <minUID>11</minUID>
      <minGID>10</minGID>
      <priority>0</priority>
      <CPUSoftLimit>60</CPUSoftLimit>
      <CPUHardLimit>120</CPUHardLimit>
      <memSoftLimit>1450M</memSoftLimit>
      <memHardLimit>1500M</memHardLimit>
      <procSoftLimit>1400</procSoftLimit>
      <procHardLimit>1450</procHardLimit>
    </CGIRLimit>
    <censorshipControl>
      <enableCensorship>0</enableCensorship>
      <logLevel>0</logLevel>
      <defaultAction>deny,log,status:403</defaultAction>
      <scanPOST>1</scanPOST>
    </censorshipControl>
    <accessDenyDir>
      <dir>/</dir>
      <dir>/etc/*</dir>
      <dir>/dev/*</dir>
      <dir>$SERVER_ROOT/conf/*</dir>
      <dir>$SERVER_ROOT/admin/conf/*</dir>
    </accessDenyDir>
    <accessControl>
      <allow>ALL</allow>
      <deny></deny>
    </accessControl>
  </security>
  <extProcessorList>
    <extProcessor>
        <type>logger</type>
        <name>/usr/local/psa/admin/sbin/pipelog</name>
        <note>Added for Plesk Pipe logger setup.</note>
        <maxConns>1</maxConns>
        <path>/usr/local/psa/admin/sbin/pipelog</path>
        <instances>1</instances>
        <priority>10</priority>
    </extProcessor>
  </extProcessorList>
  <scriptHandlerList>
  </scriptHandlerList>
  <phpConfig>
    <maxConns>35</maxConns>
    <env>PHP_LSAPI_CHILDREN=35</env>
    <initTimeout>60</initTimeout>
    <retryTimeout>0</retryTimeout>
    <pcKeepAliveTimeout>1</pcKeepAliveTimeout>
    <respBuffer>0</respBuffer>
    <extMaxIdleTime>60</extMaxIdleTime>
    <memSoftLimit></memSoftLimit>
    <memHardLimit></memHardLimit>
    <procSoftLimit>1400</procSoftLimit>
    <procHardLimit>1500</procHardLimit>
  </phpConfig>
  <railsDefaults>
    <rubyBin></rubyBin>
    <railsEnv>1</railsEnv>
    <maxConns>5</maxConns>
    <env>LSAPI_MAX_IDLE=60</env>
    <initTimeout>60</initTimeout>
    <retryTimeout>0</retryTimeout>
    <pcKeepAliveTimeout>60</pcKeepAliveTimeout>
    <respBuffer>0</respBuffer>
    <backlog>50</backlog>
    <runOnStartUp>1</runOnStartUp>
    <extMaxIdleTime>300</extMaxIdleTime>
    <priority>3</priority>
    <memSoftLimit></memSoftLimit>
    <memHardLimit></memHardLimit>
    <procSoftLimit>400</procSoftLimit>
    <procHardLimit>500</procHardLimit>
  </railsDefaults>
</httpServerConfig>
plesk/httpd_config.xml.debian000064400000015016150545647720012317 0ustar00<?xml version="1.0" encoding="UTF-8"?>
<httpServerConfig>
  <serverName>$HOSTNAME</serverName>
  <user>www-data</user>
  <group>www-data</group>
  <priority>0</priority>
  <chrootPath>/</chrootPath>
  <enableChroot>0</enableChroot>
  <inMemBufSize>60M</inMemBufSize>
  <swappingDir>/tmp/lshttpd/swap</swappingDir>
  <autoRestart>1</autoRestart>
  <autoFix503>0</autoFix503>
  <loadApacheConf>1</loadApacheConf>
  <autoReloadApacheConf>2</autoReloadApacheConf>
  <apacheBinPath>/usr/sbin/apache2</apacheBinPath>
  <apacheConfFile>/etc/apache2/apache2.conf</apacheConfFile>
  <apachePortOffset>%AP_PORT_OFFSET%</apachePortOffset>
  <apacheIpOffset>0</apacheIpOffset>
  <apacheIgnoredModules>mod_php4,mod_php5,mod_php7,sapi_apache2,python</apacheIgnoredModules>
  <phpSuExec>%PHP_SUEXEC%</phpSuExec>
  <phpSuExecMaxConn>10</phpSuExecMaxConn>
  <apacheEnvVars>APACHE_RUN_USER=www-data
APACHE_RUN_GROUP=www-data
APACHE_PID_FILE=%APACHE_PID_FILE%</apacheEnvVars>
  <mime>$SERVER_ROOT/conf/mime.properties</mime>
  <disableInitLogRotation>1</disableInitLogRotation>
  <showVersionNumber>0</showVersionNumber>
  <enableIpGeo></enableIpGeo>
  <useIpInProxyHeader>2</useIpInProxyHeader>
  <autoUpdateInterval>86400</autoUpdateInterval>
  <autoUpdateDownloadPkg>1</autoUpdateDownloadPkg>
  <adminEmails>%ADMIN_EMAIL%</adminEmails>
  <adminRoot>$SERVER_ROOT/admin/</adminRoot>
  <logging>
    <log>
      <fileName>/var/log/apache2/error.log</fileName>
      <logLevel>DEBUG</logLevel>
      <debugLevel>0</debugLevel>
      <rollingSize>2000M</rollingSize>
      <enableStderrLog>1</enableStderrLog>
      <enableAioLog>1</enableAioLog>
    </log>
    <accessLog>
      <fileName>$SERVER_ROOT/logs/access.log</fileName>
      <rollingSize>10M</rollingSize>
      <keepDays>30</keepDays>
      <compressArchive>0</compressArchive>
    </accessLog>
  </logging>
  <indexFiles>index.html, index.php, index.htm</indexFiles>
  <autoIndex></autoIndex>
  <autoIndexURI></autoIndexURI>
  <htAccess>
    <allowOverride>31</allowOverride>
    <accessFileName>.htaccess</accessFileName>
  </htAccess>
  <expires>
    <enableExpires>1</enableExpires>
    <expiresByType>image/*=A604800, text/css=A604800, application/x-javascript=A604800, application/javascript=A604800,font/*=A604800,application/x-font-ttf=A604800</expiresByType>
  </expires>
  <tuning>
    <maxConnections>10000</maxConnections>
    <maxSSLConnections>10000</maxSSLConnections>
    <connTimeout>120</connTimeout>
    <maxKeepAliveReq>10000</maxKeepAliveReq>
    <smartKeepAlive>0</smartKeepAlive>
    <keepAliveTimeout>10</keepAliveTimeout>
    <sndBufSize>0</sndBufSize>
    <rcvBufSize>0</rcvBufSize>
    <eventDispatcher>best</eventDispatcher>
    <maxCachedFileSize>4096</maxCachedFileSize>
    <totalInMemCacheSize>20M</totalInMemCacheSize>
    <maxMMapFileSize>256K</maxMMapFileSize>
    <totalMMapCacheSize>40M</totalMMapCacheSize>
    <useSendfile>1</useSendfile>
    <useAIO>1</useAIO>
    <AIOBlockSize>4</AIOBlockSize>
    <etagNoInode>1</etagNoInode>
    <SSLCryptoDevice>null</SSLCryptoDevice>
    <maxReqURLLen>8192</maxReqURLLen>
    <maxReqHeaderSize>16380</maxReqHeaderSize>
    <maxReqBodySize>500M</maxReqBodySize>
    <maxDynRespHeaderSize>8K</maxDynRespHeaderSize>
    <maxDynRespSize>500M</maxDynRespSize>
    <enableGzipCompress>1</enableGzipCompress>
    <enableDynGzipCompress>1</enableDynGzipCompress>
    <compressibleTypes>default</compressibleTypes>
    <gzipAutoUpdateStatic>1</gzipAutoUpdateStatic>
    <gzipCacheDir></gzipCacheDir>
  </tuning>
  <security>
    <fileAccessControl>
      <followSymbolLink>1</followSymbolLink>
      <checkSymbolLink>0</checkSymbolLink>
      <forceStrictOwnership>1</forceStrictOwnership>
      <requiredPermissionMask>000</requiredPermissionMask>
      <restrictedPermissionMask>000</restrictedPermissionMask>
      <restrictedScriptPermissionMask>000</restrictedScriptPermissionMask>
      <restrictedDirPermissionMask>000</restrictedDirPermissionMask>
    </fileAccessControl>
    <perClientConnLimit>
      <staticReqPerSec>0</staticReqPerSec>
      <dynReqPerSec>0</dynReqPerSec>
      <outBandwidth>0</outBandwidth>
      <inBandwidth>0</inBandwidth>
      <softLimit>10000</softLimit>
      <hardLimit>10000</hardLimit>
      <gracePeriod>15</gracePeriod>
      <banPeriod>300</banPeriod>
    </perClientConnLimit>
    <CGIRLimit>
      <maxCGIInstances>200</maxCGIInstances>
      <minUID>11</minUID>
      <minGID>10</minGID>
      <priority>0</priority>
      <CPUSoftLimit>60</CPUSoftLimit>
      <CPUHardLimit>120</CPUHardLimit>
      <memSoftLimit>1450M</memSoftLimit>
      <memHardLimit>1500M</memHardLimit>
      <procSoftLimit>1400</procSoftLimit>
      <procHardLimit>1450</procHardLimit>
    </CGIRLimit>
    <censorshipControl>
      <enableCensorship>0</enableCensorship>
      <logLevel>0</logLevel>
      <defaultAction>deny,log,status:403</defaultAction>
      <scanPOST>1</scanPOST>
    </censorshipControl>
    <accessDenyDir>
      <dir>/</dir>
      <dir>/etc/*</dir>
      <dir>/dev/*</dir>
      <dir>$SERVER_ROOT/conf/*</dir>
      <dir>$SERVER_ROOT/admin/conf/*</dir>
    </accessDenyDir>
    <accessControl>
      <allow>ALL</allow>
      <deny></deny>
    </accessControl>
  </security>
  <extProcessorList>
    <extProcessor>
        <type>logger</type>
        <name>/usr/local/psa/admin/sbin/pipelog</name>
        <note>Added for Plesk Pipe logger setup.</note>
        <maxConns>1</maxConns>
        <path>/usr/local/psa/admin/sbin/pipelog</path>
        <instances>1</instances>
        <priority>10</priority>
    </extProcessor>
  </extProcessorList>
  <scriptHandlerList>
  </scriptHandlerList>
  <phpConfig>
    <maxConns>35</maxConns>
    <env>PHP_LSAPI_CHILDREN=35</env>
    <initTimeout>60</initTimeout>
    <retryTimeout>0</retryTimeout>
    <pcKeepAliveTimeout>1</pcKeepAliveTimeout>
    <respBuffer>0</respBuffer>
    <extMaxIdleTime>60</extMaxIdleTime>
    <memSoftLimit></memSoftLimit>
    <memHardLimit></memHardLimit>
    <procSoftLimit>1400</procSoftLimit>
    <procHardLimit>1500</procHardLimit>
  </phpConfig>
  <railsDefaults>
    <rubyBin></rubyBin>
    <railsEnv>1</railsEnv>
    <maxConns>5</maxConns>
    <env>LSAPI_MAX_IDLE=60</env>
    <initTimeout>60</initTimeout>
    <retryTimeout>0</retryTimeout>
    <pcKeepAliveTimeout>60</pcKeepAliveTimeout>
    <respBuffer>0</respBuffer>
    <backlog>50</backlog>
    <runOnStartUp>1</runOnStartUp>
    <extMaxIdleTime>300</extMaxIdleTime>
    <priority>3</priority>
    <memSoftLimit></memSoftLimit>
    <memHardLimit></memHardLimit>
    <procSoftLimit>400</procSoftLimit>
    <procHardLimit>500</procHardLimit>
  </railsDefaults>
</httpServerConfig>