Автоматизированная система работы поликлиники

  • Вид работы:
    Дипломная (ВКР)
  • Предмет:
    Информационные технологии
  • Язык:
    Русский
    ,
    Формат файла:
    MS Word
  • Опубликовано:
    2022-06-16
Вы можете узнать стоимость помощи в написании студенческой работы.
Помощь в написании работы, которую точно примут!

Автоматизированная система работы поликлиники

Автоматизированная система работы поликлиники

 

 

 

СОДЕРЖАНИЕ

 

Введение. 5

1. Аналитическая часть. 7

1.1   Виды и характеристика веб-сайтов, роль в работе поликлиник. 7

1.1.2 Роль веб-сайта в работе медицинской клиники. 8

1.2 Обоснование выбора средств создания веб-сайта. 9

1.3 Обзор систем управления базами данных. 15

2.Технологическая часть. 18

2.1 Постановка задачи. 18

2.1.1 Актуальность. 18

2.1.2 Назначение веб-сайта. 18

2.1.3 Характеристики оборудования. 19

2.2 Реализация проекта. 19

2.3 Средства для разработки и проектирование сайта. 20

2.3.1 Анализ средств для разработки и создания Web-сайта. 20

2.3.2 Фреймворки, используемые при разработке Web-сайтов: сравнительный анализ. 26

2.3.4 Разработка веб-сайта в CMS WordPress. 34

3. Тестирование веб-сайта и руководство пользователя. 43

3.1. Тестирование веб-сайта. 43

3.2. Руководство пользователя. 45

Заключение. 49

Список использованной литературы.. 50

Приложение. 52

 

 

 

Введение

 

С каждым днем ??все больше и больше людей осваивают возможности Интернета для поиска информации о тех или иных услугах, Интернет стал необходимостью для человека. Путешествуя по сети, вы сталкиваетесь с большим количеством рекламы всех видов. Часто встречаются интересные сервисы, информация и ресурсы.

На современном этапе развития глобальной сети Интернет создание веб-сайтов является актуальной задачей. Создание сайтов для компаний и организаций популярно, и эта тенденция сохранится еще долгое время. В связи с этим большинство современных компаний, учреждений, организаций имеют собственные сайты в сети Интернет, на которых раскрывается основная информация об организации, сведения о характере ее деятельности, услугах и контактные данные.

Качественный сайт, вобравший в себя всю полезную информацию и являющийся лучшей визитной карточкой для деловых компаний и медицинских клиник–это прекрасная возможность познакомить клиентов и пациентов со своей клиникой, ее особенностями и методами работы, а также способ поделиться результатами своей деятельности, создать информационное пространство для пациентов, клиентов и тех, кто будет посещать клинику, но еще ничего не решено.

Грамотно созданный сайт будет способствовать его дальнейшему развитию и продвижению, а также повысит эффективность взаимодействия основного корпуса медицинской клиники (пациентов и клиентов). Сайт – это визитная карточка медицинской клиники, неотъемлемая часть медицинской отрасли, используемая для взаимодействия с людьми и создания новых возможностей для взаимодействия с клиентами. Сайт медицинской клиники – это инструмент коммуникации менеджеров, пациентов и клиентов.   Объект исследования дипломной работы — деятельность поликлиники.

Предмет исследования выпускной квалификационной работы — процесс создания веб-сайта поликлиники с помощью системы управления контентом WordPress.

Цель дипломной работы — разработать веб-сайт поликлиники.

В соответствии с поставленной целью в работе определены следующие задачи:

провести анализ предметной области;

проанализировать средства разработки веб-сайта;

разработать модель веб-сайта;

реализовать разработанную модель веб-сайта средствами веб-технологий;

 

наполнить веб-сайт контентом.

 

1.Аналитическая часть

 

1.1 Виды и характеристика веб-сайтов, роль в работе поликлиник

 

Сайты поликлиник относятся к группе медицинских сайтов. Под медицинским веб-сайтом подразумевается объединение веб-страниц с повторяющимся дизайном, несущих в себе целенаправленную информацию о мед учреждении и другую информацию.

 

1.1.1 Виды медицинских веб-сайтов

 

Веб-сайт медицинской клиники в зависимости от своего содержания может относиться к разным видам. Это относится к многофункциональным веб-сайтам. Сайты для медицинских компаний представляют собой целую автоматизированную систему, предоставляющую полный функционал для сбора и обработки данных.По функциональному назначению, их можно разделить на следующие виды:

1. Сайты лечебных заведений. Сайты медицинских учреждений, в том числе больницы, диагностические центры, госпитали, диспансеры, женские консультации.

 

2. Сайты научных исследований. Сайты исследовательских работ в области медицины, врачей, преподавателей медицинских ВУЗов, научных работников.

3. Сайты справочного характера. Сайты, содержащие справочную информацию о проводимых конференциях, конкурсах, семинарах научного и медицинского направления, о предоставляемых грантах, статьи, ссылки.

4. Сайты информационных Интернет-проектов. Сайты обществ и ассоциаций, предназначены для проведения медицинских конкурсов и предоставление информационно-развлекательных проектов медицинской тематики.

5. Сайты типа виртуальных методических объединений. Сайты методического объединения врачей по специализациям, методам лечения, сайты для тематических врачебных конференций и чатов в online режиме по вопросам лечения пациентов.

6. Сайты консультативного назначения. Консультативные сайты для врачей и пациентов, интернов и профессоров, предназначены для обмена информацией и ответов на возникающие вопросы.

 

1.1.2 Роль веб-сайта в работе медицинской клиники

 

Веб-сайт, представляющий организацию, называется корпоративным или официальным веб-сайтом организации. Официальный сайт предъявляет более строгие требования к информативности, графическому оформлению и навигации.

Официальный сайт обычно имеет следующие разделы:

 

новостная информация;

 

нормативные документы, положения;

 

направления деятельности;

 

структура учреждения;

 

кадровый состав;

  контактная информация (список ответственных лиц, их должности, координаты и часы приема).

Сайты медицинских клиник играют важную роль в организации медицинской деятельности, информационной поддержке врачей и пациентов, помощи коллегам в профильных медицинских учреждениях.

Для врачей сайт является площадкой для обмена опытом, они могут общаться с коллегами из местных и даже стран, участвовать в совместных проектах в рамках отечественных и зарубежных медицинских проектов, обмениваться медицинским опытом.

Для пациентов сайт является в первую очередь информационным ресурсом. Используя сайты клиник и других медицинских учреждений, пациенты имеют возможность сравнить их и сделать оптимальный выбор для себя, своих детей и близких.

 

1.2 Обоснование выбора средств создания веб-сайта

 

Система управления контентом — это компьютерная программа, предназначенная для упрощения управления контентом веб-сайта. Эта система позволяет веб-мастерам не использовать программный код напрямую, а использовать админ-панель со всеми необходимыми функциями для редактирования контента и создания новых материалов.

Наиболеепопулярные и распространенные системы управления контентом:

Joomla — втораяпопопулярности Content Management System (CMS),

более гибкая и простая. Joomla прекрасно подходит для разработки веб-сайта

с нестандартной структурой, например, корпоративного портала.

Данная система управления контентом производная ветвь от широко

известного проекта Mambo. В системе Joomla самые разнообразные инструменты для создания сайта.

Проблема перегрузки админки бесполезными элементами устранена благодаря важной особенности Joomla - минимальному набору инструментов при первоначальной установке. В результате снижается нагрузка на сервер и экономится место на хосте.

Обычные инструменты администрирования устанавливают каталог расширений, который включает ряд языковых пакетов. Это дает возможность перевести интерфейс фронтенда и админки практически на любой язык.   К минусам можно отнести то, что это, так сказать, упрощенная CMS,поэтому она слаба функционалом. Многие плагины и дополнения для CMS Joomla платные. В целом Joomla отличная платформа, которая обладает простым интерфейсом, приятным дизайном и большим набором шаблонов.

  MODx — это бесплатная профессиональная система управления содержимым и фреймворк для веб-приложений, предназначенная для обеспечения и организации совместного процесса создания, редактирования и управления контентом (то есть содержимым) веб-сайтов.

  Преимущества:

• поддержка ленты новостей, веб-статистики, подписок;

• платформа дает возможность осуществлять контроль над всеми элементами страницы (от платежной системы до документооборота и чата).

  При хороших навыках владения языком программирования можно легко «переписать» администрирование под себя.

  Возможности:

• создание разнообразных сайтов на стандартах, адаптирующихся под различные браузеры;

• настройка ключевых слов, дружественных Uniform Resource Locator(URL).

  Недостатки:

• маленькое количество готовых шаблонов, но разработчики обещают увеличить коллекцию;

• чтобы восстанавливать удаленные объекты, необходимо установить специальные плагины.

  Drupal — это система управления веб-сайтом, написанная на языке PHP и использующая в качестве хранилища содержания реляционную базу данных (поддерживаются MySQL, PostgreSQL, а также любые базы данных, поддерживаемые библиотекой PEAR). За счет открытого кода доступа, она удобна в использовании, настройке. Drupal является свободным программным обеспечением, защищенным лицензией GPL и создается усилиями энтузиастов со всего мира. Начал разработку голландец DriesBuytaert, который и поныне является руководителем проекта. Архитектура Drupal позволяет применять его для построения различных типов веб-сайтов — от блогов и форумов, до информационных архивов или веб-сайтов новостей. Функциональность обеспечивается подключаемыми модулями.

  1С-Битрикс — автоматизированная система управления контентом, созданная компанией 1С-Битрикс. В настоящее время «1С-Битрикс» лидирует в рейтинге систем управления сайтами платного тиража России. Продукт предназначен для использования при разработке и развитии корпоративных проектов, информационных, новостных и справочных порталов, социальных сетей, интернет-магазинов и других видов сайтов для предприятий и организаций.

  Недостатки:

• функциональная избыточность приводит к большому количеству неиспользуемого программного кода, что снижает эффективность;

• Высокие требования к управляемым ресурсам;

• При выходе из стандартного функционала сайта требуется глубокий анализ сложного кода системы;

• Из-за большого количества пользователей системы влияние сетевых студий на развитие системы стремится к нулю;

• Клиенты часто рассматривают покупку Битрикс вместо полной поддержки сайта, что снижает их лояльность;

• Многочисленные встроенные функции затрудняют обучение клиентов и вызывают проблемы с сайтом;

• Разработка сайта создается на основе любого готового шаблона, вылезает большое количество неиспользуемых элементов и программных модулей, что приводит к низкой скорости загрузки сайта;

• Для некоторых клиентов коммерческие лицензии неприемлемы.

  • Невозможно взять на себя полную ответственность за конечный продукт: система управления разработана другой компанией, размер кода веб-студии намного меньше;

• Интеграция с «1С:Управление предприятием» обычно требует существенной доработки;

• Система архитектурно неотделима от площадки. Администрирование выполняется на рабочих экземплярах сайта.

  Кратко подытожим: у системы 1С-Битрикс достаточно недостатков, чтобы вызывать только негативные отзывы разработчиков и пользователей системы. NetCat — это профессиональная система управления контентом. NetCat — одна из ведущих систем управления контентом на российском рынке. Первая версия системы была создана в 1999 году. Согласно исследованию российского рынка CMS, проведенному интернет-изданием Webinform, система NetCat является самым продаваемым инструментом управления сайтами общего назначения в России.

  WordPress — это самая популярная и известная платформа. Эта платформа изначально разрабатывалась как блог-платформа, но благодаря многочисленным дополнениям часто используется для разработки и других типов веб-сайтов.

 Главным преимуществом WordPress является простота и понятность: все действия можно проводить через админ-панель, не обязательно хорошо знать верстку и программирование. WordPress обладает большим набором шаблонов, тем и модулей, тем самым, создание веб-сайта становиться легче.

Функционал настолько велик, что могут возникнуть сложности с выбором тех или иных возможностей системы. Процесс установки WordPress довольно прост, поэтому для не опытного разработчика это может играть важную роль в выборе систем управления контентом.

  Описание основных преимуществ системы управления контентом WordPress:

  • легкость в настройке и управлении консолью. Понятно и интуитивно доходчиво, не составит большого труда разобраться с программой имея

минимальные навыки либо придерживаясь понятным урокам по WordPress;

  • предоставленных возможностей разработчиками достаточно, чтобы разрабатывать сайты практически любой сложности, создавать и редактировать шаблоны;

  • обширные возможности с целью оптимизации как отдельных компонентов, так и целого сайта;

  • достаточно развитая система безопасности;

  • плагины для расширения возможностей системы управлением контентомдают возможность настроить и представить контент более качественным и удобным методом;

  • часто обновляемая система управления показатель постоянной деятельности разработчиков над усовершенствованием системы;

  • новости о WordPress выходят достаточно часто, и это подтверждение тому, что система является действительно популярной.

  На рисунке 1 изображено сравнение CMSсистем.

 

Рисунок 1- Сравнение CMSсистем

  Таким образом, это будет идеальным вариантом для блогов, хоть и содержится много других инструментов для разработки веб-сайтов. Широкий и

простой в управлении функционал подойдет как новичку, так и опытному

веб-мастеру.

  Проанализировав наиболее популярные системы управления контентом, была выбрана система WordPress. Такой выбор обусловлен тем, что среди всех имеющихся и более популярных, WordPress имеет продуманный механизм управления данными, он дает возможность администратору сайта с легкостью добавлять, редактировать и удалять информацию, позволяя не тратить много времени на операции. Для WordPress имеется много бесплатных модулей и плагинов, которые дают возможность увеличить функциональность базовой версии данной системы. Кроме того, система управления контентом WordPress является самой популярной и востребованной среди остальных систем управления. В этом можно убедиться, воспользовавшись сервисом GoogleTrends. Результаты рейтинга за март 2021 года представлен на рисунке 2.[1]

 

Рисунок 2 - Исследование популярности CMS за 2021 год

  Популярность другого распространенного движка Joomla уменьшается, а желающих воспользоваться WordPress меньше не становится. Для тестирования и отладки используется хостинг jino.ru, с поддержкой PHP и СУБД MySQL. Что даёт возможность заказчику контролировать процесс разработки в режиме online. Внося свои корректировки и поправки.

 

1.3 Обзор систем управления базами данных

 

Система управления базами данных (СУБД) — набор программного обеспечения общего или специального назначения и языковых инструментов для управления созданием и использованием баз данных.

-   Основные возможности СУБД:

-   Управление данными на диске;

-   Управлять данными в памяти;

-   Запись изменений, резервное копирование и восстановление БД после сбоя;

-   Поддержка языка базы данных.

-   СУБД условно можно разделить на 2 части:

-   Открытый исходный код (MySQL)

-   Коммерческий (Oracle, MS SQL) [5].

База данных Oracle. Система управления базами данных Oracle популярна благодаря своей надежности и безопасности. Разработанная для предприятий любого размера, Oracle Database предлагает уникальные возможности автоматической настройки и самодиагностики, которые выводят корпоративные системы на новый уровень функциональности и надежности.

Преимущества использования Oracle:

- Хранить пространственные данные в открытом стандартизированном формате;

- Данные хранятся в одной СУБД;

- Стандартизированный доступ к данным через SQL;

- Обеспечение совместной работы с данными и совместного доступа на уровне СУБД;

- Надежность, производительность;

- Расширяемость;

- Техническая поддержка и постоянное совершенствование программного обеспечения [6].

СУБД MySQL является наиболее приспособленной, для применения в среде web, системой управления базами данных. Не секрет, что для исполнения приложений клиента на большинстве хостинг-площадок провайдеры предоставляют небольшое количество ресурсов. Поэтому для данного применения необходима высокоэффективная СУБД, обладающая высокой надежностью.

Основные преимущества MySQL:

- многопоточность;

- оптимизация связей;

- записи фиксированной и переменной длины;

- ODBC драйвер;

- гибкая система привилегий и паролей;

- гибкая поддержка форматов чисел, строк переменной длины и меток времени;

- быстрая работа;

- масштабируемость;

- совместимость с ANSI SQL;

- хорошая поддержка со стороны хостинг-провайдеров;

- быстрая поддержка транзакций [7].

Microsoft SQL Server — это система управления реляционными базами данных, разработанная Microsoft. Поддерживается несколько языков SQL. Он используется для небольших и средних баз данных, для крупных корпоративных баз данных и для конкуренции с другими СУБД. Одним из основных преимуществ SQL Server являются расширенные графические и визуальные средства управления, благодаря которым вы можете значительно снизить административную нагрузку при обслуживании.

Имеет высокую производительность с удобным и простым пользовательским интерфейсом.

Основные преимущества SQL Server :масштабируемость;превосходная производительность;простота использования;готовность к использованию в Интернете;хранилища данных;интеграция с другими продуктами Microsoft [8].

Основные преимущества рассмотренных СУБД представлены в таблице 1.

 

Таблица 1. – Преимущества СУБД

Название

Преимущества

Oracle Database

хранение пространственных данных;стандартизованный, доступ к данным;совместная работа с данными и разделение доступа;

надежность, производительность и масштабируемость;

техническая поддержка совершенствование ПО.

СУБД MySQL

многопоточность;оптимизация связей; записи фиксированной длины; ODBC драйвер;система привилегий и паролей; быстрая работа, масштабируемость;совместимость с ANSI SQL; поддержка со стороны провайдеров услуг хостинга; поддержка транзакций.

Microsoft SQL Server

масштабируемость; превосходная производительность;

простота использования;

готовность к использованию в Интернете;

хранилища данных;

интеграция с другими продуктами Microsoft.

 

2.Технологическая часть

 

2.1 Постановка задачи

 

2.1.1 Актуальность

 

Актуальность создания сайта для поликлиники заключается в том, что он позволяет лучше контролировать деятельность клиники и дает возможность дистанционно записаться к нужному врачу и управлять данными в личном кабинете, ведь у поликлиники на данный момент нет сайта и сайт будет автоматизированной системой сбора и управления информации.

Сайт поликлиники раскрывает основную информацию о клинике, информирует о характере ее деятельности и контактной информации, является визитной карточкой медицинской клиники. Создание сайта повышает авторитет поликлиники.

Для поликлиник - это уникальная возможность продемонстрировать свои услуги всем, распространяя важную информацию среди заинтересованных лиц (врачей, пациентов, клиентов, коллег в других медицинских учреждениях).

Это отличный способ поделиться результатами своей кампании и создать информационное пространство для врачей, пациентов и клиентов. На веб-сайте можно оставлять отзывы про поликлинику и врачей благодаря которым новые посетители могут ознакомится с качеством услуг.

 

2.1.2 Назначение веб-сайта

 

С помощью веб-сайта можно ознакомиться со списком врачей, о самой поликлинике и её местоположению.

Назначением сайта является информировние жителей города и заинтересованных лиц, о возможности выбора в получении услуг разного медицинского характера, а также дистанционной записи к специалистам поликлинике и контролированию записями в личном кабинете.

 

2.1.3 Характеристики оборудования

 

Для работы с системой управления контентом необходимо:

 • операционные система Windows: Microsoft Windows 10/8/7.

Требования к компьютеру:

• IntelPentium III/800 мГц или выше (или аналогичный);

• минимум 4 Гб ОЗУ;

• 1 Тб свободного места на сервере;

Характеристики используемой системы:

• операционная система Microsoft Windows 10 x64;

Intel Core i7;

• 16 ГбОЗУ;

• разрешение экрана 1366x768.

 

2.2 Реализация проекта

 

В соответствии с требованиями заказчика были выделены следующие этапы реализации проекта:

1. Проектирование веб-сайта.

2. Создание баз данных для сайта.

3. Разработка веб-сайта на платформе WordPress.

4. Тестирование веб-сайта.

 

2.3 Средства для разработки и проектирование сайта

 

2.3.1 Анализ средств для разработки и создания Web-сайта

 

Инструменты и программы, такие как HTML, CSS, JavaScript, FLASH, PHP, XML и т. д., обычно используются для создания современных веб-сайтов.

Конструктор сайтов

HTML — это фундаментальный язык в техническом мире веб-разработки, потому что его относительно легко выучить. Но излишняя простота также является его недостатком. HTML идеально подходил для ранней разработки технологии веб-сайтов, но по мере его дальнейшего развития возникали серьезные проблемы.

Язык HTML предназначен для формирования и оформления текстовых страниц, предназначенных для просмотра в сети Интернет с помощью специальной программы – браузера [14].

Генерация файлов HTML не требует использования мощного текстового процессора, который более удобен в использовании, например, редактор Notepad++. Содержимое HTML-страницы отображается в виде гипертекста, что означает, что в отображаемом на экране документе есть каким-то образом выбранное место, которое одним щелчком мыши может переместиться в другую часть той же страницы или на другую страницу.

Все, что нужно для чтения HTMLдокумента —это веб-браузер, который интерпретирует HTML-разметку и отображает документ на экране в форме, предоставленной автором. HTML позволяет использовать теги для обозначения расположения заголовков или абзацев в документе, а затем позволить веб-браузеру интерпретировать эти теги. Основное преимущество HTML заключается в том, что документы можно просматривать в различных типах веб-браузеров и на различных платформах [15].

CSS (каскадные таблицы стилей) — каскадные таблицы стилей — пытаются отделить детали дизайна страницы от ее структуры и содержимого. В классическом HTML смешаны структура и оформление: рядом с абзацем текста его цвет, размер шрифта, тип шрифта и так далее. Если вам нужно изменить простые параметры, такие как размер шрифта на вашем сайте, вам придется переписать все страницы. Команды CSS позволяют назначать стили всем объектам, описания которых можно полностью хранить в отдельных файлах. Используя декодеры CSS, вы можете изменить размер шрифта всех страниц вашего сайта, исправив только один файл стиля.

Чем больше разных стилей вы примените, тем веселее будет менять дизайн. Самое главное, что вам не придется изменять готовый HTML-документ на сервере. Браузер пользователя получит доступ к файлу со стилями (по ссылке) и придаст странице желаемый вид [16].

CSS можно добавить на веб-страницу тремя способами: встроенным, вложенным и связанным с отдельным файлом CSS. Логично использовать ссылки на файлы CSS.

Таблица стилей — это отдельный файл, содержащий только правила CSS. Неограниченное количество веб-страниц может использовать такие файлы, что позволяет обеспечить надежный и идентичный внешний вид для всех страниц сайта [17].

Фреймы — элемент языка HTML, позволяющий строго разделить страницу на несколько отдельных окон и разместить в каждом окне собственную веб-страницу. В основном он используется для организации меню, которые продолжают появляться на экране, в то время как сама информация находится в другом окне. Flash — это технология, разработанная Macromedia Inc. Разнообразить обычные текстовые страницы сайта красочной и интерактивной векторной графикой. Технология Flash позволяет создавать потрясающие презентационные видеоролики и интерактивные интерфейсы, создавая новое комфортное качество на вашем сайте.

Преимущества Flash:

- платформенная независимость;

- распространенность и предоставление дизайнерам огромное количество инструментов;

- правильно созданные Flash-файлы занимают мало места и достаточно быстро загружаются.

Недостатки Flash:

- Flash-технология сложна в изучении;

- нет желания у многих пользователей Интернет обновлять версии проигрывателей Flash, и следовательно многие новые Flash-модули не работают;

- Долгая загрузка из-за большого объема графических файлов.

JavaScript. Это отличный инструмент, позволяющий HTML-страницам, загруженным в браузер, динамически управлять своим содержимым и самим браузером. Реализация JavaScript под названием «динамический HTML» позволяет веб-страницам иметь почти полный пользовательский интерфейс, включая многоуровневые раскрывающиеся меню, перетаскивание, анимацию и многое другое. Текст программы встраивается непосредственно в HTML-документ и интерпретируется самим браузером.

Популярность языка JavaScript связана с его широким спектром возможностей для взаимодействия с элементами веб-страницы без перезагрузки веб-страницы. Это позволяет скрывать и показывать фрагменты дизайна, перемещать их и изменять внешний вид. С помощью этих действий вы можете создавать эффекты презентации, меню, мини-игры, обрабатывать данные форм и управлять контентом [18]. PHP — это язык программирования высокого уровня, используемый для написания скриптов для различных целей. Первая версия этого языка была создана Расмусом Лердофом для разработки веб-сайтов. Отсюда и исходное название языка — PHP (Personal Homepage — Персональная домашняя страница). По мере того, как его популярность росла, PHP вырос настолько, что стал полноценным языком программирования. Теперь это называется обработка гипертекста. Высокий уровень языка означает простоту его синтаксиса и принципов программирования [19].

Интерпретатор PHP имеет открытый исходный код, что позволяет программистам по всему миру расширять и улучшать его функциональность. В разработке PHP участвовало международное сообщество программистов, что обеспечило достаточно быстрое развитие языковых средств [20].

PHP можно использовать в различных операционных системах: Windows, Linux, Unix и Mac OS. Между тем есть два варианта использования PHP — создание веб-приложений и разработка программ общего назначения. Поэтому предусмотрено два исполняемых модуля интерпретатора:

PHP CGI (Common Getwaitc Interface) — используется для выполнения скриптов через веб-сервер и отображения результатов в окне браузера;

PHP CLI (интерфейс командной строки) — для выполнения общих сценариев. Этот модуль имеет интерфейс командной строки.

Сценарии PHP хранятся в виде простых текстовых файлов, поэтому их можно писать и редактировать с помощью простого текстового редактора, такого как Блокнот. Расширение файла скрипта может быть любым, но чаще всего используется .рhp.

Необходимо обратить внимание на особенности взаимодействия PHP и веб-сервера.

PHP наиболее широко используется для веб-приложений, то есть для создания сценариев, которые выполняются на стороне сервера в Интернете, а не в браузере. Как известно, скрипты также могут выполняться на стороне клиента, но они пишутся на других языках и их код вставляется в HTML-документы.

XML (eXtensible Markup Language) — расширяемый язык разметки для описания структурированных данных в текстовой форме. Этот текстовый формат во многом похож на HTML и был разработан специально для хранения и передачи данных.

XML позволяет описывать и передавать такие структурированные данные, как:

- отдельные документы;

- метаданные, описывающие содержимое какого-либо узла Internet;

- объекты, содержащие данные и методы работы с ними;

- отдельные;

- всевозможные web-ссылки на информационные и людские ресурсы в Интернете.

Данные, описанные в XML, называются XML-документом. Язык XML легко читать и легко понимать. Исходный текст XML-документа состоит из набора XML-элементов, каждый из которых содержит открывающий и закрывающий теги. Каждая пара меток представляет один фрагмент данных. То есть, как и HTML, XML использует теги для описания данных. Однако, в отличие от HTML, XML допускает бесконечный набор пар тегов, каждый из которых представляет не содержащиеся в нем данные, а то, что они означают.

Вы можете использовать специальные директивы — таблицы стилей XSL (Extensible Style Sheet Language) для управления отображением элементов в окнах клиентских программ (например, окнах браузера). Эти XSL-таблицы позволяют определять внешний вид элемента на основе его положения в документе, то есть к двум элементам с одинаковым именем могут применяться разные правила форматирования. Кроме того, базовым языком XSL является XML, а это означает, что таблицы XSL являются более общими, и для контроля правильности таких таблиц стилей можно использовать DTD или схемы данных.

Инструменты для обработки данных, полученных в формате XML, могут быть разработаны в средах Visual Basic, Java или C++ [21].

программное обеспечение для веб-разработки

Создание, поддержка и развитие сайта осуществляется с помощью специального программного обеспечения.

HTML-документы можно создавать в любом текстовом редакторе, например в Блокноте. HTML-документы могут быть преобразованы из многих программ, таких как Microsoft Word. После преобразования страница текста может быть превращена в огромный HTML-файл размером более 100 КБ. HTML-документы можно создавать с помощью пакетов визуализации, таких как Microsoft FrontPage. Эти редакторы сами генерируют html-код документа, а разработчик просто выбирает нужные ему опции из меню.

Macromedia Corporation — один из лидеров в разработке программного обеспечения для подготовки веб-публикаций. Большой популярностью пользуются пакеты Macromedia: Dreamweaver, HomeSite и специализированные пакеты для создания компьютерной графики и анимации.

Особого внимания заслуживает создание графики для веба. Следует помнить, что существует два вида графики: растровая (при описании каждой точки изображения) и векторная (при задании формулы построения изображения). Последний способ построения графиков более компактен и идеально подходит для создания анимаций.

Для использования PHP необходимы смежные серверные компоненты, а именно:

- web-сервер;

- сервер баз данных - это серверный компонент, который позволит работать с базами данных, управляемых из PHP.

В дополнение к серверным компонентам также очень полезны инструменты, без которых работа PHP-программиста может быть затруднена. Это редакторы кода PHP, позволяющие подсвечивать синтаксис PHP, что значительно упрощает написание сценариев [22].

JavaScript — это скриптовый язык программирования. Часто используется как встраиваемый язык для программного доступа к объектам приложения. Он наиболее широко используется в браузерах в качестве языка сценариев для создания интерактивных веб-страниц.

Для написания приложений вы можете использовать NotePad++, бесплатный текстовый редактор с открытым исходным кодом для Windows с подсветкой синтаксиса для большого количества языков программирования и разметки. Базовый функционал программы может быть расширен плагинами и сторонними модулями, такими как компиляторы и препроцессоры [23].

CSS и многие другие приложения в настоящее время поддерживаются почти всеми браузерами. Все, что вам нужно, это текстовый редактор для создания CSS, но есть много инструментов, которые облегчают этот процесс. Сегодня большинство инструментов веб-разработки обеспечивают некоторую поддержку таблиц стилей CSS.

Использовать XML в своих программах очень просто, поскольку он позволяет без особых усилий реализовать удобный формат обмена данными. Вот почему XML так популярен, потому что он прост в использовании и существует множество доступных инструментов обработки.

Для css и xml вы можете использовать HTML-Kit — редактор HTML, XHTML и XML с подключаемыми модулями, который предоставляет рекомендации по CSS и многое другое.

 

2.3.2 Фреймворки, используемые при разработке Web-сайтов: сравнительный анализ

 

Фреймворк — это программный фреймворк, который реализует базовую архитектуру проекта. Самыми известными современными php-фреймворками являются Zend Framework, Yii, CodeIgniter, Symfony и многие другие.

Фреймворки предоставляют разработчикам очень мощный инструмент для разработки более гибких и менее подверженных ошибкам приложений за меньшее время. Фреймворки часто помогают ускорить процесс разработки, предоставляя необходимую функциональность. К ним относятся управление пользователями/разрешениями, доступ к данным, кэширование и многое другое. Фреймворки помогают сосредоточиться на более важных деталях дизайна и с легкостью управлять проектами.Zend Framework (ZF) - является объектно-ориентированным фреймворком с открытым исходным кодом, использует PHP5 и выпущен под лицензией New BSD License.

Zend Framework был задуман в начале 2005 года, когда много новых фреймворков набирали популярность в сообществе web-разработчиков. О ZF впервые было объявлено на первой Zend конференции в октябре 2005 года.

Функции Zend Framework включают в себя:

-   большое количество модулей и библиотек;

-   разрабатывается разработчиками ядра PHP;

-   поддержка unit-тестов;

-   достаточно низкая скорость работы с библиотеками;

-   встроенный JS фреймворк DOJO и библиотеки для него.

Symfony – web-фреймворк написанный на PHP, использует платформу модель-представление-контроллер (MVC). Был выпущен под лицензией MIT. Symfony является свободным программным обеспечением.

 Symfony не следует путать с Symfony CMS, Open Source XML/XSLT системой управления контентом. Symfony ускоряет создание и поддержку web-приложений. В настоящее время совместима с ORM Propel и Doctrine. Следует отметить, что на типичном хостинге, где ускоритель PHP отсутствует, Symfony может использовать собственный движок кэширования для ускорения выполнения кода.

Symfony направлен на создание надежных приложений, с целью предоставить разработчикам полный контроль над конфигурацией.

Достоинства:

- простой в освоении;

- достаточно высокая скорость работы ядра.

Yii — высокопроизводительный фреймворк, и для организации из 10+ человек имеет смысл его изучать, а с одним Yii сложно справиться. Этот фреймворк позволяет создавать очень эффективные системы.

Yii — лучший выбор между Zend Framework и Codeingiter. Он хорошо документирован, и вы всегда можете вникнуть в код, чтобы понять, что и как работает.

Фреймворк строго написан на PHP5 и строго следует концепции ООП, поэтому его легко понять, если у вас есть базовое понимание принципов ООП.

Yii более сложен (более функционален) и лучше структурирован, чем CodeIgniter.

Он меньше и более производительный, чем фреймворк Zend. Для написания приложений требуется гораздо меньше кода, в то время как у Yii масса функций.

CodeIgniter - это PHP фреймворк, который использует платформу MVC, имеет классы для доступа к данным, классы для работы с почтой, FTP и XML-RPC.

У CodeIgniterимеется исчерпывающая документация для начала работы [24].На рисунке 3 изображён интефейс CodeIgniter.

 

Рисунок 3- Интерфейс CodeIgniter

 

Таблица 2 Характерные особенности фреймворков

 

Zend Framework 1

Code Igniter 2

Symfony 2

Описание

Академически грамотный код. Очень гибок. Требует хорошего знания PHP и ООП.

Почти микрофреймворк. Очень лёгкий для изучения. Отличная документация. Гибок. Легко использовать сторонний код.

Активно использует командную строку. Мощный ORM, хорошая система view, генераторы кода.

Необходимый уровень знаний

PHP5, ООП, шаблоны проектирования.

PHP, Основы ООП

PHP5, ООП, ORM, консоль.

Платформа

PHP 5

PHP 4/5

PHP 5

Сложность установки и настройки

Высокая

Низкая

Высокая

Поддерживаемые БД

MySQL, Oracle, PostgreSQL, MS SQL, SQLite

MySQL, Oracle, PostgreSQL, MS SQL, SQLite

MySQL, Oracle, PostgreSQL, MS SQL, SQLite

Русскоязычное сообщество

Да

Документация, форум, блоги

Нет

Лицензия

New BSD

BSD

MIT

 

 

2.3.3 Проектирование веб-сайта

 

Заказчиком является поликлиника, расположенная в городе Абиджан находящаяся по адресу 4 Bd de l'Indenie, Abidjan, Кот-д'Ивуар, поликлинику посещают жители города и ближайших населенных пунктов города Абиджан.

Деятельность клиники началась в 2015 году. В настоящее время в клинике проводят полный спектр услуг для поддержания и лечения здоровья человека. В поликлинике работают специалисты разных специальностей таких, как аллерголог, дерматолог, невролог и другие.

Структура сайта представлена на рисунке 2.

 

1.   Первая страница.

Главная страница — это лицо сайта, где обычно приводится краткая информация о направлениях деятельности поликлиники, предоставляемых услуг.

Основное назначение главной страницы web-сайта - рассказать пользователям о поликлинике, ее преимуществах. Разработанный сайт оказывает медицинские услуги. Это и отражено на главной странице путём размещения на ней прямых ссылок на главную информацию о поликлинике и её услугах.

2.   О поликлинике.

В этом разделе приводится краткая информация о поликлинике.

3.   Услуги.

В этом разделе описаны медицинские услуги, которые предоставляет поликлиника

4.   Отзывы.

Раздел содержит отзывы посетителей поликлинике совместно с оцениванием её по 5 бальной шкале

5.   Книга записей

Раздел «Книга записей» — раздел в котором показано свободное время для записей у специалистов поликлиники.

6.   Вход в систему

Раздел «Вход в систему» позволяет пользователю зарегистрироваться на веб-сайте или войти под своим логином и паролем, если он уже зарегистрирован на веб-сайте.

7.   После регистрации или входа на сайт пользователь может записаться на приём к специалисту, посмотреть активные записи, посмотреть предыдущие записи или сменить пароль своей учётной записи.

Каркас сайта считается одним из ключевых эскизных проектов, которые делаются перед созданием оригинал-макета сайта, и применяется при разработке дизайна сайта, для того чтобы продемонстрировать его структуру, 25 настраиваемые пути пользователя, наиболее значимые элементы интерфейса пользователя, их расположение и взаимосвязь между страницами сайта.

За управлением базами данных отвечает специальный плагин KiviCare.

KiviCare — плагин для клиники и управления пациентами. Он разработан для врачей и клиник, чтобы обрабатывать несколько назначений врачей и встреч в клинике. Это позволяет делать, управлять и отслеживать запись пациентов на прием к врачам. Сохраняя конфиденциальность на переднем плане, каждый визит к врачу может быть конфиденциальным для других. Администратор создаёт учётную запись для врача и присылает на его почту пароль, который врач может поменять перейдя по ссылке полученной по электронной почте. На рисунке 3 показана панель администратора при создании учётной записи врача.

 

Рисунок 3- Панель администратора

 

Созданию шаблона веб-сайта предшествовало формирование блочной структуры, которая определяет размещение функциональных элементов вебсайта. На главной странице веб-сайта расположена шапка сайта с изображением логотипа и наименованием учреждения (этот элемент будет размещаться на всех страницах веб-сайта) и панель навигации (элемент будет размещаться на всех страницах веб-сайта). Блочная структура главной страницы представлена на рисунке 4.

Рисунок 4- Структура главной страницы

 

На рисунке 5 и 6 изображены база данных пациентов и врачей , которые можно экспортировать в csvи excel.

 

Рисунок 5- База данных пациентов

 

Рисунок 6- База данных врачей

 

2.3.4 Разработка веб-сайта в CMS WordPress

 

Перед тем, как приступить к разработке веб-сайта в CMS WordPress, необходимо установить систему на хостинг и настроить необходимое ПО для работы с ним.

 Для установки CMS WordPress был скачан дистрибутив cофициального веб-сайта ru.wordpress.org. После скачивания дистрибутива был установлено программное обеспечение OpenServer. Данный программный комплекс включает в себя тщательно подобранный набор серверного программного обеспечения, а также невероятно удобную и продуманную управляющую утилиту, которая обладает мощными возможностями по администрированию и настройке всех доступных компонентов.

Базовые модули

  Apache: 2.2.31, 2.4.38, 2.4.41, 2.4.53 + auth_ntlm, fcgid, maxminddb, xsendfile

  Bind: 9.16.28

  FTP FileZilla: 0.9.60

  Ghostscript: 9.56.1

  Nginx: 1.21.6 + ssl_preread, image_filter, geoip, geoip2, brotli

  NNCron Lite: 1.17

  Sendmail: 32

После установки системы необходимо подготовить будущую базу данных и панель администратора для дальнейшей работы с дистрибутивами.OpenServer Panel изображена на рисунке 7.

Рисунок 7-OpenServerPanel

 

Для начала, необходимо подготовить файлы исходного шаблона для переноса на WordPress. Нужно создать новую папку с нашим веб-сайтом в WordPress.

После всех манипуляций создаём администратора для веб-сайта и заходим вWordPressдля создания сайта. На рисунке 8 изображён интерфейс Wordpress.

 

Рисунок 8-Интерфейс Wordpress

 

  После того, как сайт был создан нужно создать домен для него, для сайта поликлиники был выбран домен  https://delya-food.online/. Листинг сайта изображён в Приложении А.

  На основе созданных шаблонов и с помощью CMS WordPress был разработан конечный продукт — веб-сайт. На главной странице расположена активная кнопка «BookAppointment»,контактная информация, активные иконки оказываемых услуг и информация о руководстве медицинской клиники. Главная страница веб-сайта представлена на рисунке 9.

 

Рисунок 9-Главная страница веб-сайта поликлиники

 

В блоке «About» главной страницы расположена кликабельная иконка на услуги снизу блока, сверху написана информация о поликлинике. Блок «About» представлен на рисунке 10.

 

Рисунок 10-Блок «About»

 

В блоке «Procedures» главной страницы расположена информация об услугах поликлиники. Блок «Procedures» представлен на рисунке 11.

 

Рисунок 11-Блок «Procedures»

 

В блоке «Reviews» главной страницы расположены отзывы клиентов поликлиники. Блок «Reviews» представлен на рисунке 12.

 

Рисунок 12Блок «Reviews»

 

В блоке «Contact» главной страницы расположены адрес, контакты и местоположение поликлиники. Блок «Contact» представлен на рисунке 13.

 

Рисунок 13-Блок «Contact»

 

При нажатии на кнопку главной страницы «Login/SignUp» пользователя переносит на страницу регистрации и вхождения в аккаунт . Страница регистрации пользователяпредставлена на рисунке14.

 

Рисунок14 –Страница регистрации пользователя

 

На странице аккаунта показана информация о пользователе и о текущих записях. Страница аккаунта изображена  на рисунке 15.

 

Рисунок 15-Страница аккаунта

 

На странице аккаунта в блоке «Appointments» страницы расположены записи пользователя к специалистам поликлиники. Блок «Appointments» представлен на рисунке 16.

 

Рисунок 16-Блок «Appointments»

 

В блоке «BookAppointment» находится окно с выбором специалиста и временем записи к нему. Блок «BookAppointment» представлен на рисунке17.

Рисунок 17-Блок «BookAppointment»

 

В блоке «Encounters» находятся старые записи пользователя в поликлинике. Блок «Encounters» представлен на рисунке 18.

 

Рисунок 18-Блок «Encounters»

 

На странице аккаунта в блоке «Profile» страницы расположена информация о пользователе, которую пользователю может изменить в любой момент времени. Блок «Profile» представлен на рисунке 19.

 

Рисунок 19Блок «Profile»

 

Листинг веб сайта показан в Приложении А.

3. Тестирование веб-сайта и руководство пользователя

 

3.1. Тестирование веб-сайта

 

Тестирование сайта — это процесс контроля качества программного продукта.

Основная функция тестирования заключается в обнаружении и документировании дефектов (или ошибок) в программном обеспечении.

Тестирование программного обеспечения для интерактивных развлечений — это высокотехнологичная область, требующая компьютерных знаний, аналитических навыков и навыков критической оценки.

Существует несколько уровней тестирования программного обеспечения:

• Альфа-тестирование – имитация реальной работы системы штатными разработчиками;

• Бета-тестирование. Распространите бета-версию программного обеспечения среди большего числа людей, чтобы гарантировать, что продукт содержит достаточно ошибок, чтобы исправить их в будущих выпусках.

• Модульное тестирование — для тестирования используйте наименьший возможный тестовый компонент, например, один класс или функцию;

• Интеграционное тестирование – тестирование компонентов, подсистем или интерфейсов между системами;

• Системное тестирование – проверка сложных систем на соответствие требованиям;

Сайт прошел все этапы тестирования для различных версий операционных систем Microsoft Windows 7.8 и 10.

 

 

 

 

Таблица 2-Результаты функционального тестирования

п/п

Категория

набора тестов

Ожидаемый результат

Результат

1

Проверка

работоспособности кнопок

главнойстраницы

Все кнопки главной страницы функционируют должным образом

Пройден

2

Проверка

работоспособности регистрация

Регистрация на веб сайте работает, данные сохраняются в базе данных

Пройден

3

Проверка валидации при регистрации

Валидация фамилии, имени и электронной почты работают

Пройден

4

Проверка

работоспособности верификации

Верификация на сайте работает, после внесения логина и пароля, пользователя переносит в его личный кабинет

Пройден

5

Запись пользователя к врачу

Выбор врача и даты записи к врачу

Пройден

6

Просмотр записей к врачам

После того, как пользовательзаходит в личный кабинет он может видеть текущие и старые записи к врачам

 

3.2. Руководство пользователя

 

1.Общее назначение веб-сайта.

Веб-сайт предназначен для просмотра информации о поликлинике, записи к врачам, редактированию информации учётной записи и просмотру текущих и прошлых записей пользователя

2.Варианты использования веб-сайта.

В ходе анализа требований была разработана UML-диаграмма вариантов использования пользователем веб-сайта. (рис.20)

 

Рисунок 20-Варианты взаимодействия пользователя с веб-сайтом

 

Для того, чтобы зайти на веб-сайт поликлиники требуется запустить браузер и перейти по ссылке https://delya-food.online/. После перехода по ссылке на главной странице пользователь может посмотреть информацию о поликлинике и перейти на страницу регистрации нажав на кнопку Login/Signup.

 На рисунке 21 изображена страница регистрации пользователя.

 

 

 

После регистрации пользователя на странице регистрации пользователя переносит на профиль, в котором он может записываться на приём перейдя на вкладу BookAppointments , посмотреть свои записи к врачам на вкладке Appointment и изменить данные во вкладке Profile. Вкладки Appointments, Book Appointmentи Profile показаны на рисунках 22,23,24.

 

 

 

Рисунок 22- Вкладка Book Appointment

 

Рисунок 23- Вкладка Appointment

 

Рисунок 24- ВкладкаProfile

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Заключение

 

Результатом выпускной квалификационной работы является готовый веб-сайт поликлиники.

Были решены следующие частные задачи:

· ознакомление с современными Интернет - технологиями и их использование в настоящей разработке;

· изучение программного инструментария, применяемого для разработки и создания Web-сайтов программы Wordpress;

· ознакомление со структурой поликлиники;

· определение структуры Web-страниц;

· изучены методы размещения сайтов в Интернете

Полученный в итоге веб-сайт может полностью удовлетворить все требования заказчика.

 

Список использованной литературы

 

1. Голомбински К. Добавь воздуха! Основы визуального дизайна для

графики, веб и мультимедиа [Текст] / К. Голомбински, Р. Хаген. — СанктПетербург: Питер, 2013. — 272 с.

2. Городулин В. Основы CSS [Электронный ресурс]. — Режим доступа: #"_Toc104843255">Приложение

Компетенции

 

ПриложениеА

 

if (!defined('KB_IN_BYTES')) { define('KB_IN_BYTES', 1024); }

if (!defined('MB_IN_BYTES')) { define('MB_IN_BYTES', 1024 * KB_IN_BYTES); }

if (!defined('GB_IN_BYTES')) { define('GB_IN_BYTES', 1024 * MB_IN_BYTES); }

if (!defined('DUPLICATOR_PHP_MAX_MEMORY')) { define('DUPLICATOR_PHP_MAX_MEMORY', 4096 * MB_IN_BYTES); }

 

date_default_timezone_set('UTC'); // Some machines don’t have this set so just do it here.

@ignore_user_abort(true);

 

if (!function_exists('wp_is_ini_value_changeable')) {

  /**

  * Determines whether a PHP ini value is changeable at runtime.

  *

  * @staticvar array $ini_all

  *

  * @link https://secure.php.net/manual/en/function.ini-get-all.php

  *

  * @param string $setting The name of the ini setting to check.

  * @return bool True if the value is changeable at runtime. False otherwise.

  */

  function wp_is_ini_value_changeable( $setting ) {

  static $ini_all;

  if ( ! isset( $ini_all ) ) {

  $ini_all = false;

  // Sometimes `ini_get_all()` is disabled via the `disable_functions` option for "security purposes".

  if ( function_exists( 'ini_get_all' ) ) {

  $ini_all = ini_get_all();

  }

  }

 

  // Bit operator to workaround https://bugs.php.net/bug.php?id=44936 which changes access level to 63 in PHP 5.2.6 - 5.2.17.

  if ( isset( $ini_all[ $setting ]['access'] ) && ( INI_ALL === ( $ini_all[ $setting ]['access'] & 7 ) || INI_USER === ( $ini_all[ $setting ]['access'] & 7 ) ) ) {

  return true;

  }

 

  // If we were unable to retrieve the details, fail gracefully to assume it's changeable.

  if ( ! is_array( $ini_all ) ) {

  return true;

  }

 

  return false;

  }

}

 

@set_time_limit(3600);

if (wp_is_ini_value_changeable('memory_limit'))

  @ini_set('memory_limit', DUPLICATOR_PHP_MAX_MEMORY);

if (wp_is_ini_value_changeable('max_input_time'))

  @ini_set('max_input_time', '-1');

if (wp_is_ini_value_changeable('pcre.backtrack_limit'))

  @ini_set('pcre.backtrack_limit', PHP_INT_MAX);

if (wp_is_ini_value_changeable('default_socket_timeout'))

  @ini_set('default_socket_timeout', 3600);

 

DUPX_Handler::init_error_handler();

 

/**

 * Bootstrap utility to exatract the core installer

 *

 * Standard: PSR-2

 *

 * @package SC\DUPX\Bootstrap

 * @link #"\\", '/', (dirname(__FILE__). '/' .self::INSTALLER_DIR_NAME));

$this->installerExtractPath   = str_replace("\\", '/', (dirname(__FILE__)));

$this->archiveExpectedSize   = strlen(self::ARCHIVE_SIZE) ?  self::ARCHIVE_SIZE : 0 ;

$this->archiveActualSize   = $archiveActualSize;

 

  if($this->archiveExpectedSize > 0) {

  $this->archiveRatio   = (((1.0) * $this->archiveActualSize)  / $this->archiveExpectedSize) * 100;

  } else {

  $this->archiveRatio   = 100;

  }

 

  $this->overwriteMode = (isset($_GET['mode']) && ($_GET['mode'] == 'overwrite'));

}

 

/**

 * Run the bootstrap process which includes checking for requirements and running

 * the extraction process

 *

 * @return null | string Returns null if the run was successful otherwise an error message

 */

public function run()

{

date_default_timezone_set('UTC'); // Some machines don't have this set so just do it here

 

self::log('==DUPLICATOR INSTALLER BOOTSTRAP v1.4.4==');

self::log('----------------------------------------------------');

self::log('Installer bootstrap start');

 

$archive_filepath  = $this->getArchiveFilePath();

$archive_filename   = self::ARCHIVE_FILENAME;

 

$error = null;

 

$is_installer_file_valid = true;

if (preg_match('/_([a-z0-9]{7})[a-z0-9]+_[0-9]{6}([0-9]{8})_archive.(?:zip|daf)$/', $archive_filename, $matches)) {

  $expected_package_hash = $matches[1].'-'.$matches[2];

  if (self::PACKAGE_HASH != $expected_package_hash) {

  $is_installer_file_valid = false;

  self::log("[ERROR] Installer and archive mismatch detected.");

  }

} else {

  self::log("[ERROR] Invalid archive file name.");

  $is_installer_file_valid = false;

}

 

if (false  === $is_installer_file_valid) {

  $error = "Installer and archive mismatch detected.

Ensure uncorrupted installer and matching archive are present.";

  return $error;

}

 

$extract_installer   = true;

$installer_directory   = dirname(__FILE__).'/'.self::INSTALLER_DIR_NAME;

$extract_success = false;

$archiveExpectedEasy = $this->readableByteSize($this->archiveExpectedSize);

$archiveActualEasy = $this->readableByteSize($this->archiveActualSize);

 

  //$archive_extension = strtolower(pathinfo($archive_filepath)['extension']);

  $archive_extension = strtolower(pathinfo($archive_filepath, PATHINFO_EXTENSION));

$manual_extract_found = (

file_exists($installer_directory."/main.installer.php")

&&

file_exists($installer_directory."/dup-archive__".self::PACKAGE_HASH.".txt")

&&

file_exists($installer_directory."/dup-database__".self::PACKAGE_HASH.".sql")

);

 

  $isZip = ($archive_extension == 'zip');

 

//MANUAL EXTRACTION NOT FOUND

if (! $manual_extract_found) {

  //MISSING ARCHIVE FILE 

  if (! file_exists($archive_filepath)) {

  self::log("[ERROR] Archive file not found!");

  $error = "<style>.diff-list font { font-weight: bold; }</style>"

  . "<b>Archive not found!</b> The required archive file must be present in the <i>'Extraction Path'</i> below.  When the archive file name was created "

  . "it was given a secure hashed file name.  This file name must be the <i>exact same</i> name as when it was created character for character.  "

  . "Each archive file has a unique installer associated with it and must be used together.  See the list below for more options:<br/>"

  . "<ul>"

  . "<li>If the archive is not finished downloading please wait for it to complete.</li>"

  . "<li>Rename the file to it original hash name.  See WordPress-Admin ? Packages ?  Details. </li>"

  . "<li>When downloading, both files both should be from the same package line. </li>"

  . "<li>Also see: <a href='https://snapcreek.com/duplicator/docs/faqs-tech/#faq-installer-050-q' target='_blank'>How to fix various errors that show up before step-1 of the installer?</a></li>"

  . "</ul><br/>"

  ."<b>Extraction Path:</b><span>

 

  return $error;

  }

 

  // Sometimes the self::ARCHIVE_SIZE is ''.

  $archive_size = self::ARCHIVE_SIZE;

 

  if (!empty($archive_size) && !self::checkInputVaslidInt($archive_size)) {

  $no_of_bits = PHP_INT_SIZE * 8;

  $error  = 'Current is a '.$no_of_bits.'-bit SO. This archive is too large for '.$no_of_bits.'-bit PHP.'.'<br>';

  self::log('[ERROR] '.$error);

  $error  .= 'Possibibles solutions:<br>';

  $error  .= '- Use the file filters to get your package lower to support this server or try the package on a Linux server.'.'<br>';

  $error  .= '- Perform a <a target="_blank" href="#">Manual Extract Install</a>'.'<br>';

 

  switch ($no_of_bits == 32) {

  case 32:

  $error  .= '- Ask your host to upgrade the server to 64-bit PHP or install on another system has 64-bit PHP'.'<br>';

  break;

  case 64:

  $error  .= '- Ask your host to upgrade the server to 128-bit PHP or install on another system has 128-bit PHP'.'<br>';

  break;

  }

 

  if (self::isWindows()) {

  $error .= '- <a target="_blank" href="#">Windows DupArchive extractor</a> to extract all files from the archive.'.'<br>';

  }

 

  return $error;

  }

 

  //SIZE CHECK ERROR

  if (($this->archiveRatio < 90) && ($this->archiveActualSize > 0) && ($this->archiveExpectedSize > 0)) {

  self::log("ERROR: The expected archive size should be around [{$archiveExpectedEasy}].  The actual size is currently [{$archiveActualEasy}].");

  self::log("ERROR: The archive file may not have fully been downloaded to the server");

  $percent = round($this->archiveRatio);

 

  $autochecked = isset($_POST['auto-fresh']) ? "checked='true'" : '';

  $error  = "<b>Archive file size warning.</b><br/> The expected archive size should be around <b>  "

. "The actual size is currently <b>  The archive file may not have fully been downloaded to the server.  "

. "Please validate that the file sizes are close to the same size and that the file has been completely downloaded to the destination server.  If the archive is still "

. "downloading then refresh this page to get an update on the download size.<br/><br/>";

 

  return $error;

  }

 

}

 

 

  // OLD COMPATIBILITY MODE

  if (isset($_GET['extract-installer']) && !isset($_GET['force-extract-installer'])) {

  $_GET['force-extract-installer'] = $_GET['extract-installer'];

  }

 

  if ($manual_extract_found) {

  // INSTALL DIRECTORY: Check if its setup correctly AND we are not in overwrite mode

  if (isset($_GET['force-extract-installer']) && ('1' == $_GET['force-extract-installer'] || 'enable' == $_GET['force-extract-installer'] || 'false' == $_GET['force-extract-installer'])) {

  self::log("Manual extract found with force extract installer get parametr");

  $extract_installer = true;

  } else {

  $extract_installer = false;

  self::log("Manual extract found so not going to extract dup-installer dir");

  }

} else {

  $extract_installer = true;

}

 

if ($extract_installer && file_exists($installer_directory)) {

  self::log("EXTRACT dup-installer dir");

  $scanned_directory = array_diff(scandir($installer_directory), array('..', '.'));

  foreach ($scanned_directory as $object) {

  $object_file_path = $installer_directory.'/'.$object;

  if (is_file($object_file_path)) {

if (unlink($object_file_path)) {

  self::log('Successfully deleted the file '.$object_file_path);

} else {

  $error .= '[ERROR] Error deleting the file '.$object_file_path.' Please manually delete it and try again.';

  self::log($error);

}

  }

  }

}

 

//ATTEMPT EXTRACTION:

//ZipArchive and Shell Exec

if ($extract_installer) {

  self::log("Ready to extract the installer");

 

  self::log("Checking permission of destination folder");

  $destination = dirname(__FILE__);

  if (!is_writable($destination)) {

  self::log("destination folder for extraction is not writable");

  if (self::chmod($destination, 'u+rwx')) {

self::log("Permission of destination folder changed to u+rwx");

  } else {

self::log("[ERROR] Permission of destination folder failed to change to u+rwx");

  }

  }

 

  if (!is_writable($destination)) {

  self::log("WARNING: The {$destination} directory is not writable.");

  $error   = "NOTICE: The {$destination} directory is not writable on this server please talk to your host or server admin about making ";

  $error   .= "<a target='_blank' href='https://snapcreek.com/duplicator/docs/faqs-tech/#faq-trouble-055-q'>writable {$destination} directory</a> on this server. <br/>";

  return $error;

  }

 

  if ($isZip) {

  $zip_mode = $this->getZipMode();

 

  if (($zip_mode == DUPX_Bootstrap_Zip_Mode::AutoUnzip) || ($zip_mode == DUPX_Bootstrap_Zip_Mode::ZipArchive) && class_exists('ZipArchive')) {

if ($this->hasZipArchive) {

  self::log("ZipArchive exists so using that");

  $extract_success = $this->extractInstallerZipArchive($archive_filepath);

 

  if ($extract_success) {

  self::log('Successfully extracted with ZipArchive');

  } else {

  if (0 == $this->installer_files_found) {

$error = "[ERROR] This archive is not properly formatted and does not contain a dup-installer directory. Please make sure you are attempting to install the original archive and not one that has been reconstructed.";

self::log($error);

return $error;

  } else {

$error = '[ERROR] Error extracting with ZipArchive. ';

self::log($error);

  }

  }

} else {

  self::log("WARNING: ZipArchive is not enabled.");

  $error   = "NOTICE: ZipArchive is not enabled on this server please talk to your host or server admin about enabling ";

  $error   .= "<a target='_blank' href='https://snapcreek.com/duplicator/docs/faqs-tech/#faq-trouble-060-q'>ZipArchive</a> on this server. <br/>";

}

  }

 

  if (!$extract_success) {

if (($zip_mode == DUPX_Bootstrap_Zip_Mode::AutoUnzip) || ($zip_mode == DUPX_Bootstrap_Zip_Mode::ShellExec)) {

  $unzip_filepath = $this->getUnzipFilePath();

  if ($unzip_filepath != null) {

  $extract_success = $this->extractInstallerShellexec($archive_filepath);

  if ($extract_success) {

self::log('Successfully extracted with Shell Exec');

$error = null;

  } else {

$error .= '[ERROR] Error extracting with Shell Exec. Please manually extract archive then choose Advanced > Manual Extract in installer.';

self::log($error);

  }

} else {

  self::log('WARNING: Shell Exec Zip is not available');

  $error   .= "NOTICE: Shell Exec is not enabled on this server please talk to your host or server admin about enabling ";

  $error   .= "<a target='_blank' href='#";

  }

}

  }

 

  // If both ZipArchive and ShellZip are not available, Error message should be combined for both

  if (!$extract_success && $zip_mode == DUPX_Bootstrap_Zip_Mode::AutoUnzip) {

$unzip_filepath = $this->getUnzipFilePath();

if (!class_exists('ZipArchive') && empty($unzip_filepath)) {

  self::log("WARNING: ZipArchive and Shell Exec are not enabled on this server.");

  $error   = "NOTICE: ZipArchive and Shell Exec are not enabled on this server please talk to your host or server admin about enabling ";

  $error   .= "<a target='_blank' href='https://snapcreek.com/duplicator/docs/faqs-tech/#faq-trouble-060-q'>ZipArchive</a> or <a target='_blank' href='#";  

}

  }

  } else {

  DupArchiveMiniExpander::init("DUPX_Bootstrap::log");

  try {

DupArchiveMiniExpander::expandDirectory($archive_filepath, self::INSTALLER_DIR_NAME, dirname(__FILE__));

  } catch (Exception $ex) {

self::log("[ERROR] Error expanding installer subdirectory:".$ex->getMessage());

throw $ex;

  }

  }

 

  $is_apache = (strpos($_SERVER['SERVER_SOFTWARE'], 'Apache') !== false || strpos($_SERVER['SERVER_SOFTWARE'], 'LiteSpeed') !== false);

  $is_nginx = (strpos($_SERVER['SERVER_SOFTWARE'], 'nginx') !== false);

 

  $sapi_type = php_sapi_name();

  $php_ini_data = array(  

  'max_execution_time' => 3600,

  'max_input_time' => -1,

  'ignore_user_abort' => 'On',

  'post_max_size' => '4096M',

  'upload_max_filesize' => '4096M',

  'memory_limit' => DUPLICATOR_PHP_MAX_MEMORY,

  'default_socket_timeout' => 3600,

  'pcre.backtrack_limit' => 99999999999,

);

  $sapi_type_first_three_chars = substr($sapi_type, 0, 3);

  if ('fpm' === $sapi_type_first_three_chars) {

  self::log("SAPI: FPM");

  if ($is_apache) {

self::log('Server: Apache');

  } elseif ($is_nginx) {

self::log('Server: Nginx');

  }

 

  if (($is_apache && function_exists('apache_get_modules') && in_array('mod_rewrite', apache_get_modules())) || $is_nginx) {

$htaccess_data = array();

foreach ($php_ini_data as $php_ini_key=>$php_ini_val) {

  if ($is_apache) {

  $htaccess_data[] = 'SetEnv PHP_VALUE "'.$php_ini_key.' = '.$php_ini_val.'"';

  } elseif ($is_nginx) {

  if ('On' == $php_ini_val || 'Off' == $php_ini_val) {

$htaccess_data[] = 'php_flag '.$php_ini_key.' '.$php_ini_val;

  } else {

$htaccess_data[] = 'php_value '.$php_ini_key.' '.$php_ini_val;

  }  

  }

}  

 

$htaccess_text = implode("\n", $htaccess_data);

$htaccess_file_path = dirname(__FILE__).'/dup-installer/.htaccess';

self::log("creating {$htaccess_file_path} with the content:");

self::log($htaccess_text);

@file_put_contents($htaccess_file_path, $htaccess_text);

  }

  } elseif ('cgi' === $sapi_type_first_three_chars || 'litespeed' === $sapi_type) {

  if ('cgi' === $sapi_type_first_three_chars) {

self::log("SAPI: CGI");

  } else {

self::log("SAPI: litespeed");

  }

  if (version_compare(phpversion(), 5.5) >= 0 && (!$is_apache || 'litespeed' === $sapi_type)) {

$ini_data = array();

foreach ($php_ini_data as $php_ini_key=>$php_ini_val) {

  $ini_data[] = $php_ini_key.' = '.$php_ini_val;

}

$ini_text = implode("\n", $ini_data);

$ini_file_path = dirname(__FILE__).'/dup-installer/.user.ini';

self::log("creating {$ini_file_path} with the content:");

self::log($ini_text);

@file_put_contents($ini_file_path, $ini_text);

  } else{

self::log("No need to create dup-installer/.htaccess or dup-installer/.user.ini");

  }

  } else {

  self::log("No need to create dup-installer/.htaccess or dup-installer/.user.ini");

  self::log("ERROR:  SAPI: Unrecognized");

  }

} else {

  self::log("ERROR: Didn't need to extract the installer.");

}

 

if (empty($error)) {

  $config_files = glob('./dup-installer/dup-archive__*.txt');

  $config_file_absolute_path = array_pop($config_files);

  if (!file_exists($config_file_absolute_path)) {

  $error = '<b>Archive config file not found in dup-installer folder.</b><br><br>';

  return $error;

  }

}

$is_https = $this->isHttps();

 

if($is_https) {

  $current_url = 'https://';

} else {

  $current_url = '#"DONE: No detected errors so redirecting to the main installer. Main Installer URI = {$this->mainInstallerURL}");

  }

 }

 

return $error;

}

 

public function postExtractProcessing()

{

$dproInstallerDir = dirname(__FILE__) . '/dup-installer';  

$libDir = $dproInstallerDir . '/lib';

$fileopsDir = $libDir . '/fileops';

 

  if(!file_exists($dproInstallerDir)) {

 

  return 'Can\'t extract installer directory. See <a target="_blank" href="#">this FAQ item</a> for details on how to resolve.</a>';

  }

 

$sourceFilepath = "{$fileopsDir}/fileops.ppp";

$destFilepath = "{$fileopsDir}/fileops.php";

 

if(file_exists($sourceFilepath) && (!file_exists($destFilepath))) {

  if(@rename($sourceFilepath, $destFilepath) === false) {

  return "Error renaming {$sourceFilepath}";

  }

}  

}

 

/**

* Indicates if site is running https or not

*

* @return bool  Returns true if https, false if not

*/

public function isHttps()

{

$retVal = true;

  if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {

  $_SERVER ['HTTPS'] = 'on';

  }

if (isset($_SERVER['HTTPS'])) {

  $retVal = ($_SERVER['HTTPS'] !== 'off');

} else {

  $retVal = ($_SERVER['SERVER_PORT'] == 443);

  }

 

return $retVal;

}

 

  /**

* Fetches current URL via php

*

* @param bool $queryString If true the query string will also be returned.

* @param int $getParentDirLevel if 0 get current script name or parent folder, if 1 parent folder if 2 parent of parent folder ...

*

* @returns The current page url

*/

  public static function getCurrentUrl($queryString = true, $requestUri = false, $getParentDirLevel = 0)

  {

  // *** HOST

  if (isset($_SERVER['HTTP_X_ORIGINAL_HOST'])) {

  $host = $_SERVER['HTTP_X_ORIGINAL_HOST'];

  } else {

  $host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : $_SERVER['SERVER_NAME']; //WAS SERVER_NAME and caused problems on some boxes

  }

 

  // *** PROTOCOL

  if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {

  $_SERVER ['HTTPS'] = 'on';

  }

  if (isset($_SERVER['HTTP_X_FORWARDED_SSL']) && $_SERVER['HTTP_X_FORWARDED_SSL'] === 'https') {

  $_SERVER ['HTTPS'] = 'on';

  }

  if (isset($_SERVER['HTTP_CF_VISITOR'])) {

  $visitor = json_decode($_SERVER['HTTP_CF_VISITOR']);

  if ($visitor->scheme == 'https') {

  $_SERVER ['HTTPS'] = 'on';

  }

  }

  $protocol = 'http'.((isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) === 'on') ? 's' : '');

 

  $serverUrlSelf = preg_replace('/\?.*$/', '', $_SERVER['REQUEST_URI']);

  } else {

  // *** SCRIPT NAME

  $serverUrlSelf = $_SERVER['SCRIPT_NAME'];

  for ($i = 0; $i < $getParentDirLevel; $i++) {

  $serverUrlSelf = preg_match('/^[\\\\\/]?$/', dirname($serverUrlSelf)) ? '' : dirname($serverUrlSelf);

  }

  }

 

  // *** QUERY STRING

  $query = ($queryString && isset($_SERVER['QUERY_STRING']) && strlen($_SERVER['QUERY_STRING']) > 0 ) ? '?'.$_SERVER['QUERY_STRING'] : '';

 

  return $protocol.'://'.$host.$serverUrlSelf.$query;

  }

 

/**

*  Attempts to set the 'dup-installer' directory permissions

*

* @return null

*/

private function fixInstallerPerms()

{

$file_perms = 'u+rw';

$dir_perms = 'u+rwx';

 

$installer_dir_path = $this->installerContentsPath;

 

$this->setPerms($installer_dir_path, $dir_perms, false);

$this->setPerms($installer_dir_path, $file_perms, true);

}

 

/**

* Set the permissions of a given directory and optionally all files

*

* @param string $directory   The full path to the directory where perms will be set

* @param string $perms   The given permission sets to use such as '0755' or 'u+rw'

 * @param string $do_files Also set the permissions of all the files in the directory

*

* @return null

*/

private function setPerms($directory, $perms, $do_files)

{

if (!$do_files) {

  // If setting a directory hiearchy be sure to include the base directory

  $this->setPermsOnItem($directory, $perms);

}

 

$item_names = array_diff(scandir($directory), array('.', '..'));

 

foreach ($item_names as $item_name) {

  $path = "$directory/$item_name";

  if (($do_files && is_file($path)) || (!$do_files && !is_file($path))) {

  $this->setPermsOnItem($path, $perms);

  }

}

}

 

/**

* Set the permissions of a single directory or file

*

* @param string $path   The full path to the directory or file where perms will be set

* @param string $perms   The given permission sets to use such as '0755' or 'u+rw'

*

* @return bool Returns true if the permission was properly set

*/

private function setPermsOnItem($path, $perms)

{  

  if (($result = self::chmod($path, $perms)) === false) {

  self::log("ERROR: Couldn't set permissions of $path<br/>");

  } else {

  self::log("Set permissions of $path<br/>");

  }

  return $result;

}

 

  /**

* Compare two strings and return html text which represts diff

*

* @param string $oldString

* @param string $newString

*

* @return string Returns html text

*/

  private function compareStrings($oldString, $newString) {

$ret = '';

for($i=0; isset($oldString[$i]) || isset($newString[$i]); $i++) {

  if(!isset($oldString[$i])) {

  $ret .= '<font color="red">' . $newString[$i] . '</font>';

  continue;

  }

  for($char=0; isset($oldString[$i][$char]) || isset($newString[$i][$char]); $char++) {

  if(!isset($oldString[$i][$char])) {

$ret .= '<font color="red">' . substr($newString[$i], $char) . '</font>';

break;

  } elseif(!isset($newString[$i][$char])) {

  break;

  }

  if(ord($oldString[$i][$char]) != ord($newString[$i][$char]))

$ret .= '<font color="red">' . $newString[$i][$char] . '</font>';

  else

$ret .= $newString[$i][$char];

  }

}

return $ret;

}

 

  /**

* Logs a string to the dup-installer-bootlog__[HASH].txt file

*

* @param string $s   The string to log to the log file

*

* @return boog|int // This function returns the number of bytes that were written to the file, or FALSE on failure.

*/

public static function log($s, $deleteOld = false)

{

  static $logfile = null;

  if (is_null($logfile)) {

  $logfile = self::getBootLogFilePath();

  }

  if ($deleteOld && file_exists($logfile)) {

  @unlink($logfile);

  }

  $timestamp = date('M j H:i:s');

return @file_put_contents($logfile, '['.$timestamp.'] '.self::postprocessLog($s)."\n", FILE_APPEND);

}

 

  /**

* get boot log file name the dup-installer-bootlog__[HASH].txt file

*

* @return string

*/

  public static function getBootLogFilePath() {

  return dirname(__FILE__).'/dup-installer-bootlog__'.self::SECONDARY_PACKAGE_HASH.'.txt';

  }

 

  protected static function postprocessLog($str) {

  return str_replace(array(

  self::getArchiveFileHash(),

  self::PACKAGE_HASH,

  self::SECONDARY_PACKAGE_HASH

  ), '[HASH]' , $str);

  }

 

 

  public static function getArchiveFileHash()

  {

  static $fileHash = null;

  if (is_null($fileHash)) {

  $fileHash = preg_replace('/^.+_([a-z0-9]+)_[0-9]{14}_archive\.(?:daf|zip)$/', '$1', self::ARCHIVE_FILENAME);

  }

  return $fileHash;

  }

 

/**

* Extracts only the 'dup-installer' files using ZipArchive

*

* @param string $archive_filepath   The path to the archive file.

*

* @return bool Returns true if the data was properly extracted

*/

private function extractInstallerZipArchive($archive_filepath, $checkSubFolder = false)

{

$success   = true;

$zipArchive = new ZipArchive();

$subFolderArchiveList = array();

 

if (($zipOpenRes = $zipArchive->open($archive_filepath)) === true) {

  self::log("Successfully opened archive file.");

  $destination = dirname(__FILE__);

  $folder_prefix = self::INSTALLER_DIR_NAME.'/';

  self::log("Extracting all files from archive within ".self::INSTALLER_DIR_NAME);

 

  $this->installer_files_found = 0;

 

  for ($i = 0; $i < $zipArchive->numFiles; $i++) {

  $stat   = $zipArchive->statIndex($i);

  if ($checkSubFolder == false) {

$filenameCheck = $stat['name'];

$filename = $stat['name'];

  $tmpSubFolder = null;

  } else {

  $safePath = rtrim(self::setSafePath($stat['name']) , '/');

$tmpArray = explode('/' , $safePath);

if (count($tmpArray) < 2)  {

  continue;

}

 

$tmpSubFolder = $tmpArray[0];

array_shift($tmpArray);

$filenameCheck = implode('/' , $tmpArray);

$filename = $stat['name'];

  }

 

 

  if ($this->startsWith($filenameCheck , $folder_prefix)) {

$this->installer_files_found++;

 

if (!empty($tmpSubFolder) && !in_array($tmpSubFolder , $subFolderArchiveList)) {

  $subFolderArchiveList[] = $tmpSubFolder;

}

 

if ($zipArchive->extractTo($destination, $filename) === true) {

  self::log("Success: {$filename} >>> {$destination}");

} else {

  self::log("[ERROR] Error extracting {$filename} from archive archive file");

  $success = false;

  break;

}

  }

  }

 

  if ($checkSubFolder && count($subFolderArchiveList) !== 1) {

  self::log("Error: Multiple dup subfolder archive");

  $success = false;  

  } else {

  if ($checkSubFolder) {

$this->moveUpfromSubFolder(dirname(__FILE__).'/'.$subFolderArchiveList[0] , true);

  }

 

    $lib_directory = dirname(__FILE__).'/'.self::INSTALLER_DIR_NAME.'/lib';

    $snaplib_directory = $lib_directory.'/snaplib';

 

    // If snaplib files aren't present attempt to extract and copy those

    if(!file_exists($snaplib_directory))

    {

  $folder_prefix = 'snaplib/';

  $destination = $lib_directory;

 

  for ($i = 0; $i < $zipArchive->numFiles; $i++) {

    $stat = $zipArchive->statIndex($i);

    $filename = $stat['name'];

 

    if ($this->startsWith($filename, $folder_prefix)) {

    $this->installer_files_found++;

 

    if ($zipArchive->extractTo($destination, $filename) === true) {

   self::log("Success: {$filename} >>> {$destination}");

    } else {

    self::log("[ERROR] Error extracting {$filename} from archive archive file");

    $success = false;

    break;

    }

    }

  }

    }

  }

 

  if ($zipArchive->close() === true) {

  self::log("Successfully closed archive file");

  } else {

  self::log("[ERROR] Problem closing archive file");

  $success = false;

  }

 

  if ($success != false && $this->installer_files_found < 10) {

  if ($checkSubFolder) {

self::log("[ERROR] Couldn't find the installer directory in the archive!");

$success = false;

  } else {

self::log("[ERROR] Couldn't find the installer directory in archive root! Check subfolder");

$this->extractInstallerZipArchive($archive_filepath, true);

  }

  }

} else {

  self::log("[ERROR] Couldn't open archive archive file with ZipArchive CODE[".$zipOpenRes."]");

  $success = false;

}

 

return $success;

}

 

  /**

* return true if current SO is windows

*

* @staticvar bool $isWindows

* @return bool

*/

  public static function isWindows()

  {

  static $isWindows = null;

  if (is_null($isWindows)) {

  $isWindows = (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN');

  }

  return $isWindows;

  }

 

  /**

* return current SO path path len

* @staticvar int $maxPath

* @return int

*/

  public static function maxPathLen()

  {

  static $maxPath = null;

  if (is_null($maxPath)) {

  if (defined('PHP_MAXPATHLEN')) {

  $maxPath = PHP_MAXPATHLEN;

  } else {

  // for PHP < 5.3.0

  $maxPath = self::isWindows() ? 260 : 4096;

  }

  }

  return $maxPath;

  }

 

  /**

* this function make a chmod only if the are different from perms input and if chmod function is enabled

*

* this function handles the variable MODE in a way similar to the chmod of lunux

* So the MODE variable can be

* 1) an octal number (0755)

* 2) a string that defines an octal number ("644")

* 3) a string with the following format [ugoa]*([-+=]([rwx]*)+

*

* examples

* u+rw add read and write at the user

* u+rw,uo-wx add read and write ad the user and remove wx at groupd and other

* a=rw is equal at 666

* u=rwx,go-rwx is equal at 700

*

* @param string $file

* @param int|string $mode

* @return boolean

*/

  public static function chmod($file, $mode)

  {

  if (!file_exists($file)) {

  return false;

  }

 

  $octalMode = 0;

 

  if (is_int($mode)) {

  $octalMode = $mode;

  } else if (is_string($mode)) {

  $mode = trim($mode);

  if (preg_match('/([0-7]{1,3})/', $mode)) {

  $octalMode = intval(('0'.$mode), 8);

  } else if (preg_match_all('/(a|[ugo]{1,3})([-=+])([rwx]{1,3})/', $mode, $gMatch, PREG_SET_ORDER)) {

  if (!function_exists('fileperms')) {

  return false;

  }

 

  // start by file permission

  $octalMode = (fileperms($file) & 0777);

 

  foreach ($gMatch as $matches) {

  $group = $matches[1];

  if ($group === 'a') {

 $group = 'ugo';

  }

  // can be + - =

  $action = $matches[2];

  // [rwx]

  $gPerms = $matches[3];

 

  // reset octal group perms

  $octalGroupMode = 0;

 

  // Init sub perms

  $subPerm = 0;

  $subPerm += strpos($gPerms, 'x') !== false ? 1 : 0; // mask 001

  $subPerm += strpos($gPerms, 'w') !== false ? 2 : 0; // mask 010

  $subPerm += strpos($gPerms, 'r') !== false ? 4 : 0; // mask 100

 

  $ugoLen = strlen($group);

 

  if ($action === '=') {

  // generate octal group permsissions and ugo mask invert

  $ugoMaskInvert = 0777;

  for ($i = 0; $i < $ugoLen; $i++) {

  switch ($group[$i]) {

  case 'u':

  $octalGroupMode = $octalGroupMode | $subPerm << 6; // mask xxx000000

  $ugoMaskInvert  = $ugoMaskInvert & 077;

  break;

  case 'g':

  $octalGroupMode = $octalGroupMode | $subPerm << 3; // mask 000xxx000

  $ugoMaskInvert  = $ugoMaskInvert & 0707;

  break;

  case 'o':

  $octalGroupMode = $octalGroupMode | $subPerm; // mask 000000xxx

  $ugoMaskInvert  = $ugoMaskInvert & 0770;

  break;

  }

  }

  // apply = action

  $octalMode = $octalMode & ($ugoMaskInvert | $octalGroupMode);

  } else {

  // generate octal group permsissions

  for ($i = 0; $i < $ugoLen; $i++) {

  switch ($group[$i]) {

  case 'u':

  $octalGroupMode = $octalGroupMode | $subPerm << 6; // mask xxx000000

  break;

  case 'g':

  $octalGroupMode = $octalGroupMode | $subPerm << 3; // mask 000xxx000

  break;

  case 'o':

  $octalGroupMode = $octalGroupMode | $subPerm; // mask 000000xxx

  break;

  }

  }

  // apply + or - action

  switch ($action) {

  case '+':

  $octalMode = $octalMode | $octalGroupMode;

  break;

  case '-':

 $octalMode = $octalMode & ~$octalGroupMode;

  break;

  }

  }

  }

  }

  }

 

  // if input permissions are equal at file permissions return true without performing chmod

  if (function_exists('fileperms') && $octalMode === (fileperms($file) & 0777)) {

  return true;

  }

 

  if (!function_exists('chmod')) {

  return false;

  }

 

  return @chmod($file, $octalMode);

  }

 

  public static function checkInputVaslidInt($input) {

  return (filter_var($input, FILTER_VALIDATE_INT) === 0 || filter_var($input, FILTER_VALIDATE_INT));

  }

 

 

  /**

* this function creates a folder if it does not exist and performs a chmod.

* it is different from the normal mkdir function to which an umask is applied to the input permissions.

*

* this function handles the variable MODE in a way similar to the chmod of lunux

* So the MODE variable can be

* 1) an octal number (0755)

* 2) a string that defines an octal number ("644")

* 3) a string with the following format [ugoa]*([-+=]([rwx]*)+

*

* @param string $path

   * @param int|string $mode

* @param bool $recursive

* @param resource $context // not used for windows bug

* @return boolean bool TRUE on success or FALSE on failure.

*

* @todo check recursive true and multiple chmod

*/

  public static function mkdir($path, $mode = 0777, $recursive = false, $context = null)

  {

  if (strlen($path) > self::maxPathLen()) {

  throw new Exception('Skipping a file that exceeds allowed max path length ['.self::maxPathLen().']. File: '.$filepath);

  }

 

  if (!file_exists($path)) {

  if (!function_exists('mkdir')) {

  return false;

  }

  if (!@mkdir($path, 0777, $recursive)) {

  return false;

  }

  }

 

  return self::chmod($path, $mode);

  }

 

  /**

* move all folder content up to parent

*

* @param string $subFolderName full path

* @param boolean $deleteSubFolder if true delete subFolder after moved all

* @return boolean

*

*/

  private function moveUpfromSubFolder($subFolderName, $deleteSubFolder = false)

  {

  if (!is_dir($subFolderName)) {

  return false;

  }

 

  $parentFolder = dirname($subFolderName);

  if (!is_writable($parentFolder)) {

  return false;

  }

 

  $success = true;

  if (($subList = glob(rtrim($subFolderName, '/').'/*', GLOB_NOSORT)) === false) {

  self::log("[ERROR] Problem glob folder ".$subFolderName);

  return false;

  } else {

  foreach ($subList as $cName) {

  $destination = $parentFolder.'/'.basename($cName);

  if (file_exists($destination)) {

  $success = self::deletePath($destination);

  }

 

  if ($success) {

  $success = rename($cName, $destination);

  } else {

  break;

  }

  }

 

  if ($success && $deleteSubFolder) {

  $success = self::deleteDirectory($subFolderName, true);

  }

  }

 

  if (!$success) {

  self::log("[ERROR] Problem om moveUpfromSubFolder subFolder:".$subFolderName);

  }

 

  return $success;

  }

 

/**

* Extracts only the 'dup-installer' files using Shell-Exec Unzip

*

* @param string $archive_filepath   The path to the archive file.

*

* @return bool Returns true if the data was properly extracted

*/

private function extractInstallerShellexec($archive_filepath)

{

$success = false;

self::log("Attempting to use Shell Exec");

$unzip_filepath   = $this->getUnzipFilePath();

 

if ($unzip_filepath != null) {

  $unzip_command = "$unzip_filepath -q $archive_filepath ".self::INSTALLER_DIR_NAME.'/* 2>&1';

  self::log("Executing unzip command");

  $stderr   = shell_exec($unzip_command);

 

  $lib_directory = dirname(__FILE__).'/'.self::INSTALLER_DIR_NAME.'/lib';

  $snaplib_directory = $lib_directory.'/snaplib';

 

  // If snaplib files aren't present attempt to extract and copy those

  if(!file_exists($snaplib_directory))

  {

  $local_lib_directory = dirname(__FILE__).'/snaplib';

  $unzip_command = "$unzip_filepath -q $archive_filepath snaplib/* 2>&1";

  self::log("Executing unzip command");

  $stderr  .= shell_exec($unzip_command);

  self::mkdir($lib_directory,'u+rwx');

  rename($local_lib_directory, $snaplib_directory);

  }

 

  if ($stderr == '') {

  self::log("Shell exec unzip succeeded");

  $success = true;

  } else {

  self::log("[ERROR] Shell exec unzip failed. Output={$stderr}");

  }

}

 

return $success;

}

 

/**

* Attempts to get the archive file path

*

* @return string   The full path to the archive file

*/

private function getArchiveFilePath()

{

if (isset($_GET['archive'])) {

  $archive_filepath = $_GET['archive'];

} else {

$archive_filename = self::ARCHIVE_FILENAME;

  $archive_filepath = str_replace("\\", '/', dirname(__FILE__) . '/' . $archive_filename);

}

 

return $archive_filepath;

}

 

/**

* Gets the DUPX_Bootstrap_Zip_Mode enum type that should be used

*

* @return DUPX_Bootstrap_Zip_Mode   Returns the current mode of the bootstrapper

*/

private function getZipMode()

{

$zip_mode = DUPX_Bootstrap_Zip_Mode::AutoUnzip;

 

if (isset($_GET['zipmode'])) {

  $zipmode_string = $_GET['zipmode'];

  self::log("Unzip mode specified in querystring: $zipmode_string");

 

  switch ($zipmode_string) {

  case 'autounzip':

$zip_mode = DUPX_Bootstrap_Zip_Mode::AutoUnzip;

break;

 

  case 'ziparchive':

$zip_mode = DUPX_Bootstrap_Zip_Mode::ZipArchive;

break;

 

  case 'shellexec':

$zip_mode = DUPX_Bootstrap_Zip_Mode::ShellExec;

break;

  }

}

 

return $zip_mode;

}

 

/**

* Checks to see if a string starts with specific characters

*

* @return bool Returns true if the string starts with a specific format

*/

private function startsWith($haystack, $needle)

{

return $needle === "" || strrpos($haystack, $needle, - strlen($haystack)) !== false;

}

 

/**

* Checks to see if the server supports issuing commands to shell_exex

*

* @return bool Returns true shell_exec can be ran on this server

*/

public function hasShellExec()

{

$cmds = array('shell_exec', 'escapeshellarg', 'escapeshellcmd', 'extension_loaded');

 

//Function disabled at server level

if (array_intersect($cmds, array_map('trim', explode(',', @ini_get('disable_functions')))))

  return false;

 

//Suhosin: #"suhosin.executor.func.blacklist");

  if (array_intersect($cmds, array_map('trim', explode(',', $suhosin_ini))))

  return false;

}

 

  if (! function_exists('shell_exec')) {

  return false;

  }

 

// Can we issue a simple echo command?

if (!@shell_exec('echo duplicator'))

  return false;

 

return true;

}

 

/**

* Gets the possible system commands for unzip on Linux

*

* @return string Returns unzip file path that can execute the unzip command

*/

public function getUnzipFilePath()

{

$filepath = null;

 

if ($this->hasShellExec()) {

  if (shell_exec('hash unzip 2>&1') == NULL) {

  $filepath = 'unzip';

  } else {

  $possible_paths = array(

'/usr/bin/unzip',

'/opt/local/bin/unzip',

'/bin/unzip',

'/usr/local/bin/unzip',

'/usr/sfw/bin/unzip',

'/usr/xdg4/bin/unzip',

'/opt/bin/unzip',  

// RSR TODO put back in when we support shellexec on windows,

  );

 

  foreach ($possible_paths as $path) {

if (file_exists($path)) {

  $filepath = $path;

  break;

}

  }

  }

}

 

return $filepath;

}

 

/**

 * Display human readable byte sizes such as 150MB

 *

 * @param int $size The size in bytes

 *

 * @return string A readable byte size format such as 100MB

 */

public function readableByteSize($size)

{

try {

  $units = array('B', 'KB', 'MB', 'GB', 'TB');

  for ($i = 0; $size >= 1024 && $i < 4; $i++)

  return round($size, 2).$units[$i];

} catch (Exception $e) {

  return "n/a";

}

}

 

/**

*  Returns an array of zip files found in the current executing directory

*

*  @return array of zip files

*/

  public static function getFilesWithExtension($extension)

  {

  $files = array();

  foreach (glob("*.{$extension}") as $name) {

  if (file_exists($name)) {

  $files[] = $name;

  }

  }

 

  if (count($files) > 0) {

  return $files;

  }

 

  //FALL BACK: Windows XP has bug with glob,

  //add secondary check for PHP lameness

  if ($dh = opendir('.')) {

  while (false !== ($name = readdir($dh))) {

  $ext = substr($name, strrpos($name, '.') + 1);

  if (in_array($ext, array($extension))) {

  $files[] = $name;

  }

  }

  closedir($dh);

  }

 

  return $files;

 }

 

/**

* Safely remove a directory and recursively if needed

*

* @param string $directory The full path to the directory to remove

* @param string $recursive recursively remove all items

*

* @return bool Returns true if all content was removed

*/

  public static function deleteDirectory($directory, $recursive)

  {

  $success = true;

 

  $filenames = array_diff(scandir($directory), array('.', '..'));

 

  foreach ($filenames as $filename) {

  $fullPath = $directory.'/'.$filename;

 

  if (is_dir($fullPath)) {

  if ($recursive) {

  $success = self::deleteDirectory($fullPath, true);

  }

  } else {

  $success = @unlink($fullPath);

  if ($success === false) {

  self::log('[ERROR] '.__FUNCTION__.": Problem deleting file:".$fullPath);

  }

  }

 

  if ($success === false) {

  self::log("[ERROR] Problem deleting dir:".$directory);

  break;

  }

  }

 

  return $success && rmdir($directory);

  }

 

  /**

* Safely remove a file or directory and recursively if needed

*

* @param string $directory The full path to the directory to remove

*

* @return bool Returns true if all content was removed

*/

  public static function deletePath($path)

  {

  $success = true;

 

  if (is_dir($path)) {

  $success = self::deleteDirectory($path, true);

  } else {

  $success = @unlink($path);

 

  if ($success === false) {

  self::log('[ERROR] '. __FUNCTION__.": Problem deleting file:".$path);

  }

  }

 

  return $success;

  }

 

  /**

 *  Makes path safe for any OS for PHP

 *

 *  Paths should ALWAYS READ be "/"

 * uni:  /home/path/file.txt

 * win:  D:/home/path/file.txt

 *

 *  @param string $path   The path to make safe

 *

 *  @return string The original $path with a with all slashes facing '/'.

 */

public static function setSafePath($path)

{

return str_replace("\\", "/", $path);

}

}

 

class DUPX_Handler

{

  /**

*

* @var bool

*/

  private static $initialized = false;

 

  /**

* This function only initializes the error handler the first time it is called

*/

  public static function init_error_handler()

  {

  if (!self::$initialized) {

  @set_error_handler(array(__CLASS__, 'error'));

  @register_shutdown_function(array(__CLASS__, 'shutdown'));

  self::$initialized = true;

  }

  }

 

  /**

* Error handler

*

* @param  integer $errno Error level

* @param  string  $errstr  Error message

* @param  string  $errfile Error file

* @param  integer $errline Error line

* @return void

*/

  public static function error($errno, $errstr, $errfile, $errline)

  {

  switch ($errno) {

  case E_ERROR :

  $log_message = self::getMessage($errno, $errstr, $errfile, $errline);

  if (DUPX_Bootstrap::log($log_message) === false) {

  $log_message = "Can\'t write logfile\n\n".$log_message;

  }

  die('<pre>'.htmlspecialchars($log_message).'</pre>');

  break;

  case E_NOTICE :

  case E_WARNING :

  default :

  $log_message = self::getMessage($errno, $errstr, $errfile, $errline);

  DUPX_Bootstrap::log($log_message);

  break;

  }

  }

 

  private static function getMessage($errno, $errstr, $errfile, $errline)

  {

  $result = '[PHP ERR]';

  switch ($errno) {

  case E_ERROR :

  $result .= '[FATAL]';

  break;

  case E_WARNING :

  $result .= '[WARN]';

  break;

  case E_NOTICE :

  $result .= '[NOTICE]';

  break;

  default :

  $result .= '[ISSUE]';

  break;

  }

  $result .= ' MSG:';

  $result .= $errstr;

  $result .= ' [CODE:'.$errno.'|FILE:'.$errfile.'|LINE:'.$errline.']';

  return $result;

  }

 

  /**

* Shutdown handler

*

* @return void

*/

  public static function shutdown()

  {

  if (($error = error_get_last())) {

  DUPX_Handler::error($error['type'], $error['message'], $error['file'], $error['line']);

  }

  }

}

 

class DUPX_CSRF {

/**

 * Session var name prefix

 * @var string

 */

public static $prefix = '_DUPX_CSRF';

 

/**

 * Stores all CSRF values: Key as CSRF name and Val as CRF value

 * @var array

 */

private static $CSRFVars;

 

/**

 * Set new CSRF

 *

 * @param $key string CSRF Key

 * @param $key string CSRF Val

 *

 * @return Void

 */

public static function setKeyVal($key, $val) {

$CSRFVars = self::getCSRFVars();

$CSRFVars[$key] = $val;

self::saveCSRFVars($CSRFVars);

self::$CSRFVars = false;

}

 

/**

 * Get CSRF value by passing CSRF key

 *

 * @param $key string CSRF key

 *

 * @return string|boolean If CSRF value set for give n Key, It returns CRF value otherise returns false

 */

public static function getVal($key) {

$CSRFVars = self::getCSRFVars();

if (isset($CSRFVars[$key])) {

  return $CSRFVars[$key];

} else {

  return false;

}

}

/** Generate DUPX_CSRF value for form

 *

 * @param  string $form - Form name as session key

 * @return string - token

 */

public static function generate($form = NULL) {

$keyName = self::getKeyName($form);

 

$existingToken = self::getVal($keyName);

if (false !== $existingToken) {

  $token = $existingToken;

} else {

  $token = DUPX_CSRF::token() . DUPX_CSRF::fingerprint();

}

self::setKeyVal($keyName, $token);

return $token;

}

/**

 * Check DUPX_CSRF value of form

 *

 * @param  string $token   - Token

 * @param  string $form - Form name as session key

 * @return boolean

 */

public static function check($token, $form = NULL) {

$keyName = self::getKeyName($form);

$CSRFVars = self::getCSRFVars();

if (isset($CSRFVars[$keyName]) && $CSRFVars[$keyName] == $token) { // token OK

  return true;

}

return FALSE;

}

/** Generate token

 * @param  void

 * @return  string

 */

protected static function token() {

mt_srand((double) microtime() * 10000);

$charid = strtoupper(md5(uniqid(rand(), TRUE)));

return substr($charid, 0, 8) . substr($charid, 8, 4) . substr($charid, 12, 4) . substr($charid, 16, 4) . substr($charid, 20, 12);

}

/** Returns "digital fingerprint" of user

 * @param void

 * @return   string - MD5 hashed data

 */

protected static function fingerprint() {

return strtoupper(md5(implode('|', array($_SERVER['REMOTE_ADDR'], $_SERVER['HTTP_USER_AGENT']))));

}

 

/**

 * Generate CSRF Key name

 *

 * @param string the form name for which CSRF key need to generate

 * @return string CSRF key

 */

private static function getKeyName($form) {

return DUPX_CSRF::$prefix . '_' . $form;

}

 

/**

 * Get Package hash

 *

 * @return string Package hash

 */

private static function getPackageHash() {

if (class_exists('DUPX_Bootstrap')) {

  return DUPX_Bootstrap::PACKAGE_HASH;

} else {

  return $GLOBALS['DUPX_AC']->package_hash;

}

}

 

/**

 * Get file path where CSRF tokens are stored in JSON encoded format

 *

 * @return string file path where CSRF token stored

 */

private static function getFilePath() {

if (class_exists('DUPX_Bootstrap')) {

  $dupInstallerfolderPath = dirname(__FILE__).'/dup-installer/';

} else {

  $dupInstallerfolderPath = $GLOBALS['DUPX_INIT'].'/';

}

$packageHash = self::getPackageHash();

$fileName = 'dup-installer-csrf__'.$packageHash.'.txt';

$filePath = $dupInstallerfolderPath.$fileName;

return $filePath;

}

 

/**

 * Get all CSRF vars in array format

 *

 * @return array Key as CSRF name and value as CSRF value

 */

private static function getCSRFVars() {

if (!isset(self::$CSRFVars) || false === self::$CSRFVars) {

  $filePath = self::getFilePath();

  if (file_exists($filePath)) {

  $contents = file_get_contents($filePath);

  if (!($contents = file_get_contents($filePath))) {

  }

  if (empty($contents)) {

self::$CSRFVars = array();

  } else {

$CSRFobjs = json_decode($contents);

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

  self::$CSRFVars[$key] = $value;

}

  }

  } else {

  self::$CSRFVars = array();

  }

}

return self::$CSRFVars;

}

 

/**

 * Stores all CSRF vars

 *

 * @param $CSRFVars array holds all CSRF key val

 * @return void

 */

private static function saveCSRFVars($CSRFVars) {

$contents = json_encode($CSRFVars);

$filePath = self::getFilePath();

if (!file_put_contents($filePath, $contents, LOCK_EX)) {

  throw new Exception('Fail to write the CSRF file.');

}

}

}

 

try {

  $boot  = new DUPX_Bootstrap();

  $boot_error = $boot->run();

  $auto_refresh = isset($_POST['auto-fresh']) ? true : false;

 

if ($boot_error == null) {

$step1_csrf_token = DUPX_CSRF::generate('step1');

DUPX_CSRF::setKeyVal('archive', $boot->archive);

DUPX_CSRF::setKeyVal('bootloader', $boot->bootloader);

DUPX_CSRF::setKeyVal('secondaryHash', DUPX_Bootstrap::SECONDARY_PACKAGE_HASH);

DUPX_CSRF::setKeyVal('installerOrigCall', DUPX_Bootstrap::getCurrentUrl());

DUPX_CSRF::setKeyVal('installerOrigPath', __FILE__);

DUPX_CSRF::setKeyVal('booturl', '//'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']);

DUPX_CSRF::setKeyVal('bootLogFile', DUPX_Bootstrap::getBootLogFilePath());

DUPX_CSRF::setKeyVal('package_hash', DUPX_Bootstrap::PACKAGE_HASH);

}

} catch (Exception $e) {

$boot_error = $e->getMessage();

}

 

?>

 

<html>

<?php if ($boot_error == null) :?>

<head>

<meta name="robots" content="noindex,nofollow">

<title>Duplicator Installer</title>

</head>

<body>

<?php

$id = uniqid();

$html = "<form id='{$id}' method='post' action=".str_replace('\\/', '/', json_encode($boot->mainInstallerURL))." />\n";

$data = array(

  'csrf_token' => $step1_csrf_token,

);

foreach ($data as $name => $value) {

  $html .= "<input type='hidden' name='{$name}' value='{$value}' />\n";

}

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

$html .= "<script>window.onload = function() { document.getElementById('{$id}').submit(); }</script>";

echo $html;

?>

</body>

<?php else :?>

<head>

<style>

  body {font-family:Verdana,Arial,sans-serif; line-height:18px; font-size: 12px}

  h2 {font-size:20px; margin:5px 0 5px 0; border-bottom:1px solid #dfdfdf; padding:3px}

  div#content {border:1px solid #CDCDCD; width:750px; min-height:550px; margin:auto; margin-top:18px; border-radius:3px; box-shadow:0 8px 6px -6px #333; font-size:13px}

  div#content-inner {padding:10px 30px; min-height:550px}

 

  /* Header */

  table.header-wizard {border-top-left-radius:5px; border-top-right-radius:5px; width:100%; box-shadow:0 5px 3px -3px #999; background-color:#F1F1F1; font-weight:bold}

  table.header-wizard td.header {font-size:24px; padding:7px 0 7px 0; width:100%;}

  div.dupx-logfile-link {float:right; font-weight:normal; font-size:12px}

  .dupx-version {white-space:nowrap; color:#999; font-size:11px; font-style:italic; text-align:right;  padding:0 15px 5px 0; line-height:14px; font-weight:normal}

  .dupx-version a { color:#999; }

 

  div.errror-notice {text-align:center; font-style:italic; font-size:11px}

  div.errror-msg { color:maroon; padding: 10px 0 5px 0}

  .pass {color:green}

  .fail {color:red}

  span.file-info {font-size: 11px; font-style: italic}

  div.skip-not-found {padding:10px 0 5px 0;}

  div.skip-not-found label {cursor: pointer}

  table.settings {width:100%; font-size:12px}

  table.settings td {padding: 4px}

  table.settings td:first-child {font-weight: bold}

  .w3-light-grey,.w3-hover-light-grey:hover,.w3-light-gray,.w3-hover-light-gray:hover{color:#000!important;background-color:#f1f1f1!important}

  .w3-container:after,.w3-container:before,.w3-panel:after,.w3-panel:before,.w3-row:after,.w3-row:before,.w3-row-padding:after,.w3-row-padding:before,

  .w3-cell-row:before,.w3-cell-row:after,.w3-clear:after,.w3-clear:before,.w3-bar:before,.w3-bar:after

  {content:"";display:table;clear:both}

  .w3-green,.w3-hover-green:hover{color:#fff!important;background-color:#4CAF50!important}

  .w3-container{padding:0.01em 16px}

  .w3-center{display:inline-block;width:auto; text-align: center !important}

</style>

</head>

<body>

<div id="content">

 

<table cellspacing="0">

  <tr>

  <td>

  <td>

version: <?php echo DUPX_Bootstrap::VERSION ?><br/>

  </td>

  </tr>

</table>

 

<form id="error-form" method="post">

<div id="content-inner">

  <h2>

  <div>

  <div>

  <?php echo $boot_error ?>

  </div>

  <br/><br/>

 

  <h2>Server Settings:</h2>

  <table>

  <tr>

<td>ZipArchive:</td>

<td><?php echo $boot->hasZipArchive  ? '<i>

  </tr>

  <tr>

<td>ShellExec&nbsp;Unzip:</td>

<td><?php echo $boot->hasShellExecUnzip   ? '<i>

  </tr>

  <tr>

<td>Extraction&nbsp;Path:</td>

<td><?php echo $boot->installerExtractPath; ?></td>

  </tr>

  <tr>

<td>Installer Path:</td>

  <td><?php echo $boot->installerContentsPath; ?></td>

  </tr>

  <tr>

<td>Archive Name:</td>

<td>

  [HASH]_archive.zip or [HASH]_archive.daf<br/>

  <small>This is based on the format used to build the archive</small>

</td>

  </tr>

  <tr>

<td>Archive Size:</td>

<td>

  <b>Expected Size:</b><?php echo $boot->readableByteSize($boot->archiveExpectedSize); ?>&nbsp;

  <b>Actual Size:</b><?php echo $boot->readableByteSize($boot->archiveActualSize); ?>

</td>

  </tr>

  <tr>

<td>Boot Log</td>

<td>dup-installer-bootlog__[HASH].txt</td>

  </tr>

  </table>

  <br/><br/>

 

  <div>

  Please Note: Either ZipArchive or Shell Exec will need to be enabled for the installer to run automatically otherwise a manual extraction

  will need to be performed.  In order to run the installer manually follow the instructions to

  <a href='https://snapcreek.com/duplicator/docs/faqs-tech/#faq-installer-015-q' target='_blank'>manually extract</a> before running the installer.

  </div>

  <br/><br/>

 

</div>

</form>

 

</div>

</body>

 

<script>

function AutoFresh() {

  document.getElementById('error-form').submit();

}

<?php if ($auto_refresh) :?>

  var duration = 10000; //10 seconds

var counter  = 10;

  var countElement = document.getElementById('count-down');

 

  setTimeout(function(){window.location.reload(1);}, duration);

  setInterval(function() {

  counter--;

  countElement.innerHTML = (counter > 0) ? counter.toString() : "0";

  }, 1000);

 

<?php endif; ?>

</script>

 

 

<?php endif; ?>

 

<!--

Used for integrity check do not remove:

DUPLICATOR_INSTALLER_EOF  -->

</html>

Похожие работы на - Автоматизированная система работы поликлиники

 

Не нашли материал для своей работы?
Поможем написать уникальную работу
Без плагиата!